# HG changeset patch # User Faisal Memon # Date 1283422815 -3600 # Node ID 2231338401dd3c4406ed2246e7ebba77513efc30 # Parent ec0e558822c5d6130f630c207cbdf14a57fbe1a8# Parent f62733cff1a50458eefc377eb628ca9c9f3be326 Catchup with head diff -r f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/api/src/guestvideodriver.cpp --- a/guestrendering/guestvideodriver/api/src/guestvideodriver.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/api/src/guestvideodriver.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp --- a/guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/group/virtualvideohwdevice.mmp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp --- a/guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/reqhandlerextension.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwchannel.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwdevice.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwserialiser/inc/eglrfc.h --- a/guestrendering/vghwserialiser/inc/eglrfc.h Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/vghwserialiser/inc/eglrfc.h Thu Sep 02 11:20:15 2010 +0100 @@ -89,8 +89,8 @@ EeglWaitNative, // 30 EeglSwapBuffers, EeglCopyBuffers, - EeglPlatsimSetSurfaceParams, - EeglPlatsimCopyImageData, + EeglSimulatorSetSurfaceParams, + EeglSimulatorCopyImageData, EeglPixmapSurfaceSizeChanged, EeglMakeCurrentSg, //sgImage support EeglCreatePixmapSurfaceSg, diff -r f62733cff1a5 -r 2231338401dd guestrendering/vghwserialiser/src/remotefunctioncall.cpp --- a/guestrendering/vghwserialiser/src/remotefunctioncall.cpp Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/vghwserialiser/src/remotefunctioncall.cpp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/eabi/vghwutilsu.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/eabi/vghwutilsu.def Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/group/bld.inf --- a/guestrendering/vghwutils/group/bld.inf Fri Aug 27 11:42:02 2010 +0100 +++ b/guestrendering/vghwutils/group/bld.inf Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/group/vghwutils.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/group/vghwutils.mmp Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/inc/vghwutils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/inc/vghwutils.h Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/rom/vghwutils.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/rom/vghwutils.iby Thu Sep 02 11:20:15 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 f62733cff1a5 -r 2231338401dd guestrendering/vghwutils/src/vghwutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/vghwutils/src/vghwutils.cpp Thu Sep 02 11:20:15 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