1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Multi threaded EGL tests
22 *//*--------------------------------------------------------------------*/
23 #include "teglMultiThreadTests.hpp"
25 #include "egluNativeWindow.hpp"
26 #include "egluNativePixmap.hpp"
27 #include "egluUtil.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuCommandLine.hpp"
32 #include "deRandom.hpp"
34 #include "deThread.hpp"
35 #include "deMutex.hpp"
36 #include "deSemaphore.hpp"
41 #include "eglwLibrary.hpp"
42 #include "eglwEnums.hpp"
53 using std::ostringstream;
65 class BeginMessageToken {};
66 class EndMessageToken {};
70 Message (deUint64 timeUs_, const char* msg_) : timeUs(timeUs_), msg(msg_) {}
76 ThreadLog (void) { m_messages.reserve(100); }
78 ThreadLog& operator<< (const BeginMessageToken&) { return *this; }
79 ThreadLog& operator<< (const EndMessageToken&);
82 ThreadLog& operator<< (const T& t) { m_message << t; return *this; }
83 const vector<Message>& getMessages (void) const { return m_messages; }
85 static BeginMessageToken BeginMessage;
86 static EndMessageToken EndMessage;
89 ostringstream m_message;
90 vector<Message> m_messages;
93 ThreadLog& ThreadLog::operator<< (const EndMessageToken&)
95 m_messages.push_back(Message(deGetMicroseconds(), m_message.str().c_str()));
100 ThreadLog::BeginMessageToken ThreadLog::BeginMessage;
101 ThreadLog::EndMessageToken ThreadLog::EndMessage;
103 class MultiThreadedTest;
105 class TestThread : public de::Thread
110 THREADSTATUS_NOT_STARTED = 0,
111 THREADSTATUS_RUNNING,
114 THREADSTATUS_NOT_SUPPORTED,
118 TestThread (MultiThreadedTest& test, int id);
121 ThreadStatus getStatus (void) const { return m_status; }
122 ThreadLog& getLog (void) { return m_log; }
124 int getId (void) const { return m_id; }
126 void setStatus (ThreadStatus status) { m_status = status; }
128 const Library& getLibrary (void) const;
135 MultiThreadedTest& m_test;
137 ThreadStatus m_status;
141 class MultiThreadedTest : public TestCase
144 MultiThreadedTest (EglTestContext& eglTestCtx, const char* name, const char* description, int threadCount, deUint64 timeoutUs);
145 virtual ~MultiThreadedTest (void);
150 virtual bool runThread (TestThread& thread) = 0;
151 virtual IterateResult iterate (void);
152 bool execTest (TestThread& thread);
154 const Library& getLibrary (void) const { return m_eglTestCtx.getLibrary(); }
157 void barrier (TestThread& thread);
162 deUint64 m_startTimeUs;
163 const deUint64 m_timeoutUs;
164 vector<TestThread*> m_threads;
166 volatile deInt32 m_barrierWaiters;
167 de::Semaphore m_barrierSemaphore1;
168 de::Semaphore m_barrierSemaphore2;
171 EGLDisplay m_display;
174 inline const Library& TestThread::getLibrary (void) const
176 return m_test.getLibrary();
179 TestThread::TestThread (MultiThreadedTest& test, int id)
182 , m_status (THREADSTATUS_NOT_STARTED)
186 void TestThread::run (void)
188 m_status = THREADSTATUS_RUNNING;
192 if (m_test.execTest(*this))
193 m_status = THREADSTATUS_READY;
195 m_status = THREADSTATUS_ERROR;
197 catch (const TestThread::TestStop&)
199 getLog() << ThreadLog::BeginMessage << "Thread stopped" << ThreadLog::EndMessage;
201 catch (const tcu::NotSupportedError& e)
203 getLog() << ThreadLog::BeginMessage << "Not supported: '" << e.what() << "'" << ThreadLog::EndMessage;
205 catch (const std::exception& e)
207 getLog() << ThreadLog::BeginMessage << "Got exception: '" << e.what() << "'" << ThreadLog::EndMessage;
211 getLog() << ThreadLog::BeginMessage << "Unknown exception" << ThreadLog::EndMessage;
214 getLibrary().releaseThread();
217 bool MultiThreadedTest::execTest (TestThread& thread)
223 isOk = runThread(thread);
225 catch (const TestThread::TestStop&)
227 // Thread exited due to error in other thread
230 catch (const tcu::NotSupportedError&)
232 // Set status of each thread
233 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
234 m_threads[threadNdx]->setStatus(TestThread::THREADSTATUS_NOT_SUPPORTED);
237 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
239 m_barrierSemaphore1.increment();
240 m_barrierSemaphore2.increment();
247 // Set status of each thread
248 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
249 m_threads[threadNdx]->setStatus(TestThread::THREADSTATUS_ERROR);
252 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
254 m_barrierSemaphore1.increment();
255 m_barrierSemaphore2.increment();
264 MultiThreadedTest::MultiThreadedTest (EglTestContext& eglTestCtx, const char* name, const char* description, int threadCount, deUint64 timeoutUs)
265 : TestCase (eglTestCtx, name, description)
266 , m_threadCount (threadCount)
267 , m_initialized (false)
269 , m_timeoutUs (timeoutUs)
271 , m_barrierWaiters (0)
272 , m_barrierSemaphore1 (0, 0)
273 , m_barrierSemaphore2 (1, 0)
275 , m_display (EGL_NO_DISPLAY)
279 MultiThreadedTest::~MultiThreadedTest (void)
281 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
282 delete m_threads[threadNdx];
286 void MultiThreadedTest::init (void)
288 m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
291 void MultiThreadedTest::deinit (void)
293 if (m_display != EGL_NO_DISPLAY)
295 m_eglTestCtx.getLibrary().terminate(m_display);
296 m_display = EGL_NO_DISPLAY;
300 void MultiThreadedTest::barrier (TestThread& thread)
303 const deInt32 waiters = deAtomicIncrement32(&m_barrierWaiters);
305 if (waiters == m_threadCount)
307 m_barrierSemaphore2.decrement();
308 m_barrierSemaphore1.increment();
312 m_barrierSemaphore1.decrement();
313 m_barrierSemaphore1.increment();
318 const deInt32 waiters = deAtomicDecrement32(&m_barrierWaiters);
322 m_barrierSemaphore1.decrement();
323 m_barrierSemaphore2.increment();
327 m_barrierSemaphore2.decrement();
328 m_barrierSemaphore2.increment();
332 // Barrier was released due an error in other thread
333 if (thread.getStatus() != TestThread::THREADSTATUS_RUNNING)
334 throw TestThread::TestStop();
337 TestCase::IterateResult MultiThreadedTest::iterate (void)
341 m_testCtx.getLog() << tcu::TestLog::Message << "Thread timeout limit: " << m_timeoutUs << "us" << tcu::TestLog::EndMessage;
344 m_threads.reserve(m_threadCount);
346 for (int threadNdx = 0; threadNdx < m_threadCount; threadNdx++)
347 m_threads.push_back(new TestThread(*this, threadNdx));
349 m_startTimeUs = deGetMicroseconds();
352 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
353 m_threads[threadNdx]->start();
355 m_initialized = true;
359 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
361 if (m_threads[threadNdx]->getStatus() != TestThread::THREADSTATUS_RUNNING)
365 if (readyCount == m_threadCount)
368 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
369 m_threads[threadNdx]->join();
372 bool notSupported = false;
374 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
376 if (m_threads[threadNdx]->getStatus() == TestThread::THREADSTATUS_ERROR)
379 if (m_threads[threadNdx]->getStatus() == TestThread::THREADSTATUS_NOT_SUPPORTED)
385 vector<int> messageNdx;
387 messageNdx.resize(m_threads.size(), 0);
391 int nextThreadNdx = -1;
392 deUint64 nextThreadTimeUs = 0;
394 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
396 if (messageNdx[threadNdx] >= (int)m_threads[threadNdx]->getLog().getMessages().size())
399 if (nextThreadNdx == -1 || nextThreadTimeUs > m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs)
401 nextThreadNdx = threadNdx;
402 nextThreadTimeUs = m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs;
406 if (nextThreadNdx == -1)
409 m_testCtx.getLog() << tcu::TestLog::Message << "[" << (nextThreadTimeUs - m_startTimeUs) << "] (" << nextThreadNdx << ") " << m_threads[nextThreadNdx]->getLog().getMessages()[messageNdx[nextThreadNdx]].msg << tcu::TestLog::EndMessage;
411 messageNdx[nextThreadNdx]++;
416 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
417 delete m_threads[threadNdx];
425 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
427 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
430 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
437 const deUint64 currentTimeUs = deGetMicroseconds();
439 if (currentTimeUs - m_startTimeUs > m_timeoutUs)
443 vector<int> messageNdx;
445 messageNdx.resize(m_threads.size(), 0);
449 int nextThreadNdx = -1;
450 deUint64 nextThreadTimeUs = 0;
452 for (int threadNdx = 0; threadNdx < (int)m_threads.size(); threadNdx++)
454 if (messageNdx[threadNdx] >= (int)m_threads[threadNdx]->getLog().getMessages().size())
457 if (nextThreadNdx == -1 || nextThreadTimeUs > m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs)
459 nextThreadNdx = threadNdx;
460 nextThreadTimeUs = m_threads[threadNdx]->getLog().getMessages()[messageNdx[threadNdx]].timeUs;
464 if (nextThreadNdx == -1)
467 m_testCtx.getLog() << tcu::TestLog::Message << "[" << (nextThreadTimeUs - m_startTimeUs) << "] (" << nextThreadNdx << ") " << m_threads[nextThreadNdx]->getLog().getMessages()[messageNdx[nextThreadNdx]].msg << tcu::TestLog::EndMessage;
469 messageNdx[nextThreadNdx]++;
473 m_testCtx.getLog() << tcu::TestLog::Message << "[" << (currentTimeUs - m_startTimeUs) << "] (-) Timeout, Limit: " << m_timeoutUs << "us" << tcu::TestLog::EndMessage;
474 m_testCtx.getLog() << tcu::TestLog::Message << "[" << (currentTimeUs - m_startTimeUs) << "] (-) Trying to perform resource cleanup..." << tcu::TestLog::EndMessage;
476 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
490 const char* configAttributeToString (EGLint e)
494 case EGL_BUFFER_SIZE: return "EGL_BUFFER_SIZE";
495 case EGL_RED_SIZE: return "EGL_RED_SIZE";
496 case EGL_GREEN_SIZE: return "EGL_GREEN_SIZE";
497 case EGL_BLUE_SIZE: return "EGL_BLUE_SIZE";
498 case EGL_LUMINANCE_SIZE: return "EGL_LUMINANCE_SIZE";
499 case EGL_ALPHA_SIZE: return "EGL_ALPHA_SIZE";
500 case EGL_ALPHA_MASK_SIZE: return "EGL_ALPHA_MASK_SIZE";
501 case EGL_BIND_TO_TEXTURE_RGB: return "EGL_BIND_TO_TEXTURE_RGB";
502 case EGL_BIND_TO_TEXTURE_RGBA: return "EGL_BIND_TO_TEXTURE_RGBA";
503 case EGL_COLOR_BUFFER_TYPE: return "EGL_COLOR_BUFFER_TYPE";
504 case EGL_CONFIG_CAVEAT: return "EGL_CONFIG_CAVEAT";
505 case EGL_CONFIG_ID: return "EGL_CONFIG_ID";
506 case EGL_CONFORMANT: return "EGL_CONFORMANT";
507 case EGL_DEPTH_SIZE: return "EGL_DEPTH_SIZE";
508 case EGL_LEVEL: return "EGL_LEVEL";
509 case EGL_MAX_PBUFFER_WIDTH: return "EGL_MAX_PBUFFER_WIDTH";
510 case EGL_MAX_PBUFFER_HEIGHT: return "EGL_MAX_PBUFFER_HEIGHT";
511 case EGL_MAX_PBUFFER_PIXELS: return "EGL_MAX_PBUFFER_PIXELS";
512 case EGL_MAX_SWAP_INTERVAL: return "EGL_MAX_SWAP_INTERVAL";
513 case EGL_MIN_SWAP_INTERVAL: return "EGL_MIN_SWAP_INTERVAL";
514 case EGL_NATIVE_RENDERABLE: return "EGL_NATIVE_RENDERABLE";
515 case EGL_NATIVE_VISUAL_ID: return "EGL_NATIVE_VISUAL_ID";
516 case EGL_NATIVE_VISUAL_TYPE: return "EGL_NATIVE_VISUAL_TYPE";
517 case EGL_RENDERABLE_TYPE: return "EGL_RENDERABLE_TYPE";
518 case EGL_SAMPLE_BUFFERS: return "EGL_SAMPLE_BUFFERS";
519 case EGL_SAMPLES: return "EGL_SAMPLES";
520 case EGL_STENCIL_SIZE: return "EGL_STENCIL_SIZE";
521 case EGL_SURFACE_TYPE: return "EGL_SURFACE_TYPE";
522 case EGL_TRANSPARENT_TYPE: return "EGL_TRANSPARENT_TYPE";
523 case EGL_TRANSPARENT_RED_VALUE: return "EGL_TRANSPARENT_RED_VALUE";
524 case EGL_TRANSPARENT_GREEN_VALUE: return "EGL_TRANSPARENT_GREEN_VALUE";
525 case EGL_TRANSPARENT_BLUE_VALUE: return "EGL_TRANSPARENT_BLUE_VALUE";
526 default: return "<Unknown>";
532 class MultiThreadedConfigTest : public MultiThreadedTest
535 MultiThreadedConfigTest (EglTestContext& context, const char* name, const char* description, int getConfigs, int chooseConfigs, int query);
536 bool runThread (TestThread& thread);
539 const int m_getConfigs;
540 const int m_chooseConfigs;
544 MultiThreadedConfigTest::MultiThreadedConfigTest (EglTestContext& context, const char* name, const char* description, int getConfigs, int chooseConfigs, int query)
545 : MultiThreadedTest (context, name, description, 2, 20000000/*us = 20s*/) // \todo [mika] Set timeout to something relevant to frameworks timeout?
546 , m_getConfigs (getConfigs)
547 , m_chooseConfigs (chooseConfigs)
552 bool MultiThreadedConfigTest::runThread (TestThread& thread)
554 const Library& egl = getLibrary();
555 de::Random rnd (deInt32Hash(thread.getId() + 10435));
556 vector<EGLConfig> configs;
560 for (int getConfigsNdx = 0; getConfigsNdx < m_getConfigs; getConfigsNdx++)
564 // Get number of configs
568 result = egl.getConfigs(m_display, NULL, 0, &configCount);
569 thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigs(" << m_display << ", NULL, 0, " << configCount << ")" << ThreadLog::EndMessage;
570 EGLU_CHECK_MSG(egl, "eglGetConfigs()");
576 configs.resize(configs.size() + configCount);
579 if (configCount != 0)
583 result = egl.getConfigs(m_display, &(configs[configs.size() - configCount]), configCount, &configCount);
584 thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigs(" << m_display << ", &configs' " << configCount << ", " << configCount << ")" << ThreadLog::EndMessage;
585 EGLU_CHECK_MSG(egl, "eglGetConfigs()");
591 // Pop configs to stop config list growing
592 if (configs.size() > 40)
594 configs.erase(configs.begin() + 40, configs.end());
598 const int popCount = rnd.getInt(0, (int)(configs.size()-2));
600 configs.erase(configs.begin() + (configs.size() - popCount), configs.end());
604 for (int chooseConfigsNdx = 0; chooseConfigsNdx < m_chooseConfigs; chooseConfigsNdx++)
608 static const EGLint attribList[] = {
612 // Get number of configs
616 result = egl.chooseConfig(m_display, attribList, NULL, 0, &configCount);
617 thread.getLog() << ThreadLog::BeginMessage << result << " = eglChooseConfig(" << m_display << ", { EGL_NONE }, NULL, 0, " << configCount << ")" << ThreadLog::EndMessage;
618 EGLU_CHECK_MSG(egl, "eglChooseConfig()");
624 configs.resize(configs.size() + configCount);
627 if (configCount != 0)
631 result = egl.chooseConfig(m_display, attribList, &(configs[configs.size() - configCount]), configCount, &configCount);
632 thread.getLog() << ThreadLog::BeginMessage << result << " = eglChooseConfig(" << m_display << ", { EGL_NONE }, &configs, " << configCount << ", " << configCount << ")" << ThreadLog::EndMessage;
633 EGLU_CHECK_MSG(egl, "eglChooseConfig()");
639 // Pop configs to stop config list growing
640 if (configs.size() > 40)
642 configs.erase(configs.begin() + 40, configs.end());
646 const int popCount = rnd.getInt(0, (int)(configs.size()-2));
648 configs.erase(configs.begin() + (configs.size() - popCount), configs.end());
653 // Perform queries on configs
654 static const EGLint attributes[] =
663 EGL_BIND_TO_TEXTURE_RGB,
664 EGL_BIND_TO_TEXTURE_RGBA,
665 EGL_COLOR_BUFFER_TYPE,
671 EGL_MAX_PBUFFER_WIDTH,
672 EGL_MAX_PBUFFER_HEIGHT,
673 EGL_MAX_PBUFFER_PIXELS,
674 EGL_MAX_SWAP_INTERVAL,
675 EGL_MIN_SWAP_INTERVAL,
676 EGL_NATIVE_RENDERABLE,
677 EGL_NATIVE_VISUAL_ID,
678 EGL_NATIVE_VISUAL_TYPE,
684 EGL_TRANSPARENT_TYPE,
685 EGL_TRANSPARENT_RED_VALUE,
686 EGL_TRANSPARENT_GREEN_VALUE,
687 EGL_TRANSPARENT_BLUE_VALUE
690 for (int queryNdx = 0; queryNdx < m_query; queryNdx++)
692 const EGLint attribute = attributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(attributes)-1)];
693 EGLConfig config = configs[rnd.getInt(0, (int)(configs.size()-1))];
697 result = egl.getConfigAttrib(m_display, config, attribute, &value);
698 thread.getLog() << ThreadLog::BeginMessage << result << " = eglGetConfigAttrib(" << m_display << ", " << config << ", " << configAttributeToString(attribute) << ", " << value << ")" << ThreadLog::EndMessage;
699 EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");
709 class MultiThreadedObjectTest : public MultiThreadedTest
714 TYPE_PBUFFER = (1<<0),
715 TYPE_PIXMAP = (1<<1),
716 TYPE_WINDOW = (1<<2),
717 TYPE_SINGLE_WINDOW = (1<<3),
718 TYPE_CONTEXT = (1<<4)
721 MultiThreadedObjectTest (EglTestContext& context, const char* name, const char* description, deUint32 types);
722 ~MultiThreadedObjectTest (void);
724 virtual void deinit (void);
726 bool runThread (TestThread& thread);
728 void createDestroyObjects (TestThread& thread, int count);
729 void pushObjectsToShared (TestThread& thread);
730 void pullObjectsFromShared (TestThread& thread, int pbufferCount, int pixmapCount, int windowCount, int contextCount);
731 void querySetSharedObjects (TestThread& thread, int count);
732 void destroyObjects (TestThread& thread);
740 volatile deUint32 m_hasWindow;
742 vector<pair<eglu::NativePixmap*, EGLSurface> > m_sharedNativePixmaps;
743 vector<pair<eglu::NativePixmap*, EGLSurface> > m_nativePixmaps0;
744 vector<pair<eglu::NativePixmap*, EGLSurface> > m_nativePixmaps1;
746 vector<pair<eglu::NativeWindow*, EGLSurface> > m_sharedNativeWindows;
747 vector<pair<eglu::NativeWindow*, EGLSurface> > m_nativeWindows0;
748 vector<pair<eglu::NativeWindow*, EGLSurface> > m_nativeWindows1;
750 vector<EGLSurface> m_sharedPbuffers;
751 vector<EGLSurface> m_pbuffers0;
752 vector<EGLSurface> m_pbuffers1;
754 vector<EGLContext> m_sharedContexts;
755 vector<EGLContext> m_contexts0;
756 vector<EGLContext> m_contexts1;
759 MultiThreadedObjectTest::MultiThreadedObjectTest (EglTestContext& context, const char* name, const char* description, deUint32 type)
760 : MultiThreadedTest (context, name, description, 2, 20000000/*us = 20s*/) // \todo [mika] Set timeout to something relevant to frameworks timeout?
764 , m_types ((Type)type)
769 MultiThreadedObjectTest::~MultiThreadedObjectTest (void)
774 void MultiThreadedObjectTest::deinit (void)
776 const Library& egl = getLibrary();
779 for (int pbufferNdx = 0; pbufferNdx < (int)m_pbuffers0.size(); pbufferNdx++)
781 if (m_pbuffers0[pbufferNdx] != EGL_NO_SURFACE)
783 egl.destroySurface(m_display, m_pbuffers0[pbufferNdx]);
784 EGLU_CHECK_MSG(egl, "eglDestroySurface()");
785 m_pbuffers0[pbufferNdx] = EGL_NO_SURFACE;
790 for (int pbufferNdx = 0; pbufferNdx < (int)m_pbuffers1.size(); pbufferNdx++)
792 if (m_pbuffers1[pbufferNdx] != EGL_NO_SURFACE)
794 egl.destroySurface(m_display, m_pbuffers1[pbufferNdx]);
795 EGLU_CHECK_MSG(egl, "eglDestroySurface()");
796 m_pbuffers1[pbufferNdx] = EGL_NO_SURFACE;
801 for (int pbufferNdx = 0; pbufferNdx < (int)m_sharedPbuffers.size(); pbufferNdx++)
803 if (m_sharedPbuffers[pbufferNdx] != EGL_NO_SURFACE)
805 egl.destroySurface(m_display, m_sharedPbuffers[pbufferNdx]);
806 EGLU_CHECK_MSG(egl, "eglDestroySurface()");
807 m_sharedPbuffers[pbufferNdx] = EGL_NO_SURFACE;
810 m_sharedPbuffers.clear();
812 for (int contextNdx = 0; contextNdx < (int)m_sharedContexts.size(); contextNdx++)
814 if (m_sharedContexts[contextNdx] != EGL_NO_CONTEXT)
816 egl.destroyContext(m_display, m_sharedContexts[contextNdx]);
817 EGLU_CHECK_MSG(egl, "eglDestroyContext()");
818 m_sharedContexts[contextNdx] = EGL_NO_CONTEXT;
821 m_sharedContexts.clear();
823 for (int contextNdx = 0; contextNdx < (int)m_contexts0.size(); contextNdx++)
825 if (m_contexts0[contextNdx] != EGL_NO_CONTEXT)
827 egl.destroyContext(m_display, m_contexts0[contextNdx]);
828 EGLU_CHECK_MSG(egl, "eglDestroyContext()");
829 m_contexts0[contextNdx] = EGL_NO_CONTEXT;
834 for (int contextNdx = 0; contextNdx < (int)m_contexts1.size(); contextNdx++)
836 if (m_contexts1[contextNdx] != EGL_NO_CONTEXT)
838 egl.destroyContext(m_display, m_contexts1[contextNdx]);
839 EGLU_CHECK_MSG(egl, "eglDestroyContext()");
840 m_contexts1[contextNdx] = EGL_NO_CONTEXT;
846 for (int pixmapNdx = 0; pixmapNdx < (int)m_nativePixmaps0.size(); pixmapNdx++)
848 if (m_nativePixmaps0[pixmapNdx].second != EGL_NO_SURFACE)
849 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_nativePixmaps0[pixmapNdx].second));
851 m_nativePixmaps0[pixmapNdx].second = EGL_NO_SURFACE;
852 delete m_nativePixmaps0[pixmapNdx].first;
853 m_nativePixmaps0[pixmapNdx].first = NULL;
855 m_nativePixmaps0.clear();
857 for (int pixmapNdx = 0; pixmapNdx < (int)m_nativePixmaps1.size(); pixmapNdx++)
859 if (m_nativePixmaps1[pixmapNdx].second != EGL_NO_SURFACE)
860 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_nativePixmaps1[pixmapNdx].second));
862 m_nativePixmaps1[pixmapNdx].second = EGL_NO_SURFACE;
863 delete m_nativePixmaps1[pixmapNdx].first;
864 m_nativePixmaps1[pixmapNdx].first = NULL;
866 m_nativePixmaps1.clear();
868 for (int pixmapNdx = 0; pixmapNdx < (int)m_sharedNativePixmaps.size(); pixmapNdx++)
870 if (m_sharedNativePixmaps[pixmapNdx].second != EGL_NO_SURFACE)
871 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_sharedNativePixmaps[pixmapNdx].second));
873 m_sharedNativePixmaps[pixmapNdx].second = EGL_NO_SURFACE;
874 delete m_sharedNativePixmaps[pixmapNdx].first;
875 m_sharedNativePixmaps[pixmapNdx].first = NULL;
877 m_sharedNativePixmaps.clear();
880 for (int windowNdx = 0; windowNdx < (int)m_nativeWindows1.size(); windowNdx++)
882 if (m_nativeWindows1[windowNdx].second != EGL_NO_SURFACE)
883 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_nativeWindows1[windowNdx].second));
885 m_nativeWindows1[windowNdx].second = EGL_NO_SURFACE;
886 delete m_nativeWindows1[windowNdx].first;
887 m_nativeWindows1[windowNdx].first = NULL;
889 m_nativeWindows1.clear();
891 for (int windowNdx = 0; windowNdx < (int)m_nativeWindows0.size(); windowNdx++)
893 if (m_nativeWindows0[windowNdx].second != EGL_NO_SURFACE)
894 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_nativeWindows0[windowNdx].second));
896 m_nativeWindows0[windowNdx].second = EGL_NO_SURFACE;
897 delete m_nativeWindows0[windowNdx].first;
898 m_nativeWindows0[windowNdx].first = NULL;
900 m_nativeWindows0.clear();
902 for (int windowNdx = 0; windowNdx < (int)m_sharedNativeWindows.size(); windowNdx++)
904 if (m_sharedNativeWindows[windowNdx].second != EGL_NO_SURFACE)
905 EGLU_CHECK_CALL(egl, destroySurface(m_display, m_sharedNativeWindows[windowNdx].second));
907 m_sharedNativeWindows[windowNdx].second = EGL_NO_SURFACE;
908 delete m_sharedNativeWindows[windowNdx].first;
909 m_sharedNativeWindows[windowNdx].first = NULL;
911 m_sharedNativeWindows.clear();
913 MultiThreadedTest::deinit();
916 bool MultiThreadedObjectTest::runThread (TestThread& thread)
918 const Library& egl = getLibrary();
920 if (thread.getId() == 0)
922 EGLint surfaceTypes = 0;
924 if ((m_types & TYPE_WINDOW) != 0)
925 surfaceTypes |= EGL_WINDOW_BIT;
927 if ((m_types & TYPE_PBUFFER) != 0)
928 surfaceTypes |= EGL_PBUFFER_BIT;
930 if ((m_types & TYPE_PIXMAP) != 0)
931 surfaceTypes |= EGL_PIXMAP_BIT;
934 EGLint attribList[] =
936 EGL_SURFACE_TYPE, surfaceTypes,
937 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
941 EGLU_CHECK_CALL(egl, chooseConfig(m_display, attribList, &m_config, 1, &configCount));
943 if (configCount == 0)
944 TCU_THROW(NotSupportedError, "No usable config found");
949 // Create / Destroy Objects
950 if ((m_types & TYPE_SINGLE_WINDOW) != 0 && (m_types & TYPE_PBUFFER) == 0 && (m_types & TYPE_PIXMAP) == 0 && (m_types & TYPE_CONTEXT) == 0)
952 if (thread.getId() == 0)
953 createDestroyObjects(thread, 1);
956 createDestroyObjects(thread, 100);
958 // Push first threads objects to shared
959 if (thread.getId() == 0)
960 pushObjectsToShared(thread);
964 // Push second threads objects to shared
965 if (thread.getId() == 1)
966 pushObjectsToShared(thread);
970 // Make queries from shared surfaces
971 querySetSharedObjects(thread, 100);
975 // Pull surfaces for first thread from shared surfaces
976 if (thread.getId() == 0)
977 pullObjectsFromShared(thread, (int)(m_sharedPbuffers.size()/2), (int)(m_sharedNativePixmaps.size()/2), (int)(m_sharedNativeWindows.size()/2), (int)(m_sharedContexts.size()/2));
981 // Pull surfaces for second thread from shared surfaces
982 if (thread.getId() == 1)
983 pullObjectsFromShared(thread, (int)m_sharedPbuffers.size(), (int)m_sharedNativePixmaps.size(), (int)m_sharedNativeWindows.size(), (int)m_sharedContexts.size());
987 // Create / Destroy Objects
988 if ((m_types & TYPE_SINGLE_WINDOW) == 0)
989 createDestroyObjects(thread, 100);
992 destroyObjects(thread);
997 void MultiThreadedObjectTest::createDestroyObjects (TestThread& thread, int count)
999 const Library& egl = getLibrary();
1000 de::Random& rnd = (thread.getId() == 0 ? m_rnd0 : m_rnd1);
1001 vector<EGLSurface>& pbuffers = (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
1002 vector<pair<eglu::NativeWindow*, EGLSurface> >& windows = (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
1003 vector<pair<eglu::NativePixmap*, EGLSurface> >& pixmaps = (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
1004 vector<EGLContext>& contexts = (thread.getId() == 0 ? m_contexts0 : m_contexts1);
1005 set<Type> objectTypes;
1007 if ((m_types & TYPE_PBUFFER) != 0)
1008 objectTypes.insert(TYPE_PBUFFER);
1010 if ((m_types & TYPE_PIXMAP) != 0)
1011 objectTypes.insert(TYPE_PIXMAP);
1013 if ((m_types & TYPE_WINDOW) != 0)
1014 objectTypes.insert(TYPE_WINDOW);
1016 if ((m_types & TYPE_CONTEXT) != 0)
1017 objectTypes.insert(TYPE_CONTEXT);
1019 for (int createDestroyNdx = 0; createDestroyNdx < count; createDestroyNdx++)
1024 if (pbuffers.size() > 5 && ((m_types & TYPE_PBUFFER) != 0))
1027 type = TYPE_PBUFFER;
1029 else if (windows.size() > 5 && ((m_types & TYPE_WINDOW) != 0))
1034 else if (pixmaps.size() > 5 && ((m_types & TYPE_PIXMAP) != 0))
1039 else if (contexts.size() > 5 && ((m_types & TYPE_CONTEXT) != 0))
1042 type = TYPE_CONTEXT;
1044 else if (pbuffers.size() < 3 && ((m_types & TYPE_PBUFFER) != 0))
1047 type = TYPE_PBUFFER;
1049 else if (pixmaps.size() < 3 && ((m_types & TYPE_PIXMAP) != 0))
1054 else if (contexts.size() < 3 && ((m_types & TYPE_CONTEXT) != 0))
1057 type = TYPE_CONTEXT;
1059 else if (windows.size() < 3 && ((m_types & TYPE_WINDOW) != 0) && ((m_types & TYPE_SINGLE_WINDOW) == 0))
1064 else if (windows.empty() && (m_hasWindow == 0) && ((m_types & TYPE_WINDOW) != 0) && ((m_types & TYPE_SINGLE_WINDOW) != 0))
1071 create = rnd.getBool();
1073 if (!create && windows.empty())
1074 objectTypes.erase(TYPE_WINDOW);
1076 type = rnd.choose<Type>(objectTypes.begin(), objectTypes.end());
1087 const EGLint attributes[] =
1095 surface = egl.createPbufferSurface(m_display, m_config, attributes);
1096 thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreatePbufferSurface(" << m_display << ", " << m_config << ", { EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE })" << ThreadLog::EndMessage;
1097 EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
1099 pbuffers.push_back(surface);
1106 const eglu::NativeWindowFactory& windowFactory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
1108 if ((m_types & TYPE_SINGLE_WINDOW) != 0)
1110 if (deAtomicCompareExchange32(&m_hasWindow, 0, 1) == 0)
1112 eglu::NativeWindow* window = DE_NULL;
1113 EGLSurface surface = EGL_NO_SURFACE;
1117 window = windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(64, 64, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
1118 surface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, m_config, DE_NULL);
1120 thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreateWindowSurface()" << ThreadLog::EndMessage;
1121 windows.push_back(std::make_pair(window, surface));
1123 catch (const std::exception&)
1125 if (surface != EGL_NO_SURFACE)
1126 EGLU_CHECK_CALL(egl, destroySurface(m_display, surface));
1139 eglu::NativeWindow* window = DE_NULL;
1140 EGLSurface surface = EGL_NO_SURFACE;
1144 window = windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(64, 64, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
1145 surface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, m_config, DE_NULL);
1147 thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreateWindowSurface()" << ThreadLog::EndMessage;
1148 windows.push_back(std::make_pair(window, surface));
1150 catch (const std::exception&)
1152 if (surface != EGL_NO_SURFACE)
1153 EGLU_CHECK_CALL(egl, destroySurface(m_display, surface));
1163 const eglu::NativePixmapFactory& pixmapFactory = eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
1164 eglu::NativePixmap* pixmap = DE_NULL;
1165 EGLSurface surface = EGL_NO_SURFACE;
1169 pixmap = pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, 64, 64);
1170 surface = eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_display, m_config, DE_NULL);
1172 thread.getLog() << ThreadLog::BeginMessage << surface << " = eglCreatePixmapSurface()" << ThreadLog::EndMessage;
1173 pixmaps.push_back(std::make_pair(pixmap, surface));
1175 catch (const std::exception&)
1177 if (surface != EGL_NO_SURFACE)
1178 EGLU_CHECK_CALL(egl, destroySurface(m_display, surface));
1189 EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
1190 thread.getLog() << ThreadLog::BeginMessage << "eglBindAPI(EGL_OPENGL_ES_API)" << ThreadLog::EndMessage;
1192 const EGLint attributes[] =
1194 EGL_CONTEXT_CLIENT_VERSION, 2,
1198 context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attributes);
1199 thread.getLog() << ThreadLog::BeginMessage << context << " = eglCreateContext(" << m_display << ", " << m_config << ", EGL_NO_CONTEXT, { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE })" << ThreadLog::EndMessage;
1200 EGLU_CHECK_MSG(egl, "eglCreateContext()");
1201 contexts.push_back(context);
1215 const int pbufferNdx = rnd.getInt(0, (int)(pbuffers.size()-1));
1218 result = egl.destroySurface(m_display, pbuffers[pbufferNdx]);
1219 thread.getLog() << ThreadLog::BeginMessage << result << " = eglDestroySurface(" << m_display << ", " << pbuffers[pbufferNdx] << ")" << ThreadLog::EndMessage;
1220 EGLU_CHECK_MSG(egl, "eglDestroySurface()");
1222 pbuffers.erase(pbuffers.begin() + pbufferNdx);
1229 const int windowNdx = rnd.getInt(0, (int)(windows.size()-1));
1231 thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << windows[windowNdx].second << ")" << ThreadLog::EndMessage;
1233 EGLU_CHECK_CALL(egl, destroySurface(m_display, windows[windowNdx].second));
1234 windows[windowNdx].second = EGL_NO_SURFACE;
1235 delete windows[windowNdx].first;
1236 windows[windowNdx].first = DE_NULL;
1237 windows.erase(windows.begin() + windowNdx);
1239 if ((m_types & TYPE_SINGLE_WINDOW) != 0)
1247 const int pixmapNdx = rnd.getInt(0, (int)(pixmaps.size()-1));
1249 thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << pixmaps[pixmapNdx].second << ")" << ThreadLog::EndMessage;
1250 EGLU_CHECK_CALL(egl, destroySurface(m_display, pixmaps[pixmapNdx].second));
1251 pixmaps[pixmapNdx].second = EGL_NO_SURFACE;
1252 delete pixmaps[pixmapNdx].first;
1253 pixmaps[pixmapNdx].first = DE_NULL;
1254 pixmaps.erase(pixmaps.begin() + pixmapNdx);
1261 const int contextNdx = rnd.getInt(0, (int)(contexts.size()-1));
1263 EGLU_CHECK_CALL(egl, destroyContext(m_display, contexts[contextNdx]));
1264 thread.getLog() << ThreadLog::BeginMessage << "eglDestroyContext(" << m_display << ", " << contexts[contextNdx] << ")" << ThreadLog::EndMessage;
1265 contexts.erase(contexts.begin() + contextNdx);
1278 void MultiThreadedObjectTest::pushObjectsToShared (TestThread& thread)
1280 vector<EGLSurface>& pbuffers = (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
1281 vector<pair<eglu::NativeWindow*, EGLSurface> >& windows = (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
1282 vector<pair<eglu::NativePixmap*, EGLSurface> >& pixmaps = (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
1283 vector<EGLContext>& contexts = (thread.getId() == 0 ? m_contexts0 : m_contexts1);
1285 for (int pbufferNdx = 0; pbufferNdx < (int)pbuffers.size(); pbufferNdx++)
1286 m_sharedPbuffers.push_back(pbuffers[pbufferNdx]);
1290 for (int windowNdx = 0; windowNdx < (int)windows.size(); windowNdx++)
1291 m_sharedNativeWindows.push_back(windows[windowNdx]);
1295 for (int pixmapNdx = 0; pixmapNdx < (int)pixmaps.size(); pixmapNdx++)
1296 m_sharedNativePixmaps.push_back(pixmaps[pixmapNdx]);
1300 for (int contextNdx = 0; contextNdx < (int)contexts.size(); contextNdx++)
1301 m_sharedContexts.push_back(contexts[contextNdx]);
1306 void MultiThreadedObjectTest::pullObjectsFromShared (TestThread& thread, int pbufferCount, int pixmapCount, int windowCount, int contextCount)
1308 de::Random& rnd = (thread.getId() == 0 ? m_rnd0 : m_rnd1);
1309 vector<EGLSurface>& pbuffers = (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
1310 vector<pair<eglu::NativeWindow*, EGLSurface> >& windows = (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
1311 vector<pair<eglu::NativePixmap*, EGLSurface> >& pixmaps = (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
1312 vector<EGLContext>& contexts = (thread.getId() == 0 ? m_contexts0 : m_contexts1);
1314 for (int pbufferNdx = 0; pbufferNdx < pbufferCount; pbufferNdx++)
1316 const int ndx = rnd.getInt(0, (int)(m_sharedPbuffers.size()-1));
1318 pbuffers.push_back(m_sharedPbuffers[ndx]);
1319 m_sharedPbuffers.erase(m_sharedPbuffers.begin() + ndx);
1322 for (int pixmapNdx = 0; pixmapNdx < pixmapCount; pixmapNdx++)
1324 const int ndx = rnd.getInt(0, (int)(m_sharedNativePixmaps.size()-1));
1326 pixmaps.push_back(m_sharedNativePixmaps[ndx]);
1327 m_sharedNativePixmaps.erase(m_sharedNativePixmaps.begin() + ndx);
1330 for (int windowNdx = 0; windowNdx < windowCount; windowNdx++)
1332 const int ndx = rnd.getInt(0, (int)(m_sharedNativeWindows.size()-1));
1334 windows.push_back(m_sharedNativeWindows[ndx]);
1335 m_sharedNativeWindows.erase(m_sharedNativeWindows.begin() + ndx);
1338 for (int contextNdx = 0; contextNdx < contextCount; contextNdx++)
1340 const int ndx = rnd.getInt(0, (int)(m_sharedContexts.size()-1));
1342 contexts.push_back(m_sharedContexts[ndx]);
1343 m_sharedContexts.erase(m_sharedContexts.begin() + ndx);
1347 void MultiThreadedObjectTest::querySetSharedObjects (TestThread& thread, int count)
1349 const Library& egl = getLibrary();
1350 de::Random& rnd = (thread.getId() == 0 ? m_rnd0 : m_rnd1);
1351 vector<Type> objectTypes;
1353 if ((m_types & TYPE_PBUFFER) != 0)
1354 objectTypes.push_back(TYPE_PBUFFER);
1356 if ((m_types & TYPE_PIXMAP) != 0)
1357 objectTypes.push_back(TYPE_PIXMAP);
1359 if (!m_sharedNativeWindows.empty() && (m_types & TYPE_WINDOW) != 0)
1360 objectTypes.push_back(TYPE_WINDOW);
1362 if ((m_types & TYPE_CONTEXT) != 0)
1363 objectTypes.push_back(TYPE_CONTEXT);
1365 for (int queryNdx = 0; queryNdx < count; queryNdx++)
1367 const Type type = rnd.choose<Type>(objectTypes.begin(), objectTypes.end());
1368 EGLSurface surface = EGL_NO_SURFACE;
1369 EGLContext context = EGL_NO_CONTEXT;
1374 surface = m_sharedPbuffers[rnd.getInt(0, (int)(m_sharedPbuffers.size()-1))];
1378 surface = m_sharedNativePixmaps[rnd.getInt(0, (int)(m_sharedNativePixmaps.size()-1))].second;
1382 surface = m_sharedNativeWindows[rnd.getInt(0, (int)(m_sharedNativeWindows.size()-1))].second;
1386 context = m_sharedContexts[rnd.getInt(0, (int)(m_sharedContexts.size()-1))];
1393 if (surface != EGL_NO_SURFACE)
1395 static const EGLint queryAttributes[] =
1397 EGL_LARGEST_PBUFFER,
1402 const EGLint attribute = queryAttributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(queryAttributes) - 1)];
1406 result = egl.querySurface(m_display, surface, attribute, &value);
1407 thread.getLog() << ThreadLog::BeginMessage << result << " = eglQuerySurface(" << m_display << ", " << surface << ", " << attribute << ", " << value << ")" << ThreadLog::EndMessage;
1408 EGLU_CHECK_MSG(egl, "eglQuerySurface()");
1411 else if (context != EGL_NO_CONTEXT)
1413 static const EGLint attributes[] =
1416 EGL_CONTEXT_CLIENT_TYPE,
1417 EGL_CONTEXT_CLIENT_VERSION,
1421 const EGLint attribute = attributes[rnd.getInt(0, DE_LENGTH_OF_ARRAY(attributes)-1)];
1425 result = egl.queryContext(m_display, context, attribute, &value);
1426 thread.getLog() << ThreadLog::BeginMessage << result << " = eglQueryContext(" << m_display << ", " << context << ", " << attribute << ", " << value << ")" << ThreadLog::EndMessage;
1427 EGLU_CHECK_MSG(egl, "eglQueryContext()");
1435 void MultiThreadedObjectTest::destroyObjects (TestThread& thread)
1437 const Library& egl = getLibrary();
1438 vector<EGLSurface>& pbuffers = (thread.getId() == 0 ? m_pbuffers0 : m_pbuffers1);
1439 vector<pair<eglu::NativeWindow*, EGLSurface> >& windows = (thread.getId() == 0 ? m_nativeWindows0 : m_nativeWindows1);
1440 vector<pair<eglu::NativePixmap*, EGLSurface> >& pixmaps = (thread.getId() == 0 ? m_nativePixmaps0 : m_nativePixmaps1);
1441 vector<EGLContext>& contexts = (thread.getId() == 0 ? m_contexts0 : m_contexts1);
1443 for (int pbufferNdx = 0; pbufferNdx < (int)pbuffers.size(); pbufferNdx++)
1445 if (pbuffers[pbufferNdx] != EGL_NO_SURFACE)
1447 // Destroy EGLSurface
1450 result = egl.destroySurface(m_display, pbuffers[pbufferNdx]);
1451 thread.getLog() << ThreadLog::BeginMessage << result << " = eglDestroySurface(" << m_display << ", " << pbuffers[pbufferNdx] << ")" << ThreadLog::EndMessage;
1452 EGLU_CHECK_MSG(egl, "eglDestroySurface()");
1453 pbuffers[pbufferNdx] = EGL_NO_SURFACE;
1458 for (int windowNdx = 0; windowNdx < (int)windows.size(); windowNdx++)
1460 if (windows[windowNdx].second != EGL_NO_SURFACE)
1462 thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << windows[windowNdx].second << ")" << ThreadLog::EndMessage;
1463 EGLU_CHECK_CALL(egl, destroySurface(m_display, windows[windowNdx].second));
1464 windows[windowNdx].second = EGL_NO_SURFACE;
1467 if (windows[windowNdx].first)
1469 delete windows[windowNdx].first;
1470 windows[windowNdx].first = NULL;
1475 for (int pixmapNdx = 0; pixmapNdx < (int)pixmaps.size(); pixmapNdx++)
1477 if (pixmaps[pixmapNdx].first != EGL_NO_SURFACE)
1479 thread.getLog() << ThreadLog::BeginMessage << "eglDestroySurface(" << m_display << ", " << pixmaps[pixmapNdx].second << ")" << ThreadLog::EndMessage;
1480 EGLU_CHECK_CALL(egl, destroySurface(m_display, pixmaps[pixmapNdx].second));
1481 pixmaps[pixmapNdx].second = EGL_NO_SURFACE;
1484 if (pixmaps[pixmapNdx].first)
1486 delete pixmaps[pixmapNdx].first;
1487 pixmaps[pixmapNdx].first = NULL;
1492 for (int contextNdx = 0; contextNdx < (int)contexts.size(); contextNdx++)
1494 if (contexts[contextNdx] != EGL_NO_CONTEXT)
1496 EGLU_CHECK_CALL(egl, destroyContext(m_display, contexts[contextNdx]));
1497 thread.getLog() << ThreadLog::BeginMessage << "eglDestroyContext(" << m_display << ", " << contexts[contextNdx] << ")" << ThreadLog::EndMessage;
1498 contexts[contextNdx] = EGL_NO_CONTEXT;
1504 MultiThreadedTests::MultiThreadedTests (EglTestContext& context)
1505 : TestCaseGroup(context, "multithread", "Multithreaded EGL tests")
1509 void MultiThreadedTests::init (void)
1512 addChild(new MultiThreadedConfigTest(m_eglTestCtx, "config", "", 30, 30, 30));
1515 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer", "", MultiThreadedObjectTest::TYPE_PBUFFER));
1516 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap", "", MultiThreadedObjectTest::TYPE_PIXMAP));
1517 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "window", "", MultiThreadedObjectTest::TYPE_WINDOW));
1518 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "single_window", "", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
1519 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "context", "", MultiThreadedObjectTest::TYPE_CONTEXT));
1521 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_pixmap", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP));
1522 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_window", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW));
1523 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_single_window", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
1524 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_context", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_CONTEXT));
1526 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap_window", "", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW));
1527 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap_single_window", "", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
1528 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap_context", "", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_CONTEXT));
1530 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "window_context", "", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1531 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "single_window_context", "", MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1533 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_pixmap_window", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW));
1534 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_pixmap_single_window", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW));
1535 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_pixmap_context", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_CONTEXT));
1537 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_window_context", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1538 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_single_window_context", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1540 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap_window_context", "", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1541 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pixmap_single_window_context", "", MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_SINGLE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1543 addChild(new MultiThreadedObjectTest(m_eglTestCtx, "pbuffer_pixmap_window_context", "", MultiThreadedObjectTest::TYPE_PBUFFER|MultiThreadedObjectTest::TYPE_PIXMAP|MultiThreadedObjectTest::TYPE_WINDOW|MultiThreadedObjectTest::TYPE_CONTEXT));
1544 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));