--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/egl/eglrefimpl/src/syncobj.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,174 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Reference EGL implementation to support EGL sync objects and OpenWF extensions
+
+#include "eglprivate.h"
+
+CEglSync::CEglSync(CEglDisplay& aDisplay):
+ iDisplay(aDisplay),
+ iType(EGL_SYNC_REUSABLE_KHR),
+ iStatus(EGL_UNSIGNALED_KHR)
+ {
+ }
+
+CEglSync::~CEglSync()
+ {
+ iCondVar.Close();
+ iMutex.Close();
+ }
+
+TInt CEglSync::Construct()
+ {
+ TInt err = iMutex.CreateLocal();
+ if (err != KErrNone)
+ {
+ return err;
+ }
+
+ err = iCondVar.CreateLocal();
+ if (err != KErrNone)
+ {
+ return err;
+ }
+
+ err = iDisplay.RegisterSyncObj(*this);
+ if (err != KErrNone)
+ {
+ return err;
+ }
+
+ iRefCount = 1;
+ return KErrNone;
+ }
+
+CEglSync* CEglSync::Create(CEglDisplay& aDisplay)
+ {
+ // sync object will be allocated in the EGL shared heap and added to sync object list
+ // we need to switch current heap to EGL shared heap
+ //
+ RHeap* callerHeap = User::SwitchHeap(&aDisplay.Heap());
+
+ CEglSync* syncObj = new CEglSync(aDisplay);
+ if (!syncObj)
+ {
+ User::SwitchHeap(callerHeap);
+ return NULL;
+ }
+
+ const TInt err = syncObj->Construct();
+ if (err != KErrNone)
+ {
+ delete syncObj;
+ User::SwitchHeap(callerHeap);
+ return NULL;
+ }
+
+ User::SwitchHeap(callerHeap);
+ return syncObj;
+ }
+
+void CEglSync::Destroy()
+ {
+ // multiple calls to Destroy() is not allowed, it's either coming from eglDestroySyncKHR or eglTerminate
+ //
+ __ASSERT_DEBUG(!iIsDestroyed, User::Panic(KEglPanicCategory, EEglPanicSyncObjHasBeenDestroyed));
+
+ iIsDestroyed = ETrue;
+
+ // wake up all waiting threads
+ iCondVar.Broadcast();
+
+ // always remove sync obj from hash map when it is destroyed, the actual deletion will be done from Close(),
+ // which can happen when eglClientWaitSyncKHR is called by user
+ RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
+ iDisplay.UnregisterSyncObj(*this);
+ User::SwitchHeap(callerHeap);
+
+ // decrement refcount for this sync obj, it will delete the object if refcount is zero
+ Close();
+ }
+
+void CEglSync::Close()
+ {
+ if (--iRefCount == 0)
+ {
+ // we're here either from Destroy() or eglClientWaitSyncKHR
+ RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
+ delete this;
+ User::SwitchHeap(callerHeap);
+ }
+ }
+
+void CEglSync::Signal(EGLenum aMode)
+ {
+ iMutex.Wait();
+ if (iStatus != aMode)
+ {
+ iStatus = aMode;
+ if (iStatus == EGL_SIGNALED_KHR)
+ {
+ iCondVar.Broadcast();
+ }
+ }
+ iMutex.Signal();
+ }
+
+EGLint CEglSync::Wait(EGLTimeKHR aTimeOut)
+ {
+ // driver display lock is not held when we're about to enter block wait on condition variable
+ // we use sync object mutex to synchronise threads access from this point until end of this function
+ iMutex.Wait();
+ EGLint errCode = EGL_CONDITION_SATISFIED_KHR;
+
+ if (iStatus == EGL_UNSIGNALED_KHR)
+ {
+ switch(aTimeOut)
+ {
+ case EGL_FOREVER_KHR:
+ {
+ const TInt res = iCondVar.Wait(iMutex);
+ //we do not expect to fail here
+ __ASSERT_DEBUG(res == KErrNone, User::Panic(KEglPanicCategory, EEglPanicCondVarWaitFail));
+ break;
+ }
+ case 0:
+ {
+ //by setting this we notify the caller that the sync object is in unsignaled state
+ errCode = EGL_TIMEOUT_EXPIRED_KHR;
+ break;
+ }
+ default:
+ {
+ // Since the supported range of timeout at function RCondVar::TimedWait(mutex, timeout)
+ // is 0 to KMaxTInt, looping mechanism below is used to support 64bit timeout.
+ //
+ TInt res = KErrTimedOut;
+ for(TInt64 timeoutMicroseconds = aTimeOut/1000; (res == KErrTimedOut) && (timeoutMicroseconds > 0); timeoutMicroseconds -= KMaxTInt)
+ {
+ res = iCondVar.TimedWait(iMutex, (timeoutMicroseconds > KMaxTInt?KMaxTInt:timeoutMicroseconds));
+ //we do not expect to fail here
+ __ASSERT_DEBUG(res == KErrNone || res == KErrTimedOut, User::Panic(KEglPanicCategory, EEglPanicCondVarTimedWaitFail));
+ }
+ if(res == KErrTimedOut)
+ {
+ errCode = EGL_TIMEOUT_EXPIRED_KHR;
+ }
+ break;
+ }
+ }
+ }
+
+ iMutex.Signal();
+ return errCode;
+ }