os/graphics/egl/eglrefimpl/src/driver.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 #include <EGL/egluids.hrh>
    18 #include <e32uid.h>
    19 #include <WF/openwfcuids.hrh>
    20 
    21 // OpenWF Composition library
    22 //
    23 _LIT(KOwfDllName, "libWFC.dll");
    24 const TUid KOwfDllUid1 = {KDynamicLibraryUidValue};
    25 const TUid KOwfDllUid2 = {KUidSharedDllUidValue};
    26 const TUid KOwfDllUid3 = {KUidOpenWfcDllUidValue};
    27 const TUidType KOwfDllUidType = TUidType(KOwfDllUid1, KOwfDllUid2, KOwfDllUid3);
    28 
    29 // EGL_KHR_reusable_sync extensions API
    30 // Declare here so their addresses can be used to build extensions table
    31 //
    32 EGLSyncKHR eglCreateSyncKHR(EGLDisplay aDisplay, EGLenum aType, const EGLint *aAttribList);
    33 EGLBoolean eglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync);
    34 EGLint eglClientWaitSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout);
    35 EGLBoolean eglSignalSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode);
    36 EGLBoolean eglGetSyncAttribKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aAttribute, EGLint *aValue);
    37 
    38 // Private extensions
    39 //
    40 EGLint egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode);
    41 
    42 // Extensions for shared heap OOM test
    43 #ifdef _DEBUG
    44 void egliDebugHeapMarkStart();
    45 EGLint egliDebugHeapMarkEnd(EGLint aCount);
    46 void egliDebugSetBurstAllocFail(EGLenum aType, EGLint aRate, EGLint aBurst);
    47 #endif //_DEBUG
    48 
    49 struct TEglNameProcRecord
    50     {
    51     char* iName;
    52     TFuncPtrEglProc iProc;
    53     };
    54 
    55 #define MAKE_NAME_PROC_RECORD(f)    {#f,reinterpret_cast<TFuncPtrEglProc>(f)}
    56 
    57 const TEglNameProcRecord KEglExtensionFuncs[] = {
    58     MAKE_NAME_PROC_RECORD(eglCreateSyncKHR),
    59     MAKE_NAME_PROC_RECORD(eglDestroySyncKHR),
    60     MAKE_NAME_PROC_RECORD(eglClientWaitSyncKHR),
    61     MAKE_NAME_PROC_RECORD(eglSignalSyncKHR),
    62     MAKE_NAME_PROC_RECORD(eglGetSyncAttribKHR),
    63     MAKE_NAME_PROC_RECORD(egl_Private_SignalSyncNOK) 
    64 #ifdef _DEBUG
    65     ,
    66     MAKE_NAME_PROC_RECORD(egliDebugHeapMarkStart),
    67     MAKE_NAME_PROC_RECORD(egliDebugHeapMarkEnd),
    68     MAKE_NAME_PROC_RECORD(egliDebugSetBurstAllocFail)
    69 #endif //_DEBUG
    70 };
    71 
    72 // Use common EglPls() function to hide difference between WINS and target in dealing with PLS
    73 //
    74 #ifdef __WINS__
    75 #include <pls.h>
    76 static inline XEglPls* EglPls()
    77 	{
    78 	const TUid KUidEglDll = {KUidEGLDllUidValue};
    79 	return Pls<XEglPls>(KUidEglDll);
    80 	}
    81 #else
    82 static XEglPls TheEglPls;
    83 static inline XEglPls* EglPls()
    84 	{
    85 	return &TheEglPls;
    86 	}
    87 #endif
    88 
    89 
    90 // Macros for placement new and delete of shared objects
    91 //
    92 #define EGL_PLACEMENT_NEW(heap, obj, klass)         klass* obj = NULL; \
    93                                                     TAny* buf = (heap).AllocZ(sizeof(klass)); \
    94                                                     if (buf) \
    95                                                         { \
    96                                                         obj = new(buf) klass((heap)); \
    97                                                         }
    98 
    99 #define EGL_PLACEMENT_DELETE(heap, obj, klass)      obj->~klass(); \
   100                                                     (heap).Free(obj);
   101 
   102 ///////////////////////////////////////////////////////////////////////////////
   103 // PLS
   104 ///////////////////////////////////////////////////////////////////////////////
   105 
   106 XEglPls::XEglPls()
   107 	{
   108 	iError = iLock.CreateLocal();
   109 	iDriver = NULL;
   110 	}
   111 
   112 XEglPls::~XEglPls()
   113 	{
   114 	iLock.Close();
   115 	}
   116 
   117 ///////////////////////////////////////////////////////////////////////////////
   118 // EGL driver
   119 ///////////////////////////////////////////////////////////////////////////////
   120 
   121 CEglDriver::CEglDriver(RHeap& aHeap):
   122 	iHeap(aHeap)
   123 	{
   124 	}
   125 
   126 CEglDriver::~CEglDriver()
   127 	{
   128 	// EGL display was allocated on shared heap using placement new
   129 	if (iDisplay)
   130 		{
   131 		EGL_PLACEMENT_DELETE(iHeap, iDisplay, CEglDisplay)
   132 		}
   133 	
   134 	iOwfLib.Close();
   135 	iLock.Close();
   136 	}
   137 
   138 TInt CEglDriver::Open()
   139 	{
   140 	// we're in trouble if mutex creation failed during DLL initialisation
   141 	XEglPls& pls = *EglPls();
   142 	if (pls.iError != KErrNone)
   143 		{
   144 		return pls.iError;
   145 		}
   146 	
   147 	pls.Lock();
   148 
   149 	if (pls.iDriver)
   150 		{
   151 		++(pls.iDriver->iRefCount);
   152 		pls.Unlock();
   153 		return KErrNone;
   154 		}
   155 	
   156 	// create shared heap in a local chunk to allow access to shared objects from any threads within Driver
   157 	// allow heap to grow from 256 bytes up to 1MB
   158 	const TInt KMaxHeapSize = 0x100000;
   159 	const TInt KWordAlign = 4;
   160 	RHeap* heap = User::ChunkHeap(NULL, KMinHeapSize, KMaxHeapSize, KMinHeapGrowBy, KWordAlign);
   161 	if (!heap)
   162 		{
   163 		pls.Unlock();
   164 		return KErrNoMemory;
   165 		}
   166 	
   167 	EGL_PLACEMENT_NEW(*heap, drv, CEglDriver)
   168 	if (!drv)
   169 		{
   170 		heap->Close();
   171 		pls.Unlock();
   172 		return KErrNoMemory;
   173 		}
   174 	
   175 	const TInt err = drv->Construct();
   176 	if (err != KErrNone)
   177 		{
   178 		EGL_PLACEMENT_DELETE(*heap, drv, CEglDriver)
   179 		heap->Close();
   180 		pls.Unlock();
   181 		
   182 		return err;
   183 		}
   184 	
   185 	pls.iDriver = drv;
   186 	pls.iDriver->iRefCount = 1;
   187 
   188 	pls.Unlock();
   189 	
   190 	return KErrNone;
   191 	}
   192 
   193 void CEglDriver::Close()
   194 	{
   195 	XEglPls& pls = *EglPls();
   196 	// must never happen if CEglDriver::Open() succeed
   197 	__ASSERT_DEBUG(pls.iError == KErrNone, User::Panic(KEglPanicCategory, EEglPanicPlsMutexError));
   198 
   199 	pls.Lock();
   200 
   201 	if (pls.iDriver)
   202 		{
   203 		if (--(pls.iDriver->iRefCount) == 0)
   204 			{
   205 			// copy shared heap pointer out as we're about to destroy the driver
   206 			RHeap& heap = pls.iDriver->iHeap;
   207 			
   208 			// driver was allocated on shared heap using placement new
   209 			EGL_PLACEMENT_DELETE(heap, pls.iDriver, CEglDriver)
   210 			pls.iDriver = NULL;
   211 			heap.Close();
   212 			}
   213 		}
   214 
   215 	pls.Unlock();
   216 	}
   217 
   218 CEglDriver* CEglDriver::GetDriver()
   219     {
   220     XEglPls& pls = *EglPls();
   221     return pls.iDriver;    
   222     }
   223 
   224 // called when lock is held
   225 //
   226 TInt CEglDriver::Construct()
   227 	{
   228 	TInt err = iLock.CreateLocal();
   229 	if (err != KErrNone)
   230 		{
   231 		return err;
   232 		}
   233 
   234 	// create default EGL display as part of driver initialisation, it will be destroyed when the driver is destroyed
   235 	// and recreated when driver is reinitialised
   236     EGL_PLACEMENT_NEW(iHeap, disp, CEglDisplay)
   237     if (!disp)
   238         {
   239         return KErrNoMemory;
   240         }
   241 
   242     iDisplay = disp;
   243 	
   244 	// for security reason, use TUidType when loading OWF library to make sure it is not a spoofed DLL with the same name
   245 	err = iOwfLib.Load(KOwfDllName, KOwfDllUidType);
   246 	// allow initialisation to proceed even if OWF library is not found
   247 	if (err == KErrNone)
   248 	    {
   249         // promote library handle from thread-relative to process-wide to allow closing from any thread
   250         RLibrary dup = iOwfLib;
   251         err = iOwfLib.Duplicate(RThread());
   252         if (err != KErrNone)
   253             {
   254             return err;
   255             }
   256         // if Duplicate succeed, it will overwrite iOwfLib with process-wide handle
   257         // we need to close the original thread-relative handle
   258         dup.Close();
   259     
   260         // In SymbianOS implementation of Khronos API, ordinal #1 is always reserved for internal implementation use as defined in
   261         // SymbianOS standard DEF files for that API. This DEF file ensures BC among different implementations of that API.
   262         // In OWF case, ordinal #1 refers to GetExtensionFunctionTable, a function which will return a table of function pointer.
   263         // One of them is a function that implement GetProcAddress to retrieve OWF extension functions.
   264         //
   265         const TInt KOwfGetFuncTableOrdinalNum = 1;
   266         typedef void (*TFuncPtrOwfGetFuncTable)(TOwfFuncTable*);
   267         
   268         TFuncPtrOwfGetFuncTable owfGetFuncTable = reinterpret_cast<TFuncPtrOwfGetFuncTable>(iOwfLib.Lookup(KOwfGetFuncTableOrdinalNum));
   269         if (!owfGetFuncTable)
   270             {
   271             return KErrNotFound;
   272             }
   273     
   274         owfGetFuncTable(&iOwfFuncTable);
   275     
   276         if (!iOwfFuncTable.iOwfGetProcAddress)
   277             {
   278             return KErrNotSupported;
   279             }
   280 	    }
   281 
   282 	return  KErrNone;
   283 	}
   284 
   285 TFuncPtrEglProc CEglDriver::GetProcAddress(const char* aName) const
   286    {
   287    // start with EGL extension functions
   288    //
   289    TPtrC8 procName(reinterpret_cast<const TUint8*>(aName));
   290    const TInt nExts = sizeof(KEglExtensionFuncs) / sizeof(KEglExtensionFuncs[0]);
   291    for (TInt idx=0; idx<nExts; ++idx)
   292        {
   293        if (procName == TPtrC8(reinterpret_cast<TUint8*>(KEglExtensionFuncs[idx].iName)))
   294            {
   295            return KEglExtensionFuncs[idx].iProc;
   296            }
   297        }
   298    
   299    // not an EGL extension, pass it on to OWF
   300    //
   301    return iOwfFuncTable.iOwfGetProcAddress ? iOwfFuncTable.iOwfGetProcAddress(aName) : NULL;
   302    }