egl/eglrefimpl/src/driver.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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    }