# HG changeset patch # User Faisal Memon # Date 1282846112 -3600 # Node ID ec0e558822c5d6130f630c207cbdf14a57fbe1a8 # Parent 65231b4e789af3914eae4a59b6019e556b5ced6a Add dynamic framebuffer support, and associated vghw utils needed. This code does not compile, and needs companion updates in graphics (3899db667a38) and qemu (c7e943dbf70f). Some code looks like syborg-specific so tagged with FAISALMEMON. Need to check with Jani on this. A later submission will declare when the code compiles again. diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/api/src/guestvideodriver.cpp --- a/guestrendering/guestvideodriver/api/src/guestvideodriver.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/api/src/guestvideodriver.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -223,6 +223,16 @@ } // ----------------------------------------------------------------------------- +// RGuestVideDriver::MapToHWAddress +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RGuestVideoDriver::GetFrameBufferBaseAddress( TUint32& aFrameBufferBaseAddress ) + { + TPckg address( aFrameBufferBaseAddress ); + return DoControl( GuestVideoDriver::ERequestFrameBaseAddress, (TAny*)&address ); + } + +// ----------------------------------------------------------------------------- // RGuestVideoDriver::EglGetSgHandles // ----------------------------------------------------------------------------- // diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp --- a/guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp Thu Aug 26 19:08:32 2010 +0100 @@ -30,6 +30,17 @@ OS_LAYER_ESTLIB_SYSTEMINCLUDE USERINCLUDE ../inc USERINCLUDE ../../commoninc + + +// This is a co-dependency between adaptation layer packages. This needs +// to be refactored in qemu to be a OS level export +USERINCLUDE ../../../../../qemu/baseport/syborg/specific + +// There is a weird depedency here to satisfy syborg to get to the flexible +// memory model for its syborg.h header +SYSTEMINCLUDE /epoc32/include/platform/memmodel/epoc/multiple/arm +SYSTEMINCLUDE /epoc32/include/platform/memmodel/epoc/moving + SYSTEMINCLUDE /epoc32/include/drivers SOURCEPATH ../src diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp --- a/guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -11,7 +11,7 @@ // Contributors: // // Description: -// Platsim video driver - request handler extension (a.k.a. Command Scheduler extension) +// Guest video driver - request handler extension (a.k.a. Command Scheduler extension) // #include diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -236,6 +236,14 @@ } break; } + case ERequestFrameBaseAddress: + { + TPhysAddr physicalAddress(0); + physicalAddress = iHwInterface.GetFrameBase(); + TPckgC address(physicalAddress); + err = Kern::ThreadDesWrite(aUserThread, a1, address, 0, 0, aUserThread); + break; + } #ifdef FAISALMEMON_S4_SGIMAGE case ERequestSgHandles: { diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -46,6 +46,8 @@ // Just set the version. using namespace GuestVideoDriver; iVersion = TVersion( KMajorVer, KMinorVer, KBuildVer ); + iHwInterface = new DVirtualVideoHwInterface; + Kern::Printf("DVirtualVideoHwDevice::DVirtualVideoHwDevice()<"); VVHW_TRACE("DVirtualVideoHwDevice::DVirtualVideoHwDevice"); } @@ -77,7 +79,9 @@ return err; } - iHwInterface = new DVirtualVideoHwInterface; + // We have already created this during construction + // iHwInterface = new DVirtualVideoHwInterface; + if ( !iHwInterface ) { return KErrNoMemory; diff -r 65231b4e789a -r ec0e558822c5 guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -21,11 +21,13 @@ #include #include #include +#include "syborg.h" // CONSTANTS _LIT( KVirtualVideoHwInterfacePanic, "DVirtualVideoHwInterface" ); +DVirtualVideoHwInterface * DVirtualVideoHwInterface::pVVHIf = NULL; // ============================ LOCAL DATA TYPES =============================== @@ -44,7 +46,9 @@ VVI_R_INPUT_BUFFER_READ_COUNT, VVI_R_INPUT_BUFFER_WRITE_COUNT, VVI_R_INPUT_BUFFER_MAX_TAIL, - VVI_R_REQUEST_ID + VVI_R_REQUEST_ID, + VVI_R_SHARED_CMD_MEMORY_BASE, + VVI_R_SHARED_FRAMEBUFFER_MEMORY_BASE, }; #define ASSERT_PANIC(c,p) __ASSERT_DEBUG(c,Kern::PanicCurrentThread(KVirtualVideoHwInterfacePanic,p)); @@ -67,6 +71,24 @@ iInputParametersMemoryChunk = NULL; iOutputParametersMemoryChunk = NULL; iRegisterMemoryChunk = NULL; + + DVirtualVideoHwInterface::pVVHIf = this; + + Kern::Printf("DVirtualVideoHwInterface::DVirtualVideoHwInterface()>"); + // Reserve a contiguous memory chunk for graphics usage + TUint32 ramSize = VVI_PARAMETERS_INPUT_MEMORY_SIZE + + VVI_PARAMETERS_OUTPUT_MEMORY_SIZE + + VVI_FRAMEBUFFER_MEMORY_SIZE + + VVI_REGISTERS_MEMORY_SIZE; + TInt r = Epoc::AllocPhysicalRam( ramSize, iVideoRamPhys ); + VVHW_TRACE("DVirtualVideoHwInterface::DVirtualVideoHwInterface() AllocPhysicalRam %d", r); + if (r != KErrNone) + { + NKern::ThreadLeaveCS(); + Kern::Fault("DVirtualVideoHwInterface Allocate Ram %d",r); + } + iFrameRamPhys = iVideoRamPhys + VVI_FRAMEBUFFER_BASE_ADDRESS; + Kern::Printf("DVirtualVideoHwInterface::DVirtualVideoHwInterface()<"); } @@ -104,23 +126,36 @@ TInt DVirtualVideoHwInterface::InitParametersInputMemory() { - return InitPhysicalMemory( VVI_PARAMETERS_INPUT_BASE_ADDRESS, + TInt ret = InitPhysicalMemory( iVideoRamPhys + VVI_PARAMETERS_INPUT_BASE_ADDRESS, VVI_PARAMETERS_INPUT_MEMORY_SIZE, iInputParametersMemoryChunk, iInputParametersChunkKernelAddress ); - } + Kern::Printf("DVirtualVideoHwInterface::InitParametersInputMemory - Base phy: 0x%08x lin: 0x%08x ret: %d", + iVideoRamPhys + VVI_PARAMETERS_INPUT_BASE_ADDRESS, + iInputParametersChunkKernelAddress, ret ); + return ret; + } TInt DVirtualVideoHwInterface::InitParametersOutputMemory() { - return InitPhysicalMemory( VVI_PARAMETERS_OUTPUT_BASE_ADDRESS, + TInt ret = InitPhysicalMemory( iVideoRamPhys + VVI_PARAMETERS_OUTPUT_BASE_ADDRESS, VVI_PARAMETERS_OUTPUT_MEMORY_SIZE, iOutputParametersMemoryChunk, - iOutputParametersChunkKernelAddress ); + iOutputParametersChunkKernelAddress ); + Kern::Printf("DVirtualVideoHwInterface::InitParametersOutputMemory - Base phy: 0x%08x lin: 0x%08x ret: %d", + iVideoRamPhys + VVI_PARAMETERS_OUTPUT_BASE_ADDRESS, + iOutputParametersChunkKernelAddress, ret ); + return ret; } TInt DVirtualVideoHwInterface::InitRegisterMemory() { - return InitPhysicalMemory( VVI_REGISTERS_BASE_ADDRESS, - VVI_REGISTERS_MEMORY_SIZE, iRegisterMemoryChunk, - iRegisterChunkKernelAddress ); + Kern::Printf(" DVirtualVideoHwInterface::InitRegisterMemory>"); + Kern::Printf("DVirtualVideoHwInterface::InitRegisterMemory - parameter base phy: 0x%08x", iVideoRamPhys ); + SetSharedCmdMemBase( iVideoRamPhys ); + Kern::Printf("DVirtualVideoHwInterface::InitRegisterMemory - frame buffer phy: 0x%08x", iFrameRamPhys ); + SetSharedFramebufferMemBase( iFrameRamPhys ); + + Kern::Printf(" DVirtualVideoHwInterface::InitRegisterMemory<"); + return 0; } // ----------------------------------------------------------------------------- @@ -218,6 +253,22 @@ SetRegisterValue( ERegCommand, aCommand ); } +// DVirtualVideoHwInterface::SetSharedCmdMemBase +// ----------------------------------------------------------------------------- +// +void DVirtualVideoHwInterface::SetSharedCmdMemBase( TUint32 aPhysicalAddress ) + { + VVHW_TRACE("DVirtualVideoHwInterface::SetSharedCmdMemBase 0x%08x", aPhysicalAddress); + SetRegisterValue( ERegSharedCmdMemBase, aPhysicalAddress ); + } + +void DVirtualVideoHwInterface::SetSharedFramebufferMemBase( TUint32 aPhysicalAddress ) + { + VVHW_TRACE("DVirtualVideoHwInterface::SetSharedFramebufferMemBase 0x%08x", aPhysicalAddress); + SetRegisterValue( ERegSharedFramebufferMemBase, aPhysicalAddress ); + } + + // ----------------------------------------------------------------------------- // DVirtualVideoHwInterface::GetRegisterValue // ----------------------------------------------------------------------------- @@ -226,11 +277,13 @@ TRegister aRegister, TUint32& aValue ) { - if ( iRegisterMemoryChunk ) + if ( 1 /* iRegisterMemoryChunk */ ) // FAISALMEMON check this line of code with Jani. Can we get rid of it? { TLinAddr offset = RegisterOffset( aRegister ); - TUint32* ptr = reinterpret_cast( iRegisterChunkKernelAddress + offset ); - aValue = *ptr; + // FAISALMEMON check this with Jani. Will the code still work for platsim or is this now syborg specific? + //TUint32* ptr = reinterpret_cast( iRegisterChunkKernelAddress + offset ); + //aValue = *ptr; + aValue = ReadReg( KHwGraphicsRegBase, offset ); } else { @@ -259,19 +312,12 @@ } } -// TODO FAISALMEMON This is the first portion of the port of Jani's -// Dynamic framebuffer base address code. Inspect this code, and also -// put in the rest of the code. EXPORT_C TPhysAddr DVirtualVideoHwInterface::GetFrameBase() { -#ifdef FAISALMEMON_DONE_DYNAMIC_FRAMEBUFFER_PORT TPhysAddr ret = 0; if(DVirtualVideoHwInterface::pVVHIf != NULL) { ret = DVirtualVideoHwInterface::pVVHIf->iFrameRamPhys; } return ret; -#else - return 0; -#endif } diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwserialiser/inc/eglrfc.h --- a/guestrendering/vghwserialiser/inc/eglrfc.h Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/vghwserialiser/inc/eglrfc.h Thu Aug 26 19:08:32 2010 +0100 @@ -89,8 +89,8 @@ EeglWaitNative, // 30 EeglSwapBuffers, EeglCopyBuffers, - EeglPlatsimSetSurfaceParams, - EeglPlatsimCopyImageData, + EeglSimulatorSetSurfaceParams, + EeglSimulatorCopyImageData, EeglPixmapSurfaceSizeChanged, EeglMakeCurrentSg, //sgImage support EeglCreatePixmapSurfaceSg, diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwserialiser/src/remotefunctioncall.cpp --- a/guestrendering/vghwserialiser/src/remotefunctioncall.cpp Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/vghwserialiser/src/remotefunctioncall.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -19,7 +19,7 @@ #define USE_SYMBIAN_CLIENT_PANICS #include #include "serialisedapiuids.h" -// Platsim Serialiser panic codes +// Guest Serialiser panic codes typedef enum { ESerPanicMaxParamCountExceeded=1, diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/eabi/vghwutilsu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/eabi/vghwutilsu.def Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,34 @@ +EXPORTS + _Z9VghwPanic10TVghwPanicPcS0_S0_i @ 1 NONAME + _ZN10CVghwUtils14MapToHWAddressEiRm @ 2 NONAME + _ZN10CVghwUtils20DriverExecuteCommandER22RemoteFunctionCallData @ 3 NONAME + _ZN10CVghwUtils11InitStaticsEv @ 4 NONAME + _ZN10CVghwUtils5AllocEi @ 5 NONAME + _ZN10CVghwUtils4FreeEPv @ 6 NONAME + _ZN10CVghwUtils7GetHeapEv @ 7 NONAME + _ZN10CVghwUtils16SwitchToVghwHeapEv @ 8 NONAME + _ZN10CVghwUtils18SwitchFromVghwHeapEP5RHeap @ 9 NONAME + Reserved10 @ 10 NONAME ABSENT + Reserved11 @ 11 NONAME ABSENT + _ZN10CVghwUtils17CreateThreadStateEv @ 12 NONAME + _ZN10CVghwUtils18ReleaseThreadStateEv @ 13 NONAME + _ZN10CVghwUtils14EglThreadStateEv @ 14 NONAME + _ZN10CVghwUtils9VgContextEv @ 15 NONAME + _ZN10CVghwUtils11GlesContextEv @ 16 NONAME + _ZN15TEglThreadState8EglErrorEv @ 17 NONAME + _ZN15TEglThreadState17ExecEglBooleanCmdER6EglRFC @ 18 NONAME + _ZN15TEglThreadState17ExecEglContextCmdER6EglRFC @ 19 NONAME + _ZN15TEglThreadState17ExecEglSurfaceCmdER6EglRFC @ 20 NONAME + _ZN10CVghwUtils16EglManagementApiEv @ 21 NONAME + _ZN10CVghwUtils15EglGetSgHandlesEyPy @ 22 NONAME + _ZN10CVghwUtils14DestroyStaticsEv @ 23 NONAME + _ZN10CVghwUtils19SetEglManagementApiEP17MEglManagementApi @ 24 NONAME + _ZN10CVghwUtils14SetVgApiForEglEP12MVgApiForEgl @ 25 NONAME + _ZN10CVghwUtils18SetGles11ApiForEglEP16MGles11ApiForEgl @ 26 NONAME + _ZN10CVghwUtils17SetGles2ApiForEglEP15MGles2ApiForEgl @ 27 NONAME + _ZN10CVghwUtils11VgApiForEglEv @ 28 NONAME + _ZN10CVghwUtils15Gles11ApiForEglEv @ 29 NONAME + _ZN10CVghwUtils14Gles2ApiForEglEv @ 30 NONAME + + + diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/group/bld.inf --- a/guestrendering/vghwutils/group/bld.inf Thu Aug 26 13:29:31 2010 +0100 +++ b/guestrendering/vghwutils/group/bld.inf Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,22 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Build file for VG Hardware Utilities + +PRJ_PLATFORMS +DEFAULT -WINSCW + +PRJ_EXPORTS + +PRJ_MMPFILES +vghwutils.mmp diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/group/vghwutils.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/group/vghwutils.mmp Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,53 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Project file for vghwutils + +TARGET vghwutils.dll +TARGETTYPE dll +UID 0x1000008d 0x20026A32 +capability CAP_GENERAL_DLL //All -Tcb +vendorid VID_DEFAULT //0x101FB657 //Nokia vendor id + +OS_LAYER_ESTLIB_SYSTEMINCLUDE +OS_LAYER_SYSTEMINCLUDE +USERINCLUDE ../inc +SYSTEMINCLUDE /epoc32/include +//systeminclude /epoc32/include/libc // STDLIB include files +//systeminclude /epoc32/include/vg // OpenVG include files +USERINCLUDE ../../vghwserialiser/inc +// userinclude ../../platsimvideodriver/api/inc // Local include files +// userinclude ../../platsimvideodriver/commoninc // Local include files + +SOURCEPATH ../src + +SOURCE vghwutils.cpp + +// constructors & such for OpenVgRFC and EglRFC objects +SOURCEPATH ../../vghwserialiser/src +SOURCE eglrfc.cpp +SOURCE openvgrfc.cpp +SOURCE opengles11rfc.cpp + + +//nostrictdef + +LIBRARY euser.lib +LIBRARY platsimvideohwapi.lib +LIBRARY vghwserialiser.lib + +#ifdef ENABLE_ABIV2_MODE +DEBUGGABLE_UDEBONLY +#endif + +EPOCALLOWDLLDATA diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/inc/vghwutils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/inc/vghwutils.h Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,342 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: + + +#ifndef __VGHWUTILS_H__ +#define __VGHWUTILS_H__ + +// Include Files +#include // CBase +#include +#include +#include +#include "eglrfc.h" + + +class RGuestVideoDriver; + +// Virtual Graphics Hardware per thread data: TEglThreadState is concrete, MVgContext & MGlesContext are per API interfaces +class TEglThreadState; +class MGlesContext; +class MVgContext; + +// data serialisation packages +class OpenVgRFC; +class EglRFC; +class RemoteFunctionCall; +class RemoteFunctionCallData; + +// tracing +#ifdef _DEBUG + #include + #define UTIL_TRACE(fmt, args...) RDebug::Printf(fmt, ##args) + #define VGHWPANIC_ASSERT(condition, panic) if (!(condition)) { VghwPanic(panic, #panic, #condition, __FILE__, __LINE__); } + #define VGHWPANIC_ASSERT_DEBUG(condition, panic) if (!(condition)) { VghwPanic(panic, #panic, #condition, __FILE__, __LINE__); } +#else + #define UTIL_TRACE(fmt, args...) + #define VGHWPANIC_ASSERT(condition, panic) if (!(condition)) { VghwPanic(panic, NULL, NULL, NULL, __LINE__); } + #define VGHWPANIC_ASSERT_DEBUG(condition, panic) +#endif + + +// Simulator Virtual Graphics Hardware panic codes +typedef enum + { + EVghwPanicNoVideoChannel = 1, + EVghwPanicOperationDataTooBig, + EVghwPanicDriverOpenError, + EVghwPanicVghwHeapDoesNotExist, + EVghwPanicInitializeFailed, + EVghwPanicGraphicsDriverNotOpen, + EVghwPanicSwitchToVghwHeapOldHeapIsVghwHeap, + EVghwPanicSwitchFromVghwHeapParamIsNull, + EVghwPanicSwitchFromVghwHeapOldHeapIsNotVghwHeap, + EVghwPanicSwitchFromVghwHeapParamIsVghwHeap, // 10 + EVghwPanicGraphicsCreationLockDoesNotExist, + EVghwPanicExecuteCommandFailed, + EVghwPanicBadVgErrorValue, + EVghwPanicBadGlesErrorValue, + EVghwPanicBadEglErrorValue, + EVghwPanicBadEglBoundApi, + } TVghwPanic; + +// This panic function is exported to allow inline functions to use it +IMPORT_C void VghwPanic(TVghwPanic aPanicCode, char* aPanicName, char* aCondition, char* aFile, TInt aLine); + + +// Mix-in class: EGL support functions, including SgImage support, expected to be called by Open VG and Open GL ES +class MEglManagementApi + { +public: + virtual TBool EglImageOpenForVgImage(EGLImageKHR aImage, TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId) = 0; + virtual void EglImageClose(EGLImageKHR aImage) = 0; + // ToDo add an API so that Open VG can query the size of the current Context's surface + }; + + +typedef void (*ExtensionProcPointer)(...); + + +// Private interfaces for EGL to call into Open VG +class MVgApiForEgl + { +public: + virtual ExtensionProcPointer platsimGetVgProcAddress (const char *aProcName) = 0; + }; + + +// Private interfaces for EGL to call into Open GL ES 1.1 +class MGles11ApiForEgl + { +public: + virtual ExtensionProcPointer platsimGetGles11ProcAddress (const char *aProcName) = 0; + }; + + +// Private interfaces for EGL to call into Open GL ES 2 +class MGles2ApiForEgl + { +public: + virtual ExtensionProcPointer platsimGetGles2ProcAddress (const char *aProcName) = 0; + }; + + +/* + VGHWUtils APIs are static for ease of use by the other Simulator Graphics DLLs. + + One (singleton) instance is created as Writeable Static Data when the DLL is loaded. + After initialization this will hold process-wide data - e.g. a memory heap for Graphics DLLs + to store local Symbian client state information. + + ToDo maybe make this a Symbian X class because it owns resources, but only as static data. + */ +NONSHARABLE_CLASS(CVghwUtils): public CBase + { + friend class TEglThreadState; // to limit visibility of DriverExecuteCommand +public: + // open Driver connection, create Memory Heap, etc... + IMPORT_C static void InitStatics(); + IMPORT_C static void DestroyStatics(); + + IMPORT_C static TInt MapToHWAddress(const TInt aChunkHandle, TUint32& aHWAddress); + IMPORT_C static TInt GetFrameBufferBaseAddress(TUint32& aHWAddress); + IMPORT_C static TInt EglGetSgHandles(const TUint64 aId, TUint64 *aSgHandles); + + // VG Memory Pool APIs (One heap is created for the process, for use by all Simulator Graphics DLLs) + IMPORT_C static TAny* Alloc(TInt aSize); + IMPORT_C static void Free(TAny* aPtr); + IMPORT_C static RHeap* GetHeap(); + IMPORT_C static RHeap* SwitchToVghwHeap(); + IMPORT_C static void SwitchFromVghwHeap(RHeap* aOldHeapPtr); + // handy function for Debug Asserts + static inline TBool UsingVghwHeap() { return &User::Heap() == GetHeap(); } + + // if this thread does not have a state object try to alloc a new one + IMPORT_C static TEglThreadState* CreateThreadState(); + // current state object, if any, for this thread (for EGL) + IMPORT_C static TEglThreadState* EglThreadState(); + // current state object, if Open VG, for this thread (as tracked by EGL DLL) + IMPORT_C static MVgContext* VgContext(); + // current state object for Open GL ES 1.1, for this thread (as tracked by EGL DLL) + IMPORT_C static MGlesContext* GlesContext(); + // free current state object, if any, for this thread + IMPORT_C static void ReleaseThreadState(); + + IMPORT_C static void SetEglManagementApi(MEglManagementApi* aEglManagementApi); + IMPORT_C static MEglManagementApi* EglManagementApi(); + + // Private interfaces for EGL to call into Open GL ES and Open VG (avoids breaking DEF file compatibility) + IMPORT_C static void SetVgApiForEgl(MVgApiForEgl* aVgApiForEgl); + IMPORT_C static MVgApiForEgl* VgApiForEgl(); + + IMPORT_C static void SetGles11ApiForEgl(MGles11ApiForEgl* aGles11ApiForEgl); + IMPORT_C static MGles11ApiForEgl* Gles11ApiForEgl(); + + IMPORT_C static void SetGles2ApiForEgl(MGles2ApiForEgl* aGles2ApiForEgl); + IMPORT_C static MGles2ApiForEgl* Gles2ApiForEgl(); + +protected: + IMPORT_C static void DriverExecuteCommand(RemoteFunctionCallData& aRequestData); + +private: + inline static RGuestVideoDriver& Driver(); + +private: + // everything is zeroed on construction, call Initialize() to prepare + volatile static TBool iInitialized; // NB "volatile" used for thread safety in InitStaticse() + static TInt iVghwInitMutex; // required for thread safety in Initialize() + + // static member objects + static RGuestVideoDriver* iDriver; + static RHeap* iHeap; + static MEglManagementApi* iEglManagementApi; + static MVgApiForEgl* iVgApiForEgl; + static MGles11ApiForEgl* iGles11ApiForEgl; + static MGles2ApiForEgl* iGles2ApiForEgl; + static TBool iLoadedOpenVgDll; + static TBool iLoadedOpenGles11Dll; + static TBool iLoadedOpenGles2Dll; + }; + + +// Basic interface for sending GL ES 1.1 commands down to Host Open GL ES implementation - can be expanded later +class MGlesContext + { +public: + // Execute Open GL ES 1.1 commands + virtual void ExecuteGlesCommand(RemoteFunctionCall& aGlesRequestData) = 0; + virtual void ExecuteGlesFlushCommand() = 0; + virtual void ExecuteGlesFinishCommand() = 0; + // GLES state + virtual void SetGlesError(GLenum aGlesErrorCode) = 0; + virtual GLenum GlesError() = 0; + // ToDo make context tracking work for VG & GL ES + virtual EGLContext GlesEglContext() = 0; + }; + + +// Basic interface for sending VG commands down to Host Open VG implementation - can be expanded later +class MVgContext + { +public: + // Execute Open VG commands + virtual void ExecuteVgCommand(OpenVgRFC& aVgApiData) = 0; + virtual void ExecuteVgFlushCommand() = 0; + virtual void ExecuteVgFinishCommand() = 0; + // VG state + virtual void SetVgError(VGErrorCode aVgErrorCode) = 0; + virtual VGErrorCode VgError() = 0; + virtual EGLContext VgEglContext() = 0; + }; + + +NONSHARABLE_CLASS(TEglThreadState) : public MGlesContext, public MVgContext + { + friend class CVghwUtils; // to manage creation / delete of per thread state +public: + // Execute EGL commands, and analyse for success + IMPORT_C EGLBoolean ExecEglBooleanCmd(EglRFC& aEglApiData); + IMPORT_C EGLContext ExecEglContextCmd(EglRFC& aEglApiData); + IMPORT_C EGLSurface ExecEglSurfaceCmd(EglRFC& aEglApiData); + // ToDo add static export for eglTerminate + + // Execute EGL commands whose return value cannot be tested for fail/success + inline void ExecuteEglNeverErrorCmd(EglRFC& aEglApiData); + // EGL thread state + inline void ClearEglError(); + inline void SetEglError(EGLint aEglError); + IMPORT_C EGLint EglError(); + inline void SetEglBoundApi(EGLenum aEglBoundApi); + inline EGLenum EglBoundApi(); + inline EGLint PeekEglError(); // reads DLL set error code (only) + + // MGlesContext: Execute Open GL ES 1.1 commands & manage Open GL ES state + virtual void ExecuteGlesCommand(RemoteFunctionCall& aGlesRequestData); + virtual void ExecuteGlesFlushCommand(); + virtual void ExecuteGlesFinishCommand(); + virtual void SetGlesError(GLenum aGlesErrorCode); + virtual GLenum GlesError(); + virtual EGLContext GlesEglContext(); + + // MVgContext: Execute Open VG commands & manage Open VG state + virtual void ExecuteVgCommand(OpenVgRFC& aVgApiData); + virtual void ExecuteVgFlushCommand(); + virtual void ExecuteVgFinishCommand(); + virtual void SetVgError(VGErrorCode aVgErrorCode); + virtual VGErrorCode VgError(); + virtual EGLContext VgEglContext(); + +protected: + static TEglThreadState* New(); + void Destroy(); + TEglThreadState(); + ~TEglThreadState(); + +private: + GLenum GetHostGlesError(); + VGErrorCode GetHostVgError(); + +private: + // EGL thread state + EGLint iEglError; + TBool iEglHostHasRecentError; + // currently bound graphics API + EGLenum iEglBoundApi; + + // Open VG context for thread + VGErrorCode iVgError; + EGLContext iVgEglContext; + TBool iVgCommandsSinceGetError; + TBool iVgCommandsSinceFlush; + TBool iVgCommandsSinceFinish; + + // Open GL ES 1.1 context for thread + GLenum iGlesError; + EGLContext iGlesEglContext; + TBool iGlesCommandsSinceGetError; + TBool iGlesCommandsSinceFlush; + TBool iGlesCommandsSinceFinish; + }; + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// TVghwThreadState inline functions + +void TEglThreadState::ClearEglError() + { + UTIL_TRACE(" TVghwThreadState::ClearEglError"); + iEglError = EGL_SUCCESS; + iEglHostHasRecentError = EFalse; + } + + +void TEglThreadState::SetEglError(EGLint aEglError) + { + UTIL_TRACE(" TVghwThreadState::SetEglError error=0x%x", aEglError); + VGHWPANIC_ASSERT_DEBUG((aEglError >= EGL_SUCCESS) && (aEglError <= 0x301F), EVghwPanicBadEglErrorValue); + iEglError = aEglError; + iEglHostHasRecentError = EFalse; + } + + +EGLint TEglThreadState::PeekEglError() // reads DLL set error code + { + return iEglError; + } + + +void TEglThreadState::SetEglBoundApi(EGLenum aEglBoundApi) + { + VGHWPANIC_ASSERT_DEBUG((aEglBoundApi == EGL_OPENGL_ES_API) || (aEglBoundApi == EGL_OPENVG_API), EVghwPanicBadEglBoundApi); + iEglBoundApi = aEglBoundApi; + } + + +EGLenum TEglThreadState::EglBoundApi() + { + return iEglBoundApi; + } + +// Execute EGL Command simple variants + +void TEglThreadState::ExecuteEglNeverErrorCmd(EglRFC& aEglApiData) + { // for EGL commands which cannot have a host error + CVghwUtils::DriverExecuteCommand(aEglApiData.Data()); + iEglHostHasRecentError = EFalse; + iEglError = EGL_SUCCESS; + } + +#endif // __VGHWUTILS_H__ diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/rom/vghwutils.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/rom/vghwutils.iby Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,24 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: + + +#ifndef PLATSIMVGHWUTILS_IBY +#define PLATSIMVGHWUTILS_IBY + + +file=ABI_DIR\BUILD_DIR\vghwutils.dll SHARED_LIB_DIR\vghwutils.dll + +#endif // PLATSIMVGHWUTILS_IBY + +// End of File diff -r 65231b4e789a -r ec0e558822c5 guestrendering/vghwutils/src/vghwutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/src/vghwutils.cpp Thu Aug 26 19:08:32 2010 +0100 @@ -0,0 +1,902 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: + + +#include +#include + +#include + +#include "vghwutils.h" +#include "eglrfc.h" +#include "openvgrfc.h" +#include "opengles11rfc.h" + +#ifdef _DEBUG +#define EGL_ERROR_PRINT(T, E) EglErrorPrint(T, E) +#define GLES_ERROR_PRINT(T, E) GlesErrorPrint(T, E) +#define VG_ERROR_PRINT(T, E) VgErrorPrint(T, E) +static void EglErrorPrint(char* aTitle, EGLint aEglError); +static void GlesErrorPrint(char* aTitle, GLenum aGlesError); +static void VgErrorPrint(char* aTitle, VGErrorCode aVgError); +#else +#define EGL_ERROR_PRINT(T, E) +#define GLES_ERROR_PRINT(T, E) +#define VG_ERROR_PRINT(T, E) +#endif + + +// Min & Max sizes for creating Memory Heap for Guest Graphics DLLs +#define KVghwHeapMin 0x1000 +#define KVghwHeapMax 0x100000 + + +// protection against concurrent initialisation from multiple threads +volatile TBool CVghwUtils::iInitialized = EFalse; +TInt CVghwUtils::iVghwInitMutex = 0; + +// static member objects - Writeable Static Data +RGuestVideoDriver* CVghwUtils::iDriver = NULL; +RHeap* CVghwUtils::iHeap = NULL; +MEglManagementApi* CVghwUtils::iEglManagementApi = NULL; +MVgApiForEgl* CVghwUtils::iVgApiForEgl = NULL; +MGles11ApiForEgl* CVghwUtils::iGles11ApiForEgl = NULL; +MGles2ApiForEgl* CVghwUtils::iGles2ApiForEgl = NULL; +TBool CVghwUtils::iLoadedOpenVgDll = EFalse; +TBool CVghwUtils::iLoadedOpenGles11Dll = EFalse; +TBool CVghwUtils::iLoadedOpenGles2Dll = EFalse; + + + +_LIT(KVghwPanicCategory, "Guest VGHW"); + + +// NOTE: Exported because some VGHW functions are inline and could Assert & Panic from somewhere else +EXPORT_C void VghwPanic(TVghwPanic aPanicCode, char* aPanicName, char* aCondition, char* aFile, TInt aLine) + { + if (aCondition && aFile) + { + RDebug::Printf("VghwUtils Panic %s for failed Assert (%s), at %s:%d", aPanicName, aCondition, aFile, aLine); + } + else + { + RDebug::Printf("VghwUtils Panic %d for failed Assert (line %d)", aPanicCode, aLine); + } + + User::Panic(KVghwPanicCategory, aPanicCode); + } + +// inline functions + +RGuestVideoDriver& CVghwUtils::Driver() + { + // TODO remove this later in refactoring - Open VG & GL ES commands should not reach here before EGL has initialized the singleton + if (!iInitialized || !iDriver) + { + UTIL_TRACE("CVghwUtils::Driver called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iInitialized && iDriver, EVghwPanicGraphicsDriverNotOpen); + return *iDriver; + } + + +EXPORT_C void CVghwUtils::DestroyStatics() + { +#ifdef _DEBUG + TUint64 processId = RProcess().Id().Id(); + TUint64 threadId = RThread().Id().Id(); + UTIL_TRACE("CVghwUtils::DestroyStatics iInitialized=%d, iDriver=0x%x, iHeap=0x%x, Process=0x%lx, Thread=0x%lx", + iInitialized, iDriver, iHeap, processId, threadId); +#endif + if (iHeap) + { + if (iDriver) + { + iDriver->Flush(); + iDriver->Close(); + RHeap* threadHeap = SwitchToVghwHeap(); + delete iDriver; + SwitchFromVghwHeap(threadHeap); + iDriver = NULL; + } + iHeap->Reset(); + iHeap->Close(); + iHeap = NULL; + } + if (iInitialized) + { + iInitialized = EFalse; + } + } + + +// Ensure Graphics memory heap is created, and Open driver channel +EXPORT_C void CVghwUtils::InitStatics() + { +#ifdef _DEBUG + TUint64 processId = RProcess().Id().Id(); + TUint64 threadId = RThread().Id().Id(); + UTIL_TRACE("CVghwUtils::InitStatics start Process=0x%lx, Thread=0x%lx, iInitialized=%d", + processId, threadId, iInitialized); +#endif + // bootstrap creation of mutexes and Graphics memory heap + while (!iInitialized) + { + TInt creationError = KErrNone; + // thread safe initialization + // LockedDec() returns the value prior to decrement + if (0 != User::LockedDec(iVghwInitMutex)) + { + User::AfterHighRes(1000); // Yield X microseconds, review length if code is changed + } + else + { + // volatile attribute forces rereading of the pointer, in case another thread has done the allocation + if (!iInitialized) + { // loop style init exits if any stage fails, and gives per step debug logging + TInt step = 0; + do + { + switch (step) + { + case 0: + // guarantee that initialisation of the object is flushed before the pointer is published + __e32_atomic_store_rel_ptr(&iHeap, User::ChunkHeap(NULL, KVghwHeapMin, KVghwHeapMax)); + if (!iHeap) + { + creationError = KErrNoMemory; + } + break; + case 1: + { + VGHWPANIC_ASSERT_DEBUG(iHeap, EVghwPanicVghwHeapDoesNotExist); + RHeap* threadHeap = User::SwitchHeap(iHeap); // switch to VGHW graphics Heap + iDriver = new RGuestVideoDriver(); + if (!iDriver) + { + creationError = KErrNoMemory; + } + User::SwitchHeap(threadHeap); // switch back to client Heap + } + break; + case 2: + creationError = User::LoadLogicalDevice(_L("platsimvideohw")); + if ( (KErrNone == creationError) || (KErrAlreadyExists == creationError) ) + { + creationError = iDriver->Open(); + } + break; + default: // all initialisation steps completed + iInitialized = ETrue; + } + ++step; + } + while (!iInitialized && !creationError); + UTIL_TRACE("CVghwUtils::InitStatics %s step=%d; creationError=%d, iInitialized=%d, iDriver=0x%x, iHeap=0x%x", + creationError ? "failed at" : "completed", step, creationError, iInitialized, iDriver, iHeap); + } + } + User::LockedInc(iVghwInitMutex); + + VGHWPANIC_ASSERT(creationError == KErrNone, EVghwPanicInitializeFailed); + } + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVghwUtils::DriverExecuteCommand(RemoteFunctionCallData& aRequestData) + { + if (!iInitialized || !iDriver) + { + UTIL_TRACE("CVghwUtils::DriverExecuteCommand called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iInitialized && iDriver, EVghwPanicGraphicsDriverNotOpen); + iDriver->ExecuteCommand(aRequestData); + } + + +// ----------------------------------------------------------------------------- +// Use driver to discover linear memory address of chunk. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CVghwUtils::MapToHWAddress( const TInt aChunkHandle, TUint32& aHWAddress ) + { + UTIL_TRACE("CVghwUtils::MapToHWAddress"); + return Driver().MapToHWAddress( aChunkHandle, aHWAddress ); + } + + +// SgImage support function - get underlying VGImage & Pbuffer handles +EXPORT_C TInt CVghwUtils::EglGetSgHandles( const TUint64 aId, TUint64 *aSgHandles ) + { + UTIL_TRACE("CVghwUtils::EglGetSgHandles"); + return Driver().EglGetSgHandles( aId, aSgHandles ); + } + + +// Memory Heap Management functions + +EXPORT_C TAny* CVghwUtils::Alloc(TInt aSize) + { + if (!iInitialized || !iHeap) + { + UTIL_TRACE("CVghwUtils::Alloc called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist); + return iHeap->Alloc(aSize); + } + + +EXPORT_C void CVghwUtils::Free(TAny* aPtr) + { + if (!iInitialized || !iHeap) + { + UTIL_TRACE("CVghwUtils::Free called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist); + iHeap->Free(aPtr); + } + + +EXPORT_C RHeap* CVghwUtils::GetHeap() + { + if (!iInitialized || !iHeap) + { + UTIL_TRACE("CVghwUtils::GetHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iInitialized && iHeap, EVghwPanicVghwHeapDoesNotExist); + return iHeap; + } + + +// Switch to VGHW Memory Heap. +EXPORT_C RHeap* CVghwUtils::SwitchToVghwHeap() + { + if (!iInitialized || !iHeap) + { + UTIL_TRACE("CVghwUtils::SwitchToVghwHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iHeap, EVghwPanicVghwHeapDoesNotExist); + RHeap* oldHeap = User::SwitchHeap(iHeap); // switch to Guest graphics heap + VGHWPANIC_ASSERT(oldHeap != iHeap, EVghwPanicSwitchToVghwHeapOldHeapIsVghwHeap); + return oldHeap; + } + + +// Switch back to original heap +EXPORT_C void CVghwUtils::SwitchFromVghwHeap(RHeap* aOldHeapPtr) + { + if (!iInitialized || !iHeap) + { + UTIL_TRACE("CVghwUtils::SwitchFromVghwHeap called before EGL has initialised VghwUtils: iInitialized=%d, iDriver=0x%x", iInitialized, iDriver); + InitStatics(); + } + VGHWPANIC_ASSERT(iHeap, EVghwPanicVghwHeapDoesNotExist); + VGHWPANIC_ASSERT(aOldHeapPtr, EVghwPanicSwitchFromVghwHeapParamIsNull); + VGHWPANIC_ASSERT(aOldHeapPtr != iHeap, EVghwPanicSwitchFromVghwHeapParamIsVghwHeap); + + RHeap* oldHeap = User::SwitchHeap(aOldHeapPtr); // switch from Guest graphics heap back to thread heap + VGHWPANIC_ASSERT(oldHeap == iHeap, EVghwPanicSwitchFromVghwHeapOldHeapIsNotVghwHeap); + } + + +// if this thread does not have an object try to alloc a new one +EXPORT_C TEglThreadState* CVghwUtils::CreateThreadState() + { + TEglThreadState* threadState = reinterpret_cast(Dll::Tls()); + if (!threadState) + { + UTIL_TRACE("CVghwUtils::CreateThreadState - object is currently 0x%x, iInitialized=%d", + threadState, iInitialized); + if (!iInitialized) + { + InitStatics(); + } + threadState = TEglThreadState::New(); + Dll::SetTls(threadState); + } + return threadState; + } + + +// current state object, if any, for this thread +EXPORT_C TEglThreadState* CVghwUtils::EglThreadState() + { + TEglThreadState* threadState = reinterpret_cast(Dll::Tls()); + return threadState; + } + + +// current state object, if Open VG is the current bound API, for this thread +EXPORT_C MVgContext* CVghwUtils::VgContext() + { + TEglThreadState* threadState = reinterpret_cast(Dll::Tls()); + return threadState; + // ToDo sort this to check for valid Open VG context + /* + if (threadState && threadState->VgEglContext()) + return threadState; + return NULL; + */ + } + + +// current state object, if Open GL ES is the current bound API, for this thread (for EGL) +EXPORT_C MGlesContext* CVghwUtils::GlesContext() + { + TEglThreadState* threadState = reinterpret_cast(Dll::Tls()); + return threadState; + // ToDo sort this to check for valid Open GL ES context + /* + if (threadState && threadState->GlesEglContext()) + return threadState; + return NULL; */ + } + + +// free current state object, if any, for this thread +EXPORT_C void CVghwUtils::ReleaseThreadState() + { + TEglThreadState* threadState = reinterpret_cast(Dll::Tls()); + UTIL_TRACE("CVghwUtils::ReleaseThreadState - object = 0x%x", threadState); + if (threadState) + { + threadState->Destroy(); + Dll::FreeTls(); + } + } + + +EXPORT_C MEglManagementApi* CVghwUtils::EglManagementApi() + { + return iEglManagementApi; + } + + +EXPORT_C void CVghwUtils::SetEglManagementApi(MEglManagementApi* aEglManagementApi) + { + UTIL_TRACE("CVghwUtils::SetEglManagementApi aEglManagementApi=0x%x", aEglManagementApi); + iEglManagementApi = aEglManagementApi; + } + + +/* + Stored pointers into Open GL ES 1.1, GL ES 2 and Open VG are problematic if the DLL is later unloaded. + (RSgDriver::Open currently loads & unloads all the Open VG & GL ES DLLs, to determine features to publish.) + Possibly Open the DLL again when the non-NULL pointer is fetched by EGL, probably needs flags so that + this is only done once. + */ +EXPORT_C void CVghwUtils::SetVgApiForEgl(MVgApiForEgl* aVgApiForEgl) + { + UTIL_TRACE("CVghwUtils::SetVgApiForEgl aVgApiForEgl=0x%x, iVgApiForEgl=0x%x, iLoadedOpenVgDll=0x%x", + aVgApiForEgl, iVgApiForEgl, iLoadedOpenVgDll); + // don't let a thread set this to NULL if we have forced the DLL to stay loaded + if (aVgApiForEgl || !iLoadedOpenVgDll) + { + iVgApiForEgl = aVgApiForEgl; + } + } + + +EXPORT_C MVgApiForEgl* CVghwUtils::VgApiForEgl() + { + if (iVgApiForEgl && !iLoadedOpenVgDll) + { // ensure Open VG DLL stays loaded from now on + _LIT(KLibOpenVg, "libOpenVG.dll"); + RLibrary lib; + if (lib.Load(KLibOpenVg) == KErrNone) + { + UTIL_TRACE("CVghwUtils::VgApiForEgl - Open VG dll loaded, iVgApiForEgl=0x%x", iVgApiForEgl); + iLoadedOpenVgDll = ETrue; + return iVgApiForEgl; + } + } + UTIL_TRACE("CVghwUtils::VgApiForEgl - Open VG dll not loaded or not safe to use"); + return NULL; + } + + +EXPORT_C void CVghwUtils::SetGles11ApiForEgl(MGles11ApiForEgl* aGles11ApiForEgl) + { + UTIL_TRACE("CVghwUtils::SetGles11ApiForEgl aGles11ApiForEgl=0x%x, iGles11ApiForEgl=0x%x, iLoadedOpenGles11Dll=0x%x", + aGles11ApiForEgl, iGles11ApiForEgl, iLoadedOpenGles11Dll); + // don't let a thread set this to NULL if we have forced the DLL to stay loaded + if (aGles11ApiForEgl || !iLoadedOpenGles11Dll) + { + iGles11ApiForEgl = aGles11ApiForEgl; + } + } + + +EXPORT_C MGles11ApiForEgl* CVghwUtils::Gles11ApiForEgl() + { + if (iGles11ApiForEgl && !iLoadedOpenGles11Dll) + { // ensure Open VG DLL stays loaded from now on + _LIT(KLibOpenGles, "libGLESv1_CM.dll"); + RLibrary lib; + if (lib.Load(KLibOpenGles) == KErrNone) + { + UTIL_TRACE("CVghwUtils::Gles11ApiForEgl - Open GL ES 1.1 dll loaded, iGles11ApiForEgl=0x%x", iGles11ApiForEgl); + iLoadedOpenGles11Dll = ETrue; + return iGles11ApiForEgl; + } + } + UTIL_TRACE("CVghwUtils::Gles11ApiForEgl - Open GL ES 1.1 dll not loaded or not safe to use"); + return NULL; + } + + +EXPORT_C void CVghwUtils::SetGles2ApiForEgl(MGles2ApiForEgl* aGles2ApiForEgl) + { + UTIL_TRACE("CVghwUtils::SetGles2ApiForEgl aGles2ApiForEgl=0x%x, iGles2ApiForEgl=0x%x, iLoadedOpenGles2Dll=0x%x", + aGles2ApiForEgl, iGles2ApiForEgl, iLoadedOpenGles2Dll); + // don't let a thread set this to NULL if we have forced the DLL to stay loaded + if (aGles2ApiForEgl || !iLoadedOpenGles2Dll) + { + iGles2ApiForEgl = aGles2ApiForEgl; + } + } + + +EXPORT_C MGles2ApiForEgl* CVghwUtils::Gles2ApiForEgl() + { + if (iGles2ApiForEgl && !iLoadedOpenGles2Dll) + { // ensure Open VG DLL stays loaded from now on + _LIT(KLibOpenGles2, "libGLESv2.dll"); + RLibrary lib; + if (lib.Load(KLibOpenGles2) == KErrNone) + { + UTIL_TRACE("CVghwUtils::Gles2ApiForEgl - Open GL ES 2 dll loaded, iGles2ApiForEgl=0x%x", iGles2ApiForEgl); + iLoadedOpenGles2Dll = ETrue; + return iGles2ApiForEgl; + } + } + UTIL_TRACE("CVghwUtils::Gles2ApiForEgl - Open GL ES 2 dll not loaded or not safe to use"); + return NULL; + } + + +//////////////////////////////////////////////////////////////////////////////////// + +// factory method +TEglThreadState* TEglThreadState::New() + { + UTIL_TRACE("TEglThreadState::New"); + RHeap* currentHeap = CVghwUtils::SwitchToVghwHeap(); + TEglThreadState* self = new TEglThreadState(); + CVghwUtils::SwitchFromVghwHeap(currentHeap); + return self; + } + + +TEglThreadState::TEglThreadState() : + // EGL thread state + iEglError(EGL_SUCCESS), + iEglHostHasRecentError(EFalse), + // currently bound graphics API, initial value from EGL spec + iEglBoundApi(EGL_OPENGL_ES_API), + // Open VG thread state + iVgError(VG_NO_ERROR), + iVgEglContext(EGL_NO_CONTEXT), + iVgCommandsSinceGetError(EFalse), + iVgCommandsSinceFlush(EFalse), + iVgCommandsSinceFinish(EFalse), + // Open GL ES 1.1 state + iGlesError(GL_NO_ERROR), + iGlesEglContext(EGL_NO_CONTEXT), + iGlesCommandsSinceGetError(EFalse), + iGlesCommandsSinceFlush(EFalse), + iGlesCommandsSinceFinish(EFalse) + {} + + +void TEglThreadState::Destroy() + { + UTIL_TRACE("TEglThreadState::Destroy"); + RHeap* currentHeap = CVghwUtils::SwitchToVghwHeap(); + delete this; + CVghwUtils::SwitchFromVghwHeap(currentHeap); + } + + +TEglThreadState::~TEglThreadState() + {} + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EXPORT_C EGLBoolean TEglThreadState::ExecEglBooleanCmd(EglRFC& aEglApiData) + { + CVghwUtils::DriverExecuteCommand(aEglApiData.Data()); + + EGLBoolean hostResult = (EGLBoolean) aEglApiData.ReturnValue(); + if (hostResult == EGL_TRUE) + { + ClearEglError(); + } + else + { // error present in host graphics stack + iEglHostHasRecentError = ETrue; + } + return hostResult; + } + + +EXPORT_C EGLContext TEglThreadState::ExecEglContextCmd(EglRFC& aEglApiData) + { + CVghwUtils::DriverExecuteCommand(aEglApiData.Data()); + + EGLContext hostResult = (EGLContext) aEglApiData.ReturnValue(); + if (hostResult != EGL_NO_CONTEXT) + { + ClearEglError(); + } + else + { // error present in host graphics stack + iEglHostHasRecentError = ETrue; + } + return hostResult; + } + + +EXPORT_C EGLSurface TEglThreadState::ExecEglSurfaceCmd(EglRFC& aEglApiData) + { + CVghwUtils::DriverExecuteCommand(aEglApiData.Data()); + + EGLSurface hostResult = (EGLSurface) aEglApiData.ReturnValue(); + if (hostResult != EGL_NO_SURFACE) + { + ClearEglError(); + } + else + { // error present in host graphics stack + iEglHostHasRecentError = ETrue; + } + return hostResult; + } + + +/* + Get details of the last EGL api error. + (Resets stored last error value to EGL_SUCCESS.) + + @return EGL_SUCCESS or an EGL_xxxx error constant. + */ +EXPORT_C EGLint TEglThreadState::EglError() + { + EGLint eglError = iEglError; + if (iEglHostHasRecentError) + { + // last EGL command was executed/failed in the Host side, so need to ask it for the error + RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata); + eglApiData.Init(EglRFC::EeglGetError); + CVghwUtils::DriverExecuteCommand(eglApiData.Data()); + eglError = (EGLint)eglApiData.ReturnValue(); + EGL_ERROR_PRINT("TEglThreadState::EglError newest error fetched from Host EGL", eglError); + iEglHostHasRecentError = EFalse; + } + else + { + EGL_ERROR_PRINT("TEglThreadState::EglError newest EGL error set by DLL", eglError); + } + iEglError = EGL_SUCCESS; + return eglError; + } + + +void TEglThreadState::ExecuteVgCommand(OpenVgRFC& aVgApiData) + { + CVghwUtils::DriverExecuteCommand(aVgApiData.Data()); + iVgCommandsSinceGetError = ETrue; + iVgCommandsSinceFlush = ETrue; + iVgCommandsSinceFinish = ETrue; + } + + +void TEglThreadState::ExecuteVgFlushCommand() + { + if (iVgCommandsSinceFlush) + { + RemoteFunctionCallData data; OpenVgRFC vgApiData(data); + vgApiData.Init(OpenVgRFC::EvgFlush); + + CVghwUtils::DriverExecuteCommand(vgApiData.Data()); + iVgCommandsSinceFlush = EFalse; + iVgCommandsSinceFinish = EFalse; + } + } + + +void TEglThreadState::ExecuteVgFinishCommand() + { + if (iVgCommandsSinceFinish) + { + RemoteFunctionCallData data; OpenVgRFC vgApiData(data); + vgApiData.Init(OpenVgRFC::EvgFinish); + + CVghwUtils::DriverExecuteCommand(vgApiData.Data()); + iVgCommandsSinceFinish = EFalse; + } + } + + +VGErrorCode TEglThreadState::VgError() + { + VGErrorCode vgError = iVgError; + VG_ERROR_PRINT("TEglThreadState::VgError oldest Open VG DLL error", vgError); + + if (iVgCommandsSinceGetError) + { // fetch and clear the host error state + VGErrorCode hostVgError = GetHostVgError(); + VG_ERROR_PRINT("TEglThreadState::VgError oldest Host Open VG DLL error", hostVgError); + + if (vgError == VG_NO_ERROR) + { + vgError = hostVgError; + } + iVgCommandsSinceGetError = EFalse; + } + + iVgError = VG_NO_ERROR; + return vgError; + } + + +VGErrorCode TEglThreadState::GetHostVgError() + { + RemoteFunctionCallData data; OpenVgRFC vgApiData(data); + vgApiData.Init( OpenVgRFC::EvgGetError ); + + CVghwUtils::DriverExecuteCommand(vgApiData.Data()); + return (VGErrorCode)vgApiData.ReturnValue(); + } + + +// Open GL ES + +GLenum TEglThreadState::GlesError() + { + GLenum glesError = iGlesError; + GLES_ERROR_PRINT("TEglThreadState::GlesError oldest Open GL ES DLL error", glesError); + + if (iGlesCommandsSinceGetError) + { // fetch and clear the host error state + GLenum hostGlesError = GetHostGlesError(); + GLES_ERROR_PRINT("TEglThreadState::GlesError oldest Host Open GL ES DLL error", hostGlesError); + + if (glesError == GL_NO_ERROR) + { + glesError = hostGlesError; + } + iGlesCommandsSinceGetError = EFalse; + } + + iGlesError = GL_NO_ERROR; + return glesError; + } + + +GLenum TEglThreadState::GetHostGlesError() + { + RemoteFunctionCallData data; + OpenGlES11RFC glesApiData(data); + glesApiData.Init(OpenGlES11RFC::EglGetError); + CVghwUtils::DriverExecuteCommand(glesApiData.Data()); + return (GLint)glesApiData.ReturnValue(); + } + + +void TEglThreadState::ExecuteGlesCommand(RemoteFunctionCall& aGlesRequestData) + { + CVghwUtils::DriverExecuteCommand(aGlesRequestData.Data()); + iGlesCommandsSinceGetError = ETrue; + iGlesCommandsSinceFlush = ETrue; + iGlesCommandsSinceFinish = ETrue; + } + + +void TEglThreadState::ExecuteGlesFlushCommand() + { + if (iGlesCommandsSinceFlush) + { + RemoteFunctionCallData rfcData; + OpenGlES11RFC glesApiData( rfcData ); + glesApiData.Init(OpenGlES11RFC::EglFlush, RemoteFunctionCallData::EOpRequest); + CVghwUtils::DriverExecuteCommand(glesApiData.Data()); + iGlesCommandsSinceFlush = EFalse; + iGlesCommandsSinceFinish = EFalse; + } + } + + +void TEglThreadState::ExecuteGlesFinishCommand() + { + if (iGlesCommandsSinceFinish) + { + RemoteFunctionCallData rfcData; + OpenGlES11RFC glesApiData( rfcData ); + glesApiData.Init(OpenGlES11RFC::EglFinish, RemoteFunctionCallData::EOpRequest); + CVghwUtils::DriverExecuteCommand(glesApiData.Data()); + iGlesCommandsSinceFinish = EFalse; + } + } + + +// Open VG state +void TEglThreadState::SetVgError(VGErrorCode aVgError) + { + VGHWPANIC_ASSERT_DEBUG( (aVgError >= VG_BAD_HANDLE_ERROR) && (aVgError <= 0x10FF), EVghwPanicBadVgErrorValue); + // for Open VG track the oldest uncleared error + VG_ERROR_PRINT("TEglThreadState::SetVgError error", aVgError); + if ( (iVgError == VG_NO_ERROR) && (aVgError >= VG_BAD_HANDLE_ERROR) && (aVgError <= 0x10FF) ) + { + if (iVgCommandsSinceGetError) + { + iVgError = GetHostVgError(); + VG_ERROR_PRINT("TEglThreadState::SetVgError oldest Host Open VG DLL error", iVgError); + if (iVgError != VG_NO_ERROR) + { + return; + } + } + iVgError = aVgError; + } + } + + +EGLContext TEglThreadState::VgEglContext() + { + return iVgEglContext; + } + + +// Open GL ES thread state +void TEglThreadState::SetGlesError(GLenum aGlesError) + { + VGHWPANIC_ASSERT_DEBUG( (aGlesError >= GL_INVALID_ENUM) && (aGlesError <= 0x05FF), EVghwPanicBadGlesErrorValue); + // for Open GL ES track the oldest uncleared error + GLES_ERROR_PRINT("TEglThreadState::SetGlesError error", aGlesError); + if ( (iGlesError == GL_NO_ERROR) && (aGlesError >= GL_INVALID_ENUM) && (aGlesError <= 0x05FF) ) + { + if (iGlesCommandsSinceGetError) + { + iGlesError = GetHostGlesError(); + GLES_ERROR_PRINT("TEglThreadState::SetGlesError oldest Host Open GL ES DLL error", iGlesError); + if (iGlesError != GL_NO_ERROR) + { + return; + } + } + iGlesError = aGlesError; + } + } + + +EGLContext TEglThreadState::GlesEglContext() + { + return iGlesEglContext; + } + +// ----------------------------------------------------------------------------- +// Use driver to discover base address of the frame memory. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt TVghwUtils::GetFrameBufferBaseAddress( TUint32& aHWAddress ) + { + UTIL_TRACE("TVghwUtils::GetFrameBufferBaseAddress"); + return VghwSingleton.Driver().GetFrameBufferBaseAddress( aHWAddress ); + } + +#ifdef _DEBUG +static void EglErrorPrint(char* aTitle, EGLint aEglError) + { + char* errName = NULL; + switch (aEglError) + { + case EGL_SUCCESS: errName = "EGL_SUCCESS"; break; + case EGL_NOT_INITIALIZED: errName = "EGL_NOT_INITIALIZED"; break; + case EGL_BAD_ACCESS: errName = "EGL_BAD_ACCESS"; break; + case EGL_BAD_ALLOC: errName = "EGL_BAD_ALLOC"; break; + case EGL_BAD_ATTRIBUTE: errName = "EGL_BAD_ATTRIBUTE"; break; + case EGL_BAD_CONFIG: errName = "EGL_BAD_CONFIG"; break; + case EGL_BAD_CONTEXT: errName = "EGL_BAD_CONTEXT"; break; + case EGL_BAD_CURRENT_SURFACE: errName = "EGL_BAD_CURRENT_SURFACE"; break; + case EGL_BAD_DISPLAY: errName = "EGL_BAD_DISPLAY"; break; + case EGL_BAD_MATCH: errName = "EGL_BAD_MATCH"; break; + case EGL_BAD_NATIVE_PIXMAP: errName = "EGL_BAD_NATIVE_PIXMAP"; break; + case EGL_BAD_NATIVE_WINDOW: errName = "EGL_BAD_NATIVE_WINDOW"; break; + case EGL_BAD_PARAMETER: errName = "EGL_BAD_PARAMETER"; break; + case EGL_BAD_SURFACE: errName = "EGL_BAD_SURFACE"; break; + case EGL_CONTEXT_LOST: errName = "EGL_CONTEXT_LOST"; break; + default: break; // Error is from a new version of EGL + } + + if (errName) + { + UTIL_TRACE( " %s=%s (0x%x)", aTitle, errName, aEglError); + } + else + { + UTIL_TRACE( " %s=0x%x", aTitle, aEglError); + } + } + + +static void VgErrorPrint(char* aTitle, VGErrorCode aVgError) + { + char* errName = NULL; + switch (aVgError) + { + case VG_NO_ERROR: errName = "VG_NO_ERROR"; break; + case VG_BAD_HANDLE_ERROR: errName = "VG_BAD_HANDLE_ERROR"; break; + case VG_ILLEGAL_ARGUMENT_ERROR: errName = "VG_ILLEGAL_ARGUMENT_ERROR"; break; + case VG_OUT_OF_MEMORY_ERROR: errName = "VG_OUT_OF_MEMORY_ERROR"; break; + case VG_PATH_CAPABILITY_ERROR: errName = "VG_PATH_CAPABILITY_ERROR"; break; + case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR: errName = "VG_UNSUPPORTED_IMAGE_FORMAT_ERROR"; break; + case VG_UNSUPPORTED_PATH_FORMAT_ERROR: errName = "VG_UNSUPPORTED_PATH_FORMAT_ERROR"; break; + case VG_IMAGE_IN_USE_ERROR: errName = "VG_IMAGE_IN_USE_ERROR"; break; + case VG_NO_CONTEXT_ERROR: errName = "VG_NO_CONTEXT_ERROR"; break; + default: break; // unknown error code from a new version of Open VG + } + + if (errName) + { + UTIL_TRACE( " %s=%s (0x%x)", aTitle, errName, aVgError); + } + else + { + UTIL_TRACE( " %s=0x%x", aTitle, aVgError); + } + } + + +static void GlesErrorPrint(char* aTitle, GLenum aGlesError) + { + char* errName = NULL; + switch (aGlesError) + { + case GL_NO_ERROR: errName = "GL_NO_ERROR"; break; + case GL_INVALID_ENUM: errName = "GL_INVALID_ENUM"; break; + case GL_INVALID_VALUE: errName = "GL_INVALID_VALUE"; break; + case GL_INVALID_OPERATION: errName = "GL_INVALID_OPERATION"; break; + case GL_STACK_OVERFLOW: errName = "GL_STACK_OVERFLOW"; break; + case GL_STACK_UNDERFLOW: errName = "GL_STACK_UNDERFLOW"; break; + case GL_OUT_OF_MEMORY: errName = "GL_OUT_OF_MEMORY"; break; + default: break; // unknown error code from a new version of Open GL ES + } + + if (errName) + { + UTIL_TRACE( " %s=%s (0x%x)", aTitle, errName, aGlesError); + } + else + { + UTIL_TRACE( " %s=0x%x", aTitle, aGlesError); + } + } +#endif + + +// end of file vghwutils.cpp