guestrendering/vghwutils/src/vghwutils.cpp
branchbug235_bringup_0
changeset 51 4f400a6ea71f
parent 49 3b4f7e9d873f
child 52 39e5f73667ba
equal deleted inserted replaced
49:3b4f7e9d873f 51:4f400a6ea71f
     1 // Copyright (c) 2010 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 
       
    15 
       
    16 #include <e32atomics.h>
       
    17 #include <e32debug.h>
       
    18 
       
    19 #include <graphics/guestvideodriver.h>
       
    20 
       
    21 #include "vghwutils.h"
       
    22 #include "eglrfc.h"
       
    23 #include "openvgrfc.h"
       
    24 #include "opengles11rfc.h"
       
    25 
       
    26 #ifdef _DEBUG
       
    27 #define EGL_ERROR_PRINT(T, E)  EglErrorPrint(T, E)
       
    28 #define GLES_ERROR_PRINT(T, E) GlesErrorPrint(T, E)
       
    29 #define VG_ERROR_PRINT(T, E)   VgErrorPrint(T, E)
       
    30 static void EglErrorPrint(char* aTitle, EGLint aEglError);
       
    31 static void GlesErrorPrint(char* aTitle, GLenum aGlesError);
       
    32 static void VgErrorPrint(char* aTitle, VGErrorCode aVgError);
       
    33 #else
       
    34 #define EGL_ERROR_PRINT(T, E)
       
    35 #define GLES_ERROR_PRINT(T, E)
       
    36 #define VG_ERROR_PRINT(T, E)
       
    37 #endif
       
    38 
       
    39 
       
    40 // Min & Max sizes for creating Memory Heap for Guest Graphics DLLs
       
    41 #define KVghwHeapMin 0x1000
       
    42 #define KVghwHeapMax 0x100000
       
    43 
       
    44 
       
    45 // protection against concurrent initialisation from multiple threads
       
    46 volatile TBool       CVghwUtils::iInitialized = EFalse;
       
    47 TInt                 CVghwUtils::iVghwInitMutex = 0;
       
    48 
       
    49 // static member objects - Writeable Static Data
       
    50 RGuestVideoDriver* CVghwUtils::iDriver = NULL;
       
    51 RHeap*               CVghwUtils::iHeap = NULL;
       
    52 MEglManagementApi*   CVghwUtils::iEglManagementApi = NULL;
       
    53 MVgApiForEgl*        CVghwUtils::iVgApiForEgl = NULL;
       
    54 MGles11ApiForEgl*    CVghwUtils::iGles11ApiForEgl = NULL;
       
    55 MGles2ApiForEgl*     CVghwUtils::iGles2ApiForEgl = NULL;
       
    56 TBool                CVghwUtils::iLoadedOpenVgDll = EFalse;
       
    57 TBool                CVghwUtils::iLoadedOpenGles11Dll = EFalse;
       
    58 TBool                CVghwUtils::iLoadedOpenGles2Dll = EFalse;	
       
    59 
       
    60 
       
    61 
       
    62 _LIT(KVghwPanicCategory, "Guest VGHW");
       
    63 
       
    64 
       
    65 // NOTE: Exported because some VGHW functions are inline and could Assert & Panic from somewhere else
       
    66 EXPORT_C void VghwPanic(TVghwPanic aPanicCode, char* aPanicName, char* aCondition, char* aFile, TInt aLine)
       
    67 	{
       
    68 	if (aCondition && aFile)
       
    69 		{
       
    70 		RDebug::Printf("VghwUtils Panic %s for failed Assert (%s), at %s:%d", aPanicName, aCondition, aFile, aLine);
       
    71 		}
       
    72 	else
       
    73 		{  
       
    74 		RDebug::Printf("VghwUtils Panic %d for failed Assert (line %d)", aPanicCode, aLine);
       
    75 		}
       
    76 		
       
    77 	User::Panic(KVghwPanicCategory, aPanicCode);
       
    78 	}
       
    79 
       
    80 // inline functions
       
    81 
       
    82 RGuestVideoDriver& CVghwUtils::Driver()
       
    83 	{
       
    84 	// TODO remove this later in refactoring - Open VG & GL ES commands should not reach here before EGL has initialized the singleton
       
    85 	if (!iInitialized || !iDriver)
       
    86 		{
       
    87 		UTIL_TRACE("CVghwUtils::Driver called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
    88 		InitStatics();
       
    89 		}
       
    90 	VGHWPANIC_ASSERT(iInitialized && iDriver, EVghwPanicGraphicsDriverNotOpen);
       
    91 	return *iDriver;
       
    92 	}
       
    93 
       
    94 
       
    95 EXPORT_C void CVghwUtils::DestroyStatics()
       
    96 	{
       
    97 #ifdef _DEBUG
       
    98 	TUint64 processId = RProcess().Id().Id();
       
    99 	TUint64 threadId = RThread().Id().Id();
       
   100 	UTIL_TRACE("CVghwUtils::DestroyStatics iInitialized=%d, iDriver=0x%x, iHeap=0x%x, Process=0x%lx, Thread=0x%lx",
       
   101 		iInitialized, iDriver, iHeap, processId, threadId);
       
   102 #endif
       
   103 	if (iHeap)
       
   104 		{
       
   105 		if (iDriver)
       
   106 			{
       
   107 			iDriver->Flush();
       
   108 			iDriver->Close();
       
   109 			RHeap* threadHeap = SwitchToVghwHeap();
       
   110 			delete iDriver;
       
   111 			SwitchFromVghwHeap(threadHeap);
       
   112 			iDriver = NULL;
       
   113 			}
       
   114 		iHeap->Reset();
       
   115 		iHeap->Close();
       
   116 		iHeap = NULL;
       
   117 		}
       
   118 	if (iInitialized)
       
   119 		{
       
   120 		iInitialized = EFalse;
       
   121 		}
       
   122 	}
       
   123 
       
   124 
       
   125 // Ensure Graphics memory heap is created, and Open driver channel
       
   126 EXPORT_C void CVghwUtils::InitStatics()
       
   127 	{
       
   128 #ifdef _DEBUG
       
   129 	TUint64 processId = RProcess().Id().Id();
       
   130 	TUint64 threadId = RThread().Id().Id();
       
   131 	UTIL_TRACE("CVghwUtils::InitStatics start Process=0x%lx, Thread=0x%lx, iInitialized=%d",
       
   132 		processId, threadId, iInitialized);
       
   133 #endif
       
   134 	// bootstrap creation of mutexes and Graphics memory heap
       
   135 	while (!iInitialized)
       
   136 		{
       
   137 		TInt creationError = KErrNone;
       
   138 		// thread safe initialization
       
   139 		// LockedDec() returns the value prior to decrement
       
   140 		if (0 != User::LockedDec(iVghwInitMutex))
       
   141 			{
       
   142 			User::AfterHighRes(1000);     // Yield X microseconds, review length if code is changed
       
   143 			}
       
   144 		else
       
   145 			{
       
   146 			// volatile attribute forces rereading of the pointer, in case another thread has done the allocation
       
   147 			if (!iInitialized)
       
   148 				{ // loop style init exits if any stage fails, and gives per step debug logging
       
   149 				TInt step = 0;
       
   150 				do
       
   151 					{
       
   152 					switch (step)
       
   153 						{
       
   154 						case 0:
       
   155 							// guarantee that initialisation of the object is flushed before the pointer is published
       
   156 							__e32_atomic_store_rel_ptr(&iHeap, User::ChunkHeap(NULL, KVghwHeapMin, KVghwHeapMax));
       
   157 							if (!iHeap)
       
   158 								{
       
   159 								creationError = KErrNoMemory;
       
   160 								}
       
   161 							break;
       
   162 						case 1:
       
   163 							{
       
   164 							VGHWPANIC_ASSERT_DEBUG(iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   165 							RHeap* threadHeap = User::SwitchHeap(iHeap); // switch to VGHW graphics Heap
       
   166 							iDriver = new RGuestVideoDriver();
       
   167 							if (!iDriver)
       
   168 								{
       
   169 								creationError = KErrNoMemory;
       
   170 								}
       
   171 							User::SwitchHeap(threadHeap); // switch back to client Heap
       
   172 							}
       
   173 							break;
       
   174 						case 2:
       
   175 							creationError = User::LoadLogicalDevice(_L("guestvideohw"));
       
   176 							if ( (KErrNone == creationError) || (KErrAlreadyExists == creationError) )
       
   177 								{
       
   178 								creationError = iDriver->Open();
       
   179 								}
       
   180 							break;
       
   181 						default: // all initialisation steps completed
       
   182 							iInitialized = ETrue;
       
   183 						}
       
   184 					++step;
       
   185 					}
       
   186 				while (!iInitialized && !creationError);
       
   187 				UTIL_TRACE("CVghwUtils::InitStatics %s step=%d; creationError=%d, iInitialized=%d, iDriver=0x%x, iHeap=0x%x",
       
   188 						creationError ? "failed at" : "completed", step, creationError, iInitialized, iDriver, iHeap);
       
   189 				}
       
   190 			}
       
   191 		User::LockedInc(iVghwInitMutex);
       
   192 
       
   193 		VGHWPANIC_ASSERT(creationError == KErrNone, EVghwPanicInitializeFailed);
       
   194 		}
       
   195 	}
       
   196 
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // 
       
   200 // -----------------------------------------------------------------------------
       
   201 //
       
   202 EXPORT_C void CVghwUtils::DriverExecuteCommand(RemoteFunctionCallData& aRequestData)
       
   203 	{
       
   204 	if (!iInitialized || !iDriver)
       
   205 		{
       
   206 		UTIL_TRACE("CVghwUtils::DriverExecuteCommand called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   207 		InitStatics();
       
   208 		}
       
   209 	VGHWPANIC_ASSERT(iInitialized && iDriver, EVghwPanicGraphicsDriverNotOpen);
       
   210 	iDriver->ExecuteCommand(aRequestData);
       
   211 	}
       
   212 
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // Use driver to discover linear memory address of chunk.
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 EXPORT_C TInt CVghwUtils::MapToHWAddress( const TInt aChunkHandle, TUint32& aHWAddress )
       
   219 	{
       
   220 	UTIL_TRACE("CVghwUtils::MapToHWAddress");
       
   221 	return Driver().MapToHWAddress( aChunkHandle, aHWAddress );
       
   222 	}
       
   223 
       
   224 
       
   225 // SgImage support function - get underlying VGImage & Pbuffer handles
       
   226 EXPORT_C TInt CVghwUtils::EglGetSgHandles( const TUint64 aId, TUint64 *aSgHandles )
       
   227 	{
       
   228 	UTIL_TRACE("CVghwUtils::EglGetSgHandles");
       
   229 	return Driver().EglGetSgHandles( aId, aSgHandles );
       
   230 	}
       
   231 
       
   232 
       
   233 // Memory Heap Management functions
       
   234 
       
   235 EXPORT_C TAny* CVghwUtils::Alloc(TInt aSize)
       
   236 	{
       
   237 	if (!iInitialized || !iHeap)
       
   238 		{
       
   239 		UTIL_TRACE("CVghwUtils::Alloc called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   240 		InitStatics();
       
   241 		}
       
   242 	VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   243 	return iHeap->Alloc(aSize);
       
   244 	}
       
   245 
       
   246 
       
   247 EXPORT_C void CVghwUtils::Free(TAny* aPtr)
       
   248 	{
       
   249 	if (!iInitialized || !iHeap)
       
   250 		{
       
   251 		UTIL_TRACE("CVghwUtils::Free called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   252 		InitStatics();
       
   253 		}
       
   254 	VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   255 	iHeap->Free(aPtr);
       
   256 	}
       
   257 
       
   258 
       
   259 EXPORT_C RHeap* CVghwUtils::GetHeap()
       
   260 	{
       
   261 	if (!iInitialized || !iHeap)
       
   262 		{
       
   263 		UTIL_TRACE("CVghwUtils::GetHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   264 		InitStatics();
       
   265 		}
       
   266 	VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   267 	return iHeap;
       
   268 	}
       
   269 
       
   270 
       
   271 // Switch to VGHW Memory Heap.
       
   272 EXPORT_C RHeap* CVghwUtils::SwitchToVghwHeap()
       
   273 	{
       
   274 	if (!iInitialized || !iHeap)
       
   275 		{
       
   276 		UTIL_TRACE("CVghwUtils::SwitchToVghwHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   277 		InitStatics();
       
   278 		}
       
   279 	VGHWPANIC_ASSERT(iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   280 	RHeap* oldHeap = User::SwitchHeap(iHeap); // switch to Guest graphics heap
       
   281 	VGHWPANIC_ASSERT(oldHeap != iHeap, EVghwPanicSwitchToVghwHeapOldHeapIsVghwHeap);
       
   282 	return oldHeap;
       
   283 	}
       
   284 
       
   285 
       
   286 // Switch back to original heap 
       
   287 EXPORT_C void CVghwUtils::SwitchFromVghwHeap(RHeap* aOldHeapPtr)
       
   288 	{
       
   289 	if (!iInitialized || !iHeap)
       
   290 		{
       
   291 		UTIL_TRACE("CVghwUtils::SwitchFromVghwHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   292 		InitStatics();
       
   293 		}
       
   294 	VGHWPANIC_ASSERT(iHeap, EVghwPanicVghwHeapDoesNotExist);
       
   295 	VGHWPANIC_ASSERT(aOldHeapPtr, EVghwPanicSwitchFromVghwHeapParamIsNull);
       
   296 	VGHWPANIC_ASSERT(aOldHeapPtr != iHeap, EVghwPanicSwitchFromVghwHeapParamIsVghwHeap);
       
   297 
       
   298 	RHeap* oldHeap = User::SwitchHeap(aOldHeapPtr); // switch from Guest graphics heap back to thread heap
       
   299 	VGHWPANIC_ASSERT(oldHeap == iHeap, EVghwPanicSwitchFromVghwHeapOldHeapIsNotVghwHeap);
       
   300 	}
       
   301 
       
   302 
       
   303 // if this thread does not have an object try to alloc a new one
       
   304 EXPORT_C TEglThreadState* CVghwUtils::CreateThreadState()
       
   305 	{
       
   306 	TEglThreadState* threadState = reinterpret_cast<TEglThreadState*>(Dll::Tls());
       
   307 	if (!threadState)
       
   308 		{
       
   309 		UTIL_TRACE("CVghwUtils::CreateThreadState - object is currently 0x%x, iInitialized=%d",
       
   310 				threadState, iInitialized);
       
   311 		if (!iInitialized)
       
   312 			{
       
   313 			InitStatics();
       
   314 			}
       
   315 		threadState = TEglThreadState::New();
       
   316 		Dll::SetTls(threadState);
       
   317 		}
       
   318 	return threadState;
       
   319 	}
       
   320 
       
   321 
       
   322 // current state object, if any, for this thread
       
   323 EXPORT_C TEglThreadState* CVghwUtils::EglThreadState()
       
   324 	{
       
   325 	TEglThreadState* threadState = reinterpret_cast<TEglThreadState*>(Dll::Tls());
       
   326 	return threadState;
       
   327 	}
       
   328 
       
   329 
       
   330 // current state object, if Open VG is the current bound API, for this thread 
       
   331 EXPORT_C MVgContext* CVghwUtils::VgContext()
       
   332 	{
       
   333 	TEglThreadState* threadState = reinterpret_cast<TEglThreadState*>(Dll::Tls());
       
   334 	return threadState;
       
   335 	// ToDo sort this to check for valid Open VG context
       
   336 	/*
       
   337 	if (threadState && threadState->VgEglContext())
       
   338 		return threadState;
       
   339 	return NULL;
       
   340 	*/
       
   341 	}
       
   342 
       
   343 
       
   344 // current state object, if Open GL ES is the current bound API, for this thread (for EGL)
       
   345 EXPORT_C MGlesContext* CVghwUtils::GlesContext()
       
   346 	{
       
   347 	TEglThreadState* threadState = reinterpret_cast<TEglThreadState*>(Dll::Tls());
       
   348 	return threadState;
       
   349 	// ToDo sort this to check for valid Open GL ES context
       
   350 	/*
       
   351 	if (threadState && threadState->GlesEglContext())
       
   352 		return threadState;
       
   353 	return NULL; */
       
   354 	}
       
   355 
       
   356 
       
   357 // free current state object, if any, for this thread
       
   358 EXPORT_C void CVghwUtils::ReleaseThreadState()
       
   359 	{
       
   360 	TEglThreadState* threadState = reinterpret_cast<TEglThreadState*>(Dll::Tls());
       
   361 	UTIL_TRACE("CVghwUtils::ReleaseThreadState - object = 0x%x", threadState);
       
   362 	if (threadState)
       
   363 		{
       
   364 		threadState->Destroy();
       
   365 		Dll::FreeTls();
       
   366 		}
       
   367 	}
       
   368 
       
   369 
       
   370 EXPORT_C MEglManagementApi* CVghwUtils::EglManagementApi()
       
   371 	{
       
   372 	return iEglManagementApi;
       
   373 	}
       
   374 
       
   375 
       
   376 EXPORT_C void CVghwUtils::SetEglManagementApi(MEglManagementApi* aEglManagementApi)
       
   377 	{
       
   378 	UTIL_TRACE("CVghwUtils::SetEglManagementApi  aEglManagementApi=0x%x", aEglManagementApi);
       
   379 	iEglManagementApi = aEglManagementApi;
       
   380 	}
       
   381 
       
   382 
       
   383 /*
       
   384  Stored pointers into Open GL ES 1.1, GL ES 2 and Open VG are problematic if the DLL is later unloaded.
       
   385  (RSgDriver::Open currently loads & unloads all the Open VG & GL ES DLLs, to determine features to publish.)
       
   386  Possibly Open the DLL again when the non-NULL pointer is fetched by EGL, probably needs flags so that
       
   387  this is only done once.
       
   388  */
       
   389 EXPORT_C void CVghwUtils::SetVgApiForEgl(MVgApiForEgl* aVgApiForEgl)
       
   390 	{
       
   391 	UTIL_TRACE("CVghwUtils::SetVgApiForEgl  aVgApiForEgl=0x%x, iVgApiForEgl=0x%x, iLoadedOpenVgDll=0x%x",
       
   392 			aVgApiForEgl, iVgApiForEgl, iLoadedOpenVgDll);
       
   393 	// don't let a thread set this to NULL if we have forced the DLL to stay loaded
       
   394 	if (aVgApiForEgl || !iLoadedOpenVgDll)
       
   395 		{
       
   396 		iVgApiForEgl = aVgApiForEgl;
       
   397 		}
       
   398 	}
       
   399 
       
   400 
       
   401 EXPORT_C MVgApiForEgl* CVghwUtils::VgApiForEgl()
       
   402 	{
       
   403 	if (iVgApiForEgl && !iLoadedOpenVgDll)
       
   404 		{ // ensure Open VG DLL stays loaded from now on
       
   405 		_LIT(KLibOpenVg, "libOpenVG.dll");
       
   406 		RLibrary lib;
       
   407 		if (lib.Load(KLibOpenVg) == KErrNone)
       
   408 			{
       
   409 			UTIL_TRACE("CVghwUtils::VgApiForEgl - Open VG dll loaded, iVgApiForEgl=0x%x", iVgApiForEgl);
       
   410 			iLoadedOpenVgDll = ETrue;
       
   411 			return iVgApiForEgl;
       
   412 			}
       
   413 		}
       
   414 	UTIL_TRACE("CVghwUtils::VgApiForEgl - Open VG dll not loaded or not safe to use");
       
   415 	return NULL;
       
   416 	}
       
   417 
       
   418 
       
   419 EXPORT_C void CVghwUtils::SetGles11ApiForEgl(MGles11ApiForEgl* aGles11ApiForEgl)
       
   420 	{
       
   421 	UTIL_TRACE("CVghwUtils::SetGles11ApiForEgl  aGles11ApiForEgl=0x%x, iGles11ApiForEgl=0x%x, iLoadedOpenGles11Dll=0x%x",
       
   422 			aGles11ApiForEgl, iGles11ApiForEgl, iLoadedOpenGles11Dll);
       
   423 	// don't let a thread set this to NULL if we have forced the DLL to stay loaded
       
   424 	if (aGles11ApiForEgl || !iLoadedOpenGles11Dll)
       
   425 		{
       
   426 		iGles11ApiForEgl = aGles11ApiForEgl;
       
   427 		}
       
   428 	}
       
   429 
       
   430 
       
   431 EXPORT_C MGles11ApiForEgl* CVghwUtils::Gles11ApiForEgl()
       
   432 	{
       
   433 	if (iGles11ApiForEgl && !iLoadedOpenGles11Dll)
       
   434 		{ // ensure Open VG DLL stays loaded from now on
       
   435 		_LIT(KLibOpenGles, "libGLESv1_CM.dll");
       
   436 		RLibrary lib;
       
   437 		if (lib.Load(KLibOpenGles) == KErrNone)
       
   438 			{
       
   439 			UTIL_TRACE("CVghwUtils::Gles11ApiForEgl - Open GL ES 1.1 dll loaded, iGles11ApiForEgl=0x%x", iGles11ApiForEgl);
       
   440 			iLoadedOpenGles11Dll = ETrue;
       
   441 			return iGles11ApiForEgl;
       
   442 			}
       
   443 		}
       
   444 	UTIL_TRACE("CVghwUtils::Gles11ApiForEgl - Open GL ES 1.1 dll not loaded or not safe to use");
       
   445 	return NULL;
       
   446 	}
       
   447 
       
   448 
       
   449 EXPORT_C void CVghwUtils::SetGles2ApiForEgl(MGles2ApiForEgl* aGles2ApiForEgl)
       
   450 	{
       
   451 	UTIL_TRACE("CVghwUtils::SetGles2ApiForEgl  aGles2ApiForEgl=0x%x, iGles2ApiForEgl=0x%x, iLoadedOpenGles2Dll=0x%x",
       
   452 			aGles2ApiForEgl, iGles2ApiForEgl, iLoadedOpenGles2Dll);
       
   453 	// don't let a thread set this to NULL if we have forced the DLL to stay loaded
       
   454 	if (aGles2ApiForEgl || !iLoadedOpenGles2Dll)
       
   455 		{
       
   456 		iGles2ApiForEgl = aGles2ApiForEgl;
       
   457 		}
       
   458 	}
       
   459 
       
   460 
       
   461 EXPORT_C MGles2ApiForEgl* CVghwUtils::Gles2ApiForEgl()
       
   462 	{
       
   463 	if (iGles2ApiForEgl && !iLoadedOpenGles2Dll)
       
   464 		{ // ensure Open VG DLL stays loaded from now on
       
   465 		_LIT(KLibOpenGles2, "libGLESv2.dll");
       
   466 		RLibrary lib;
       
   467 		if (lib.Load(KLibOpenGles2) == KErrNone)
       
   468 			{
       
   469 			UTIL_TRACE("CVghwUtils::Gles2ApiForEgl - Open GL ES 2 dll loaded, iGles2ApiForEgl=0x%x", iGles2ApiForEgl);
       
   470 			iLoadedOpenGles2Dll = ETrue;
       
   471 			return iGles2ApiForEgl;
       
   472 			}
       
   473 		}
       
   474 	UTIL_TRACE("CVghwUtils::Gles2ApiForEgl - Open GL ES 2 dll not loaded or not safe to use");
       
   475 	return NULL;
       
   476 	}
       
   477 
       
   478 
       
   479 ////////////////////////////////////////////////////////////////////////////////////
       
   480 
       
   481 // factory method
       
   482 TEglThreadState* TEglThreadState::New()
       
   483 	{
       
   484 	UTIL_TRACE("TEglThreadState::New");
       
   485 	RHeap* currentHeap = CVghwUtils::SwitchToVghwHeap();
       
   486 	TEglThreadState* self = new TEglThreadState();
       
   487 	CVghwUtils::SwitchFromVghwHeap(currentHeap);
       
   488 	return self;
       
   489 	}
       
   490 
       
   491 
       
   492 TEglThreadState::TEglThreadState() :
       
   493 	// EGL thread state
       
   494 	iEglError(EGL_SUCCESS),
       
   495 	iEglHostHasRecentError(EFalse),
       
   496 	// currently bound graphics API, initial value from EGL spec 
       
   497 	iEglBoundApi(EGL_OPENGL_ES_API),
       
   498 	// Open VG thread state 
       
   499 	iVgError(VG_NO_ERROR),
       
   500 	iVgEglContext(EGL_NO_CONTEXT),
       
   501 	iVgCommandsSinceGetError(EFalse),
       
   502 	iVgCommandsSinceFlush(EFalse),
       
   503 	iVgCommandsSinceFinish(EFalse),
       
   504 	// Open GL ES 1.1 state
       
   505 	iGlesError(GL_NO_ERROR),
       
   506 	iGlesEglContext(EGL_NO_CONTEXT),
       
   507 	iGlesCommandsSinceGetError(EFalse),
       
   508 	iGlesCommandsSinceFlush(EFalse),
       
   509 	iGlesCommandsSinceFinish(EFalse)
       
   510 	{}
       
   511 
       
   512 
       
   513 void TEglThreadState::Destroy()
       
   514 	{
       
   515 	UTIL_TRACE("TEglThreadState::Destroy");
       
   516 	RHeap* currentHeap = CVghwUtils::SwitchToVghwHeap();
       
   517 	delete this;
       
   518 	CVghwUtils::SwitchFromVghwHeap(currentHeap);
       
   519 	}
       
   520 
       
   521 
       
   522 TEglThreadState::~TEglThreadState()
       
   523 	{}
       
   524 
       
   525 
       
   526 // -----------------------------------------------------------------------------
       
   527 // 
       
   528 // -----------------------------------------------------------------------------
       
   529 //
       
   530 EXPORT_C EGLBoolean TEglThreadState::ExecEglBooleanCmd(EglRFC& aEglApiData)
       
   531 	{
       
   532 	CVghwUtils::DriverExecuteCommand(aEglApiData.Data());
       
   533 
       
   534 	EGLBoolean hostResult = (EGLBoolean) aEglApiData.ReturnValue();
       
   535 	if (hostResult == EGL_TRUE)
       
   536 		{
       
   537 		ClearEglError();
       
   538 		}
       
   539 	else
       
   540 		{ // error present in host graphics stack
       
   541 		iEglHostHasRecentError = ETrue;
       
   542 		}
       
   543 	return hostResult;
       
   544 	}
       
   545 
       
   546 
       
   547 EXPORT_C EGLContext TEglThreadState::ExecEglContextCmd(EglRFC& aEglApiData)
       
   548 	{
       
   549 	CVghwUtils::DriverExecuteCommand(aEglApiData.Data());
       
   550 
       
   551 	EGLContext hostResult = (EGLContext) aEglApiData.ReturnValue();
       
   552 	if (hostResult != EGL_NO_CONTEXT)
       
   553 		{
       
   554 		ClearEglError();
       
   555 		}
       
   556 	else
       
   557 		{ // error present in host graphics stack
       
   558 		iEglHostHasRecentError = ETrue;
       
   559 		}
       
   560 	return hostResult;
       
   561 	}
       
   562 
       
   563 
       
   564 EXPORT_C EGLSurface TEglThreadState::ExecEglSurfaceCmd(EglRFC& aEglApiData)
       
   565 	{
       
   566 	CVghwUtils::DriverExecuteCommand(aEglApiData.Data());
       
   567 
       
   568 	EGLSurface hostResult = (EGLSurface) aEglApiData.ReturnValue();
       
   569 	if (hostResult != EGL_NO_SURFACE)
       
   570 		{
       
   571 		ClearEglError();
       
   572 		}
       
   573 	else
       
   574 		{ // error present in host graphics stack
       
   575 		iEglHostHasRecentError = ETrue;
       
   576 		}
       
   577 	return hostResult;
       
   578 	}
       
   579 
       
   580 
       
   581 /*
       
   582  Get details of the last EGL api error.
       
   583  (Resets stored last error value to EGL_SUCCESS.)
       
   584 
       
   585  @return EGL_SUCCESS or an EGL_xxxx error constant.
       
   586  */
       
   587 EXPORT_C EGLint TEglThreadState::EglError()
       
   588 	{
       
   589 	EGLint eglError = iEglError;
       
   590 	if (iEglHostHasRecentError)
       
   591 		{
       
   592 		// last EGL command was executed/failed in the Host side, so need to ask it for the error
       
   593 		RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata);
       
   594 		eglApiData.Init(EglRFC::EeglGetError);
       
   595 		CVghwUtils::DriverExecuteCommand(eglApiData.Data());
       
   596 		eglError = (EGLint)eglApiData.ReturnValue();
       
   597 		EGL_ERROR_PRINT("TEglThreadState::EglError newest error fetched from Host EGL", eglError);
       
   598 		iEglHostHasRecentError = EFalse;
       
   599 		}
       
   600 	else
       
   601 		{
       
   602 		EGL_ERROR_PRINT("TEglThreadState::EglError newest EGL error set by DLL", eglError);
       
   603 		}
       
   604 	iEglError = EGL_SUCCESS;
       
   605 	return eglError;
       
   606 	}
       
   607 
       
   608 
       
   609 void TEglThreadState::ExecuteVgCommand(OpenVgRFC& aVgApiData)
       
   610 	{
       
   611 	CVghwUtils::DriverExecuteCommand(aVgApiData.Data());
       
   612 	iVgCommandsSinceGetError = ETrue;
       
   613 	iVgCommandsSinceFlush = ETrue;
       
   614 	iVgCommandsSinceFinish = ETrue;
       
   615 	}
       
   616 
       
   617 
       
   618 void TEglThreadState::ExecuteVgFlushCommand()
       
   619 	{
       
   620 	if (iVgCommandsSinceFlush)
       
   621 		{
       
   622 		RemoteFunctionCallData data; OpenVgRFC vgApiData(data);
       
   623 		vgApiData.Init(OpenVgRFC::EvgFlush);
       
   624 
       
   625 		CVghwUtils::DriverExecuteCommand(vgApiData.Data());
       
   626 		iVgCommandsSinceFlush = EFalse;
       
   627 		iVgCommandsSinceFinish = EFalse;
       
   628 		}
       
   629 	}
       
   630 
       
   631 
       
   632 void TEglThreadState::ExecuteVgFinishCommand()
       
   633 	{
       
   634 	if (iVgCommandsSinceFinish)
       
   635 		{
       
   636 		RemoteFunctionCallData data; OpenVgRFC vgApiData(data);
       
   637 		vgApiData.Init(OpenVgRFC::EvgFinish);
       
   638 
       
   639 		CVghwUtils::DriverExecuteCommand(vgApiData.Data());
       
   640 		iVgCommandsSinceFinish = EFalse;
       
   641 		}
       
   642 	}
       
   643 
       
   644 
       
   645 VGErrorCode TEglThreadState::VgError()
       
   646 	{
       
   647 	VGErrorCode vgError = iVgError;
       
   648 	VG_ERROR_PRINT("TEglThreadState::VgError oldest Open VG DLL error", vgError);
       
   649 
       
   650 	if (iVgCommandsSinceGetError)
       
   651 		{ // fetch and clear the host error state
       
   652 		VGErrorCode hostVgError = GetHostVgError();
       
   653 		VG_ERROR_PRINT("TEglThreadState::VgError oldest Host Open VG DLL error", hostVgError);
       
   654 
       
   655 		if (vgError == VG_NO_ERROR)
       
   656 			{
       
   657 			vgError = hostVgError;
       
   658 			}
       
   659 		iVgCommandsSinceGetError = EFalse;
       
   660 		}
       
   661 
       
   662 	iVgError = VG_NO_ERROR;
       
   663 	return vgError;
       
   664 	}
       
   665 
       
   666 
       
   667 VGErrorCode TEglThreadState::GetHostVgError()
       
   668 	{
       
   669 	RemoteFunctionCallData data; OpenVgRFC vgApiData(data);
       
   670 	vgApiData.Init( OpenVgRFC::EvgGetError );
       
   671 
       
   672 	CVghwUtils::DriverExecuteCommand(vgApiData.Data());
       
   673 	return (VGErrorCode)vgApiData.ReturnValue();
       
   674 	}
       
   675 
       
   676 
       
   677 // Open GL ES
       
   678 
       
   679 GLenum TEglThreadState::GlesError()
       
   680 	{
       
   681 	GLenum glesError = iGlesError;
       
   682 	GLES_ERROR_PRINT("TEglThreadState::GlesError oldest Open GL ES DLL error", glesError);
       
   683 
       
   684 	if (iGlesCommandsSinceGetError)
       
   685 		{ // fetch and clear the host error state
       
   686 		GLenum hostGlesError = GetHostGlesError();
       
   687 		GLES_ERROR_PRINT("TEglThreadState::GlesError oldest Host Open GL ES DLL error", hostGlesError);
       
   688 
       
   689 		if (glesError == GL_NO_ERROR)
       
   690 			{
       
   691 			glesError = hostGlesError;
       
   692 			}
       
   693 		iGlesCommandsSinceGetError = EFalse;
       
   694 		}
       
   695 
       
   696 	iGlesError = GL_NO_ERROR;
       
   697 	return glesError;
       
   698 	}
       
   699 
       
   700 
       
   701 GLenum TEglThreadState::GetHostGlesError()
       
   702 	{
       
   703 	RemoteFunctionCallData data;
       
   704 	OpenGlES11RFC glesApiData(data);
       
   705 	glesApiData.Init(OpenGlES11RFC::EglGetError);
       
   706 	CVghwUtils::DriverExecuteCommand(glesApiData.Data());
       
   707 	return (GLint)glesApiData.ReturnValue();
       
   708 	}
       
   709 
       
   710 
       
   711 void TEglThreadState::ExecuteGlesCommand(RemoteFunctionCall& aGlesRequestData)
       
   712 	{
       
   713 	CVghwUtils::DriverExecuteCommand(aGlesRequestData.Data());
       
   714 	iGlesCommandsSinceGetError = ETrue;
       
   715 	iGlesCommandsSinceFlush = ETrue;
       
   716 	iGlesCommandsSinceFinish = ETrue;
       
   717 	}
       
   718 
       
   719 
       
   720 void TEglThreadState::ExecuteGlesFlushCommand()
       
   721 	{
       
   722 	if (iGlesCommandsSinceFlush)
       
   723 		{
       
   724 		RemoteFunctionCallData rfcData;
       
   725 		OpenGlES11RFC glesApiData( rfcData );
       
   726 		glesApiData.Init(OpenGlES11RFC::EglFlush, RemoteFunctionCallData::EOpRequest);
       
   727 		CVghwUtils::DriverExecuteCommand(glesApiData.Data());
       
   728 		iGlesCommandsSinceFlush = EFalse;
       
   729 		iGlesCommandsSinceFinish = EFalse;
       
   730 		}
       
   731 	}
       
   732 
       
   733 
       
   734 void TEglThreadState::ExecuteGlesFinishCommand()
       
   735 	{
       
   736 	if (iGlesCommandsSinceFinish)
       
   737 		{
       
   738 		RemoteFunctionCallData rfcData;
       
   739 		OpenGlES11RFC glesApiData( rfcData );
       
   740 		glesApiData.Init(OpenGlES11RFC::EglFinish, RemoteFunctionCallData::EOpRequest);
       
   741 		CVghwUtils::DriverExecuteCommand(glesApiData.Data());
       
   742 		iGlesCommandsSinceFinish = EFalse;
       
   743 		}
       
   744 	}
       
   745 
       
   746 
       
   747 // Open VG state
       
   748 void TEglThreadState::SetVgError(VGErrorCode aVgError)
       
   749 	{
       
   750 	VGHWPANIC_ASSERT_DEBUG( (aVgError >= VG_BAD_HANDLE_ERROR) && (aVgError <= 0x10FF), EVghwPanicBadVgErrorValue);
       
   751 	// for Open VG track the oldest uncleared error
       
   752 	VG_ERROR_PRINT("TEglThreadState::SetVgError error", aVgError);
       
   753 	if ( (iVgError == VG_NO_ERROR) && (aVgError >= VG_BAD_HANDLE_ERROR) && (aVgError <= 0x10FF) )
       
   754 		{
       
   755 		if (iVgCommandsSinceGetError)
       
   756 			{
       
   757 			iVgError = GetHostVgError();
       
   758 			VG_ERROR_PRINT("TEglThreadState::SetVgError oldest Host Open VG DLL error", iVgError);
       
   759 			if (iVgError != VG_NO_ERROR)
       
   760 				{
       
   761 				return;
       
   762 				}
       
   763 			}
       
   764 		iVgError = aVgError;
       
   765 		}
       
   766 	}
       
   767 
       
   768 
       
   769 EGLContext TEglThreadState::VgEglContext()
       
   770 	{
       
   771 	return iVgEglContext;
       
   772 	}
       
   773 
       
   774 
       
   775 // Open GL ES thread state
       
   776 void TEglThreadState::SetGlesError(GLenum aGlesError)
       
   777 	{
       
   778 	VGHWPANIC_ASSERT_DEBUG( (aGlesError >= GL_INVALID_ENUM) && (aGlesError <= 0x05FF), EVghwPanicBadGlesErrorValue);
       
   779 	// for Open GL ES track the oldest uncleared error
       
   780 	GLES_ERROR_PRINT("TEglThreadState::SetGlesError error", aGlesError);
       
   781 	if ( (iGlesError == GL_NO_ERROR) && (aGlesError >= GL_INVALID_ENUM) && (aGlesError <= 0x05FF) )
       
   782 		{
       
   783 		if (iGlesCommandsSinceGetError)
       
   784 			{
       
   785 			iGlesError = GetHostGlesError();
       
   786 			GLES_ERROR_PRINT("TEglThreadState::SetGlesError oldest Host Open GL ES DLL error", iGlesError);
       
   787 			if (iGlesError != GL_NO_ERROR)
       
   788 				{
       
   789 				return;
       
   790 				}
       
   791 			}
       
   792 		iGlesError = aGlesError;
       
   793 		}
       
   794 	}
       
   795 
       
   796 
       
   797 EGLContext TEglThreadState::GlesEglContext()
       
   798 	{
       
   799 	return iGlesEglContext;
       
   800 	}
       
   801 
       
   802 // -----------------------------------------------------------------------------
       
   803 // Use driver to discover base address of the surface memory.
       
   804 // -----------------------------------------------------------------------------
       
   805 //	  
       
   806 EXPORT_C TInt CVghwUtils::GetSurfaceBufferBaseAddress( TUint32& aHWAddress )
       
   807 	{
       
   808 	UTIL_TRACE("CVghwUtils::GetSurfaceBufferBaseAddress");
       
   809 	if (!iInitialized || !iDriver)
       
   810 		{
       
   811 		UTIL_TRACE("CVghwUtils::GetSurfaceBufferBaseAddress called before initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver);
       
   812 		InitStatics();
       
   813 		}
       
   814 	VGHWPANIC_ASSERT(iInitialized && iDriver, EVghwPanicGraphicsDriverNotOpen);
       
   815 	return iDriver->GetSurfaceBufferBaseAddress( aHWAddress );
       
   816 	}
       
   817 
       
   818 #ifdef _DEBUG
       
   819 static void EglErrorPrint(char* aTitle, EGLint aEglError)
       
   820 	{
       
   821 	char* errName = NULL;
       
   822 	switch (aEglError)
       
   823 		{
       
   824 		case EGL_SUCCESS: errName = "EGL_SUCCESS"; break;
       
   825 		case EGL_NOT_INITIALIZED: errName = "EGL_NOT_INITIALIZED"; break;
       
   826 		case EGL_BAD_ACCESS: errName = "EGL_BAD_ACCESS"; break;
       
   827 		case EGL_BAD_ALLOC: errName = "EGL_BAD_ALLOC"; break;
       
   828 		case EGL_BAD_ATTRIBUTE: errName = "EGL_BAD_ATTRIBUTE"; break;
       
   829 		case EGL_BAD_CONFIG: errName = "EGL_BAD_CONFIG"; break;
       
   830 		case EGL_BAD_CONTEXT: errName = "EGL_BAD_CONTEXT"; break;
       
   831 		case EGL_BAD_CURRENT_SURFACE: errName = "EGL_BAD_CURRENT_SURFACE"; break;
       
   832 		case EGL_BAD_DISPLAY: errName = "EGL_BAD_DISPLAY"; break;
       
   833 		case EGL_BAD_MATCH: errName = "EGL_BAD_MATCH"; break;
       
   834 		case EGL_BAD_NATIVE_PIXMAP: errName = "EGL_BAD_NATIVE_PIXMAP"; break;
       
   835 		case EGL_BAD_NATIVE_WINDOW: errName = "EGL_BAD_NATIVE_WINDOW"; break;
       
   836 		case EGL_BAD_PARAMETER: errName = "EGL_BAD_PARAMETER"; break;
       
   837 		case EGL_BAD_SURFACE: errName = "EGL_BAD_SURFACE"; break;
       
   838 		case EGL_CONTEXT_LOST: errName = "EGL_CONTEXT_LOST"; break;
       
   839 		default: break; // Error is from a new version of EGL
       
   840 		}
       
   841 
       
   842 	if (errName)
       
   843 		{
       
   844 		UTIL_TRACE( "  %s=%s (0x%x)", aTitle, errName, aEglError);
       
   845 		}
       
   846 	else
       
   847 		{
       
   848 		UTIL_TRACE( "  %s=0x%x", aTitle, aEglError);
       
   849 		}
       
   850 	}
       
   851 
       
   852 
       
   853 static void VgErrorPrint(char* aTitle, VGErrorCode aVgError)
       
   854 	{
       
   855 	char* errName = NULL;
       
   856 	switch (aVgError)
       
   857 		{
       
   858 		case VG_NO_ERROR: errName = "VG_NO_ERROR"; break;
       
   859 		case VG_BAD_HANDLE_ERROR: errName = "VG_BAD_HANDLE_ERROR"; break;
       
   860 		case VG_ILLEGAL_ARGUMENT_ERROR: errName = "VG_ILLEGAL_ARGUMENT_ERROR"; break;
       
   861 		case VG_OUT_OF_MEMORY_ERROR: errName = "VG_OUT_OF_MEMORY_ERROR"; break;
       
   862 		case VG_PATH_CAPABILITY_ERROR: errName = "VG_PATH_CAPABILITY_ERROR"; break;
       
   863 		case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR: errName = "VG_UNSUPPORTED_IMAGE_FORMAT_ERROR"; break;
       
   864 		case VG_UNSUPPORTED_PATH_FORMAT_ERROR: errName = "VG_UNSUPPORTED_PATH_FORMAT_ERROR"; break;
       
   865 		case VG_IMAGE_IN_USE_ERROR: errName = "VG_IMAGE_IN_USE_ERROR"; break;
       
   866 		case VG_NO_CONTEXT_ERROR: errName = "VG_NO_CONTEXT_ERROR"; break;
       
   867 		default: break; // unknown error code from a new version of Open VG
       
   868 		}
       
   869 
       
   870 	if (errName)
       
   871 		{
       
   872 		UTIL_TRACE( "  %s=%s (0x%x)", aTitle, errName, aVgError);
       
   873 		}
       
   874 	else
       
   875 		{
       
   876 		UTIL_TRACE( "  %s=0x%x", aTitle, aVgError);
       
   877 		}
       
   878 	}
       
   879 
       
   880 
       
   881 static void GlesErrorPrint(char* aTitle, GLenum aGlesError)
       
   882 	{
       
   883 	char* errName = NULL;
       
   884 	switch (aGlesError)
       
   885 		{
       
   886 		case GL_NO_ERROR: errName = "GL_NO_ERROR"; break;
       
   887 		case GL_INVALID_ENUM: errName = "GL_INVALID_ENUM"; break;
       
   888 		case GL_INVALID_VALUE: errName = "GL_INVALID_VALUE"; break;
       
   889 		case GL_INVALID_OPERATION: errName = "GL_INVALID_OPERATION"; break;
       
   890 		case GL_STACK_OVERFLOW: errName = "GL_STACK_OVERFLOW"; break;
       
   891 		case GL_STACK_UNDERFLOW: errName = "GL_STACK_UNDERFLOW"; break;
       
   892 		case GL_OUT_OF_MEMORY: errName = "GL_OUT_OF_MEMORY"; break;
       
   893 		default: break; // unknown error code from a new version of Open GL ES
       
   894 		}
       
   895 
       
   896 	if (errName)
       
   897 		{
       
   898 		UTIL_TRACE( "  %s=%s (0x%x)", aTitle, errName, aGlesError);
       
   899 		}
       
   900 	else
       
   901 		{
       
   902 		UTIL_TRACE( "  %s=0x%x", aTitle, aGlesError);
       
   903 		}
       
   904 	}
       
   905 #endif
       
   906 
       
   907 
       
   908 // end of file vghwutils.cpp