egl/eglrefimpl/src/syncobj.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Reference EGL implementation to support EGL sync objects and OpenWF extensions
       
    15 
       
    16 #include "eglprivate.h"
       
    17 
       
    18 CEglSync::CEglSync(CEglDisplay& aDisplay):
       
    19     iDisplay(aDisplay),
       
    20     iType(EGL_SYNC_REUSABLE_KHR),
       
    21     iStatus(EGL_UNSIGNALED_KHR)
       
    22     {
       
    23     }
       
    24 
       
    25 CEglSync::~CEglSync()
       
    26     {
       
    27     iCondVar.Close();
       
    28     iMutex.Close();
       
    29     }
       
    30 
       
    31 TInt CEglSync::Construct()
       
    32     {
       
    33     TInt err = iMutex.CreateLocal();
       
    34     if (err != KErrNone)
       
    35         {
       
    36         return err;
       
    37         }
       
    38 
       
    39     err = iCondVar.CreateLocal();
       
    40     if (err != KErrNone)
       
    41         {
       
    42         return err;
       
    43         }
       
    44     
       
    45     err = iDisplay.RegisterSyncObj(*this);
       
    46     if (err != KErrNone)
       
    47         {
       
    48         return err;
       
    49         }
       
    50 
       
    51     iRefCount = 1;
       
    52     return KErrNone;
       
    53     }
       
    54 
       
    55 CEglSync* CEglSync::Create(CEglDisplay& aDisplay)
       
    56     {
       
    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
       
    59     //
       
    60     RHeap* callerHeap = User::SwitchHeap(&aDisplay.Heap());
       
    61 
       
    62     CEglSync* syncObj = new CEglSync(aDisplay);
       
    63     if (!syncObj)
       
    64         {
       
    65         User::SwitchHeap(callerHeap);
       
    66         return NULL;
       
    67         }
       
    68     
       
    69     const TInt err = syncObj->Construct();
       
    70     if (err != KErrNone)
       
    71         {
       
    72         delete syncObj;
       
    73         User::SwitchHeap(callerHeap);
       
    74         return NULL;
       
    75         }
       
    76     
       
    77     User::SwitchHeap(callerHeap);
       
    78     return syncObj;
       
    79     }
       
    80 
       
    81 void CEglSync::Destroy()
       
    82     {
       
    83     // multiple calls to Destroy() is not allowed, it's either coming from eglDestroySyncKHR or eglTerminate
       
    84     //
       
    85     __ASSERT_DEBUG(!iIsDestroyed, User::Panic(KEglPanicCategory, EEglPanicSyncObjHasBeenDestroyed));
       
    86     
       
    87     iIsDestroyed = ETrue;
       
    88 
       
    89     // wake up all waiting threads
       
    90     iCondVar.Broadcast();
       
    91 
       
    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);
       
    97     
       
    98     // decrement refcount for this sync obj, it will delete the object if refcount is zero
       
    99     Close();
       
   100     }
       
   101 
       
   102 void CEglSync::Close()
       
   103     {
       
   104     if (--iRefCount == 0)
       
   105         {
       
   106         // we're here either from Destroy() or eglClientWaitSyncKHR
       
   107         RHeap* callerHeap = User::SwitchHeap(&iDisplay.Heap());
       
   108         delete this;
       
   109         User::SwitchHeap(callerHeap);
       
   110         }
       
   111     }
       
   112 
       
   113 void CEglSync::Signal(EGLenum aMode)
       
   114     {
       
   115     iMutex.Wait();
       
   116     if (iStatus != aMode)
       
   117         {
       
   118         iStatus = aMode;
       
   119         if (iStatus == EGL_SIGNALED_KHR)
       
   120             {
       
   121             iCondVar.Broadcast();
       
   122             }
       
   123         }
       
   124     iMutex.Signal();
       
   125     }
       
   126 
       
   127 EGLint CEglSync::Wait(EGLTimeKHR aTimeOut)
       
   128     {
       
   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
       
   131     iMutex.Wait();
       
   132     EGLint errCode = EGL_CONDITION_SATISFIED_KHR;
       
   133     
       
   134     if (iStatus == EGL_UNSIGNALED_KHR)
       
   135         {
       
   136         switch(aTimeOut) 
       
   137             {
       
   138             case EGL_FOREVER_KHR:
       
   139                 {
       
   140                 const TInt res = iCondVar.Wait(iMutex); 
       
   141                 //we do not expect to fail here
       
   142                 __ASSERT_DEBUG(res == KErrNone, User::Panic(KEglPanicCategory, EEglPanicCondVarWaitFail));
       
   143                 break;
       
   144                 }
       
   145             case 0:
       
   146                 {
       
   147                 //by setting this we notify the caller that the sync object is in unsignaled state
       
   148                 errCode = EGL_TIMEOUT_EXPIRED_KHR; 
       
   149                 break;
       
   150                 }
       
   151             default:
       
   152                 {
       
   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.      
       
   155                 //
       
   156                 TInt res = KErrTimedOut;
       
   157                 for(TInt64 timeoutMicroseconds = aTimeOut/1000; (res == KErrTimedOut) && (timeoutMicroseconds > 0); timeoutMicroseconds -= KMaxTInt)
       
   158                     {
       
   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));
       
   162                     }
       
   163                 if(res == KErrTimedOut)
       
   164                     {
       
   165                     errCode = EGL_TIMEOUT_EXPIRED_KHR;
       
   166                     }
       
   167                 break;
       
   168                 }
       
   169             }
       
   170         }
       
   171 
       
   172     iMutex.Signal();
       
   173     return errCode;
       
   174     }