os/graphics/egl/eglrefimpl/src/syncobj.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     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     }