First public contribution.
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Reference EGL implementation to support EGL sync objects and OpenWF extensions
16 #include "eglprivate.h"
18 CEglSync::CEglSync(CEglDisplay& aDisplay):
20 iType(EGL_SYNC_REUSABLE_KHR),
21 iStatus(EGL_UNSIGNALED_KHR)
31 TInt CEglSync::Construct()
33 TInt err = iMutex.CreateLocal();
39 err = iCondVar.CreateLocal();
45 err = iDisplay.RegisterSyncObj(*this);
55 CEglSync* CEglSync::Create(CEglDisplay& aDisplay)
57 // sync object will be allocated in the EGL shared heap and added to sync object list
58 // we need to switch current heap to EGL shared heap
60 RHeap* callerHeap = User::SwitchHeap(&aDisplay.Heap());
62 CEglSync* syncObj = new CEglSync(aDisplay);
65 User::SwitchHeap(callerHeap);
69 const TInt err = syncObj->Construct();
73 User::SwitchHeap(callerHeap);
77 User::SwitchHeap(callerHeap);
81 void CEglSync::Destroy()
83 // multiple calls to Destroy() is not allowed, it's either coming from eglDestroySyncKHR or eglTerminate
85 __ASSERT_DEBUG(!iIsDestroyed, User::Panic(KEglPanicCategory, EEglPanicSyncObjHasBeenDestroyed));
89 // wake up all waiting threads
92 // always remove sync obj from hash map when it is destroyed, the actual deletion will be done from Close(),
93 // which can happen when eglClientWaitSyncKHR is called by user
94 RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
95 iDisplay.UnregisterSyncObj(*this);
96 User::SwitchHeap(callerHeap);
98 // decrement refcount for this sync obj, it will delete the object if refcount is zero
102 void CEglSync::Close()
104 if (--iRefCount == 0)
106 // we're here either from Destroy() or eglClientWaitSyncKHR
107 RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
109 User::SwitchHeap(callerHeap);
113 void CEglSync::Signal(EGLenum aMode)
116 if (iStatus != aMode)
119 if (iStatus == EGL_SIGNALED_KHR)
121 iCondVar.Broadcast();
127 EGLint CEglSync::Wait(EGLTimeKHR aTimeOut)
129 // driver display lock is not held when we're about to enter block wait on condition variable
130 // we use sync object mutex to synchronise threads access from this point until end of this function
132 EGLint errCode = EGL_CONDITION_SATISFIED_KHR;
134 if (iStatus == EGL_UNSIGNALED_KHR)
138 case EGL_FOREVER_KHR:
140 const TInt res = iCondVar.Wait(iMutex);
141 //we do not expect to fail here
142 __ASSERT_DEBUG(res == KErrNone, User::Panic(KEglPanicCategory, EEglPanicCondVarWaitFail));
147 //by setting this we notify the caller that the sync object is in unsignaled state
148 errCode = EGL_TIMEOUT_EXPIRED_KHR;
153 // Since the supported range of timeout at function RCondVar::TimedWait(mutex, timeout)
154 // is 0 to KMaxTInt, looping mechanism below is used to support 64bit timeout.
156 TInt res = KErrTimedOut;
157 for(TInt64 timeoutMicroseconds = aTimeOut/1000; (res == KErrTimedOut) && (timeoutMicroseconds > 0); timeoutMicroseconds -= KMaxTInt)
159 res = iCondVar.TimedWait(iMutex, (timeoutMicroseconds > KMaxTInt?KMaxTInt:timeoutMicroseconds));
160 //we do not expect to fail here
161 __ASSERT_DEBUG(res == KErrNone || res == KErrTimedOut, User::Panic(KEglPanicCategory, EEglPanicCondVarTimedWaitFail));
163 if(res == KErrTimedOut)
165 errCode = EGL_TIMEOUT_EXPIRED_KHR;