diff -r 000000000000 -r 5d03bc08d59c egl/eglrefimpl/src/display.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/egl/eglrefimpl/src/display.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,164 @@ +// 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" + +CEglDisplay::CEglDisplay(RHeap& aHeap): + iHandle(KEglDefaultDisplayHandle), + iHeap(aHeap) + { + } + +CEglDisplay::~CEglDisplay() + { + Terminate(); + + if (iSyncObjList) + { + __ASSERT_DEBUG(iSyncObjList->Count() == 0, User::Panic(KEglPanicCategory, EEglPanicOutstandingSyncObj)); + + // we're about to free hash map and its underlying memory, make sure EGL shared heap is used + RHeap* callerHeap = User::SwitchHeap(&iHeap); + iSyncObjList->Close(); + delete iSyncObjList; + User::SwitchHeap(callerHeap); + } + } + +TInt CEglDisplay::Initialize() + { + TInt err = KErrNone; + if (iIsInitialized) + { + return err; + } + + // hash map is only created once, check that when re-initialising display + if (iSyncObjList) + { + iIsInitialized = ETrue; + } + else + { + // make sure underlying hash implementation memory is allocated in share heap + // + RHeap* callerHeap = User::SwitchHeap(&iHeap); + iSyncObjList = new REglSyncHashMap; + if (iSyncObjList) + { + iIsInitialized = ETrue; + } + else + { + err = KErrNoMemory; + } + User::SwitchHeap(callerHeap); + } + + return err; + } + +void CEglDisplay::Terminate() + { + if (!iIsInitialized) + { + return; + } + + REglSyncHashMap::TIter iter(*iSyncObjList); + // iter begin at index -1, must move it once to get to first item + while (iter.NextKey()) + { + CEglSync** ppSyncObj = iter.CurrentValue(); + __ASSERT_DEBUG(ppSyncObj, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); + + // In a regular iteration, we should not modify the hash map itself while it is being iterated. + // However, this is not a regular iteration, we need to remove destroyed object from + // this hash map without using additional memory e.g. copying destroyed object key temporarily. + // The reason we do not want to do that is because allocating memory can fail and Terminate + // must not fail. + CEglSync* syncObj = *ppSyncObj; + + // Destroy() will switch current heap to the EGL shared heap and restore it back. + // It will also remove the sync object from hash map, but not necessarily delete it (because + // some other threads may still use it) + syncObj->Destroy(); + iter.Reset(); + } + + iIsInitialized = EFalse; + } + +CEglSync* CEglDisplay::FindSyncObj(EGLSyncKHR aObj) const + { + __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); + + const TInt key = reinterpret_cast(aObj); + CEglSync** ppso = iSyncObjList->Find(key); + CEglSync* syncObj = ppso ? *ppso : NULL; + + return syncObj; + } + +CEglSync* CEglDisplay::CreateSyncObj() + { + __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); + + CEglSync* syncObj = CEglSync::Create(*this); + + return syncObj; + } + +TInt CEglDisplay::DestroySyncObj(EGLSyncKHR aSyncObj) + { + __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); + + CEglSync* syncObj = reinterpret_cast(aSyncObj); + const TInt key = reinterpret_cast(syncObj); + CEglSync** ppso = iSyncObjList->Find(key); + if (!ppso) + { + return KErrNotFound; + } + + // Destroy() will not delete sync obj or remove it from the list if it is still being used in other threads + // 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 + __ASSERT_DEBUG(syncObj == *ppso, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); + syncObj->Destroy(); + + return KErrNone; + } + +TInt CEglDisplay::RegisterSyncObj(CEglSync& aSyncObj) + { + __ASSERT_DEBUG(&iHeap == &User::Heap(), User::Panic(KEglPanicCategory, EEglPanicInvalidHeap)); + __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); + + const TInt key = reinterpret_cast(&aSyncObj); + const TInt err = iSyncObjList->Insert(key, &aSyncObj); + + return err; + } + +void CEglDisplay::UnregisterSyncObj(CEglSync& aSyncObj) + { + __ASSERT_DEBUG(&iHeap == &User::Heap(), User::Panic(KEglPanicCategory, EEglPanicInvalidHeap)); + __ASSERT_DEBUG(iSyncObjList, User::Panic(KEglPanicCategory, EEglPanicDisplayStateInvalid)); + + const TInt key = reinterpret_cast(&aSyncObj); + const TInt err = iSyncObjList->Remove(key); + // the only possible error is KErrNotFound which should never happen in our case + __ASSERT_DEBUG(err == KErrNone, User::Panic(KEglPanicCategory, EEglPanicInvalidSyncObj)); + }