1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/egl/eglrefimpl/src/driver.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,302 @@
1.4 +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Reference EGL implementation to support EGL sync objects and OpenWF extensions
1.18 +
1.19 +#include "eglprivate.h"
1.20 +#include <EGL/egluids.hrh>
1.21 +#include <e32uid.h>
1.22 +#include <WF/openwfcuids.hrh>
1.23 +
1.24 +// OpenWF Composition library
1.25 +//
1.26 +_LIT(KOwfDllName, "libWFC.dll");
1.27 +const TUid KOwfDllUid1 = {KDynamicLibraryUidValue};
1.28 +const TUid KOwfDllUid2 = {KUidSharedDllUidValue};
1.29 +const TUid KOwfDllUid3 = {KUidOpenWfcDllUidValue};
1.30 +const TUidType KOwfDllUidType = TUidType(KOwfDllUid1, KOwfDllUid2, KOwfDllUid3);
1.31 +
1.32 +// EGL_KHR_reusable_sync extensions API
1.33 +// Declare here so their addresses can be used to build extensions table
1.34 +//
1.35 +EGLSyncKHR eglCreateSyncKHR(EGLDisplay aDisplay, EGLenum aType, const EGLint *aAttribList);
1.36 +EGLBoolean eglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync);
1.37 +EGLint eglClientWaitSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout);
1.38 +EGLBoolean eglSignalSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode);
1.39 +EGLBoolean eglGetSyncAttribKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aAttribute, EGLint *aValue);
1.40 +
1.41 +// Private extensions
1.42 +//
1.43 +EGLint egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode);
1.44 +
1.45 +// Extensions for shared heap OOM test
1.46 +#ifdef _DEBUG
1.47 +void egliDebugHeapMarkStart();
1.48 +EGLint egliDebugHeapMarkEnd(EGLint aCount);
1.49 +void egliDebugSetBurstAllocFail(EGLenum aType, EGLint aRate, EGLint aBurst);
1.50 +#endif //_DEBUG
1.51 +
1.52 +struct TEglNameProcRecord
1.53 + {
1.54 + char* iName;
1.55 + TFuncPtrEglProc iProc;
1.56 + };
1.57 +
1.58 +#define MAKE_NAME_PROC_RECORD(f) {#f,reinterpret_cast<TFuncPtrEglProc>(f)}
1.59 +
1.60 +const TEglNameProcRecord KEglExtensionFuncs[] = {
1.61 + MAKE_NAME_PROC_RECORD(eglCreateSyncKHR),
1.62 + MAKE_NAME_PROC_RECORD(eglDestroySyncKHR),
1.63 + MAKE_NAME_PROC_RECORD(eglClientWaitSyncKHR),
1.64 + MAKE_NAME_PROC_RECORD(eglSignalSyncKHR),
1.65 + MAKE_NAME_PROC_RECORD(eglGetSyncAttribKHR),
1.66 + MAKE_NAME_PROC_RECORD(egl_Private_SignalSyncNOK)
1.67 +#ifdef _DEBUG
1.68 + ,
1.69 + MAKE_NAME_PROC_RECORD(egliDebugHeapMarkStart),
1.70 + MAKE_NAME_PROC_RECORD(egliDebugHeapMarkEnd),
1.71 + MAKE_NAME_PROC_RECORD(egliDebugSetBurstAllocFail)
1.72 +#endif //_DEBUG
1.73 +};
1.74 +
1.75 +// Use common EglPls() function to hide difference between WINS and target in dealing with PLS
1.76 +//
1.77 +#ifdef __WINS__
1.78 +#include <pls.h>
1.79 +static inline XEglPls* EglPls()
1.80 + {
1.81 + const TUid KUidEglDll = {KUidEGLDllUidValue};
1.82 + return Pls<XEglPls>(KUidEglDll);
1.83 + }
1.84 +#else
1.85 +static XEglPls TheEglPls;
1.86 +static inline XEglPls* EglPls()
1.87 + {
1.88 + return &TheEglPls;
1.89 + }
1.90 +#endif
1.91 +
1.92 +
1.93 +// Macros for placement new and delete of shared objects
1.94 +//
1.95 +#define EGL_PLACEMENT_NEW(heap, obj, klass) klass* obj = NULL; \
1.96 + TAny* buf = (heap).AllocZ(sizeof(klass)); \
1.97 + if (buf) \
1.98 + { \
1.99 + obj = new(buf) klass((heap)); \
1.100 + }
1.101 +
1.102 +#define EGL_PLACEMENT_DELETE(heap, obj, klass) obj->~klass(); \
1.103 + (heap).Free(obj);
1.104 +
1.105 +///////////////////////////////////////////////////////////////////////////////
1.106 +// PLS
1.107 +///////////////////////////////////////////////////////////////////////////////
1.108 +
1.109 +XEglPls::XEglPls()
1.110 + {
1.111 + iError = iLock.CreateLocal();
1.112 + iDriver = NULL;
1.113 + }
1.114 +
1.115 +XEglPls::~XEglPls()
1.116 + {
1.117 + iLock.Close();
1.118 + }
1.119 +
1.120 +///////////////////////////////////////////////////////////////////////////////
1.121 +// EGL driver
1.122 +///////////////////////////////////////////////////////////////////////////////
1.123 +
1.124 +CEglDriver::CEglDriver(RHeap& aHeap):
1.125 + iHeap(aHeap)
1.126 + {
1.127 + }
1.128 +
1.129 +CEglDriver::~CEglDriver()
1.130 + {
1.131 + // EGL display was allocated on shared heap using placement new
1.132 + if (iDisplay)
1.133 + {
1.134 + EGL_PLACEMENT_DELETE(iHeap, iDisplay, CEglDisplay)
1.135 + }
1.136 +
1.137 + iOwfLib.Close();
1.138 + iLock.Close();
1.139 + }
1.140 +
1.141 +TInt CEglDriver::Open()
1.142 + {
1.143 + // we're in trouble if mutex creation failed during DLL initialisation
1.144 + XEglPls& pls = *EglPls();
1.145 + if (pls.iError != KErrNone)
1.146 + {
1.147 + return pls.iError;
1.148 + }
1.149 +
1.150 + pls.Lock();
1.151 +
1.152 + if (pls.iDriver)
1.153 + {
1.154 + ++(pls.iDriver->iRefCount);
1.155 + pls.Unlock();
1.156 + return KErrNone;
1.157 + }
1.158 +
1.159 + // create shared heap in a local chunk to allow access to shared objects from any threads within Driver
1.160 + // allow heap to grow from 256 bytes up to 1MB
1.161 + const TInt KMaxHeapSize = 0x100000;
1.162 + const TInt KWordAlign = 4;
1.163 + RHeap* heap = User::ChunkHeap(NULL, KMinHeapSize, KMaxHeapSize, KMinHeapGrowBy, KWordAlign);
1.164 + if (!heap)
1.165 + {
1.166 + pls.Unlock();
1.167 + return KErrNoMemory;
1.168 + }
1.169 +
1.170 + EGL_PLACEMENT_NEW(*heap, drv, CEglDriver)
1.171 + if (!drv)
1.172 + {
1.173 + heap->Close();
1.174 + pls.Unlock();
1.175 + return KErrNoMemory;
1.176 + }
1.177 +
1.178 + const TInt err = drv->Construct();
1.179 + if (err != KErrNone)
1.180 + {
1.181 + EGL_PLACEMENT_DELETE(*heap, drv, CEglDriver)
1.182 + heap->Close();
1.183 + pls.Unlock();
1.184 +
1.185 + return err;
1.186 + }
1.187 +
1.188 + pls.iDriver = drv;
1.189 + pls.iDriver->iRefCount = 1;
1.190 +
1.191 + pls.Unlock();
1.192 +
1.193 + return KErrNone;
1.194 + }
1.195 +
1.196 +void CEglDriver::Close()
1.197 + {
1.198 + XEglPls& pls = *EglPls();
1.199 + // must never happen if CEglDriver::Open() succeed
1.200 + __ASSERT_DEBUG(pls.iError == KErrNone, User::Panic(KEglPanicCategory, EEglPanicPlsMutexError));
1.201 +
1.202 + pls.Lock();
1.203 +
1.204 + if (pls.iDriver)
1.205 + {
1.206 + if (--(pls.iDriver->iRefCount) == 0)
1.207 + {
1.208 + // copy shared heap pointer out as we're about to destroy the driver
1.209 + RHeap& heap = pls.iDriver->iHeap;
1.210 +
1.211 + // driver was allocated on shared heap using placement new
1.212 + EGL_PLACEMENT_DELETE(heap, pls.iDriver, CEglDriver)
1.213 + pls.iDriver = NULL;
1.214 + heap.Close();
1.215 + }
1.216 + }
1.217 +
1.218 + pls.Unlock();
1.219 + }
1.220 +
1.221 +CEglDriver* CEglDriver::GetDriver()
1.222 + {
1.223 + XEglPls& pls = *EglPls();
1.224 + return pls.iDriver;
1.225 + }
1.226 +
1.227 +// called when lock is held
1.228 +//
1.229 +TInt CEglDriver::Construct()
1.230 + {
1.231 + TInt err = iLock.CreateLocal();
1.232 + if (err != KErrNone)
1.233 + {
1.234 + return err;
1.235 + }
1.236 +
1.237 + // create default EGL display as part of driver initialisation, it will be destroyed when the driver is destroyed
1.238 + // and recreated when driver is reinitialised
1.239 + EGL_PLACEMENT_NEW(iHeap, disp, CEglDisplay)
1.240 + if (!disp)
1.241 + {
1.242 + return KErrNoMemory;
1.243 + }
1.244 +
1.245 + iDisplay = disp;
1.246 +
1.247 + // for security reason, use TUidType when loading OWF library to make sure it is not a spoofed DLL with the same name
1.248 + err = iOwfLib.Load(KOwfDllName, KOwfDllUidType);
1.249 + // allow initialisation to proceed even if OWF library is not found
1.250 + if (err == KErrNone)
1.251 + {
1.252 + // promote library handle from thread-relative to process-wide to allow closing from any thread
1.253 + RLibrary dup = iOwfLib;
1.254 + err = iOwfLib.Duplicate(RThread());
1.255 + if (err != KErrNone)
1.256 + {
1.257 + return err;
1.258 + }
1.259 + // if Duplicate succeed, it will overwrite iOwfLib with process-wide handle
1.260 + // we need to close the original thread-relative handle
1.261 + dup.Close();
1.262 +
1.263 + // In SymbianOS implementation of Khronos API, ordinal #1 is always reserved for internal implementation use as defined in
1.264 + // SymbianOS standard DEF files for that API. This DEF file ensures BC among different implementations of that API.
1.265 + // In OWF case, ordinal #1 refers to GetExtensionFunctionTable, a function which will return a table of function pointer.
1.266 + // One of them is a function that implement GetProcAddress to retrieve OWF extension functions.
1.267 + //
1.268 + const TInt KOwfGetFuncTableOrdinalNum = 1;
1.269 + typedef void (*TFuncPtrOwfGetFuncTable)(TOwfFuncTable*);
1.270 +
1.271 + TFuncPtrOwfGetFuncTable owfGetFuncTable = reinterpret_cast<TFuncPtrOwfGetFuncTable>(iOwfLib.Lookup(KOwfGetFuncTableOrdinalNum));
1.272 + if (!owfGetFuncTable)
1.273 + {
1.274 + return KErrNotFound;
1.275 + }
1.276 +
1.277 + owfGetFuncTable(&iOwfFuncTable);
1.278 +
1.279 + if (!iOwfFuncTable.iOwfGetProcAddress)
1.280 + {
1.281 + return KErrNotSupported;
1.282 + }
1.283 + }
1.284 +
1.285 + return KErrNone;
1.286 + }
1.287 +
1.288 +TFuncPtrEglProc CEglDriver::GetProcAddress(const char* aName) const
1.289 + {
1.290 + // start with EGL extension functions
1.291 + //
1.292 + TPtrC8 procName(reinterpret_cast<const TUint8*>(aName));
1.293 + const TInt nExts = sizeof(KEglExtensionFuncs) / sizeof(KEglExtensionFuncs[0]);
1.294 + for (TInt idx=0; idx<nExts; ++idx)
1.295 + {
1.296 + if (procName == TPtrC8(reinterpret_cast<TUint8*>(KEglExtensionFuncs[idx].iName)))
1.297 + {
1.298 + return KEglExtensionFuncs[idx].iProc;
1.299 + }
1.300 + }
1.301 +
1.302 + // not an EGL extension, pass it on to OWF
1.303 + //
1.304 + return iOwfFuncTable.iOwfGetProcAddress ? iOwfFuncTable.iOwfGetProcAddress(aName) : NULL;
1.305 + }