1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/eglrefimpl/src/syncobj.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,174 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Reference EGL implementation to support EGL sync objects and OpenWF extensions
1.18 +
1.19 +#include "eglprivate.h"
1.20 +
1.21 +CEglSync::CEglSync(CEglDisplay& aDisplay):
1.22 + iDisplay(aDisplay),
1.23 + iType(EGL_SYNC_REUSABLE_KHR),
1.24 + iStatus(EGL_UNSIGNALED_KHR)
1.25 + {
1.26 + }
1.27 +
1.28 +CEglSync::~CEglSync()
1.29 + {
1.30 + iCondVar.Close();
1.31 + iMutex.Close();
1.32 + }
1.33 +
1.34 +TInt CEglSync::Construct()
1.35 + {
1.36 + TInt err = iMutex.CreateLocal();
1.37 + if (err != KErrNone)
1.38 + {
1.39 + return err;
1.40 + }
1.41 +
1.42 + err = iCondVar.CreateLocal();
1.43 + if (err != KErrNone)
1.44 + {
1.45 + return err;
1.46 + }
1.47 +
1.48 + err = iDisplay.RegisterSyncObj(*this);
1.49 + if (err != KErrNone)
1.50 + {
1.51 + return err;
1.52 + }
1.53 +
1.54 + iRefCount = 1;
1.55 + return KErrNone;
1.56 + }
1.57 +
1.58 +CEglSync* CEglSync::Create(CEglDisplay& aDisplay)
1.59 + {
1.60 + // sync object will be allocated in the EGL shared heap and added to sync object list
1.61 + // we need to switch current heap to EGL shared heap
1.62 + //
1.63 + RHeap* callerHeap = User::SwitchHeap(&aDisplay.Heap());
1.64 +
1.65 + CEglSync* syncObj = new CEglSync(aDisplay);
1.66 + if (!syncObj)
1.67 + {
1.68 + User::SwitchHeap(callerHeap);
1.69 + return NULL;
1.70 + }
1.71 +
1.72 + const TInt err = syncObj->Construct();
1.73 + if (err != KErrNone)
1.74 + {
1.75 + delete syncObj;
1.76 + User::SwitchHeap(callerHeap);
1.77 + return NULL;
1.78 + }
1.79 +
1.80 + User::SwitchHeap(callerHeap);
1.81 + return syncObj;
1.82 + }
1.83 +
1.84 +void CEglSync::Destroy()
1.85 + {
1.86 + // multiple calls to Destroy() is not allowed, it's either coming from eglDestroySyncKHR or eglTerminate
1.87 + //
1.88 + __ASSERT_DEBUG(!iIsDestroyed, User::Panic(KEglPanicCategory, EEglPanicSyncObjHasBeenDestroyed));
1.89 +
1.90 + iIsDestroyed = ETrue;
1.91 +
1.92 + // wake up all waiting threads
1.93 + iCondVar.Broadcast();
1.94 +
1.95 + // always remove sync obj from hash map when it is destroyed, the actual deletion will be done from Close(),
1.96 + // which can happen when eglClientWaitSyncKHR is called by user
1.97 + RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
1.98 + iDisplay.UnregisterSyncObj(*this);
1.99 + User::SwitchHeap(callerHeap);
1.100 +
1.101 + // decrement refcount for this sync obj, it will delete the object if refcount is zero
1.102 + Close();
1.103 + }
1.104 +
1.105 +void CEglSync::Close()
1.106 + {
1.107 + if (--iRefCount == 0)
1.108 + {
1.109 + // we're here either from Destroy() or eglClientWaitSyncKHR
1.110 + RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
1.111 + delete this;
1.112 + User::SwitchHeap(callerHeap);
1.113 + }
1.114 + }
1.115 +
1.116 +void CEglSync::Signal(EGLenum aMode)
1.117 + {
1.118 + iMutex.Wait();
1.119 + if (iStatus != aMode)
1.120 + {
1.121 + iStatus = aMode;
1.122 + if (iStatus == EGL_SIGNALED_KHR)
1.123 + {
1.124 + iCondVar.Broadcast();
1.125 + }
1.126 + }
1.127 + iMutex.Signal();
1.128 + }
1.129 +
1.130 +EGLint CEglSync::Wait(EGLTimeKHR aTimeOut)
1.131 + {
1.132 + // driver display lock is not held when we're about to enter block wait on condition variable
1.133 + // we use sync object mutex to synchronise threads access from this point until end of this function
1.134 + iMutex.Wait();
1.135 + EGLint errCode = EGL_CONDITION_SATISFIED_KHR;
1.136 +
1.137 + if (iStatus == EGL_UNSIGNALED_KHR)
1.138 + {
1.139 + switch(aTimeOut)
1.140 + {
1.141 + case EGL_FOREVER_KHR:
1.142 + {
1.143 + const TInt res = iCondVar.Wait(iMutex);
1.144 + //we do not expect to fail here
1.145 + __ASSERT_DEBUG(res == KErrNone, User::Panic(KEglPanicCategory, EEglPanicCondVarWaitFail));
1.146 + break;
1.147 + }
1.148 + case 0:
1.149 + {
1.150 + //by setting this we notify the caller that the sync object is in unsignaled state
1.151 + errCode = EGL_TIMEOUT_EXPIRED_KHR;
1.152 + break;
1.153 + }
1.154 + default:
1.155 + {
1.156 + // Since the supported range of timeout at function RCondVar::TimedWait(mutex, timeout)
1.157 + // is 0 to KMaxTInt, looping mechanism below is used to support 64bit timeout.
1.158 + //
1.159 + TInt res = KErrTimedOut;
1.160 + for(TInt64 timeoutMicroseconds = aTimeOut/1000; (res == KErrTimedOut) && (timeoutMicroseconds > 0); timeoutMicroseconds -= KMaxTInt)
1.161 + {
1.162 + res = iCondVar.TimedWait(iMutex, (timeoutMicroseconds > KMaxTInt?KMaxTInt:timeoutMicroseconds));
1.163 + //we do not expect to fail here
1.164 + __ASSERT_DEBUG(res == KErrNone || res == KErrTimedOut, User::Panic(KEglPanicCategory, EEglPanicCondVarTimedWaitFail));
1.165 + }
1.166 + if(res == KErrTimedOut)
1.167 + {
1.168 + errCode = EGL_TIMEOUT_EXPIRED_KHR;
1.169 + }
1.170 + break;
1.171 + }
1.172 + }
1.173 + }
1.174 +
1.175 + iMutex.Signal();
1.176 + return errCode;
1.177 + }