egl/eglrefimpl/src/display.cpp
changeset 0 5d03bc08d59c
--- /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<TInt>(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<CEglSync*>(aSyncObj);
+    const TInt key = reinterpret_cast<TInt>(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<TInt>(&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<TInt>(&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));
+    }