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 Multi threaded EGL tests
     22  *//*--------------------------------------------------------------------*/
     23 #include "teglMultiThreadTests.hpp"
     24 
     25 #include "egluNativeWindow.hpp"
     26 #include "egluNativePixmap.hpp"
     27 #include "egluUtil.hpp"
     28 
     29 #include "tcuTestLog.hpp"
     30 #include "tcuCommandLine.hpp"
     31 
     32 #include "deRandom.hpp"
     33 
     34 #include "deThread.hpp"
     35 #include "deMutex.hpp"
     36 #include "deSemaphore.hpp"
     37 
     38 #include "deAtomic.h"
     39 #include "deClock.h"
     40 
     41 #include <vector>
     42 #include <string>
     43 #include <sstream>
     44 
     45 using std::vector;
     46 using std::string;
     47 using std::pair;
     48 using std::ostringstream;
     49 
     50 namespace deqp
     51 {
     52 namespace egl
     53 {
     54 
     55 class ThreadLog
     56 {
     57 public:
     58 	class BeginMessageToken	{};
     59 	class EndMessageToken	{};
     60 
     61 	struct Message
     62 	{
     63 					Message	(deUint64 timeUs_, const char* msg_) : timeUs(timeUs_), msg(msg_) {}
     64 
     65 		deUint64	timeUs;
     66 		string		msg;
     67 	};
     68 
     69 								ThreadLog	(void)						{ m_messages.reserve(100); }
     70 
     71 	ThreadLog&					operator<<	(const BeginMessageToken&)	{ return *this; }
     72 	ThreadLog&					operator<<	(const EndMessageToken&);
     73 
     74 	template<class T>
     75 	ThreadLog&					operator<< 	(const T& t)				{ m_message << t; return *this; }
     76 	const vector<Message>&		getMessages (void) const				{ return m_messages; }
     77 
     78 	static BeginMessageToken	BeginMessage;
     79 	static EndMessageToken		EndMessage;
     80 
     81 private:
     82 	ostringstream		m_message;
     83 	vector<Message>		m_messages;
     84 };
     85 
     86 ThreadLog& ThreadLog::operator<< (const EndMessageToken&)
     87 {
     88 	m_messages.push_back(Message(deGetMicroseconds(), m_message.str().c_str()));
     89 	m_message.str("");
     90 	return *this;
     91 }
     92 
     93 ThreadLog::BeginMessageToken	ThreadLog::BeginMessage;
     94 ThreadLog::EndMessageToken		ThreadLog::EndMessage;
     95 
     96 class MultiThreadedTest;
     97 
     98 class TestThread : public de::Thread
     99 {
    100 public:
    101 	enum ThreadStatus
    102 	{
    103 		THREADSTATUS_NOT_STARTED = 0,
    104 		THREADSTATUS_RUNNING,
    105 		THREADSTATUS_READY,
    106 
    107 		THREADSTATUS_NOT_SUPPORTED,
    108 		THREADSTATUS_ERROR
    109 	};
    110 
    111 					TestThread	(MultiThreadedTest& test, int id);
    112 	void			run			(void);
    113 
    114 	ThreadStatus	getStatus	(void) const	{ return m_status; }
    115 	ThreadLog&		getLog		(void)			{ return m_log; }
    116 
    117 	int				getId		(void) const	{ return m_id; }
    118 
    119 	void			setStatus	(ThreadStatus status)	{ m_status = status; }
    120 
    121 
    122 	// Test has stopped
    123 	class TestStop {};
    124 
    125 
    126 private:
    127 	MultiThreadedTest&	m_test;
    128 	const int			m_id;
    129 	ThreadStatus		m_status;
    130 	ThreadLog			m_log;
    131 };
    132 
    133 class MultiThreadedTest : public TestCase
    134 {
    135 public:
    136 							MultiThreadedTest	(EglTestContext& eglTestCtx, const char* name, const char* description, int threadCount, deUint64 timeoutUs);
    137 	virtual					~MultiThreadedTest	(void);
    138 	virtual void			deinit				(void) {}
    139 
    140 	virtual bool			runThread			(TestThread& thread) = 0;
    141 	virtual IterateResult	iterate				(void);
    142 	bool					execTest			(TestThread& thread);
    143 
    144 protected:
    145 	void					barrier				(TestThread& thread);
    146 
    147 private:
    148 	int						m_threadCount;
    149 	bool					m_initialized;
    150 	deUint64				m_startTimeUs;
    151 	const deUint64			m_timeoutUs;
    152 	vector<TestThread*>		m_threads;
    153 
    154 	volatile deInt32		m_barrierWaiters;
    155 	de::Semaphore			m_barrierSemaphore1;
    156 	de::Semaphore			m_barrierSemaphore2;
    157 };
    158 
    159 TestThread::TestThread (MultiThreadedTest& test, int id)
    160 	: m_test	(test)
    161 	, m_id		(id)
    162 	, m_status	(THREADSTATUS_NOT_STARTED)
    163 {
    164 }
    165 
    166 void TestThread::run (void)
    167 {
    168 	m_status = THREADSTATUS_RUNNING;
    169 
    170 	try
    171 	{
    172 		if (m_test.execTest(*this))
    173 			m_status = THREADSTATUS_READY;
    174 		else
    175 			m_status = THREADSTATUS_ERROR;
    176 	}
    177 	catch (const TestThread::TestStop&)
    178 	{
    179 		getLog() << ThreadLog::BeginMessage << "Thread stopped" << ThreadLog::EndMessage;
    180 	}
    181 	catch (const tcu::NotSupportedError& e)
    182 	{
    183 		getLog() << ThreadLog::BeginMessage << "Not supported: '" << e.what() << "'" << ThreadLog::EndMessage;
    184 	}
    185 	catch (const std::exception& e)
    186 	{
    187 		getLog() << ThreadLog::BeginMessage << "Got exception: '" << e.what() << "'" << ThreadLog::EndMessage;
    188 	}
    189 	catch (...)
    190 	{
    191 		getLog() << ThreadLog::BeginMessage << "Unknown exception" << ThreadLog::EndMessage;
    192 	}
    193 }
    194 
    195 bool MultiThreadedTest::execTest (TestThread& thread)
    196 {
    197 	bool isOk = false;
    198 
    199 	try
    200 	{
    201 		isOk = runThread(thread);
    202 	}
    203 	catch (const TestThread::TestStop&)
    204 	{
    205 		// Thread exited due to error in other thread
    206 		throw;
    207 	}
    208 	catch (const tcu::NotSupportedError&)
    209 	{
    210 		// Set status of each thread
    211 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    212 			m_threads[threadNdx]->setStatus(TestThread::THREADSTATUS_NOT_SUPPORTED);
    213 
    214 		// Release barriers
    215 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    216 		{
    217 			m_barrierSemaphore1.increment();
    218 			m_barrierSemaphore2.increment();
    219 		}
    220 
    221 		throw;
    222 	}
    223 	catch(...)
    224 	{
    225 		// Set status of each thread
    226 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    227 			m_threads[threadNdx]->setStatus(TestThread::THREADSTATUS_ERROR);
    228 
    229 		// Release barriers
    230 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    231 		{
    232 			m_barrierSemaphore1.increment();
    233 			m_barrierSemaphore2.increment();
    234 		}
    235 
    236 		throw;
    237 	}
    238 
    239 	return isOk;
    240 }
    241 
    242 MultiThreadedTest::MultiThreadedTest (EglTestContext& eglTestCtx, const char* name, const char* description, int threadCount, deUint64 timeoutUs)
    243 	: TestCase				(eglTestCtx, name, description)
    244 	, m_threadCount			(threadCount)
    245 	, m_initialized			(false)
    246 	, m_startTimeUs			(0)
    247 	, m_timeoutUs			(timeoutUs)
    248 
    249 	, m_barrierWaiters		(0)
    250 	, m_barrierSemaphore1	(0, 0)
    251 	, m_barrierSemaphore2	(1, 0)
    252 {
    253 }
    254 
    255 MultiThreadedTest::~MultiThreadedTest (void)
    256 {
    257 	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    258 		delete m_threads[threadNdx];
    259 	m_threads.clear();
    260 }
    261 
    262 void MultiThreadedTest::barrier (TestThread& thread)
    263 {
    264 	{
    265 		const deInt32 waiters = deAtomicIncrement32(&m_barrierWaiters);
    266 
    267 		if (waiters == m_threadCount)
    268 		{
    269 			m_barrierSemaphore2.decrement();
    270 			m_barrierSemaphore1.increment();
    271 		}
    272 		else
    273 		{
    274 			m_barrierSemaphore1.decrement();
    275 			m_barrierSemaphore1.increment();
    276 		}
    277 	}
    278 
    279 	{
    280 		const deInt32 waiters = deAtomicDecrement32(&m_barrierWaiters);
    281 
    282 		if (waiters == 0)
    283 		{
    284 			m_barrierSemaphore1.decrement();
    285 			m_barrierSemaphore2.increment();
    286 		}
    287 		else
    288 		{
    289 			m_barrierSemaphore2.decrement();
    290 			m_barrierSemaphore2.increment();
    291 		}
    292 	}
    293 
    294 	// Barrier was released due an error in other thread
    295 	if (thread.getStatus() != TestThread::THREADSTATUS_RUNNING)
    296 		throw TestThread::TestStop();
    297 }
    298 
    299 TestCase::IterateResult MultiThreadedTest::iterate (void)
    300 {
    301 	if (!m_initialized)
    302 	{
    303 		m_testCtx.getLog() << tcu::TestLog::Message << "Thread timeout limit: " << m_timeoutUs << "us" << tcu::TestLog::EndMessage;
    304 
    305 		// Create threads
    306 		m_threads.reserve(m_threadCount);
    307 
    308 		for (int threadNdx = 0; threadNdx < m_threadCount; threadNdx++)
    309 			m_threads.push_back(new TestThread(*this, threadNdx));
    310 
    311 		m_startTimeUs = deGetMicroseconds();
    312 
    313 		// Run threads
    314 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    315 			m_threads[threadNdx]->start();
    316 
    317 		m_initialized = true;
    318 	}
    319 
    320 	int readyCount = 0;
    321 	for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    322 	{
    323 		if (m_threads[threadNdx]->getStatus() != TestThread::THREADSTATUS_RUNNING)
    324 			readyCount++;
    325 	}
    326 
    327 	if (readyCount == m_threadCount)
    328 	{
    329 		// Join threads
    330 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    331 			m_threads[threadNdx]->join();
    332 
    333 		bool isOk			= true;
    334 		bool notSupported	= false;
    335 
    336 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    337 		{
    338 			if (m_threads[threadNdx]->getStatus() == TestThread::THREADSTATUS_ERROR)
    339 				isOk = false;
    340 
    341 			if (m_threads[threadNdx]->getStatus() == TestThread::THREADSTATUS_NOT_SUPPORTED)
    342 				notSupported = true;
    343 		}
    344 
    345 		// Get logs
    346 		{
    347 			vector<int> messageNdx;
    348 
    349 			messageNdx.resize(m_threads.size(), 0);
    350 
    351 			while (true)
    352 			{
    353 				int			nextThreadNdx		= -1;
    354 				deUint64	nextThreadTimeUs	= 0;
    355 
    356 				for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    357 				{
    358 					if (messageNdx[threadNdx] >= (int)m_threads[threadNdx]->getLog().getMessages().size())
    359 						continue;
    360 
    361 					if (nextThreadNdx == -1 || nextThreadTimeUs > m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs)
    362 					{
    363 						nextThreadNdx		= threadNdx;
    364 						nextThreadTimeUs	= m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs;
    365 					}
    366 				}
    367 
    368 				if (nextThreadNdx == -1)
    369 					break;
    370 
    371 				m_testCtx.getLog() << tcu::TestLog::Message << "[" << (nextThreadTimeUs - m_startTimeUs) << "] (" << nextThreadNdx << ") " << m_threads[nextThreadNdx]->getLog().getMessages()[messageNdx[nextThreadNdx]].msg << tcu::TestLog::EndMessage;
    372 
    373 				messageNdx[nextThreadNdx]++;
    374 			}
    375 		}
    376 
    377 		// Destroy threads
    378 		for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    379 			delete m_threads[threadNdx];
    380 
    381 		m_threads.clear();
    382 
    383 		// Set result
    384 		if (isOk)
    385 		{
    386 			if (notSupported)
    387 				m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
    388 			else
    389 				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    390 		}
    391 		else
    392 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    393 
    394 		return STOP;
    395 	}
    396 	else
    397 	{
    398 		// Check for timeout
    399 		const deUint64 currentTimeUs = deGetMicroseconds();
    400 
    401 		if (currentTimeUs - m_startTimeUs > m_timeoutUs)
    402 		{
    403 			// Get logs
    404 			{
    405 				vector<int> messageNdx;
    406 
    407 				messageNdx.resize(m_threads.size(), 0);
    408 
    409 				while (true)
    410 				{
    411 					int			nextThreadNdx		= -1;
    412 					deUint64	nextThreadTimeUs	= 0;
    413 
    414 					for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
    415 					{
    416 						if (messageNdx[threadNdx] >= (int)m_threads[threadNdx]->getLog().getMessages().size())
    417 							continue;
    418 
    419 						if (nextThreadNdx == -1 || nextThreadTimeUs > m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs)
    420 						{
    421 							nextThreadNdx		= threadNdx;
    422 							nextThreadTimeUs	= m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs;
    423 						}
    424 					}
    425 
    426 					if (nextThreadNdx == -1)
    427 						break;
    428 
    429 					m_testCtx.getLog() << tcu::TestLog::Message << "[" << (nextThreadTimeUs - m_startTimeUs) << "] (" << nextThreadNdx << ") " << m_threads[nextThreadNdx]->getLog().getMessages()[messageNdx[nextThreadNdx]].msg << tcu::TestLog::EndMessage;
    430 
    431 					messageNdx[nextThreadNdx]++;
    432 				}
    433 			}
    434 
    435 			m_testCtx.getLog() << tcu::TestLog::Message << "[" << (currentTimeUs - m_startTimeUs) << "] (-) Timeout, Limit: " << m_timeoutUs << "us" << tcu::TestLog::EndMessage;
    436 			m_testCtx.getLog() << tcu::TestLog::Message << "[" << (currentTimeUs - m_startTimeUs) << "] (-) Trying to perform resource cleanup..." << tcu::TestLog::EndMessage;
    437 
    438 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    439 			return STOP;
    440 		}
    441 
    442 		// Sleep
    443 		deSleep(10);
    444 	}
    445 
    446 	return CONTINUE;
    447 }
    448 
    449 namespace
    450 {
    451 
    452 const char* configAttributeToString (EGLint e)
    453 {
    454 	switch (e)
    455 	{
    456 		case EGL_BUFFER_SIZE:				return "EGL_BUFFER_SIZE";
    457 		case EGL_RED_SIZE:					return "EGL_RED_SIZE";
    458 		case EGL_GREEN_SIZE:				return "EGL_GREEN_SIZE";
    459 		case EGL_BLUE_SIZE:					return "EGL_BLUE_SIZE";
    460 		case EGL_LUMINANCE_SIZE:			return "EGL_LUMINANCE_SIZE";
    461 		case EGL_ALPHA_SIZE:				return "EGL_ALPHA_SIZE";
    462 		case EGL_ALPHA_MASK_SIZE:			return "EGL_ALPHA_MASK_SIZE";
    463 		case EGL_BIND_TO_TEXTURE_RGB:		return "EGL_BIND_TO_TEXTURE_RGB";
    464 		case EGL_BIND_TO_TEXTURE_RGBA:		return "EGL_BIND_TO_TEXTURE_RGBA";
    465 		case EGL_COLOR_BUFFER_TYPE:			return "EGL_COLOR_BUFFER_TYPE";
    466 		case EGL_CONFIG_CAVEAT:				return "EGL_CONFIG_CAVEAT";
    467 		case EGL_CONFIG_ID:					return "EGL_CONFIG_ID";
    468 		case EGL_CONFORMANT:				return "EGL_CONFORMANT";
    469 		case EGL_DEPTH_SIZE:				return "EGL_DEPTH_SIZE";
    470 		case EGL_LEVEL:						return "EGL_LEVEL";
    471 		case EGL_MAX_PBUFFER_WIDTH:			return "EGL_MAX_PBUFFER_WIDTH";
    472 		case EGL_MAX_PBUFFER_HEIGHT:		return "EGL_MAX_PBUFFER_HEIGHT";
    473 		case EGL_MAX_PBUFFER_PIXELS:		return "EGL_MAX_PBUFFER_PIXELS";
    474 		case EGL_MAX_SWAP_INTERVAL:			return "EGL_MAX_SWAP_INTERVAL";
    475 		case EGL_MIN_SWAP_INTERVAL:			return "EGL_MIN_SWAP_INTERVAL";
    476 		case EGL_NATIVE_RENDERABLE:			return "EGL_NATIVE_RENDERABLE";
    477 		case EGL_NATIVE_VISUAL_ID:			return "EGL_NATIVE_VISUAL_ID";
    478 		case EGL_NATIVE_VISUAL_TYPE:		return "EGL_NATIVE_VISUAL_TYPE";
    479 		case EGL_RENDERABLE_TYPE:			return "EGL_RENDERABLE_TYPE";
    480 		case EGL_SAMPLE_BUFFERS:			return "EGL_SAMPLE_BUFFERS";
    481 		case EGL_SAMPLES:					return "EGL_SAMPLES";
    482 		case EGL_STENCIL_SIZE:				return "EGL_STENCIL_SIZE";
    483 		case EGL_SURFACE_TYPE:				return "EGL_SURFACE_TYPE";
    484 		case EGL_TRANSPARENT_TYPE:			return "EGL_TRANSPARENT_TYPE";
    485 		case EGL_TRANSPARENT_RED_VALUE:		return "EGL_TRANSPARENT_RED_VALUE";
    486 		case EGL_TRANSPARENT_GREEN_VALUE:	return "EGL_TRANSPARENT_GREEN_VALUE";
    487 		case EGL_TRANSPARENT_BLUE_VALUE:	return "EGL_TRANSPARENT_BLUE_VALUE";
    488 		default:							return "<Unknown>";
    489 	}
    490 }
    491 
    492 } // anonymous
    493 
    494 class MultiThreadedConfigTest : public MultiThreadedTest
    495 {
    496 public:
    497 				MultiThreadedConfigTest		(EglTestContext& context, const char* name, const char* description, int getConfigs, int chooseConfigs, int query);
    498 	bool		runThread					(TestThread& thread);
    499 
    500 private:
    501 	EGLDisplay	m_display;
    502 	const int	m_getConfigs;
    503 	const int	m_chooseConfigs;
    504 	const int	m_query;
    505 };
    506 
    507 MultiThreadedConfigTest::MultiThreadedConfigTest (EglTestContext& context, const char* name, const char* description, int getConfigs, int chooseConfigs, int query)
    508 	: MultiThreadedTest (context, name, description, 2, 20000000/*us = 20s*/) // \todo [mika] Set timeout to something relevant to frameworks timeout?
    509 	, m_display			(EGL_NO_DISPLAY)
    510 	, m_getConfigs		(getConfigs)
    511 	, m_chooseConfigs	(chooseConfigs)
    512 	, m_query			(query)
    513 {
    514 }
    515 
    516 bool MultiThreadedConfigTest::runThread (TestThread& thread)
    517 {
    518 	de::Random			rnd(deInt32Hash(thread.getId() + 10435));
    519 	vector<EGLConfig>	configs;
    520 
    521 	if (thread.getId() == 0)
    522 		m_display = m_eglTestCtx.getDisplay().getEGLDisplay();
    523 
    524 	barrier(thread);
    525 
    526 	for (int getConfigsNdx = 0; getConfigsNdx < m_getConfigs; getConfigsNdx++)
    527 	{
    528 		EGLint configCount;
    529 
    530 		// Get number of configs
    531 		{
    532 			EGLBoolean result;
    533 
    534 			result = eglGetConfigs(m_display, NULL, 0, &configCount);
    535 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigs(" << m_display << ", NULL, 0, " << configCount << ")" <<  ThreadLog::EndMessage;
    536 			TCU_CHECK_EGL_MSG("eglGetConfigs()");
    537 
    538 			if (!result)
    539 				return false;
    540 		}
    541 
    542 		configs.resize(configs.size() + configCount);
    543 
    544 		// Get configs
    545 		if (configCount != 0)
    546 		{
    547 			EGLBoolean result;
    548 
    549 			result = eglGetConfigs(m_display, &(configs[configs.size() - configCount]), configCount, &configCount);
    550 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigs(" << m_display << ", &configs' " << configCount << ", " << configCount << ")" <<  ThreadLog::EndMessage;
    551 			TCU_CHECK_EGL_MSG("eglGetConfigs()");
    552 
    553 			if (!result)
    554 				return false;
    555 		}
    556 
    557 		// Pop configs to stop config list growing
    558 		if (configs.size() > 40)
    559 		{
    560 			configs.erase(configs.begin() + 40, configs.end());
    561 		}
    562 		else
    563 		{
    564 			const int popCount = rnd.getInt(0, (int)(configs.size()-2));
    565 
    566 			configs.erase(configs.begin() + (configs.size() - popCount), configs.end());
    567 		}
    568 	}
    569 
    570 	for (int chooseConfigsNdx = 0; chooseConfigsNdx < m_chooseConfigs; chooseConfigsNdx++)
    571 	{
    572 		EGLint configCount;
    573 
    574 		static const EGLint attribList[] = {
    575 			EGL_NONE
    576 		};
    577 
    578 		// Get number of configs
    579 		{
    580 			EGLBoolean result;
    581 
    582 			result = eglChooseConfig(m_display, attribList, NULL, 0, &configCount);
    583 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglChooseConfig(" << m_display << ", { EGL_NONE }, NULL, 0, " << configCount << ")" <<  ThreadLog::EndMessage;
    584 			TCU_CHECK_EGL_MSG("eglChooseConfig()");
    585 
    586 			if (!result)
    587 				return false;
    588 		}
    589 
    590 		configs.resize(configs.size() + configCount);
    591 
    592 		// Get configs
    593 		if (configCount != 0)
    594 		{
    595 			EGLBoolean result;
    596 
    597 			result = eglChooseConfig(m_display, attribList, &(configs[configs.size() - configCount]), configCount, &configCount);
    598 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglChooseConfig(" << m_display << ", { EGL_NONE }, &configs, " << configCount << ", " << configCount << ")" <<  ThreadLog::EndMessage;
    599 			TCU_CHECK_EGL_MSG("eglChooseConfig()");
    600 
    601 			if (!result)
    602 				return false;
    603 		}
    604 
    605 		// Pop configs to stop config list growing
    606 		if (configs.size() > 40)
    607 		{
    608 			configs.erase(configs.begin() + 40, configs.end());
    609 		}
    610 		else
    611 		{
    612 			const int popCount = rnd.getInt(0, (int)(configs.size()-2));
    613 
    614 			configs.erase(configs.begin() + (configs.size() - popCount), configs.end());
    615 		}
    616 	}
    617 
    618 	{
    619 		// Perform queries on configs
    620 		static const EGLint attributes[] =
    621 		{
    622 			EGL_BUFFER_SIZE,
    623 			EGL_RED_SIZE,
    624 			EGL_GREEN_SIZE,
    625 			EGL_BLUE_SIZE,
    626 			EGL_LUMINANCE_SIZE,
    627 			EGL_ALPHA_SIZE,
    628 			EGL_ALPHA_MASK_SIZE,
    629 			EGL_BIND_TO_TEXTURE_RGB,
    630 			EGL_BIND_TO_TEXTURE_RGBA,
    631 			EGL_COLOR_BUFFER_TYPE,
    632 			EGL_CONFIG_CAVEAT,
    633 			EGL_CONFIG_ID,
    634 			EGL_CONFORMANT,
    635 			EGL_DEPTH_SIZE,
    636 			EGL_LEVEL,
    637 			EGL_MAX_PBUFFER_WIDTH,
    638 			EGL_MAX_PBUFFER_HEIGHT,
    639 			EGL_MAX_PBUFFER_PIXELS,
    640 			EGL_MAX_SWAP_INTERVAL,
    641 			EGL_MIN_SWAP_INTERVAL,
    642 			EGL_NATIVE_RENDERABLE,
    643 			EGL_NATIVE_VISUAL_ID,
    644 			EGL_NATIVE_VISUAL_TYPE,
    645 			EGL_RENDERABLE_TYPE,
    646 			EGL_SAMPLE_BUFFERS,
    647 			EGL_SAMPLES,
    648 			EGL_STENCIL_SIZE,
    649 			EGL_SURFACE_TYPE,
    650 			EGL_TRANSPARENT_TYPE,
    651 			EGL_TRANSPARENT_RED_VALUE,
    652 			EGL_TRANSPARENT_GREEN_VALUE,
    653 			EGL_TRANSPARENT_BLUE_VALUE
    654 		};
    655 
    656 		for (int queryNdx = 0; queryNdx < m_query; queryNdx++)
    657 		{
    658 			const EGLint	attribute	= attributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(attributes)-1)];
    659 			EGLConfig		config		= configs[rnd.getInt(0, (int)(configs.size()-1))];
    660 			EGLint			value;
    661 			EGLBoolean		result;
    662 
    663 			result = eglGetConfigAttrib(m_display, config, attribute, &value);
    664 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigAttrib(" << m_display << ", " << config << ", " << configAttributeToString(attribute) << ", " << value << ")" <<  ThreadLog::EndMessage;
    665 			TCU_CHECK_EGL_MSG("eglGetConfigAttrib()");
    666 
    667 			if (!result)
    668 				return false;
    669 		}
    670 	}
    671 
    672 	return true;
    673 }
    674 
    675 class MultiThreadedObjectTest : public MultiThreadedTest
    676 {
    677 public:
    678 	enum Type
    679 	{
    680 		TYPE_PBUFFER			= (1<<0),
    681 		TYPE_PIXMAP				= (1<<1),
    682 		TYPE_WINDOW				= (1<<2),
    683 		TYPE_SINGLE_WINDOW		= (1<<3),
    684 		TYPE_CONTEXT			= (1<<4)
    685 	};
    686 
    687 					MultiThreadedObjectTest			(EglTestContext& context, const char* name, const char* description, deUint32 types);
    688 					~MultiThreadedObjectTest		(void);
    689 
    690 	virtual void	deinit							(void);
    691 
    692 	bool			runThread						(TestThread& thread);
    693 
    694 	void			createDestroyObjects			(TestThread& thread, int count);
    695 	void			pushObjectsToShared				(TestThread& thread);
    696 	void			pullObjectsFromShared			(TestThread& thread, int pbufferCount, int pixmapCount, int windowCount, int contextCount);
    697 	void			querySetSharedObjects			(TestThread& thread, int count);
    698 	void			destroyObjects					(TestThread& thread);
    699 
    700 private:
    701 	EGLDisplay			m_display;
    702 	EGLConfig			m_config;
    703 	de::Random			m_rnd0;
    704 	de::Random			m_rnd1;
    705 	Type				m_types;
    706 
    707 	volatile deUint32	m_hasWindow;
    708 
    709 	vector<pair<eglu::NativePixmap*, EGLSurface> >	m_sharedNativePixmaps;
    710 	vector<pair<eglu::NativePixmap*, EGLSurface> >	m_nativePixmaps0;
    711 	vector<pair<eglu::NativePixmap*, EGLSurface> >	m_nativePixmaps1;
    712 
    713 	vector<pair<eglu::NativeWindow*, EGLSurface> >	m_sharedNativeWindows;
    714 	vector<pair<eglu::NativeWindow*, EGLSurface> >	m_nativeWindows0;
    715 	vector<pair<eglu::NativeWindow*, EGLSurface> >	m_nativeWindows1;
    716 
    717 	vector<EGLSurface>								m_sharedPbuffers;
    718 	vector<EGLSurface>								m_pbuffers0;
    719 	vector<EGLSurface>								m_pbuffers1;
    720 
    721 	vector<EGLContext>								m_sharedContexts;
    722 	vector<EGLContext>								m_contexts0;
    723 	vector<EGLContext>								m_contexts1;
    724 };
    725 
    726 MultiThreadedObjectTest::MultiThreadedObjectTest (EglTestContext& context, const char* name, const char* description, deUint32 type)
    727 	: MultiThreadedTest (context, name, description, 2, 20000000/*us = 20s*/) // \todo [mika] Set timeout to something relevant to frameworks timeout?
    728 	, m_display			(EGL_NO_DISPLAY)
    729 	, m_config			(DE_NULL)
    730 	, m_rnd0			(58204327)
    731 	, m_rnd1			(230983)
    732 	, m_types			((Type)type)
    733 	, m_hasWindow		(0)
    734 {
    735 }
    736 
    737 MultiThreadedObjectTest::~MultiThreadedObjectTest (void)
    738 {
    739 	deinit();
    740 }
    741 
    742 void MultiThreadedObjectTest::deinit (void)
    743 {
    744 	// Clear pbuffers
    745 	for (int pbufferNdx = 0; pbufferNdx < (int)m_pbuffers0.size(); pbufferNdx++)
    746 	{
    747 		if (m_pbuffers0[pbufferNdx] != EGL_NO_SURFACE)
    748 		{
    749 			eglDestroySurface(m_display, m_pbuffers0[pbufferNdx]);
    750 			TCU_CHECK_EGL_MSG("eglDestroySurface()");
    751 			m_pbuffers0[pbufferNdx] = EGL_NO_SURFACE;
    752 		}
    753 	}
    754 	m_pbuffers0.clear();
    755 
    756 	for (int pbufferNdx = 0; pbufferNdx < (int)m_pbuffers1.size(); pbufferNdx++)
    757 	{
    758 		if (m_pbuffers1[pbufferNdx] != EGL_NO_SURFACE)
    759 		{
    760 			eglDestroySurface(m_display, m_pbuffers1[pbufferNdx]);
    761 			TCU_CHECK_EGL_MSG("eglDestroySurface()");
    762 			m_pbuffers1[pbufferNdx] = EGL_NO_SURFACE;
    763 		}
    764 	}
    765 	m_pbuffers1.clear();
    766 
    767 	for (int pbufferNdx = 0; pbufferNdx < (int)m_sharedPbuffers.size(); pbufferNdx++)
    768 	{
    769 		if (m_sharedPbuffers[pbufferNdx] != EGL_NO_SURFACE)
    770 		{
    771 			eglDestroySurface(m_display, m_sharedPbuffers[pbufferNdx]);
    772 			TCU_CHECK_EGL_MSG("eglDestroySurface()");
    773 			m_sharedPbuffers[pbufferNdx] = EGL_NO_SURFACE;
    774 		}
    775 	}
    776 	m_sharedPbuffers.clear();
    777 
    778 	for (int contextNdx = 0; contextNdx < (int)m_sharedContexts.size(); contextNdx++)
    779 	{
    780 		if (m_sharedContexts[contextNdx] != EGL_NO_CONTEXT)
    781 		{
    782 			eglDestroyContext(m_display, m_sharedContexts[contextNdx]);
    783 			TCU_CHECK_EGL_MSG("eglDestroyContext()");
    784 			m_sharedContexts[contextNdx] =  EGL_NO_CONTEXT;
    785 		}
    786 	}
    787 	m_sharedContexts.clear();
    788 
    789 	for (int contextNdx = 0; contextNdx < (int)m_contexts0.size(); contextNdx++)
    790 	{
    791 		if (m_contexts0[contextNdx] != EGL_NO_CONTEXT)
    792 		{
    793 			eglDestroyContext(m_display, m_contexts0[contextNdx]);
    794 			TCU_CHECK_EGL_MSG("eglDestroyContext()");
    795 			m_contexts0[contextNdx] =  EGL_NO_CONTEXT;
    796 		}
    797 	}
    798 	m_contexts0.clear();
    799 
    800 	for (int contextNdx = 0; contextNdx < (int)m_contexts1.size(); contextNdx++)
    801 	{
    802 		if (m_contexts1[contextNdx] != EGL_NO_CONTEXT)
    803 		{
    804 			eglDestroyContext(m_display, m_contexts1[contextNdx]);
    805 			TCU_CHECK_EGL_MSG("eglDestroyContext()");
    806 			m_contexts1[contextNdx] =  EGL_NO_CONTEXT;
    807 		}
    808 	}
    809 	m_contexts1.clear();
    810 
    811 	// Clear pixmaps
    812 	for (int pixmapNdx = 0; pixmapNdx < (int)m_nativePixmaps0.size(); pixmapNdx++)
    813 	{
    814 		if (m_nativePixmaps0[pixmapNdx].second != EGL_NO_SURFACE)
    815 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_nativePixmaps0[pixmapNdx].second));
    816 
    817 		m_nativePixmaps0[pixmapNdx].second = EGL_NO_SURFACE;
    818 		delete m_nativePixmaps0[pixmapNdx].first;
    819 		m_nativePixmaps0[pixmapNdx].first = NULL;
    820 	}
    821 	m_nativePixmaps0.clear();
    822 
    823 	for (int pixmapNdx = 0; pixmapNdx < (int)m_nativePixmaps1.size(); pixmapNdx++)
    824 	{
    825 		if (m_nativePixmaps1[pixmapNdx].second != EGL_NO_SURFACE)
    826 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_nativePixmaps1[pixmapNdx].second));
    827 
    828 		m_nativePixmaps1[pixmapNdx].second = EGL_NO_SURFACE;
    829 		delete m_nativePixmaps1[pixmapNdx].first;
    830 		m_nativePixmaps1[pixmapNdx].first = NULL;
    831 	}
    832 	m_nativePixmaps1.clear();
    833 
    834 	for (int pixmapNdx = 0; pixmapNdx < (int)m_sharedNativePixmaps.size(); pixmapNdx++)
    835 	{
    836 		if (m_sharedNativePixmaps[pixmapNdx].second != EGL_NO_SURFACE)
    837 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_sharedNativePixmaps[pixmapNdx].second));
    838 
    839 		m_sharedNativePixmaps[pixmapNdx].second = EGL_NO_SURFACE;
    840 		delete m_sharedNativePixmaps[pixmapNdx].first;
    841 		m_sharedNativePixmaps[pixmapNdx].first = NULL;
    842 	}
    843 	m_sharedNativePixmaps.clear();
    844 
    845 	// Clear windows
    846 	for (int windowNdx = 0; windowNdx < (int)m_nativeWindows1.size(); windowNdx++)
    847 	{
    848 		if (m_nativeWindows1[windowNdx].second != EGL_NO_SURFACE)
    849 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_nativeWindows1[windowNdx].second));
    850 
    851 		m_nativeWindows1[windowNdx].second = EGL_NO_SURFACE;
    852 		delete m_nativeWindows1[windowNdx].first;
    853 		m_nativeWindows1[windowNdx].first = NULL;
    854 	}
    855 	m_nativeWindows1.clear();
    856 
    857 	for (int windowNdx = 0; windowNdx < (int)m_nativeWindows0.size(); windowNdx++)
    858 	{
    859 		if (m_nativeWindows0[windowNdx].second != EGL_NO_SURFACE)
    860 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_nativeWindows0[windowNdx].second));
    861 
    862 		m_nativeWindows0[windowNdx].second = EGL_NO_SURFACE;
    863 		delete m_nativeWindows0[windowNdx].first;
    864 		m_nativeWindows0[windowNdx].first = NULL;
    865 	}
    866 	m_nativeWindows0.clear();
    867 
    868 	for (int windowNdx = 0; windowNdx < (int)m_sharedNativeWindows.size(); windowNdx++)
    869 	{
    870 		if (m_sharedNativeWindows[windowNdx].second != EGL_NO_SURFACE)
    871 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, m_sharedNativeWindows[windowNdx].second));
    872 
    873 		m_sharedNativeWindows[windowNdx].second = EGL_NO_SURFACE;
    874 		delete m_sharedNativeWindows[windowNdx].first;
    875 		m_sharedNativeWindows[windowNdx].first = NULL;
    876 	}
    877 	m_sharedNativeWindows.clear();
    878 }
    879 
    880 bool MultiThreadedObjectTest::runThread (TestThread& thread)
    881 {
    882 	if (thread.getId() == 0)
    883 	{
    884 		m_display = m_eglTestCtx.getDisplay().getEGLDisplay();
    885 
    886 		EGLint surfaceTypes = 0;
    887 
    888 		if ((m_types & TYPE_WINDOW) != 0)
    889 			surfaceTypes |= EGL_WINDOW_BIT;
    890 
    891 		if ((m_types & TYPE_PBUFFER) != 0)
    892 			surfaceTypes |= EGL_PBUFFER_BIT;
    893 
    894 		if ((m_types & TYPE_PIXMAP) != 0)
    895 			surfaceTypes |= EGL_PIXMAP_BIT;
    896 
    897 		EGLint configCount;
    898 		EGLint attribList[] =
    899 		{
    900 			EGL_SURFACE_TYPE, surfaceTypes,
    901 			EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    902 			EGL_NONE
    903 		};
    904 
    905 		TCU_CHECK_EGL_CALL(eglChooseConfig(m_display, attribList, &m_config, 1, &configCount));
    906 
    907 		if (configCount == 0)
    908 			throw tcu::NotSupportedError("No usable config found", "", __FILE__, __LINE__);
    909 	}
    910 
    911 	barrier(thread);
    912 
    913 	// Create / Destroy Objects
    914 	if ((m_types & TYPE_SINGLE_WINDOW) != 0 && (m_types & TYPE_PBUFFER) == 0 && (m_types & TYPE_PIXMAP) == 0 && (m_types & TYPE_CONTEXT) == 0)
    915 	{
    916 		if (thread.getId() == 0)
    917 			createDestroyObjects(thread, 1);
    918 	}
    919 	else
    920 		createDestroyObjects(thread, 100);
    921 
    922 	// Push first threads objects to shared
    923 	if (thread.getId() == 0)
    924 		pushObjectsToShared(thread);
    925 
    926 	barrier(thread);
    927 
    928 	// Push second threads objects to shared
    929 	if (thread.getId() == 1)
    930 		pushObjectsToShared(thread);
    931 
    932 	barrier(thread);
    933 
    934 	// Make queries from shared surfaces
    935 	querySetSharedObjects(thread, 100);
    936 
    937 	barrier(thread);
    938 
    939 	// Pull surfaces for first thread from shared surfaces
    940 	if (thread.getId() == 0)
    941 		pullObjectsFromShared(thread, (int)(m_sharedPbuffers.size()/2), (int)(m_sharedNativePixmaps.size()/2), (int)(m_sharedNativeWindows.size()/2), (int)(m_sharedContexts.size()/2));
    942 
    943 	barrier(thread);
    944 
    945 	// Pull surfaces for second thread from shared surfaces
    946 	if (thread.getId() == 1)
    947 		pullObjectsFromShared(thread, (int)m_sharedPbuffers.size(), (int)m_sharedNativePixmaps.size(), (int)m_sharedNativeWindows.size(), (int)m_sharedContexts.size());
    948 
    949 	barrier(thread);
    950 
    951 	// Create / Destroy Objects
    952 	if ((m_types & TYPE_SINGLE_WINDOW) == 0)
    953 		createDestroyObjects(thread, 100);
    954 
    955 	// Destroy surfaces
    956 	destroyObjects(thread);
    957 
    958 	return true;
    959 }
    960 
    961 void MultiThreadedObjectTest::createDestroyObjects (TestThread& thread, int count)
    962 {
    963 	de::Random&										rnd			= (thread.getId() == 0 ? m_rnd0 : m_rnd1);
    964 	vector<EGLSurface>&								pbuffers	= (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
    965 	vector<pair<eglu::NativeWindow*, EGLSurface> >&	windows		= (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
    966 	vector<pair<eglu::NativePixmap*, EGLSurface> >&	pixmaps		= (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
    967 	vector<EGLContext>&								contexts	= (thread.getId() == 0 ? m_contexts0 : m_contexts1);
    968 
    969 	vector<Type>		objectTypes;
    970 
    971 	if ((m_types & TYPE_PBUFFER) != 0)
    972 		objectTypes.push_back(TYPE_PBUFFER);
    973 
    974 	if ((m_types & TYPE_PIXMAP) != 0)
    975 		objectTypes.push_back(TYPE_PIXMAP);
    976 
    977 	if ((m_types & TYPE_WINDOW) != 0)
    978 		objectTypes.push_back(TYPE_WINDOW);
    979 
    980 	if ((m_types & TYPE_CONTEXT) != 0)
    981 		objectTypes.push_back(TYPE_CONTEXT);
    982 
    983 	for (int createDestroyNdx = 0; createDestroyNdx < count; createDestroyNdx++)
    984 	{
    985 		bool create;
    986 		Type type;
    987 
    988 		if (pbuffers.size() > 5 && ((m_types & TYPE_PBUFFER) != 0))
    989 		{
    990 			create	= false;
    991 			type	= TYPE_PBUFFER;
    992 		}
    993 		else if (windows.size() > 5 && ((m_types & TYPE_WINDOW) != 0))
    994 		{
    995 			create	= false;
    996 			type	= TYPE_WINDOW;
    997 		}
    998 		else if (pixmaps.size() > 5 && ((m_types & TYPE_PIXMAP) != 0))
    999 		{
   1000 			create	= false;
   1001 			type	= TYPE_PIXMAP;
   1002 		}
   1003 		else if (contexts.size() > 5 && ((m_types & TYPE_CONTEXT) != 0))
   1004 		{
   1005 			create	= false;
   1006 			type	= TYPE_CONTEXT;
   1007 		}
   1008 		else if (pbuffers.size() < 3 && ((m_types & TYPE_PBUFFER) != 0))
   1009 		{
   1010 			create	= true;
   1011 			type	= TYPE_PBUFFER;
   1012 		}
   1013 		else if (pixmaps.size() < 3 && ((m_types & TYPE_PIXMAP) != 0))
   1014 		{
   1015 			create	= true;
   1016 			type	= TYPE_PIXMAP;
   1017 		}
   1018 		else if (contexts.size() < 3 && ((m_types & TYPE_CONTEXT) != 0))
   1019 		{
   1020 			create	= true;
   1021 			type	= TYPE_CONTEXT;
   1022 		}
   1023 		else if (windows.size() < 3 && ((m_types & TYPE_WINDOW) != 0) && ((m_types & TYPE_SINGLE_WINDOW) == 0))
   1024 		{
   1025 			create	= true;
   1026 			type	= TYPE_WINDOW;
   1027 		}
   1028 		else if (windows.empty() && ((m_types & TYPE_WINDOW) != 0) && ((m_types & TYPE_SINGLE_WINDOW) != 0))
   1029 		{
   1030 			create	= true;
   1031 			type	= TYPE_WINDOW;
   1032 		}
   1033 		else
   1034 		{
   1035 			create	= rnd.getBool();
   1036 			type	= rnd.choose<Type>(objectTypes.begin(), objectTypes.end());
   1037 		}
   1038 
   1039 		if (create)
   1040 		{
   1041 			switch (type)
   1042 			{
   1043 				case TYPE_PBUFFER:
   1044 				{
   1045 					EGLSurface surface;
   1046 
   1047 					const EGLint attributes[] =
   1048 					{
   1049 						EGL_WIDTH,	64,
   1050 						EGL_HEIGHT,	64,
   1051 
   1052 						EGL_NONE
   1053 					};
   1054 
   1055 					surface = eglCreatePbufferSurface(m_display, m_config, attributes);
   1056 					thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreatePbufferSurface(" << m_display << ", " << m_config << ", { EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE })" << ThreadLog::EndMessage;
   1057 					TCU_CHECK_EGL_MSG("eglCreatePbufferSurface()");
   1058 
   1059 					pbuffers.push_back(surface);
   1060 
   1061 					break;
   1062 				}
   1063 
   1064 				case TYPE_WINDOW:
   1065 				{
   1066 					if ((m_types & TYPE_SINGLE_WINDOW) != 0)
   1067 					{
   1068 						if (deAtomicCompareExchange32(&m_hasWindow, 0, 1) == 0)
   1069 						{
   1070 							eglu::NativeWindow* window	= DE_NULL;
   1071 							EGLSurface			surface = EGL_NO_SURFACE;
   1072 
   1073 							try
   1074 							{
   1075 								window = m_eglTestCtx.createNativeWindow(m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL, 64, 64, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
   1076 								surface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL);
   1077 
   1078 								thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreateWindowSurface()" << ThreadLog::EndMessage;
   1079 								windows.push_back(std::make_pair(window, surface));
   1080 							}
   1081 							catch (const std::exception&)
   1082 							{
   1083 								if (surface != EGL_NO_SURFACE)
   1084 									TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, surface));
   1085 								delete window;
   1086 								throw;
   1087 							}
   1088 						}
   1089 						else
   1090 						{
   1091 							createDestroyNdx--;
   1092 						}
   1093 					}
   1094 					else
   1095 					{
   1096 						eglu::NativeWindow* window	= DE_NULL;
   1097 						EGLSurface			surface = EGL_NO_SURFACE;
   1098 
   1099 						try
   1100 						{
   1101 							window	= m_eglTestCtx.createNativeWindow(m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL, 64, 64, eglu::parseWindowVisibility(m_testCtx.getCommandLine()));
   1102 							surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL);
   1103 
   1104 							thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreateWindowSurface()" << ThreadLog::EndMessage;
   1105 							windows.push_back(std::make_pair(window, surface));
   1106 						}
   1107 						catch (const std::exception&)
   1108 						{
   1109 							if (surface != EGL_NO_SURFACE)
   1110 								TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, surface));
   1111 							delete window;
   1112 							throw;
   1113 						}
   1114 					}
   1115 					break;
   1116 				}
   1117 
   1118 				case TYPE_PIXMAP:
   1119 				{
   1120 					eglu::NativePixmap* pixmap	= DE_NULL;
   1121 					EGLSurface			surface	= EGL_NO_SURFACE;
   1122 
   1123 					try
   1124 					{
   1125 						pixmap	= m_eglTestCtx.createNativePixmap(m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL, 64, 64);
   1126 						surface	= eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_eglTestCtx.getDisplay().getEGLDisplay(), m_config, DE_NULL);
   1127 
   1128 						thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreatePixmapSurface()" << ThreadLog::EndMessage;
   1129 						pixmaps.push_back(std::make_pair(pixmap, surface));
   1130 					}
   1131 					catch (const std::exception&)
   1132 					{
   1133 						if (surface != EGL_NO_SURFACE)
   1134 							TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, surface));
   1135 						delete pixmap;
   1136 						throw;
   1137 					}
   1138 					break;
   1139 				}
   1140 
   1141 				case TYPE_CONTEXT:
   1142 				{
   1143 					EGLContext context;
   1144 
   1145 					TCU_CHECK_EGL_CALL(eglBindAPI(EGL_OPENGL_ES_API));
   1146 					thread.getLog() << ThreadLog::BeginMessage << "eglBindAPI(EGL_OPENGL_ES_API)" << ThreadLog::EndMessage;
   1147 
   1148 					const EGLint attributes[] =
   1149 					{
   1150 						EGL_CONTEXT_CLIENT_VERSION, 2,
   1151 						EGL_NONE
   1152 					};
   1153 
   1154 					context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, attributes);
   1155 					thread.getLog() << ThreadLog::BeginMessage << context << " = eglCreateContext(" << m_display << ", " << m_config << ", EGL_NO_CONTEXT, { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << ThreadLog::EndMessage;
   1156 					TCU_CHECK_EGL_MSG("eglCreateContext()");
   1157 					contexts.push_back(context);
   1158 					break;
   1159 				}
   1160 
   1161 				default:
   1162 					DE_ASSERT(false);
   1163 			};
   1164 		}
   1165 		else
   1166 		{
   1167 			switch (type)
   1168 			{
   1169 				case TYPE_PBUFFER:
   1170 				{
   1171 					const int pbufferNdx = rnd.getInt(0, (int)(pbuffers.size()-1));
   1172 					EGLBoolean result;
   1173 
   1174 					result = eglDestroySurface(m_display, pbuffers[pbufferNdx]);
   1175 					thread.getLog() << ThreadLog::BeginMessage << result << " = eglDestroySurface(" << m_display << ", " << pbuffers[pbufferNdx] << ")" << ThreadLog::EndMessage;
   1176 					TCU_CHECK_EGL_MSG("eglDestroySurface()");
   1177 
   1178 					pbuffers.erase(pbuffers.begin() + pbufferNdx);
   1179 
   1180 					break;
   1181 				}
   1182 
   1183 				case TYPE_WINDOW:
   1184 				{
   1185 					const int windowNdx = rnd.getInt(0, (int)(windows.size()-1));
   1186 
   1187 					thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << windows[windowNdx].second << ")" << ThreadLog::EndMessage;
   1188 
   1189 					TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, windows[windowNdx].second));
   1190 					windows[windowNdx].second = EGL_NO_SURFACE;
   1191 					delete windows[windowNdx].first;
   1192 					windows[windowNdx].first = DE_NULL;
   1193 					windows.erase(windows.begin() + windowNdx);
   1194 
   1195 					if ((m_types & TYPE_SINGLE_WINDOW) != 0)
   1196 						m_hasWindow = 0;
   1197 
   1198 					break;
   1199 				}
   1200 
   1201 				case TYPE_PIXMAP:
   1202 				{
   1203 					const int pixmapNdx = rnd.getInt(0, (int)(pixmaps.size()-1));
   1204 
   1205 					thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << pixmaps[pixmapNdx].second << ")" << ThreadLog::EndMessage;
   1206 					TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, pixmaps[pixmapNdx].second));
   1207 					pixmaps[pixmapNdx].second = EGL_NO_SURFACE;
   1208 					delete pixmaps[pixmapNdx].first;
   1209 					pixmaps[pixmapNdx].first = DE_NULL;
   1210 					pixmaps.erase(pixmaps.begin() + pixmapNdx);
   1211 
   1212 					break;
   1213 				}
   1214 
   1215 				case TYPE_CONTEXT:
   1216 				{
   1217 					const int contextNdx = rnd.getInt(0, (int)(contexts.size()-1));
   1218 
   1219 					TCU_CHECK_EGL_CALL(eglDestroyContext(m_display, contexts[contextNdx]));
   1220 					thread.getLog() << ThreadLog::BeginMessage << "eglDestroyContext(" << m_display << ", " << contexts[contextNdx]  << ")" << ThreadLog::EndMessage;
   1221 					contexts.erase(contexts.begin() + contextNdx);
   1222 
   1223 					break;
   1224 				}
   1225 
   1226 				default:
   1227 					DE_ASSERT(false);
   1228 			}
   1229 
   1230 		}
   1231 	}
   1232 }
   1233 
   1234 void MultiThreadedObjectTest::pushObjectsToShared (TestThread& thread)
   1235 {
   1236 	vector<EGLSurface>&									pbuffers	= (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
   1237 	vector<pair<eglu::NativeWindow*, EGLSurface> >&		windows		= (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
   1238 	vector<pair<eglu::NativePixmap*, EGLSurface> >&		pixmaps		= (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
   1239 	vector<EGLContext>&									contexts	= (thread.getId() == 0 ? m_contexts0 : m_contexts1);
   1240 
   1241 	for (int pbufferNdx = 0; pbufferNdx < (int)pbuffers.size(); pbufferNdx++)
   1242 		m_sharedPbuffers.push_back(pbuffers[pbufferNdx]);
   1243 
   1244 	pbuffers.clear();
   1245 
   1246 	for (int windowNdx = 0; windowNdx < (int)windows.size(); windowNdx++)
   1247 		m_sharedNativeWindows.push_back(windows[windowNdx]);
   1248 
   1249 	windows.clear();
   1250 
   1251 	for (int pixmapNdx = 0; pixmapNdx < (int)pixmaps.size(); pixmapNdx++)
   1252 		m_sharedNativePixmaps.push_back(pixmaps[pixmapNdx]);
   1253 
   1254 	pixmaps.clear();
   1255 
   1256 	for (int contextNdx = 0; contextNdx < (int)contexts.size(); contextNdx++)
   1257 		m_sharedContexts.push_back(contexts[contextNdx]);
   1258 
   1259 	contexts.clear();
   1260 }
   1261 
   1262 void MultiThreadedObjectTest::pullObjectsFromShared (TestThread& thread, int pbufferCount, int pixmapCount, int windowCount, int contextCount)
   1263 {
   1264 	de::Random&											rnd			= (thread.getId() == 0 ? m_rnd0 : m_rnd1);
   1265 	vector<EGLSurface>&									pbuffers	= (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
   1266 	vector<pair<eglu::NativeWindow*, EGLSurface> >&		windows		= (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
   1267 	vector<pair<eglu::NativePixmap*, EGLSurface> >&		pixmaps		= (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
   1268 	vector<EGLContext>&									contexts	= (thread.getId() == 0 ? m_contexts0 : m_contexts1);
   1269 
   1270 	for (int pbufferNdx = 0; pbufferNdx < pbufferCount; pbufferNdx++)
   1271 	{
   1272 		const int ndx = rnd.getInt(0, (int)(m_sharedPbuffers.size()-1));
   1273 
   1274 		pbuffers.push_back(m_sharedPbuffers[ndx]);
   1275 		m_sharedPbuffers.erase(m_sharedPbuffers.begin() + ndx);
   1276 	}
   1277 
   1278 	for (int pixmapNdx = 0; pixmapNdx < pixmapCount; pixmapNdx++)
   1279 	{
   1280 		const int ndx = rnd.getInt(0, (int)(m_sharedNativePixmaps.size()-1));
   1281 
   1282 		pixmaps.push_back(m_sharedNativePixmaps[ndx]);
   1283 		m_sharedNativePixmaps.erase(m_sharedNativePixmaps.begin() + ndx);
   1284 	}
   1285 
   1286 	for (int windowNdx = 0; windowNdx < windowCount; windowNdx++)
   1287 	{
   1288 		const int ndx = rnd.getInt(0, (int)(m_sharedNativeWindows.size()-1));
   1289 
   1290 		windows.push_back(m_sharedNativeWindows[ndx]);
   1291 		m_sharedNativeWindows.erase(m_sharedNativeWindows.begin() + ndx);
   1292 	}
   1293 
   1294 	for (int contextNdx = 0; contextNdx < contextCount; contextNdx++)
   1295 	{
   1296 		const int ndx = rnd.getInt(0, (int)(m_sharedContexts.size()-1));
   1297 
   1298 		contexts.push_back(m_sharedContexts[ndx]);
   1299 		m_sharedContexts.erase(m_sharedContexts.begin() + ndx);
   1300 	}
   1301 }
   1302 
   1303 void MultiThreadedObjectTest::querySetSharedObjects (TestThread& thread, int count)
   1304 {
   1305 	de::Random& rnd = (thread.getId() == 0 ? m_rnd0 : m_rnd1);
   1306 	vector<Type> objectTypes;
   1307 
   1308 	if ((m_types & TYPE_PBUFFER) != 0)
   1309 		objectTypes.push_back(TYPE_PBUFFER);
   1310 
   1311 	if ((m_types & TYPE_PIXMAP) != 0)
   1312 		objectTypes.push_back(TYPE_PIXMAP);
   1313 
   1314 	if ((m_types & TYPE_WINDOW) != 0)
   1315 		objectTypes.push_back(TYPE_WINDOW);
   1316 
   1317 	if ((m_types & TYPE_CONTEXT) != 0)
   1318 		objectTypes.push_back(TYPE_CONTEXT);
   1319 
   1320 	for (int queryNdx = 0; queryNdx < count; queryNdx++)
   1321 	{
   1322 		const Type	type		= rnd.choose<Type>(objectTypes.begin(), objectTypes.end());
   1323 		EGLSurface	surface		= EGL_NO_SURFACE;
   1324 		EGLContext	context		= EGL_NO_CONTEXT;
   1325 
   1326 		switch (type)
   1327 		{
   1328 			case TYPE_PBUFFER:
   1329 				surface = m_sharedPbuffers[rnd.getInt(0, (int)(m_sharedPbuffers.size()-1))];
   1330 				break;
   1331 
   1332 			case TYPE_PIXMAP:
   1333 				surface = m_sharedNativePixmaps[rnd.getInt(0, (int)(m_sharedNativePixmaps.size()-1))].second;
   1334 				break;
   1335 
   1336 			case TYPE_WINDOW:
   1337 				surface = m_sharedNativeWindows[rnd.getInt(0, (int)(m_sharedNativeWindows.size()-1))].second;
   1338 				break;
   1339 
   1340 			case TYPE_CONTEXT:
   1341 				context = m_sharedContexts[rnd.getInt(0, (int)(m_sharedContexts.size()-1))];
   1342 				break;
   1343 
   1344 			default:
   1345 				DE_ASSERT(false);
   1346 		}
   1347 
   1348 		if (surface != EGL_NO_SURFACE)
   1349 		{
   1350 			static const EGLint queryAttributes[] =
   1351 			{
   1352 				EGL_LARGEST_PBUFFER,
   1353 				EGL_HEIGHT,
   1354 				EGL_WIDTH
   1355 			};
   1356 
   1357 			const EGLint	attribute	= queryAttributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(queryAttributes) - 1)];
   1358 			EGLBoolean		result;
   1359 			EGLint			value;
   1360 
   1361 			result = eglQuerySurface(m_display, surface, attribute, &value);
   1362 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglQuerySurface(" << m_display << ", " << surface << ", " << attribute << ", " << value << ")" << ThreadLog::EndMessage;
   1363 			TCU_CHECK_EGL_MSG("eglQuerySurface()");
   1364 
   1365 		}
   1366 		else if (context != EGL_NO_CONTEXT)
   1367 		{
   1368 			static const EGLint attributes[] =
   1369 			{
   1370 				EGL_CONFIG_ID,
   1371 				EGL_CONTEXT_CLIENT_TYPE,
   1372 				EGL_CONTEXT_CLIENT_VERSION,
   1373 				EGL_RENDER_BUFFER
   1374 			};
   1375 
   1376 			const EGLint	attribute = attributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(attributes)-1)];
   1377 			EGLint			value;
   1378 			EGLBoolean		result;
   1379 
   1380 			result = eglQueryContext(m_display, context, attribute, &value);
   1381 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglQueryContext(" << m_display << ", " << context << ", " << attribute << ", " << value << ")" << ThreadLog::EndMessage;
   1382 			TCU_CHECK_EGL_MSG("eglQueryContext()");
   1383 
   1384 		}
   1385 		else
   1386 			DE_ASSERT(false);
   1387 	}
   1388 }
   1389 
   1390 void MultiThreadedObjectTest::destroyObjects (TestThread& thread)
   1391 {
   1392 	vector<EGLSurface>&									pbuffers	= (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
   1393 	vector<pair<eglu::NativeWindow*, EGLSurface> >&		windows		= (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
   1394 	vector<pair<eglu::NativePixmap*, EGLSurface> >&		pixmaps		= (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
   1395 	vector<EGLContext>&									contexts	= (thread.getId() == 0 ? m_contexts0 : m_contexts1);
   1396 
   1397 	for (int pbufferNdx = 0; pbufferNdx < (int)pbuffers.size(); pbufferNdx++)
   1398 	{
   1399 		if (pbuffers[pbufferNdx] != EGL_NO_SURFACE)
   1400 		{
   1401 			// Destroy EGLSurface
   1402 			EGLBoolean result;
   1403 
   1404 			result = eglDestroySurface(m_display, pbuffers[pbufferNdx]);
   1405 			thread.getLog() << ThreadLog::BeginMessage << result << " = eglDestroySurface(" << m_display << ", " << pbuffers[pbufferNdx] << ")" << ThreadLog::EndMessage;
   1406 			TCU_CHECK_EGL_MSG("eglDestroySurface()");
   1407 			pbuffers[pbufferNdx] = EGL_NO_SURFACE;
   1408 		}
   1409 	}
   1410 	pbuffers.clear();
   1411 
   1412 	for (int windowNdx = 0; windowNdx < (int)windows.size(); windowNdx++)
   1413 	{
   1414 		if (windows[windowNdx].second != EGL_NO_SURFACE)
   1415 		{
   1416 			thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << windows[windowNdx].second << ")" << ThreadLog::EndMessage;
   1417 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, windows[windowNdx].second));
   1418 			windows[windowNdx].second = EGL_NO_SURFACE;
   1419 		}
   1420 
   1421 		if (windows[windowNdx].first)
   1422 		{
   1423 			delete windows[windowNdx].first;
   1424 			windows[windowNdx].first = NULL;
   1425 		}
   1426 	}
   1427 	windows.clear();
   1428 
   1429 	for (int pixmapNdx = 0; pixmapNdx < (int)pixmaps.size(); pixmapNdx++)
   1430 	{
   1431 		if (pixmaps[pixmapNdx].first != EGL_NO_SURFACE)
   1432 		{
   1433 			thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << pixmaps[pixmapNdx].second << ")" << ThreadLog::EndMessage;
   1434 			TCU_CHECK_EGL_CALL(eglDestroySurface(m_display, pixmaps[pixmapNdx].second));
   1435 			pixmaps[pixmapNdx].second = EGL_NO_SURFACE;
   1436 		}
   1437 
   1438 		if (pixmaps[pixmapNdx].first)
   1439 		{
   1440 			delete pixmaps[pixmapNdx].first;
   1441 			pixmaps[pixmapNdx].first = NULL;
   1442 		}
   1443 	}
   1444 	pixmaps.clear();
   1445 
   1446 	for (int contextNdx = 0; contextNdx < (int)contexts.size(); contextNdx++)
   1447 	{
   1448 		if (contexts[contextNdx] != EGL_NO_CONTEXT)
   1449 		{
   1450 			TCU_CHECK_EGL_CALL(eglDestroyContext(m_display, contexts[contextNdx]));
   1451 			thread.getLog() << ThreadLog::BeginMessage << "eglDestroyContext(" << m_display << ", " << contexts[contextNdx]  << ")" << ThreadLog::EndMessage;
   1452 			contexts[contextNdx] = EGL_NO_CONTEXT;
   1453 		}
   1454 	}
   1455 	contexts.clear();
   1456 }
   1457 
   1458 MultiThreadedTests::MultiThreadedTests (EglTestContext& context)
   1459 	: TestCaseGroup(context, "multithread", "Multithreaded EGL tests")
   1460 {
   1461 }
   1462 
   1463 void MultiThreadedTests::init (void)
   1464 {
   1465 	// Config tests
   1466 	addChild(new MultiThreadedConfigTest(m_eglTestCtx,	"config",	"",	30,	30,	30));
   1467 
   1468 	// Object tests
   1469 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer",								"", MultiThreadedObjectTest::TYPE_PBUFFER));
   1470 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap",								"", MultiThreadedObjectTest::TYPE_PIXMAP));
   1471 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"window",								"", MultiThreadedObjectTest::TYPE_WINDOW));
   1472 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"single_window",						"", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
   1473 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"context",								"", MultiThreadedObjectTest::TYPE_CONTEXT));
   1474 
   1475 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap",						"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP));
   1476 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_window",						"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW));
   1477 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_single_window",				"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
   1478 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_context",						"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_CONTEXT));
   1479 
   1480 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap_window",						"", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW));
   1481 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap_single_window",					"", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
   1482 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap_context",						"", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_CONTEXT));
   1483 
   1484 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"window_context",						"", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1485 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"single_window_context",				"", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1486 
   1487 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap_window",				"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW));
   1488 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap_single_window",			"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
   1489 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap_context",				"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_CONTEXT));
   1490 
   1491 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_window_context",				"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1492 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_single_window_context",		"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1493 
   1494 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap_window_context",				"", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1495 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pixmap_single_window_context",			"", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1496 
   1497 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap_window_context",		"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1498 	addChild(new MultiThreadedObjectTest(m_eglTestCtx,	"pbuffer_pixmap_single_window_context",	"", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
   1499 }
   1500 
   1501 } // egl
   1502 } // deqp
   1503