diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/guestegl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/guestegl.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,2274 @@ +// 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: +// Guest EGL implementation + +#include +#include +#include +#include +#include +#include // for malloc +#include "eglapi.h" + +#include + + +// FAISALMEMON HOLE 0 + +// ----------------------------------------------------------------------------- +// constructor +// ----------------------------------------------------------------------------- +// + +// FAISALMEMON STUB CODE +#define PITCH_OF_TWIPS_PIXELS(a, b) 1 /* This is incorrect; just a stub*/ +#define EGL_CHECK_ERROR(a, b, c) /* This does no checking; just a stub */ +void CGuestEGL::EglInternalFunction_DestroyWindowSurface(TSurfaceInfo&) + { + return; // stub code + } + +EGLBoolean CGuestEGL::EglInternalFunction_SurfaceResized(TEglThreadState&, TSurfaceInfo&, int, int) + { + return EFalse; // stub code + } + +TBool CGuestEGL::EglInternalFunction_SwapWindowSurface(TEglThreadState&, int, int) + { + return EFalse; // stub code + } +TSymbianPixmapTypeId CGuestEGL::EglInternalFunction_GetNativePixmapType(void*) + { + return EPixmapTypeNone; // stub code + } +TBool CGuestEGL::EglInternalFunction_IsValidNativePixmap(void*, TSymbianPixmapTypeId) + { + return EFalse; // stub code + } +const char * CGuestEGL::EglInternalFunction_QueryExtensionList() + { + return NULL; // stub code + } +ProcPointer CGuestEGL::eglGetProcAddress(const char*) + { + return NULL; // stub code + } + +EGLSurface CGuestEGL::eglCreateWindowSurface(TEglThreadState&, int, int, void*, const int*) + { + return 0; // stub code + } +const char* CGuestEGL::eglQueryString(EGLDisplay aDisplay, EGLint aName) + { + return NULL; // stub code + } +// FAISALMEMON END OF STUB CODE + +CGuestEGL::CGuestEGL() : + iEglSyncExtension(NULL) + { + } + +#ifdef FAISALMEMON_S4_SGIMAGE +void CGuestEGL::OpenSgResources() + { + // ToDo delay opening SgDriver until needed, as it force loads Open GL ES 1.1, GL ES 2 and Open VG DLLs if it finds them + TInt err = iSgDriver.Open(); + EGL_TRACE(" CGuestEGL::Create SgDriver.Open err=%d", err); + EGLPANIC_ASSERT(err == KErrNone, EEglPanicSgDriverCreateLocalFailed); + + TVersion sgImageVer = RSgDriver::Version(); + EGL_TRACE(" CGuestEGL::Create sgImageVer=%d.%d", sgImageVer.iMajor, sgImageVer.iMinor); + EGLPANIC_ASSERT(sgImageVer.iMajor == 1, EEglPanicBadSgDriverVersion); + + } +void CGuestEGL::CloseSgResources() + { + iSgDriver.Close(); + } +#else +void CGuestEGL::CloseSgResources() + { + } + +void CGuestEGL::OpenSgResources() + { + } +#endif + +// ----------------------------------------------------------------------------- +// destructor +// ----------------------------------------------------------------------------- +// +CGuestEGL::~CGuestEGL() + { + EGL_TRACE("CGuestEGL::~CGuestEGL"); + // only expected to be called during process termination + if (iEglSyncExtension) + { + delete iEglSyncExtension; + iEglSyncExtension = NULL; + } + iDisplayMapLock.Close(); + CloseSgResources(); + iEglImageLock.Close(); + } + +// ----------------------------------------------------------------------------- +// 2nd phase constructor +// ----------------------------------------------------------------------------- +// +void CGuestEGL::Create() + { + EGL_TRACE(" CGuestEGL::Create -->"); + OpenSgResources(); + TInt err; + err = iDisplayMapLock.CreateLocal(); + EGLPANIC_ASSERT(err == KErrNone, EEglPanicDisplayMapLockCreateLocalFailed); + + err = iEglImageLock.CreateLocal(); + EGLPANIC_ASSERT(err == KErrNone, EEglPanicEglImageLockCreateLocalFailed); + + InitialiseExtensions(); + + const char* initExtensionList = EglInternalFunction_QueryExtensionList(); + EGL_TRACE(" CGuestEGL::Create initExtensionList=0x%x (\"%s\") <--", + initExtensionList, initExtensionList ? initExtensionList : ""); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +CGuestEGL* CGuestEGL::New() + { + EGL_TRACE("CGuestEGL::New start -->"); + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + CGuestEGL* result = new CGuestEGL(); + CVghwUtils::SwitchFromVghwHeap(threadHeap); + EGLPANIC_ASSERT(result, EEglPanicGuestGraphicsAllocFailed); + if (result) + { + result->Create(); + } + EGL_TRACE("CGuestEGL::New end - result=0x%x <--", result); + return result; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CGuestEGL::SetError(EGLint aError) + { // ToDo remove - everything except EGL Sync already uses threadState->SetEglError + EGL_TRACE( "CGuestEGL::SetError EGL error=0x%x", aError); + TEglThreadState* threadState = CVghwUtils::EglThreadState(); + if (threadState) + { + threadState->SetEglError(aError); + } + } + +EGLint CGuestEGL::CheckColorAttributes(const EGLint* aAttribList, EGLint aColorBufferType, EGLint aLuminanceBits, EGLint aRedBits, + EGLint aGreenBits, EGLint aBlueBits, EGLint aAlphaBits) + { + const EGLint* pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_COLOR_BUFFER_TYPE); + if (pValue && (*pValue != aColorBufferType)) + { + return EGL_BAD_MATCH; + } + EGLint colorBits = 0; + if (aColorBufferType == EGL_RGB_BUFFER) + { + colorBits = aRedBits + aGreenBits + aBlueBits + aAlphaBits; + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_RED_SIZE); + if (pValue && (*pValue < aRedBits)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_GREEN_SIZE); + if (pValue && (*pValue < aGreenBits)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_BLUE_SIZE); + if (pValue && (*pValue < aBlueBits)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_LUMINANCE_SIZE); + if (pValue && (*pValue != 0)) + { + return EGL_BAD_MATCH; + } + } + else + { // EGL_LUMINANCE_BUFFER + colorBits = aLuminanceBits + aAlphaBits; + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_RED_SIZE); + if (pValue && (*pValue != 0)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_GREEN_SIZE); + if (pValue && (*pValue != 0)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_BLUE_SIZE); + if (pValue && (*pValue != 0)) + { + return EGL_BAD_MATCH; + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_LUMINANCE_SIZE); + if (pValue && (*pValue < aLuminanceBits)) + { + return EGL_BAD_MATCH; + } + } + + if (aAlphaBits) + { + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_ALPHA_SIZE); + if (pValue && (*pValue < aAlphaBits)) + { + return EGL_BAD_MATCH; + } + } + + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_BUFFER_SIZE); + if (pValue && (*pValue < colorBits)) + { + return EGL_BAD_MATCH; + } + return EGL_SUCCESS; + } + +void CGuestEGL::AppendColorAttributes(EGLint* aAttribList, EGLint aColorBufferType, EGLint aLuminanceBits, EGLint aRedBits, + EGLint aGreenBits, EGLint aBlueBits, EGLint aAlphaBits, TBool aSetVgPreMultAlpha) + { + const EGLint* pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_COLOR_BUFFER_TYPE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_COLOR_BUFFER_TYPE, aColorBufferType); + } + + EGLint colorBits = 0; + if (aColorBufferType == EGL_RGB_BUFFER) + { + colorBits = aRedBits + aGreenBits + aBlueBits + aAlphaBits; + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_RED_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_RED_SIZE, aRedBits); + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_GREEN_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_GREEN_SIZE, aGreenBits); + } + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_BLUE_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_BLUE_SIZE, aBlueBits); + } + } + else + { // EGL_LUMINANCE_BUFFER + colorBits = aLuminanceBits + aAlphaBits; + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_LUMINANCE_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_LUMINANCE_SIZE, aLuminanceBits); + } + } + + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_BUFFER_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_BUFFER_SIZE, colorBits); + } + + if (aAlphaBits) + { + pValue = TAttribUtils::FindAttribValue(aAttribList, EGL_ALPHA_SIZE); + if (!pValue) + { + TAttribUtils::AppendAttribValue(aAttribList, EGL_ALPHA_SIZE, aAlphaBits); + } + } + if (aSetVgPreMultAlpha) + { + EGLint* pSurfaceType = TAttribUtils::FindAttribValue(aAttribList, EGL_SURFACE_TYPE); + if (pSurfaceType) + { + *pSurfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT; + } + } + } + +EGLBoolean CGuestEGL::ChooseConfigForPixmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint* aAttribList, EGLConfig* aConfigs, EGLint aConfigSize, + EGLint* aNumConfig, const void* aPixmap) + { + EGLint error = EGL_SUCCESS; + EGLint* newList = NULL; + + switch ( EglInternalFunction_GetNativePixmapType((EGLNativePixmapType) (aPixmap)) ) + { + case EPixmapTypeFbsBitmap: + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 1.a pixmap type is FbsBitmap (aPixmap=0x%x)", aPixmap); + error = ChooseConfigAttribsForFbsBitmap(aThreadState, aAttribList, reinterpret_cast(aPixmap), &newList); + break; + +#ifdef FAISALMEMON_S4_SGIMAGE + case EPixmapTypeSgImage: + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 1.b pixmap type is SgImage (aPixmap=0x%x)", aPixmap); + error = ChooseConfigAttribsForSgImage(aThreadState, aAttribList, reinterpret_cast(aPixmap), &newList); + break; +#endif + + case EPixmapTypeNone: + default: + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 1.c pixmap type is unknown (aPixmap=0x%x)", aPixmap); + error = EGL_BAD_NATIVE_PIXMAP; + break; + } + + if (error != EGL_SUCCESS) + { + aThreadState.SetEglError(error); + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 2.a encountered error=0x%x", error); + if (newList) + { + CVghwUtils::Free(newList); + } + return EGL_FALSE; + } + + EGLPANIC_ASSERT(newList, EEglPanicTemp); + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 2.b temp AttribList ... (*newList=0x%x)", *newList); + EGL_TRACE_ATTRIB_LIST(newList); + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglChooseConfig ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLintVector(newList, TAttribUtils::AttribListLength(newList) ); + eglApiData.AppendEGLConfigVector(aConfigs, aConfigSize, RemoteFunctionCallData::EOut); + eglApiData.AppendEGLint(aConfigSize); + eglApiData.AppendEGLintVector(aNumConfig, 1, RemoteFunctionCallData::EOut); + EGLBoolean result = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE("CGuestEGL::ChooseConfigForPixmapSurface 3. Host EGL success=%d", result); + + CVghwUtils::Free(newList); + return result; + } + +#ifdef FAISALMEMON_S4_SGIMAGE +EGLBoolean CGuestEGL::ChooseConfigForNativeSgImagePixmapSurface( TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint* aAttribList, EGLConfig* aConfigs, EGLint aConfigSize, + EGLint* aNumConfig, const EGLint* aPixmap ) + { + EGLConfig* sgConfigs; + EGLint sgConfigCnt; + TBool* sgConfigsMatchingAttributes; + TInt sgConfigsMatchingAttributesCnt=0; + EGLint* sgConfigAttribs; + EGLint sgConfigsAttribtCnt; + EGL_TRACE( "CGuestEGL::eglChooseConfig: ChooseConfigForNativePixmapSurface" ); + EglInternalFunction_MetaGetConfigs( aThreadState, sgConfigs, sgConfigCnt, sgConfigAttribs, sgConfigsAttribtCnt ); + EGL_TRACE( "EglInternalFunction_MetaGetConfigAttirb cnt = %d ", sgConfigsAttribtCnt ); + + sgConfigsMatchingAttributes = new TBool[sgConfigCnt]; + + TInt attribs_per_config = EglRFC::MetaGetConfigAttributeCnt(); + TInt configcnt = (TInt) sgConfigsAttribtCnt / attribs_per_config; + EGL_TRACE( "EglInternalFunction_MetaGetConfigs cnt = %d ", configcnt ); + + //The attribute values of aAttribList, in the order of MetaGetConfigAttribute(i) + EGLint* specAttribVals = new EGLint[ attribs_per_config ]; + for( TInt i=0;i *( sgConfigAttribs + i_config*attribs_per_config + i_attr ) ) + { + pass = EFalse; + } + break; + } + case EMask: + { + if( !(*( specAttribVals + i_attr ) & *( sgConfigAttribs + i_config*attribs_per_config + i_attr )) ) + { + pass = EFalse; + } + break; + } + }//switch comparison method + + }//if attribute value specified by client + }//for through the attributes of a configuration + if( pass ) + { + *(sgConfigsMatchingAttributes + i_config) = ETrue; + } + else + { + *(sgConfigsMatchingAttributes + i_config) = EFalse; + } + }//end for through the configurations + + //Now get the configs that match, and return those + TInt aConfigsIndex = 0; + for( TInt i_config = 0;i_config < configcnt; ++i_config ) + { + if( *(sgConfigsMatchingAttributes + i_config) ) + { + if( aConfigsIndex < aConfigSize ) + { + *(aConfigs + (aConfigsIndex++)) = *(sgConfigs + i_config); + ++sgConfigsMatchingAttributesCnt; + } + } + } + //Ok, all done. Delete allocated memory + // ToDo use correct Heap! + delete[] sgConfigs; + delete[] sgConfigsMatchingAttributes; + delete[] sgConfigAttribs; + delete[] specAttribVals; + return EGL_TRUE; + } +#endif + +EGLint CGuestEGL::ChooseConfigAttribsForFbsBitmap(TEglThreadState& aThreadState, const EGLint* aAttribList, const CFbsBitmap* aBitmap, EGLint** aNewList) + { + EGLPANIC_ASSERT_DEBUG(aNewList, EEglPanicTemp); + EGLint error = EGL_SUCCESS; + const TInt listLength = TAttribUtils::AttribListLength(aAttribList); + ASSERT(listLength); + TDisplayMode mode = ENone; + const EGLint* pRenderType = TAttribUtils::FindAttribValue(aAttribList, EGL_RENDERABLE_TYPE); + + mode = aBitmap->DisplayMode(); + EGL_TRACE("CGuestEGL::ChooseConfigAttribsForFbsBitmap bitmap addr=0x%x, Display Mode=%d", aBitmap, mode); + switch (mode) + { + case EColor64K: + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 5, 6, 5); + break; + case EColor16M: + case EColor16MU: + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 8, 8, 8); + break; + case EColor16MA: + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + break; + case EColor16MAP: + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + break; + default: // pixmap not supported + error = EGL_BAD_NATIVE_PIXMAP; + break; + } + + if (error != EGL_SUCCESS) + { + return error; + } + + const TInt KExpansionSpace = 10 * 2; // want enough space for 10 extra attribute/value pairs + *aNewList = (EGLint*) CVghwUtils::Alloc( (listLength + KExpansionSpace) * sizeof(EGLint) ); + if (!*aNewList) + { + return EGL_BAD_ALLOC; + } + memcpy(*aNewList, aAttribList, listLength * sizeof(EGLint)); + + switch (mode) + { + case EColor64K: + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 5, 6, 5); + break; + case EColor16M: + case EColor16MU: + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8); + break; + case EColor16MA: + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + break; + case EColor16MAP: + if (pRenderType && ( (*pRenderType) & EGL_OPENVG_BIT) ) + { + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8, ETrue); + } + else + { + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + } + break; + default: + EGLPANIC_ALWAYS(EEglPanicTemp); + } + + return EGL_SUCCESS; + } + +#ifdef FAISALMEMON_S4_SGIMAGE +EGLint CGuestEGL::ChooseConfigAttribsForSgImage(TEglThreadState& aThreadState, const EGLint* aAttribList, const RSgImage* aSgImage, EGLint** aNewList) + { + ASSERT(aNewList); + EGLint error = EGL_SUCCESS; + const TInt listLength = TAttribUtils::AttribListLength(aAttribList); + ASSERT(listLength); + const EGLint* pRenderType = TAttribUtils::FindAttribValue(aAttribList, EGL_RENDERABLE_TYPE); + + /* + if (!iSgConfigAttribs) + { + EGL_TRACE( "CGuestEGL::ChooseConfigAttribsForSgImage 1. EglInternalFunction_MetaGetConfigs" ); + EGLConfig* config; + EGLint config_cnt; + EglInternalFunction_MetaGetConfigs(aThreadState, config, config_cnt, iSgConfigAttribs, iSgConfigsAttribtCnt); + EGL_TRACE( "EglInternalFunction_MetaGetConfigs cnt = %d ", iSgConfigsAttribtCnt ); + } + if (!iSgConfigAttribs) + { // exit if EglInternalFunction_MetaGetConfigs still failed + return EGL_BAD_ALLOC; + } + */ + // ToDo use iSgConfigAttribs + + // temporarily open a handle to the SgImage + TSgDrawableId sgId = aSgImage->Id(); + RSgDrawable sgHandle; + TSgImageInfo imgInfo; + EGL_TRACE("CGuestEGL::ChooseConfigAttribsForSgImage 1. SgImage Id=0x%lx", sgId); + + // ToDo check SgImage usage bits + if ( (sgId != KSgNullDrawableId) && (KErrNone == sgHandle.Open(sgId)) && (KErrNone == aSgImage->GetInfo(imgInfo)) ) + { + EGL_TRACE("CGuestEGL::ChooseConfigAttribsForSgImage 2. SgImage PixelFormat=0x%x; size=%d,%d; Usage=0x%x", + imgInfo.iPixelFormat, imgInfo.iSizeInPixels.iWidth, imgInfo.iSizeInPixels.iHeight, imgInfo.iUsage); + + switch (imgInfo.iPixelFormat) + { + case ESgPixelFormatARGB_8888_PRE: // == EUidPixelFormatARGB_8888_PRE + case ESgPixelFormatARGB_8888: // == EUidPixelFormatARGB_8888, + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + break; + case ESgPixelFormatXRGB_8888: // == EUidPixelFormatXRGB_8888, + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 8, 8, 8); + break; + case ESgPixelFormatRGB_565: // == EUidPixelFormatRGB_565, + error = CheckColorAttributes(aAttribList, EGL_RGB_BUFFER, 0, 5, 6, 5); + break; + case ESgPixelFormatA_8: // == EUidPixelFormatA_8 + error = CheckColorAttributes(aAttribList, EGL_LUMINANCE_BUFFER, 8, 0, 0, 0); + break; + default: // pixmap not supported + error = EGL_BAD_NATIVE_PIXMAP; + break; + } + } + else + { + error = EGL_BAD_PARAMETER; + } + sgHandle.Close(); + + + if (error != EGL_SUCCESS) + { + return error; + } + + const TInt KExpansionSpace = 10 * 2; // want enough space for 10 extra attribute/value pairs + *aNewList = (EGLint*) CVghwUtils::Alloc( (listLength + KExpansionSpace) * sizeof(EGLint) ); + if (!*aNewList) + { + return EGL_BAD_ALLOC; + } + memcpy(*aNewList, aAttribList, listLength * sizeof(EGLint)); + + switch (imgInfo.iPixelFormat) + { + case ESgPixelFormatARGB_8888_PRE: // == EUidPixelFormatARGB_8888_PRE + if (pRenderType && ( (*pRenderType) & EGL_OPENVG_BIT) ) + { + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8, ETrue); + } + else + { + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + } + break; + case ESgPixelFormatARGB_8888: // == EUidPixelFormatARGB_8888, + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8, 8); + break; + case ESgPixelFormatXRGB_8888: // == EUidPixelFormatXRGB_8888, + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 8, 8, 8); + break; + case ESgPixelFormatRGB_565: // == EUidPixelFormatRGB_565, + AppendColorAttributes(*aNewList, EGL_RGB_BUFFER, 0, 5, 6, 5); + break; + case ESgPixelFormatA_8: // == EUidPixelFormatA_8 + AppendColorAttributes(*aNewList, EGL_LUMINANCE_BUFFER, 8, 0, 0, 0); + break; + default: // pixmap not supported - panic because this code should be in-sync with supported SgImage formats + EGLPANIC_ALWAYS(EEglPanicTemp); + break; + } + + // change requested surface type from pixmap to Pbuffer + EGLint* pSurfaceType = TAttribUtils::FindAttribValue(*aNewList, EGL_SURFACE_TYPE); + EGLint surfaceType = *pSurfaceType; + *pSurfaceType = EGL_PBUFFER_BIT | (surfaceType & ~EGL_PIXMAP_BIT); + + TAttribUtils::RemoveAttrib(*aNewList, EGL_MATCH_NATIVE_PIXMAP); + return EGL_SUCCESS; + } +#endif + +/* + Create an information object for an opened Display. + */ +TBool CGuestEGL::CreateDisplayInfo(EGLDisplay aDisplay) + { + TBool result = EFalse; + EGL_TRACE("CGuestEGL::CreateDisplayInfo begin aDisplay=%d", aDisplay); + iDisplayMapLock.WriteLock(); + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + if (NULL != iDisplayMap.Find( aDisplay)) + { + result = ETrue; + } + else + { + TInt err = KErrNoMemory; + CEglDisplayInfo* dispInfo = new CEglDisplayInfo; + + if (dispInfo) + { + err = iDisplayMap.Insert(aDisplay, dispInfo); + // EGL_TRACE("CreateDisplayInfo - DisplayMap insert error %d", err); + EGLPANIC_ASSERT_DEBUG(err == KErrNone, EEglPanicDisplayMapInsertFailed); + + //added for egl sync extension benefit + if (iEglSyncExtension) + { + err = iEglSyncExtension->EglSyncDisplayCreate(aDisplay); + // EGL_TRACE("CreateDisplayInfo - EglSyncDisplayCreate error %d", err); + EGLPANIC_ASSERT_DEBUG(err == KErrNone, EEglPanicEglSyncDisplayCreateFailed); + + if (err) + { + iDisplayMap.Remove(aDisplay); + } + } + } + + if (err == KErrNone) + { + result = ETrue; + } + } + CVghwUtils::SwitchFromVghwHeap(threadHeap); + iDisplayMapLock.Unlock(); + + EGL_TRACE("CreateDisplayInfo end, result=%d", result); + return result; + } + +/* + Mark information object for Display as Initialised + */ +TBool CGuestEGL::InitializeDisplayInfo(EGLDisplay aDisplay) + { + TBool result = EFalse; + EGL_TRACE("CGuestEGL::InitialiseDisplayInfo begin aDisplay=%d", aDisplay); + iDisplayMapLock.WriteLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (pDispInfo && *pDispInfo) + { + (*pDispInfo)->iInitialized = ETrue; + result = ETrue; + } + iDisplayMapLock.Unlock(); + + EGL_TRACE("InitialiseDisplayInfo end, result=%d", result); + return result; + } + +/* + Check whether Display exists and is Initialised + */ +TBool CGuestEGL::IsDisplayInitialized(EGLDisplay aDisplay) + { + TBool result = EFalse; + EGL_TRACE("CGuestEGL::IsDisplayInitialized begin aDisplay=%d", aDisplay); + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if ( pDispInfo && *pDispInfo && (*pDispInfo)->iInitialized) + { + result = ETrue; + } + iDisplayMapLock.Unlock(); + + EGL_TRACE("IsDisplayInitialized end, result=%d", result); + return result; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TInt CGuestEGL::EglInternalFunction_GetPitch(RWindow* aNativeWindow, TInt& aHorizontalPitch, TInt& aVerticalPitch) + { + RWsSession* ws = aNativeWindow->Session(); + CWsScreenDevice* screenDevice = new CWsScreenDevice(*ws); + if ( !screenDevice ) + { + return KErrNoMemory; + } + TInt err = screenDevice->Construct(); + + if ( KErrNone == err ) + { + TSize pixelSize = screenDevice->SizeInPixels(); + TSize twipSize = screenDevice->SizeInTwips(); + + aHorizontalPitch = PITCH_OF_TWIPS_PIXELS(twipSize.iWidth , pixelSize.iWidth); + aVerticalPitch = PITCH_OF_TWIPS_PIXELS(twipSize.iHeight, pixelSize.iHeight); + } + delete screenDevice; + return err; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLBoolean CGuestEGL::eglSwapBuffers(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface) + { + EglInternalFunction_SwapWindowSurface(aThreadState, aDisplay, aSurface); + + // ToDo when all surfaces are recorded in client validate BEFORE sending cmd to host + TSurfaceInfo* surfaceInfo = EglInternalFunction_GetPlatformSurface( aDisplay, aSurface ); + EGL_CHECK_ERROR( surfaceInfo, EGL_BAD_SURFACE, EGL_FALSE ); + + //Check if surface size has changed + TSize size = surfaceInfo->iNativeWindow->Size(); + + if (size != surfaceInfo->iSize) + { + EGL_TRACE("CGuestEGL::eglSwapBuffers Surface Resized size=%d,%d, surfaceInfo->iSize=%d,%d", + size.iHeight, size.iWidth, surfaceInfo->iSize.iHeight, surfaceInfo->iSize.iWidth); + return EglInternalFunction_SurfaceResized(aThreadState, *surfaceInfo, aDisplay, aSurface); + } + return EGL_TRUE; + } + +EGLBoolean CGuestEGL::eglMakeCurrent(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aDraw, EGLSurface aRead, EGLContext aContext) + { + if (aContext == EGL_NO_CONTEXT) + { + if ( (aDraw != EGL_NO_SURFACE) || (aRead != EGL_NO_SURFACE) ) + { + aThreadState.SetEglError(EGL_BAD_SURFACE); + return EGL_FALSE; + } + EGL_TRACE("CGuestEGL::eglMakeCurrent call host"); + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglMakeCurrent ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(EGL_NO_SURFACE); + eglApiData.AppendEGLSurface(EGL_NO_SURFACE); + eglApiData.AppendEGLContext(EGL_NO_CONTEXT); + + EGLBoolean ret = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE("CGuestEGL::eglMakeCurrent end success=%d", ret); + return (EGLBoolean)ret; + } + else + { + if ( (aDraw == EGL_NO_SURFACE) || (aRead == EGL_NO_SURFACE) ) + { + aThreadState.SetEglError(EGL_BAD_SURFACE); + return EGL_FALSE; + } + // ToDo use new CEglContext code + const TInt KMaxSurfaces( 2 ); + EGLSurface surfaces[KMaxSurfaces]; + TSurfaceInfo* surfaceInfo[KMaxSurfaces] = {NULL, NULL}; + surfaces[0] = aDraw; + if (aDraw != aRead) + { + surfaces[1] = aRead; + } + else + { + surfaces[1] = EGL_NO_SURFACE; + } + + for ( TInt i = 0; i < KMaxSurfaces; i++ ) + { + if ( EGL_NO_SURFACE != surfaces[i] ) + { + EGL_TRACE("CGuestEGL::eglMakeCurrent check surface %d", surfaces[i] ); + surfaceInfo[i] = EglInternalFunction_GetPlatformSurface( aDisplay, surfaces[i] ); + //EGL_CHECK_ERROR( surfaceInfo, EGL_BAD_SURFACE , EGL_FALSE ); + if ( surfaceInfo[i] ) + { + TSize newSize; + switch (surfaceInfo[i]->iSurfaceType) + { + case ESurfaceTypePixmapFbsBitmap: + EGLPANIC_ASSERT_DEBUG(surfaceInfo[i]->iFbsBitmap, EEglPanicTemp); + newSize = surfaceInfo[i]->iFbsBitmap->SizeInPixels(); + break; + case ESurfaceTypeWindow: + EGLPANIC_ASSERT_DEBUG(surfaceInfo[i]->iNativeWindow, EEglPanicTemp); + newSize = surfaceInfo[i]->iNativeWindow->Size(); + break; + default: + // size cannot change for other surface types + newSize = surfaceInfo[i]->iSize; + break; + } + if (newSize != surfaceInfo[i]->iSize) + { + EGL_TRACE("CGuestEGL::eglMakeCurrent resize surface"); + if ( !EglInternalFunction_SurfaceResized(aThreadState, *surfaceInfo[i], aDisplay, surfaces[i] ) ) + { + return EGL_FALSE; + } + surfaceInfo[i]->iSize = newSize; + } + } + } + } + + // adapt to only some surfaces having CEglSurfaceInfo objects so far + EGLSurface drawId = surfaceInfo[0] ? surfaceInfo[0]->iHostSurfaceId : aDraw; + EGLSurface readId = aRead; + if ((aRead == aDraw) && surfaceInfo[0]) + { + readId = surfaceInfo[0]->iHostSurfaceId; + } + else if (surfaceInfo[1]) + { + readId = surfaceInfo[1]->iHostSurfaceId; + } + + EGL_TRACE(" eglMakeCurrent surfaces[0]=0x%x, surfaces[1]=0x%x", surfaces[0], surfaces[1]); + EGL_TRACE(" eglMakeCurrent surfacesInfo[0]=0x%x, surfacesInfo[0].iHostSurfaceId=0x%x", + surfaceInfo[0], surfaceInfo[0] ? surfaceInfo[0]->iHostSurfaceId : NULL); + EGL_TRACE(" eglMakeCurrent surfacesInfo[1]=0x%x, surfacesInfo[1].iHostSurfaceId=0x%x", + surfaceInfo[1], surfaceInfo[1] ? surfaceInfo[1]->iHostSurfaceId : NULL); + + EGL_TRACE("CGuestEGL::eglMakeCurrent call host"); + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglMakeCurrent ); + eglApiData.AppendEGLDisplay(aDisplay); + + EGL_TRACE(" eglApiData.AppendEGLSurface(drawId = 0x%x)", drawId); + eglApiData.AppendEGLSurface(drawId); + EGL_TRACE(" eglApiData.AppendEGLSurface(readId = 0x%x);", readId); + eglApiData.AppendEGLSurface(readId); + + eglApiData.AppendEGLContext(aContext); + EGLBoolean ret = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE("CGuestEGL::eglMakeCurrent end success=%d", ret); + return (EGLBoolean)ret; + } + } + +// FAISALMEMON HOLE 0.1 + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool CGuestEGL::EglInternalFunction_CreateSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLConfig aConfig, RWindow* aNativeWindow, + TSurfaceInfo& aSurfaceInfo) + { + RSurfaceManager::TSurfaceCreationAttributesBuf attributes; + RSurfaceManager::TInfoBuf info; + + aSurfaceInfo.iNativeWindow = aNativeWindow; + aSurfaceInfo.iSurfaceType = ESurfaceTypeWindow; + aSurfaceInfo.iSize = aNativeWindow->Size(); + aSurfaceInfo.iConfigId = aConfig; + aSurfaceInfo.iHostSurfaceId = aSurface; + + // ToDo have function variants that do not validate parameters + eglQuerySurface(aThreadState, aDisplay, aSurface, EGL_VG_ALPHA_FORMAT, &aSurfaceInfo.iAlphaFormat); + eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_BUFFER_SIZE, &aSurfaceInfo.iColorBits); + eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_RED_SIZE, &aSurfaceInfo.iRedBits); + eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_GREEN_SIZE, &aSurfaceInfo.iGreenBits); + eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_BLUE_SIZE, &aSurfaceInfo.iBlueBits); + eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_ALPHA_SIZE, &aSurfaceInfo.iAlphaBits); + + /* + TInt err = LastError(); + EGL_CHECK_ERROR( EGL_SUCCESS == err, err, EGL_FALSE ); + */ + EGL_TRACE(" Win surface details: width=%d height=%d colorbits=%d red=%d green=%d blue=%d alpha=%d alphaformat=0x%x", + aSurfaceInfo.iSize.iWidth, aSurfaceInfo.iSize.iHeight, aSurfaceInfo.iColorBits, aSurfaceInfo.iRedBits, + aSurfaceInfo.iGreenBits, aSurfaceInfo.iBlueBits, aSurfaceInfo.iAlphaBits, aSurfaceInfo.iAlphaFormat); + + TSize size; + + // FAISALMEMON HOLE 1 + + // FAISALMEMON STUB CODE + TUint8 offsetToFirstBuffer = 0; // This is wrong; just stub code + TUint8 offsetToSecondBuffer = 0; // This is wrong; just stub code + // FAISALMEMON END OF STUB CODE + + TUint32 chunkHWBase = 0; + (void)CVghwUtils::MapToHWAddress(aSurfaceInfo.iChunk->Handle(), chunkHWBase); + // FAISALMEMON write code to handle errors in the above function + EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface AFTER VGHWUtils::MapToHWAddress"); + + /* Store the pointer to the pixel data */ + aSurfaceInfo.iBuffer0 = aSurfaceInfo.iChunk->Base() + offsetToFirstBuffer; + aSurfaceInfo.iBuffer1 = aSurfaceInfo.iChunk->Base() + offsetToSecondBuffer; + + aSurfaceInfo.iBuffer0Index = (chunkHWBase + offsetToFirstBuffer) - VVI_FRAMEBUFFER_BASE_ADDRESS; + aSurfaceInfo.iBuffer1Index = (chunkHWBase + offsetToSecondBuffer) - VVI_FRAMEBUFFER_BASE_ADDRESS; + EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface %u %x %x %x %x",chunkHWBase, offsetToFirstBuffer, offsetToSecondBuffer, + aSurfaceInfo.iBuffer0Index, + aSurfaceInfo.iBuffer1Index); + + if ( !EglInternalFunction_CallSetSurfaceParams(aThreadState, aDisplay, aSurface, aSurfaceInfo) ) + { + EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface end failure"); + + return EGL_FALSE; + } + EGL_TRACE("CGuestEGL::EglInternalFunction_CreateSurface end success"); + + return EGL_TRUE; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLBoolean CGuestEGL::eglDestroySurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + EGLBoolean result = EGL_FALSE; + + // do not destroy SgImage surfaces on the Host! + TSurfaceInfo* surfaceInfo = EglInternalFunction_GetPlatformSurface(aDisplay, aSurface); + if (!surfaceInfo) + { // Note: Pbuffer surfaces are not currently recorded in client + eglApiData.Init( EglRFC::EeglDestroySurface ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + result = aThreadState.ExecEglBooleanCmd(eglApiData); + } + else + { + if (surfaceInfo->iSurfaceType != ESurfaceTypePixmapSgImage) + { // destroy surface allocated by Host EGL + eglApiData.Init( EglRFC::EeglDestroySurface ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(surfaceInfo->iHostSurfaceId); + result = aThreadState.ExecEglBooleanCmd(eglApiData); + } +#ifdef FAISALMEMON_S4_SGIMAGE + else + { // release SgImage handle + surfaceInfo->iSgHandle.Close(); + } +#endif + + DestroySurfaceInfo(aDisplay, aSurface); + } + + return result; + } +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CGuestEGL::DestroySurfaceInfo(EGLDisplay aDisplay, EGLSurface aSurface) + { + EGL_TRACE("DestroySurfaceInfo begin"); + + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE("cannot find display %d", aDisplay); + } + else + { + TSurfaceInfo** pSurfaceInfo = (*pDispInfo)->iSurfaceMap.Find(aSurface); + if (!pSurfaceInfo) + { + EGL_TRACE("cannot find surface %d for display %d", aSurface, aDisplay); + } + else + { + TSurfaceInfo* surfaceInfo = *pSurfaceInfo; + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + if (surfaceInfo->iNativeWindow) + { + EglInternalFunction_DestroyWindowSurface(*surfaceInfo); + } + delete surfaceInfo; + (*pDispInfo)->iSurfaceMap.Remove( aSurface ); + CVghwUtils::SwitchFromVghwHeap(threadHeap); + EGL_TRACE("DestroySurfaceInfo end"); + } + } + + iDisplayMapLock.Unlock(); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool CGuestEGL::DestroyDisplayInfo (EGLDisplay aDisplay) + { + EGL_TRACE("DestroyDisplayInfo begin aDisplay=%d", aDisplay); + TBool success = EFalse; + + iDisplayMapLock.WriteLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE("cannot find display %d", aDisplay); + } + else + { + success = ETrue; + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + RHashMap::TIter iter((*pDispInfo)->iSurfaceMap); + for (;;) + { + TSurfaceInfo** pSurfaceInfo = const_cast(iter.NextValue()); + if (!pSurfaceInfo) + { + break; + } + + EGL_TRACE("destroying surface %d", *iter.CurrentKey()); + + TSurfaceInfo* surfaceInfo = *pSurfaceInfo; + if (surfaceInfo->iNativeWindow) + { + EglInternalFunction_DestroyWindowSurface(*surfaceInfo); + } + delete surfaceInfo; + } + iDisplayMap.Remove(aDisplay); + CVghwUtils::SwitchFromVghwHeap(threadHeap); + + //added for egl sync extension benefit + if (iEglSyncExtension) + { + iEglSyncExtension->EglSyncDisplayDestroy(aDisplay); + } + } + + iDisplayMapLock.Unlock(); + EGL_TRACE("DestroyDisplayInfo end - ret=%d", success); + return success; + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLBoolean CGuestEGL::EglInternalFunction_CallSetSurfaceParams(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, TSurfaceInfo& aSurfaceInfo) + { + EGL_TRACE("EglInternalFunction_CallSetSurfaceParams begin"); + + RemoteFunctionCallData rfcdata; + EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglSimulatorSetSurfaceParams); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface( aSurface ); + EGLNativeWindowType win = (EGLNativeWindowType)aSurfaceInfo.iNativeWindow->ClientHandle(); + eglApiData.AppendEGLNativeWindowType( win ); + eglApiData.AppendEGLSize(aSurfaceInfo.iSize); + eglApiData.AppendEGLint(aSurfaceInfo.iStride); + eglApiData.AppendEGLint(aSurfaceInfo.iBuffer0Index); + eglApiData.AppendEGLint(aSurfaceInfo.iBuffer1Index); + aThreadState.ExecuteEglNeverErrorCmd(eglApiData); + + EGL_TRACE("EglInternalFunction_CallSetSurfaceParams end"); + return EGL_TRUE; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLint CGuestEGL::ConfigMatchesFbsBitmapPixmap(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const EGLint* aAttribList, TDisplayMode aMode) + { + // ToDo check EGL_VG_ALPHA_FORMAT ? + EGLint colorBits, redBits, greenBits, blueBits, alphaBits; + EGLint wantColorBits, wantRedBits, wantGreenBits, wantBlueBits; + EGLint wantAlphaBits = 0; + switch (aMode) + { + case EColor64K: + wantColorBits = 12; + wantRedBits = 5; + wantGreenBits = 6; + wantBlueBits = 5; + break; + case EColor16M: + case EColor16MU: + wantColorBits = 24; + wantRedBits = 8; + wantGreenBits = 8; + wantBlueBits = 8; + break; + case EColor16MA: + wantColorBits = 32; + wantRedBits = 8; + wantGreenBits = 8; + wantBlueBits = 8; + wantAlphaBits = 8; + break; + case EColor16MAP: + wantColorBits = 32; + wantRedBits = 8; + wantGreenBits = 8; + wantBlueBits = 8; + wantAlphaBits = 8; + break; + default: // pixmap format not supported + return EGL_BAD_NATIVE_PIXMAP; + } + + // ToDo version of these functions lighter on parameter checking - maybe use cached values + if (!eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_BUFFER_SIZE, &colorBits) || + !eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_RED_SIZE, &redBits) || + !eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_GREEN_SIZE, &greenBits) || + !eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_BLUE_SIZE, &blueBits) || + !eglGetConfigAttrib(aThreadState, aDisplay, aConfig, EGL_ALPHA_SIZE, &alphaBits) ) + { // fetch failed + return EGL_BAD_MATCH; + } + + EGL_TRACE("CGuestEGL::ConfigMatchesFbsBitmapPixmap: want %d bpp, %d red, %d green, %d blue, %d alpha\n\tconfig has %d bpp, %d red, %d green, %d blue, %d alpha", + wantColorBits, wantRedBits, wantGreenBits, wantBlueBits, wantAlphaBits, + colorBits, redBits, greenBits, blueBits, alphaBits); + + if ( (colorBits < wantColorBits) || (redBits < wantRedBits) || (greenBits < wantGreenBits) || + (blueBits < wantBlueBits) || (alphaBits < wantAlphaBits) ) + { // config does not match bitmap + return EGL_BAD_MATCH; + } + + return EGL_SUCCESS; + } + +/* + Returns EGL_NO_SURFACE on failure. If the attributes of pixmap do not + correspond to config, then an EGL_BAD_MATCH error is generated. If config does + not support rendering to pixmaps (the EGL_SURFACE_TYPE attribute does not + contain EGL_PIXMAP_BIT), an EGL_BAD_MATCH error is generated. If config does + not support the colorspace or alpha format attributes specified in attrib list + (as defined for eglCreateWindowSurface), an EGL_BAD_MATCH error is generated. + If config is not a valid EGLConfig, an EGL_BAD_CONFIG error is generated. If + pixmap is not a valid native pixmap handle, then an EGL_BAD_NATIVE_PIXMAP + error should be generated. If there is already an EGLSurface associated with + pixmap (as a result of a previous eglCreatePixmapSurface call), then a + EGL_BAD_ALLOC error is generated. Finally, if the implementation cannotallocate + resources for the new EGL pixmap, an EGL_BAD_ALLOC error is generated. + */ +EGLSurface CGuestEGL::eglCreatePixmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, EGLNativePixmapType aNativePixmap, const EGLint *aAttribList) + { + EGL_TRACE( "CGuestEGL::eglCreatePixmapSurface"); + EGL_TRACE_ATTRIB_LIST(aAttribList); + + EGLSurface newSurfaceId = EGL_NO_SURFACE; + TSurfaceInfo* surfaceInfo = NULL; + EGLint error = EGL_BAD_DISPLAY; + TSymbianPixmapTypeId pixmapType = EPixmapTypeNone; + + const EGLint* pixmapMatch = TAttribUtils::FindAttribValue(aAttribList, EGL_MATCH_NATIVE_PIXMAP); + if ( pixmapMatch && ( (*pixmapMatch) != (EGLint)(aNativePixmap) ) ) + { // if EGL_MATCH_NATIVE_PIXMAP is in the attribute list it must be the same pixmap as aNativePixmap + error = EGL_BAD_MATCH; + } + else + { + iDisplayMapLock.WriteLock(); + CEglDisplayInfo** pDispInfo; + pDispInfo = iDisplayMap.Find(aDisplay); + + if (pDispInfo && *pDispInfo) + { + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + + surfaceInfo = new TSurfaceInfo(); + if (surfaceInfo) + { + surfaceInfo->iConfigId = aConfig; + pixmapType = EglInternalFunction_GetNativePixmapType(aNativePixmap); + switch (pixmapType) + { + case EPixmapTypeFbsBitmap: + newSurfaceId = CreateFbsBitmapSurface(aThreadState, aDisplay, aConfig, reinterpret_cast(aNativePixmap), aAttribList, + *surfaceInfo); + break; +#ifdef FAISALMEMON_S4_SGIMAGE + case EPixmapTypeSgImage: + newSurfaceId = CreateSgImageSurface(aThreadState, aDisplay, aConfig, reinterpret_cast(aNativePixmap), aAttribList, + *surfaceInfo); + break; +#endif + default: + break; + } + if (newSurfaceId == EGL_NO_SURFACE) + { + error = EGL_BAD_NATIVE_PIXMAP; + } + else + { + error = EGL_SUCCESS; + EGL_TRACE( "CGuestEGL::eglCreatePixmapSurface inserting surface 0x%x to display %d", newSurfaceId, aDisplay); + if (KErrNone != (*pDispInfo)->iSurfaceMap.Insert(newSurfaceId, surfaceInfo)) + { + error = EGL_BAD_ALLOC; + if (pixmapType == EPixmapTypeFbsBitmap) + { + (void) eglDestroySurface(aThreadState, aDisplay, newSurfaceId); + } + newSurfaceId = EGL_NO_SURFACE; + } + } + if (error != EGL_SUCCESS) + { + delete surfaceInfo; + surfaceInfo = NULL; + } + } + else + { + error = EGL_BAD_ALLOC; + } + CVghwUtils::SwitchFromVghwHeap(threadHeap); + } // dispInfo + iDisplayMapLock.Unlock(); + } + + aThreadState.SetEglError(error); + + // parameter check failed + if (error != EGL_SUCCESS) + { + EGLPANIC_ASSERT_DEBUG(newSurfaceId == EGL_NO_SURFACE, EEglPanicTemp); + EGLPANIC_ASSERT_DEBUG(surfaceInfo == NULL, EEglPanicTemp); + return EGL_NO_SURFACE; + } + + EGLPANIC_ASSERT_DEBUG(newSurfaceId != EGL_NO_SURFACE, EEglPanicTemp); + EGLPANIC_ASSERT_DEBUG(surfaceInfo != NULL, EEglPanicTemp); + + return newSurfaceId; + } + +EGLSurface CGuestEGL::CreateFbsBitmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, CFbsBitmap* aBitmap, + const EGLint *aAttribList, TSurfaceInfo& aSurfaceInfo) + { + EGLSurface newSurfaceId = EGL_NO_SURFACE; + aSurfaceInfo.iSurfaceType = ESurfaceTypePixmapFbsBitmap; + aSurfaceInfo.iFbsBitmap = aBitmap; + + TDisplayMode mode = ENone; + TInt stride; + aSurfaceInfo.iSize = aBitmap->SizeInPixels(); + EGL_TRACE("CGuestEGL::CreateFbsBitmapSurface image width=%d, height=%d", aSurfaceInfo.iSize.iWidth, aSurfaceInfo.iSize.iHeight); + + // check that a pixmap surface has not previously been created from this CFbsBitmap + if (!EglInternalFunction_PixmapSurfacePreviouslyCreated(aBitmap, EPixmapTypeFbsBitmap)) + { + // error = EGL_BAD_ALLOC; + return EGL_NO_SURFACE; + } + else + { + mode = aBitmap->DisplayMode(); + if (EGL_SUCCESS != ConfigMatchesFbsBitmapPixmap(aThreadState, aDisplay, aConfig, aAttribList, mode)) + { + return EGL_NO_SURFACE; + } + } + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + stride = CFbsBitmap::ScanLineLength(aSurfaceInfo.iSize.iWidth, mode); + eglApiData.Init( EglRFC::EeglCreatePixmapSurface ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLConfig(aConfig); + eglApiData.AppendEGLNativePixmapType((EGLNativePixmapType) aBitmap); + eglApiData.AppendEGLint(mode); + eglApiData.AppendEGLSize(aSurfaceInfo.iSize); + eglApiData.AppendEGLint(stride); + eglApiData.AppendEGLint(EPixmapTypeFbsBitmap); + eglApiData.AppendEGLintVector(aAttribList, TAttribUtils::AttribListLength(aAttribList)); + newSurfaceId = aThreadState.ExecEglSurfaceCmd(eglApiData); + EGL_TRACE( "EeglCreatePixmapSurface aDisplay=%d, config=%d, format=%d, width=%d, height=%d, stride=%d, pixmapType=%d, newSurface=%d", + aDisplay, aConfig, mode, aSurfaceInfo.iSize.iWidth, aSurfaceInfo.iSize.iHeight, stride, EPixmapTypeFbsBitmap, newSurfaceId); + + aSurfaceInfo.iHostSurfaceId = newSurfaceId; + return newSurfaceId; + } + +#ifdef FAISALMEMON_S4_SGIMAGE +EGLSurface CGuestEGL::CreateSgImageSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const RSgImage* aSgImage, + const EGLint *aAttribList, TSurfaceInfo& aSurfaceInfo) + { + // ToDo check that the SgImage is not already being used for a surface or EglImage + aSurfaceInfo.iSurfaceType = ESurfaceTypePixmapSgImage; + aSurfaceInfo.iSgId = aSgImage->Id(); + + EGL_TRACE("CGuestEGL::CreateSgImageSurface sgImage id 0x%lx", aSurfaceInfo.iSgId); + TSgImageInfo imgInfo; + // ToDo ensure SgImage has correct suitable usage bits + if ( (aSurfaceInfo.iSgId != KSgNullDrawableId) && (KErrNone == aSurfaceInfo.iSgHandle.Open(aSurfaceInfo.iSgId)) && + (KErrNone == aSgImage->GetInfo(imgInfo)) ) + { + EGL_TRACE("CGuestEGL::CreateSgImageSurface 1. SgImage PixelFormat=%d; size=%d,%d; Usage=0x%x", + imgInfo.iPixelFormat, imgInfo.iSizeInPixels.iWidth, imgInfo.iSizeInPixels.iHeight, imgInfo.iUsage); + aSurfaceInfo.iSize = imgInfo.iSizeInPixels; + + /* Package the handles to 64-bit value, since there's only one parameter available. + pbufferHandle is the lower 32 bits, VGImageHandle is the upper bits. */ + TUint64 sgHandles; + EGLint hostResult = CVghwUtils::EglGetSgHandles(aSurfaceInfo.iSgId.iId, &sgHandles); + EGL_TRACE("CGuestEGL::CreateSgImageSurface 2. EglGetSgHandles result=%d, sgHandles=0x%lx", hostResult, sgHandles); + aSurfaceInfo.iHostSurfaceId = (EGLSurface)(sgHandles&0xFFFFFFFF); + return aSurfaceInfo.iHostSurfaceId; + } + + aSurfaceInfo.iSgHandle.Close(); + return EGL_NO_SURFACE; + } +#endif + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TSurfaceInfo* CGuestEGL::EglInternalFunction_GetPlatformSurface( EGLDisplay display, EGLSurface surface ) + { + EGL_TRACE( "CGuestEGL::EglInternalFunction_GetPlatformSurface"); + TSurfaceInfo* result = NULL; + + iDisplayMapLock.ReadLock(); + + CEglDisplayInfo** pDispInfo = iDisplayMap.Find( display ); + if (pDispInfo && *pDispInfo) + { + TSurfaceInfo** pSurfaceInfo = (*pDispInfo)->iSurfaceMap.Find( surface ); + if (pSurfaceInfo) + { + result = *pSurfaceInfo; + } + } + + // TODO on success should probably Unlock() the surface in the caller + iDisplayMapLock.Unlock(); + + /* TODO review calling code, to see if this suggestion makes sense + if (result == NULL) + { + EGL_RAISE_ERROR( EGL_BAD_SURFACE, NULL); //Enable this when all surfaces are in surface map + } + */ + return result; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLBoolean CGuestEGL::eglWaitClient(TEglThreadState& aThreadState) + { + EGL_TRACE( "CGuestEGL::eglWaitClient"); + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglWaitClient); + EGLBoolean result = aThreadState.ExecEglBooleanCmd(eglApiData); + + if (result) + { + // ToDo cache in client, check results are not EGL_NO_DISPLAY / EGL_NO_SURFACE + EGLDisplay display = eglGetCurrentDisplay(aThreadState); + EGLSurface surface = eglGetCurrentSurface(aThreadState, EGL_DRAW); + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find( display ); + TSurfaceInfo* surfaceInfo = NULL; + + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE( "cannot find display %d", display ); + } + else + { + TSurfaceInfo** pSurfaceInfo = (*pDispInfo)->iSurfaceMap.Find( surface ); + if (!pSurfaceInfo) + { + EGL_TRACE( "cannot find surface %d for display %d", surface, display ); + } + else + { + surfaceInfo = *pSurfaceInfo; + } + } + iDisplayMapLock.Unlock(); + if (surfaceInfo == NULL) + { + return EGL_FALSE; + } + if (surfaceInfo->iSurfaceType == ESurfaceTypePixmapFbsBitmap) + { + EGLPANIC_ASSERT_DEBUG(surfaceInfo->iFbsBitmap, EEglPanicTemp); + surfaceInfo->iFbsBitmap->BeginDataAccess(); + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglSimulatorCopyImageData ); + const TSize sizePixels( surfaceInfo->iFbsBitmap->Header().iSizeInPixels ); + eglApiData.AppendVector( (void*)surfaceInfo->iFbsBitmap->DataAddress(), + CFbsBitmap::ScanLineLength( sizePixels.iWidth, surfaceInfo->iFbsBitmap->DisplayMode() )*sizePixels.iHeight, + RemoteFunctionCallData::EOut ); + aThreadState.ExecuteEglNeverErrorCmd(eglApiData); + + surfaceInfo->iFbsBitmap->EndDataAccess(); + } + } + + return result; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLSurface CGuestEGL::eglGetCurrentSurface(TEglThreadState& aThreadState, EGLint aReadDraw) + { + // ToDo cache in client + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglGetCurrentSurface); + eglApiData.AppendEGLint(aReadDraw); + return ExecEglSurfaceNoErrorCmd(aThreadState, eglApiData); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLDisplay CGuestEGL::eglGetCurrentDisplay(TEglThreadState& aThreadState) + { + // ToDo cache in client + EGL_TRACE("CGuestEGL::eglGetCurrentDisplay"); + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglGetCurrentDisplay); + return ExecEglDisplayNoErrorCmd(aThreadState, eglApiData); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLBoolean CGuestEGL::eglCopyBuffers(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLNativePixmapType aTarget) + { + TSize pixmapSize; + + EGL_TRACE("CGuestEGL::eglCopyBuffers"); + EGLBoolean hostResult = EGL_FALSE; + TSymbianPixmapTypeId targetPixmapType = EglInternalFunction_GetNativePixmapType(aTarget); + + // Only CFbsBitmap native pixmaps are supported by this API. (SgImages are not supported, as per the SgImsge Lite spec.) + if ( (targetPixmapType == EPixmapTypeFbsBitmap) && EglInternalFunction_IsValidNativePixmap(aTarget, targetPixmapType) ) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata); + CFbsBitmap* bitmap = (CFbsBitmap*)aTarget; + TSize pixmapSize = bitmap->SizeInPixels(); + bitmap->BeginDataAccess(); + + TDisplayMode mode = bitmap->DisplayMode(); + EGLint stride = CFbsBitmap::ScanLineLength(bitmap->Header().iSizeInPixels.iWidth, mode); + void* data = bitmap->DataAddress(); + +#ifdef _DEBUG + char* modeName = NULL; + switch (mode) + { + case ENone: modeName = "ENone"; break; + case EGray2: modeName = "EGray2"; break; + case EGray4: modeName = "EGray4"; break; + case EGray16: modeName = "EGray16"; break; + case EGray256: modeName = "EGray256"; break; + case EColor16: modeName = "EColor16"; break; + case EColor256: modeName = "EColor256"; break; + case EColor64K: modeName = "EColor64K"; break; + case EColor16M: modeName = "EColor16M"; break; + case ERgb: modeName = "ERgb"; break; + case EColor4K: modeName = "EColor4K"; break; + case EColor16MU: modeName = "EColor16MU"; break; + case EColor16MA: modeName = "EColor16MA"; break; + case EColor16MAP: modeName = "EColor16MAP"; break; + case EColorLast: modeName = "EColorLast"; break; + default: modeName = "unknown"; break; + } + EGL_TRACE("EglInternalFunction_GetNativePixmapInfo (0x%x) -> CFbsBitmap: DisplayMode=%d (\"%s\"), ScanLineLength=%d, data addr=0x%x", + bitmap, mode, modeName, stride, data); +#endif + + eglApiData.Init(EglRFC::EeglCopyBuffers); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + const TSize sizePixels( bitmap->Header().iSizeInPixels ); + eglApiData.AppendVector((void*)bitmap->DataAddress(), + stride*pixmapSize.iHeight, + RemoteFunctionCallData::EOut); + + eglApiData.AppendEGLint((EGLint) mode); + eglApiData.AppendEGLSize(pixmapSize); + eglApiData.AppendEGLint(stride); + eglApiData.AppendEGLint(targetPixmapType); + + hostResult = aThreadState.ExecEglBooleanCmd(eglApiData); + bitmap->EndDataAccess(); + } + else + { + aThreadState.SetEglError(EGL_BAD_NATIVE_PIXMAP); + } + + return hostResult; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +// Beware odd logic: EFalse if surface is found, otherwise ETrue +TBool CGuestEGL::EglInternalFunction_PixmapSurfacePreviouslyCreated(EGLNativePixmapType pixmap, TSymbianPixmapTypeId pixmapType) + { + // ToDo keep a hashmap of pixmap addresses currently used for surfaces + TBool result = ETrue; + if(pixmapType == EPixmapTypeFbsBitmap) + { + iDisplayMapLock.ReadLock(); + RHashMap::TIter iter( iDisplayMap ); + for (;;) + { + CEglDisplayInfo** pDispInfo = const_cast(iter.NextValue()); + if (!pDispInfo || !*pDispInfo) + { + break; + } + + RHashMap::TIter iter2((*pDispInfo)->iSurfaceMap); + for (;;) + { + TSurfaceInfo** pSurfaceInfo = const_cast(iter2.NextValue()); + if (!pSurfaceInfo) + { + break; + } + + TSurfaceInfo* surfaceInfo = *pSurfaceInfo; + if ( (surfaceInfo->iSurfaceType == ESurfaceTypePixmapFbsBitmap) && (surfaceInfo->iFbsBitmap == pixmap) ) + { + result = EFalse; + } + } + } + iDisplayMapLock.Unlock(); + } + + EGL_TRACE("CGuestEGL::EglInternalFunction_PixmapSurfacePreviouslyCreated %d", result); + return result; + } + +// FAISALMEMON HOLE 2 + +EGLDisplay CGuestEGL::eglGetDisplay(TEglThreadState& aThreadState, EGLNativeDisplayType aDisplayId) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata); + eglApiData.Init(EglRFC::EeglGetDisplay); + eglApiData.AppendEGLNativeDisplayType(aDisplayId); + EGLDisplay display = ExecEglDisplayNoErrorCmd(aThreadState, eglApiData); + + if (display != EGL_NO_DISPLAY) + { + if (!CreateDisplayInfo(display)) + { // alloc failed + display = EGL_NO_DISPLAY; + } + } + return display; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +EGLint CGuestEGL::InitialiseExtensions() + { + iEglSyncExtension = CEglSyncExtension::Create(*this); + return EGL_SUCCESS; + } + + +// API supporting EGL sync extension +// lock the display once found +EGLint CGuestEGL::FindAndLockDisplay(EGLDisplay aDisplay) + { + EGLint result = EGL_BAD_DISPLAY; + EGL_TRACE("CGuestEGL::FindAndLockDisplay aDisplay=%d", aDisplay); + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDisp = iDisplayMap.Find(aDisplay); + if (pDisp && *pDisp) + { + CEglDisplayInfo* disp = *pDisp; + if (disp->iInitialized) + { + EGL_TRACE("CGuestEGL::FindAndLockDisplay display found"); + result = EGL_SUCCESS; + } + else + { + EGL_TRACE("CGuestEGL::FindAndLockDisplay display not initialized"); + result = EGL_NOT_INITIALIZED; + } + } + else + { + EGL_TRACE("CGuestEGL::FindAndLockDisplay cannot find display"); + } + if (result != EGL_SUCCESS) + { + iDisplayMapLock.Unlock(); + } + return result; + } + +// release the lock +void CGuestEGL::ReleaseDisplayLock(EGLDisplay aDisplay) + { + EGL_TRACE("CGuestEGL::ReleaseDisplayLock aDisplay=%d", aDisplay); + iDisplayMapLock.Unlock(); + } + + +CEglSyncExtension* CGuestEGL::EGLSyncExtension() + { + return iEglSyncExtension; + } + + +/* + EGL_FALSE is returned on failure and major and minor are not updated. An + EGL_BAD_DISPLAY error is generated if the dpy argument does not refer to a valid + EGLDisplay. An EGL_NOT_INITIALIZED error is generated if EGL cannot be + initialized for an otherwise valid dpy. + */ +EGLBoolean CGuestEGL::eglInitialize(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLint *aMajor, EGLint *aMinor) + { + if ((aDisplay == EGL_NO_DISPLAY) || !InitializeDisplayInfo(aDisplay)) + { + aThreadState.SetEglError(EGL_BAD_DISPLAY); + return EGL_FALSE; + } + + RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata); + eglApiData.Init(EglRFC::EeglInitialize); + eglApiData.AppendEGLDisplay(aDisplay); + EGLBoolean ret = aThreadState.ExecEglBooleanCmd(eglApiData); + + if(ret) + { + if(aMajor) + *aMajor = EGL_VERSION_MAJOR; + if(aMinor) + *aMinor = EGL_VERSION_MINOR; + } + EGL_TRACE("eglInitialize <-" ); + return ret; + } + +/* + Returns EGL_FALSE on failure and value is not updated. If attribute is not a + valid EGL surface attribute, then an EGL_BAD_ATTRIBUTE error is generated. If + surface is not a valid EGLSurface then an EGL_BAD_SURFACE error is generated. + */ +EGLBoolean CGuestEGL::eglQuerySurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aAttribute, EGLint *aValue) + { + // ToDo more parameter validation, and possibly use cached values + if ( (aValue == NULL) || (3 & (TUint32)aValue) ) + { + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_FALSE; + } + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglQuerySurface); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + eglApiData.AppendEGLint(aAttribute); + eglApiData.AppendEGLintVector(aValue, 1, RemoteFunctionCallData::EOut); + + EGLBoolean result = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE_GET_ATTRIB("eglQuerySurface", "surface", aDisplay, aSurface, aAttribute, aValue, result); + return result; + } + +/* + On failure eglCreatePbufferFromClientBuffer returns EGL_NO_SURFACE. In + addition to the errors described eglCreatePbufferSurface, + eglCreatePbufferFromClientBuffer may fail and generate errors for the + following reasons: + * If buftype is not a recognized client API resource type (e.g. is not + EGL_OPENVG_IMAGE), an EGL_BAD_PARAMETER error is generated. + * If buffer is not a valid handle or name of a client API resource of the + specified buftype in the currently bound context corresponding to that + type, an EGL_BAD_PARAMETER error is generated. + * If the buffers contained in buffer do not correspond to a proper subset + of the buffers described by config, and match the bit depths for those + buffers specified in config, then an EGL_BAD_MATCH error is generated. + For example, a VGImage with pixel format VG_lRGBA_8888 corresponds to an + EGLConfig with EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, and + EGL_ALPHA_SIZE values of 8. + * If no context corresponding to the specified buftype is current, an + EGL_BAD_ACCESS error is generated. + * There may be additional constraints on which types of buffers may be + bound to EGL surfaces, as described in client API specifications. If + those constraints are violated, then an EGL_BAD_MATCH error is generated. + * If buffer is already bound to another pbuffer, or is in use by a client + API an EGL_BAD_ACCESS error is generated. + */ +EGLSurface CGuestEGL::eglCreatePbufferFromClientBuffer(TEglThreadState& aThreadState, + EGLDisplay aDisplay, EGLenum aBufType, EGLClientBuffer aBuffer, EGLConfig aConfig, const EGLint *aAttribList) + { + // ToDo validate parameters + // ToDo SgImage Design Spec 5.12 - eglCreatePbufferFromClientBuffer should fail with EGL_BAD_ACCESS for VgImages derived from SgImages + EGL_TRACE("eglCreatePbufferFromClientBuffer %d %d %d", aDisplay, aBufType, aConfig); + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglCreatePbufferFromClientBuffer); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLenum(aBufType); + eglApiData.AppendEGLClientBuffer(aBuffer); + eglApiData.AppendEGLConfig(aConfig); + eglApiData.AppendEGLintVector(aAttribList, TAttribUtils::AttribListLength(aAttribList) ); + + return aThreadState.ExecEglSurfaceCmd(eglApiData); + } + +/* + If the dpy argument does not refer to a valid EGLDisplay, EGL_FALSE is + returned, and an EGL_BAD_DISPLAY error is generated. + */ +EGLBoolean CGuestEGL::eglTerminate(TEglThreadState& aThreadState, EGLDisplay aDisplay) + { + EGLBoolean success = EGL_FALSE; + if (DestroyDisplayInfo(aDisplay)) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglTerminate); + eglApiData.AppendEGLDisplay(aDisplay); + + success = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE("eglTerminate display=%d ret=%d", aDisplay, success); + } + else + { + aThreadState.SetEglError(EGL_BAD_DISPLAY); + } + + return success; + } + +/* + On failure, EGL_FALSE is returned. An EGL_NOT_INITIALIZED error is generated + if EGL is not initialized on dpy. An EGL_BAD_PARAMETER error is generated + if num config is NULL. + */ +EGLBoolean CGuestEGL::eglGetConfigs(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig *aConfigs, + EGLint aConfigSize, EGLint *aNumConfig) + { + EGLint error = EGL_SUCCESS; + + if (aNumConfig == NULL) + { + error = EGL_BAD_PARAMETER; + } + + // ToDo check display is valid + if (error != EGL_SUCCESS) + { + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_FALSE; + } + if (aConfigs && !aConfigSize) + aConfigSize = 1; + else if (!aConfigs) + aConfigSize = 0; + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglGetConfigs); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLConfigVector(aConfigs, aConfigSize, RemoteFunctionCallData::EOut); + eglApiData.AppendEGLint(aConfigSize); + eglApiData.AppendEGLintVector(aNumConfig, 1, RemoteFunctionCallData::EOut); + + // ToDo cache successful result for next time + EGLBoolean result = aThreadState.ExecEglBooleanCmd(eglApiData); + return result; + } + +EGLBoolean CGuestEGL::eglChooseConfig(TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint *aAttribList, + EGLConfig *aConfigs, EGLint aConfigSize, EGLint *aNumConfig) + { + if (aConfigs && !aConfigSize) + { + aConfigSize = 1; + } + else if (!aConfigs) + { + aConfigSize = 0; + } + + const EGLint* surfaceType = TAttribUtils::FindAttribValue(aAttribList, EGL_SURFACE_TYPE); + if (surfaceType && (*surfaceType & EGL_PIXMAP_BIT)) + { + EGL_TRACE("CGuestEGL::eglChooseConfig for Pixmap Surface"); + const EGLint* pixmapMatch = TAttribUtils::FindAttribValue(aAttribList, EGL_MATCH_NATIVE_PIXMAP); + if (pixmapMatch && *pixmapMatch) + { + EGL_TRACE("CGuestEGL::eglChooseConfig attributes include EGL_MATCH_NATIVE_PIXMAP, value is 0x%x", *pixmapMatch); + // check/copy color & alpha sizes from pixmap + return ChooseConfigForPixmapSurface(aThreadState, aDisplay, aAttribList, aConfigs, aConfigSize, aNumConfig, (const void*)*pixmapMatch); + } + else + { // Pixmap to match is missing + EGL_TRACE("CGuestEGL::eglChooseConfig EGL_MATCH_NATIVE_PIXMAP attribute is missing or NULL"); + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_FALSE; + } + } + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglChooseConfig ); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLintVector(aAttribList, TAttribUtils::AttribListLength(aAttribList)); + eglApiData.AppendEGLConfigVector(aConfigs, aConfigSize, RemoteFunctionCallData::EOut ); + eglApiData.AppendEGLint(aConfigSize); + eglApiData.AppendEGLintVector(aNumConfig, 1, RemoteFunctionCallData::EOut); + + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + On failure returns EGL_FALSE. If attribute + is not a valid attribute then EGL_BAD_ATTRIBUTE is generated. + */ +EGLBoolean CGuestEGL::eglGetConfigAttrib(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLint aAttribute, EGLint *aValue) + { + // ToDo validate display & aAttribute, and maybe get result from local cache + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglGetConfigAttrib); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLConfig(aConfig); + eglApiData.AppendEGLint(aAttribute); + eglApiData.AppendEGLintVector(aValue, 1, RemoteFunctionCallData::EOut); + + EGLBoolean result = aThreadState.ExecEglBooleanCmd(eglApiData); + EGL_TRACE_GET_ATTRIB("eglGetConfigAttrib", "config", aDisplay, aConfig, aAttribute, aValue, result); + return result; + } + +/* + Returns EGL_FALSE on failure and value is not updated. If attribute is not a + valid EGL surface attribute, then an EGL_BAD_ATTRIBUTE error is generated. If + surface is not a valid EGLSurface then an EGL_BAD_SURFACE error is generated. + */ +EGLBoolean CGuestEGL::eglSurfaceAttrib(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, + EGLint aAttribute, EGLint aValue) + { + EGL_TRACE_SET_ATTRIB("eglSurfaceAttrib", "surface", aDisplay, aSurface, aAttribute, aValue); + + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglSurfaceAttrib); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + eglApiData.AppendEGLint(aAttribute); + eglApiData.AppendEGLint(aValue); + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + If eglBindTexImage is called and the surface attribute EGL_TEXTURE_FORMAT is set + to EGL_NO_TEXTURE, then an EGL_BAD_MATCH error is returned. If buffer is already + bound to a texture then an EGL_BAD_ACCESS error is returned. If buffer is not a + valid buffer, then an EGL_BAD_PARAMETER error is generated. If surface is not a + valid EGLSurface, or is not a pbuffer surface supporting texture + binding, then an EGL_BAD_SURFACE error is generated. + */ +EGLBoolean CGuestEGL::eglBindTexImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer) + { + // ToDo validate parameters + if ( (aBuffer == NULL) || (3 & (TUint)aBuffer)) + { + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_FALSE; + } + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglBindTexImage); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + eglApiData.AppendEGLint(aBuffer); + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + If the value of surface attribute EGL_TEXTURE_FORMAT is EGL_NO_TEXTURE, + then an EGL_BAD_MATCH error is returned. If buffer is not a valid buffer + (currently only EGL_BACK_BUFFER may be specified), then an + EGL_BAD_PARAMETER error is generated. If surface is not a valid EGLSurface, + or is not a bound pbuffer surface, then an EGL_BAD_SURFACE error is + returned. + */ +EGLBoolean CGuestEGL::eglReleaseTexImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer) + { + // ToDo validate parameters + if ( (aBuffer == NULL) || (3 & (TUint)aBuffer)) + { + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_FALSE; + } + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglReleaseTexImage); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLSurface(aSurface); + eglApiData.AppendEGLint(aBuffer); + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + Returns EGL_FALSE on failure. If there is no current context on the calling + thread, a EGL_BAD_CONTEXT error is generated. If there is no surface bound + to the current context, a EGL_BAD_SURFACE error is generated. + */ +EGLBoolean CGuestEGL::eglSwapInterval(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLint aInterval) + { + // ToDo validate parameters + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglSwapInterval); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLint(aInterval); + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + On failure returns EGL_NO_CONTEXT. If the current rendering api is EGL_NONE, + then an EGL_BAD_MATCH error is generated (this situation can only arise in + an implementation which does not support OpenGL ES, and prior to the first + call to eglBindAPI). If share context is neither zero nor a valid context + of the same client API type as the newly created context, then an EGL_- + BAD_CONTEXT error is generated. + + ... + */ +EGLContext CGuestEGL::eglCreateContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLContext aShareContext, const EGLint *aAttribList) + { + EGLContext result = EGL_NO_CONTEXT; + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE("cannot find display %d", aDisplay); + } + else + { + CEglContext* shareContext = NULL; + if (aShareContext) + { + CEglContext** pContext = (*pDispInfo)->iContextMap.Find(aShareContext); + if (!pContext || (*pContext)->IsDestroyed()) + { + EGL_TRACE("cannot find share context %d for display %d, or it is destroyed", aShareContext, aDisplay); + aThreadState.SetEglError(EGL_BAD_CONTEXT); + iDisplayMapLock.Unlock(); + return EGL_NO_CONTEXT; + } + } + + CEglContext* newContext = CEglContext::Create(aThreadState, aDisplay, aConfig, shareContext, aAttribList); + if (newContext) + { + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + TInt err = (*pDispInfo)->iContextMap.Insert(newContext->ClientContext(), newContext); + CVghwUtils::SwitchFromVghwHeap(threadHeap); + if (err != KErrNone) + { + newContext->Destroy(aThreadState); + aThreadState.SetEglError(EGL_BAD_ALLOC); + } + else + { + result = newContext->ClientContext(); + } + } + } + + iDisplayMapLock.Unlock(); + return result; + } + +/* + Returns EGL_FALSE on failure. An EGL_BAD_CONTEXT error is generated if ctx is + not a valid context. + */ +EGLBoolean CGuestEGL::eglDestroyContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext) + { + EGLBoolean success = EGL_FALSE; + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE("cannot find display %d", aDisplay); + aThreadState.SetEglError(EGL_BAD_DISPLAY); + } + else + { + CEglContext** pContext = (*pDispInfo)->iContextMap.Find(aContext); + if (!pContext || (*pContext)->IsDestroyed()) + { + EGL_TRACE("cannot find context %d for display %d, or it is destroyed", aContext, aDisplay); + aThreadState.SetEglError(EGL_BAD_CONTEXT); + } + else + { + success = EGL_TRUE; + if ((*pContext)->Destroy(aThreadState)) + { + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + (*pDispInfo)->iContextMap.Remove(aContext); + CVghwUtils::SwitchFromVghwHeap(threadHeap); + } + EGL_TRACE("eglDestroyContext end"); + } + } + + iDisplayMapLock.Unlock(); + return success; + } + +/* + Returns EGL_FALSE on failure and value is not updated. If attribute is not + a valid EGL context attribute, then an EGL_BAD_ATTRIBUTE error is generated. + If ctx is invalid, an EGL_BAD_CONTEXT error is generated. + */ +EGLBoolean CGuestEGL::eglQueryContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext, EGLint aAttribute, EGLint *aValue) + { + EGLBoolean success = EGL_FALSE; + iDisplayMapLock.ReadLock(); + CEglDisplayInfo** pDispInfo = iDisplayMap.Find(aDisplay); + if (!pDispInfo || !*pDispInfo) + { + EGL_TRACE("cannot find display %d", aDisplay); + aThreadState.SetEglError(EGL_BAD_DISPLAY); + } + else + { + CEglContext** pContext = (*pDispInfo)->iContextMap.Find(aContext); + if (!pContext || (*pContext)->IsDestroyed()) + { + EGL_TRACE("cannot find context %d for display %d, or it is destroyed", aContext, aDisplay); + aThreadState.SetEglError(EGL_BAD_CONTEXT); + } + else + { + success = (*pContext)->QueryAttribute(aThreadState, aAttribute, aValue); + } + } + + iDisplayMapLock.Unlock(); + return success; + } + +/* + On failure returns EGL_NO_SURFACE. If the pbuffer could not be created due + to insufficient resources, then an EGL_BAD_ALLOC error is generated. If + config is not a valid EGLConfig, an EGL_BAD_CONFIG error is generated. If + the value specified for either EGL_WIDTH or EGL_HEIGHT is less than zero, + an EGL_BAD_PARAMETER error is generated. If config does not support + pbuffers, an EGL_BAD_MATCH error is generated. + + ... see also comment on exported API + */ +EGLSurface CGuestEGL::eglCreatePbufferSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const EGLint *aAttribList) + { + // ToDo validate parameters + // ToDo store info about surface + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglCreatePbufferSurface); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLConfig(aConfig); + eglApiData.AppendEGLintVector(aAttribList, TAttribUtils::AttribListLength(aAttribList) ); + return aThreadState.ExecEglBooleanCmd(eglApiData); + } + +/* + If there is no current context for the current rendering API, or if the + current rendering API is EGL_NONE, then EGL_NO_CONTEXT is returned (this + is not an error). + */ +EGLContext CGuestEGL::eglGetCurrentContext(TEglThreadState& aThreadState) + { + // ToDo should have this information cached + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglGetCurrentContext); + return ExecEglContextNoErrorCmd(aThreadState, eglApiData); + } + +/** + * + * + * @param aConfigs handle to an EGLConfig pointer, where the new configuration data will be. Ownership is transferred to the client. + * @param aConfigsCnt number of configs that will be in aConfigs upon returning + * + * @param aConfigAttribs handle to a pointer, where the memory will be allocated, and data copied. This will contain a list of + * config attribute _values_, in the order set out in eglrfc::MetaGetConfigAttribute(). + * Format: c1attrval1, c1attrval2, ..., c2attrval1, c2attrval2, ... cNattrvalM + * (the number of attribute values per config is eglrfc::MetaGetConfigAttributeCnt() + * Ownership is transferred to the client. + * @param aConfigAttribsLen handle to an integer value, where the size of the above vector will be stored. + * @param aFetchMode: which configs to fetch, default = EMetaGetConfigsSg (get configs that support sgImage), possible values are + * EMetaGetConfigsAll, //get all the configs available + * EMetaGetConfigsSg, //get configs supporting sg images + * EMetaGetConfigsNonSg, //get configs not supporting sg images + * (only sgImage implemented!) + * + */ +TBool CGuestEGL::EglInternalFunction_MetaGetConfigs(TEglThreadState& aThreadState, EGLConfig*& aConfigs, EGLint& aConfigCnt, EGLint*& aConfigAttribs, EGLint& aConfigAttribsLen, TMetaGetConfigsMode aFetchMode ) + { + aConfigCnt = KConfigsMaxCnt; + //TODO: optimize this so that the length is the number of returned items + aConfigs = (EGLConfig*) CVghwUtils::Alloc( sizeof(EGLConfig) * aConfigCnt ); + aConfigAttribsLen = KConfigsMaxCnt * 29; + //TODO: optimize this so that the length is the number of returned items + aConfigAttribs = (EGLint*) CVghwUtils::Alloc( sizeof(EGLint) * aConfigAttribsLen ); + + RemoteFunctionCallData rfcdata; EglRFC call( rfcdata ); + call.Init( EglRFC::EeglMetaGetConfigs ); + call.AppendEGLintVector( aConfigs, aConfigCnt, RemoteFunctionCallData::EInOut ); + call.AppendEGLintVector( aConfigAttribs, aConfigAttribsLen, RemoteFunctionCallData::EInOut ); + + call.AppendEGLint( (EGLint)aFetchMode ); + + return aThreadState.ExecEglBooleanCmd( call ); + } + + +// Private interfaces for EGL to call into Open VG & Open GL ES +// class MVgApiForEgl - redirects via CVghwUtils to exported functions from Open VG +ExtensionProcPointer CGuestEGL::guestGetVgProcAddress (const char *aProcName) + { + if (!iVgApiForEgl) + { + iVgApiForEgl = CVghwUtils::VgApiForEgl(); + } + if (iVgApiForEgl) + { + return iVgApiForEgl->guestGetVgProcAddress(aProcName); + } + return NULL; + } + + +// class MGles11ApiForEgl - redirects via CVghwUtils to exported functions from Open GL ES 1.1 +ExtensionProcPointer CGuestEGL::guestGetGles11ProcAddress (const char *aProcName) + { + if (!iGles11ApiForEgl) + { + iGles11ApiForEgl = CVghwUtils::Gles11ApiForEgl(); + } + if (iGles11ApiForEgl) + { + return iGles11ApiForEgl->guestGetGles11ProcAddress(aProcName); + } + return NULL; + } + + +// class MGles2ApiForEgl - redirects via CVghwUtils to exported functions from Open GL ES 2 +ExtensionProcPointer CGuestEGL::guestGetGles2ProcAddress (const char *aProcName) + { + if (!iGles2ApiForEgl) + { + iGles2ApiForEgl = CVghwUtils::Gles2ApiForEgl(); + } + if (iGles2ApiForEgl) + { + return iGles2ApiForEgl->guestGetGles2ProcAddress(aProcName); + } + return NULL; + }