|
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 |