sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Reference EGL implementation to support EGL sync objects and OpenWF extensions sl@0: sl@0: #include "eglprivate.h" sl@0: sl@0: CEglDisplay::CEglDisplay(RHeap& aHeap): sl@0: iHandle(KEglDefaultDisplayHandle), sl@0: iHeap(aHeap) sl@0: { sl@0: } sl@0: sl@0: CEglDisplay::~CEglDisplay() sl@0: { sl@0: Terminate(); sl@0: sl@0: if (iSyncObjList) sl@0: { sl@0: __ASSERT_DEBUG(iSyncObjList->Count() == 0, User::Panic(KEglPanicCategory, EEglPanicOutstandingSyncObj)); sl@0: sl@0: // we're about to free hash map and its underlying memory, make sure EGL shared heap is used sl@0: RHeap* callerHeap = User::SwitchHeap(&iHeap); sl@0: iSyncObjList->Close(); sl@0: delete iSyncObjList; sl@0: User::SwitchHeap(callerHeap); sl@0: } sl@0: } sl@0: sl@0: TInt CEglDisplay::Initialize() sl@0: { sl@0: TInt err = KErrNone; sl@0: if (iIsInitialized) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: // hash map is only created once, check that when re-initialising display sl@0: if (iSyncObjList) sl@0: { sl@0: iIsInitialized = ETrue; sl@0: } sl@0: else sl@0: { sl@0: // make sure underlying hash implementation memory is allocated in share heap sl@0: // sl@0: RHeap* callerHeap = User::SwitchHeap(&iHeap); sl@0: iSyncObjList = new REglSyncHashMap; sl@0: if (iSyncObjList) sl@0: { sl@0: iIsInitialized = ETrue; sl@0: } sl@0: else sl@0: { sl@0: err = KErrNoMemory; sl@0: } sl@0: User::SwitchHeap(callerHeap); sl@0: } sl@0: sl@0: return err; sl@0: } sl@0: sl@0: void CEglDisplay::Terminate() sl@0: { sl@0: if (!iIsInitialized) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: REglSyncHashMap::TIter iter(*iSyncObjList); sl@0: // iter begin at index -1, must move it once to get to first item sl@0: while (iter.NextKey()) sl@0: { sl@0: CEglSync** ppSyncObj = iter.CurrentValue(); sl@0: __ASSERT_DEBUG(ppSyncObj, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); sl@0: sl@0: // In a regular iteration, we should not modify the hash map itself while it is being iterated. sl@0: // However, this is not a regular iteration, we need to remove destroyed object from sl@0: // this hash map without using additional memory e.g. copying destroyed object key temporarily. sl@0: // The reason we do not want to do that is because allocating memory can fail and Terminate sl@0: // must not fail. sl@0: CEglSync* syncObj = *ppSyncObj; sl@0: sl@0: // Destroy() will switch current heap to the EGL shared heap and restore it back. sl@0: // It will also remove the sync object from hash map, but not necessarily delete it (because sl@0: // some other threads may still use it) sl@0: syncObj->Destroy(); sl@0: iter.Reset(); sl@0: } sl@0: sl@0: iIsInitialized = EFalse; sl@0: } sl@0: sl@0: CEglSync* CEglDisplay::FindSyncObj(EGLSyncKHR aObj) const sl@0: { sl@0: __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); sl@0: sl@0: const TInt key = reinterpret_cast(aObj); sl@0: CEglSync** ppso = iSyncObjList->Find(key); sl@0: CEglSync* syncObj = ppso ? *ppso : NULL; sl@0: sl@0: return syncObj; sl@0: } sl@0: sl@0: CEglSync* CEglDisplay::CreateSyncObj() sl@0: { sl@0: __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); sl@0: sl@0: CEglSync* syncObj = CEglSync::Create(*this); sl@0: sl@0: return syncObj; sl@0: } sl@0: sl@0: TInt CEglDisplay::DestroySyncObj(EGLSyncKHR aSyncObj) sl@0: { sl@0: __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); sl@0: sl@0: CEglSync* syncObj = reinterpret_cast(aSyncObj); sl@0: const TInt key = reinterpret_cast(syncObj); sl@0: CEglSync** ppso = iSyncObjList->Find(key); sl@0: if (!ppso) sl@0: { sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: // Destroy() will not delete sync obj or remove it from the list if it is still being used in other threads sl@0: // if there is no more reference to this sync obj when Destroy() is called, it will delete the object and remove it from the list sl@0: __ASSERT_DEBUG(syncObj == *ppso, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); sl@0: syncObj->Destroy(); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CEglDisplay::RegisterSyncObj(CEglSync& aSyncObj) sl@0: { sl@0: __ASSERT_DEBUG(&iHeap == &User::Heap(), User::Panic(KEglPanicCategory, EEglPanicInvalidHeap)); sl@0: __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); sl@0: sl@0: const TInt key = reinterpret_cast(&aSyncObj); sl@0: const TInt err = iSyncObjList->Insert(key, &aSyncObj); sl@0: sl@0: return err; sl@0: } sl@0: sl@0: void CEglDisplay::UnregisterSyncObj(CEglSync& aSyncObj) sl@0: { sl@0: __ASSERT_DEBUG(&iHeap == &User::Heap(), User::Panic(KEglPanicCategory, EEglPanicInvalidHeap)); sl@0: __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); sl@0: sl@0: const TInt key = reinterpret_cast(&aSyncObj); sl@0: const TInt err = iSyncObjList->Remove(key); sl@0: // the only possible error is KErrNotFound which should never happen in our case sl@0: __ASSERT_DEBUG(err == KErrNone, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); sl@0: }