# HG changeset patch # User Faisal Memon # Date 1283957118 -3600 # Node ID 220791dae4c42b8a3e96b05dcd1079ce327dadc5 # Parent a4c94be9fb92055fc1aadf4b703a67ab3dce6817 Add TPIP free guest egl diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/group/guestegl.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/group/guestegl.mmp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,64 @@ +// 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 guest egl implementation + +#include +#include // For uids + +TARGET guestegl.dll +TARGETTYPE dll +LINKAS libegl.dll +UID KUidSharedDllUidValue KUidEGLDllUidValue +CAPABILITY CAP_GENERAL_DLL +VENDORID VID_DEFAULT + +OS_LAYER_SYSTEMINCLUDE +OS_LAYER_KERNEL_SYSTEMINCLUDE +OS_LAYER_ESTLIB_SYSTEMINCLUDE + +USERINCLUDE ../inc +USERINCLUDE ../../vghwutils/inc +USERINCLUDE ../../vghwserialiser/inc +USERINCLUDE ../../guestopenvg/inc +USERINCLUDE ../../guestopengles11/inc + +SOURCEPATH ../../vghwserialiser/src +SOURCE eglrfc.cpp + +SOURCEPATH ../src +SOURCE guestegl.cpp +SOURCE eglapi.cpp // exported C functions for EGL +SOURCE egldebug.cpp // verbose debug trace +SOURCE eglsync.cpp // EGL Sync extension +SOURCE eglsgimage.cpp // EGL SgImage Lite extension +SOURCE eglcontext.cpp // client side class for EGL Context +SOURCE eglattribs.cpp // utilities for managing EGL AttribLists + +LIBRARY euser.lib // Mandatory +LIBRARY fbscli.lib // For CFbsBitmap, etc +LIBRARY ws32.lib // For RWindow, Direct Screen Access, etc +LIBRARY surfacemanager.lib +LIBRARY surfaceupdateclient.lib +LIBRARY vghwutils.lib +LIBRARY vghwserialiser.lib +LIBRARY libc.lib // For strcmp, etc + +#ifdef FAISALMEMON_S4_SGIMAGE +LIBRARY sgresource.lib // For RSgImage +#endif + +// standard ARM def file baseline for all implementions +DEFFILE /epoc32/include/def/eabi/libegl14.def // ARM def file + +EPOCALLOWDLLDATA diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/inc/eglapi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/inc/eglapi.h Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,136 @@ +// 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: +// Header file for guest egl implementation + +#ifndef EGLAPI_H_ +#define EGLAPI_H_ + +// INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef FAISALMEMON_S4_SGIMAGE +#include +#endif + +#define EGL_EGLEXT_PROTOTYPES +#include + +class CEglSyncExtension; +#include "remotefunctioncall.h" // data serialisation data types +#include "eglsync.h" // EGL Sync extension +#include "eglrfc.h" // data serialisation stuff +#include "vghwutils.h" // VGHW Utils DLL +#include "guestegl.h" // CGuestEGL class + + +extern CGuestEGL* guestEGL; + +/* + Change value to control how much tracing is generated in UDEB builds + 0 = API traces only + 1 = API traces and parameter validation diagnostics + 2 = API traces, param validation, extra diagnostics + */ +#define EGL_TRACE_LEVEL 0 + +/* +EGL version info +*/ +#define EGL_VERSION_MAJOR 1 +#define EGL_VERSION_MINOR 4 +#define MAKE_VERSION_STRING(major, minor) #major "." #minor + +// tracing +#include +#ifdef _DEBUG + #define EGL_TRACE(fmt, args...) RDebug::Printf(fmt, ##args) + #define EGL_TRACE_DETAIL(level, fmt, args...) if (level <= EGL_TRACE_LEVEL) RDebug::Printf(fmt, ##args) + #define EGLPANIC_ASSERT(condition, panic) if (!(condition)) { EglPanic(panic, #panic, #condition, __FILE__, __LINE__); } + #define EGLPANIC_ASSERT_DEBUG(condition, panic) if (!(condition)) { EglPanic(panic, #panic, #condition, __FILE__, __LINE__); } + #define EGLPANIC_ALWAYS(panic) { EglPanic(panic, #panic, NULL, __FILE__, __LINE__); } + #define EGLPANIC_DEBUG(panic) { EglPanic(panic, #panic, NULL, __FILE__, __LINE__); } + #define EGL_TRACE_ATTRIB_LIST(aAttribList) TAttribUtils::TraceAttribList(aAttribList) + #define EGL_TRACE_GET_ATTRIB(N, T, D, O, A, V, R) TAttribUtils::TraceGetAttrib(N, T, D, O, A, V, R) + #define EGL_TRACE_SET_ATTRIB(N, T, D, O, A, V) TAttribUtils::TraceSetAttrib(N, T, D, O, A, V) +#else + #define EGL_TRACE(fmt, args...) + #define EGL_TRACE_DETAIL(level, fmt, args...) + #define EGLPANIC_ASSERT(condition, panic) if (!(condition)) { EglPanic(panic, NULL, NULL, NULL, __LINE__); } + #define EGLPANIC_ASSERT_DEBUG(condition, panic) + #define EGLPANIC_ALWAYS(panic) { EglPanic(panic, NULL, NULL, NULL, __LINE__); } + #define EGLPANIC_DEBUG(panic) + #define EGL_TRACE_ATTRIB_LIST(aAttribList) + #define EGL_TRACE_GET_ATTRIB(N, T, D, O, A, V, R) + #define EGL_TRACE_SET_ATTRIB(N, T, D, O, A, V) +#endif + + +// Guest EGL panic codes +typedef enum + { + EEglPanicCGuestEGLAllocFailed=1, + EEglPanicDisplayMapLockCreateLocalFailed, + EEglPanicGuestGraphicsAllocFailed, + EEglPanicSgImageHandleInvalid, + EEglPanicExtensionListAllocFailed, + EEglPanicExtensionListCreationError, + EEglPanicHostAndClientBoundApiOutOfSync, + EEglPanicUnexpectedBoundApi, + EEglPanicSymbianPixmapNotSetInSurface, + EEglPanicSymbianWindowNotSetInSurface, // 10 + EEglPanicHostAndClientEglInitOutOfSync, + EEglPanicHostAndClientEglTerminateOutOfSync, + EEglPanicErrorNotSet, + EEglPanicThreadStateNotValidInInternalFunction, + EEglPanicNotReplyOpcode, + EEglPanicDisplayMapInsertFailed, + EEglPanicEglSyncDisplayCreateFailed, + EEglPanicReleaseInvalidDisplay, + EEglPanicNullDisplayPointerInMap, + EEglPanicLockedDisplayNotFound, // 20 + EEglPanicStrayDisplayUnlock, + EEglPanicDisplayNotLockedForWriting, + EEglPanicDisplayAlreadyLocked, + EEglPanicReadLockExpected, + EEglPanicReadFromUnlockedDisplay, + EEglPanicDisplayAlreadyInMap, + EEglPanicDisplayNotFound, + EEglPanicSgDriverCreateLocalFailed, + EEglPanicInvalidNativePixmap, + EEglPanicEglImageLockCreateLocalFailed, // 30 + EEglPanicBadSgDriverVersion, + EEglPanicEglImageRefCountNonZero, + EEglPanicEglImageIsDestroyed, + EEglPanicAtribListLengthTooLong, + EEglPanicTemp, // temporary panic in development code + } TEglPanic; + +void EglPanic(TEglPanic aPanicCode, char* aPanicName, char* aCondition, char* aFile, TInt aLine); + + +inline CGuestEGL& Instance() + { + CGuestEGL* result = (CGuestEGL*)guestEGL; // read value and cast away volatile attribute + EGLPANIC_ASSERT(result, EEglPanicTemp); + return *result; + } + +#endif /* EGLAPI_H_ */ diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/inc/eglsync.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/inc/eglsync.h Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,410 @@ +// 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: +// The API provides functionality which allows waiting on the aSync object +// to become signaled and to change status from signaled to unsignaled or vice +// versa. + +/** + @file + @internalTechnology +*/ + +#ifndef __GUEST_EGL_SYNC_H_ +#define __GUEST_EGL_SYNC_H_ + + +NONSHARABLE_CLASS(CEglSync): public CBase +{ +public: + /*-------------------------------------------------------------------*//*! + * \brief Factory function used to create a CEglSync instance + * \ingroup eglSync + * \param aFrontLock Reference to the lock protecting the sync map + * aHeap Reference to the Heap to be used by EGL Sync extension + * \param aSync the sync id for the new sync to be created + * \param aDisplay the display id of the associated display + * \param aType the sync type + * \return a pointer to the extension instance if successful or NULL otherwise + *//*-------------------------------------------------------------------*/ + static CEglSync* Create(RFastLock& aFrontLock, + EGLSyncKHR aSync, + EGLDisplay aDisplay, + EGLenum aType); + + /*-------------------------------------------------------------------*//*! + * \brief Public destructor + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + ~CEglSync(); + +private: + /*-------------------------------------------------------------------*//*! + * \brief Private constructor + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + CEglSync(RFastLock& aFrontLock, + EGLSyncKHR aSync, + EGLDisplay aDisplay, + EGLenum aType); + + /*-------------------------------------------------------------------*//*! + * \brief Private initialisation method to be used by the factory method + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + TInt Initialize(); + +public: + /*-------------------------------------------------------------------*//*! + * \brief Blocks the calling thread until the specified aSync object + * is signaled, or until nanoseconds have passed. + * It is supposed that the lock protecting + * the sync map is already acquired. The call will release this lock. + * \ingroup eglSync + * \param aFlags If the EGL_FLUSH_COMMANDS_BIT_KHR bit is set in + * and is unsignaled when the function is called, then the equivalent + * of Flush() will be performed for the current API context. + * \param aTimeout The thread will be unblocked when is expired. + * If the is to zero, the function just test the current status + * of the aSync object. If the is set to EGL_FOREVER_KHR, then the + * function does not time out. For all other values, is adjusted to + * the closest aValue which may be substantially longer than one nanosecond. + * \return EGL_CONDITION_SATISFIED if was signaled before + * the timeout expired, which includes the case when was already + * signaled when eglClientWaitSyncKHR was called; EGL_TIMEOUT_EXPIRED_KHR if the + * specified timeout period expired before was signaled; + * EGL_FALSE if an error occurs. + * \error EGL_BAD_PARAMETER if does not equal + * to 0 or EGL_SYNC_FLUSH_COMMAND_BIT_KHR + *//*-------------------------------------------------------------------*/ + EGLint ClientWaitSync(EGLint aFlags, EGLTimeKHR aTimeout); + + /*-------------------------------------------------------------------*//*! + * \brief Signals or unsignals the reusable aSync object. + * \ingroup eglSync + * \param aMode Status of the aSync object. There are two possible states: + * EGL_SIGNALED_KHR and EGL_UNSIGNALED_KHR. + * \return EGL_SUCCESS if an operation was successful; + * EGL_BAD_MATCH if the type of is not EGL_SYNC_REUSABLE_KHR + *//*-------------------------------------------------------------------*/ + EGLint SignalSync(EGLenum aMode); + + /*-------------------------------------------------------------------*//*! + * \brief Preapares the sync object for destruction. + * \ingroup eglSync + * \return EGL_TRUE if the object can be destroyed immediately (the sync lock is not released) + * EGL_FALSE if the object cannot be deleted (the sync lock is released) + *//*-------------------------------------------------------------------*/ + EGLBoolean DestroySyncReady(); + + /*-------------------------------------------------------------------*//*! + * \brief Query an aAttribute of the aSync object + * \ingroup eglSync + * \param aDisplay Identifier of the display which owns the aSync object + * \param aValue Pointer to the aValue for the + * requested aAttribute which will be filled on function return. + * \return EGL_TRUE if an operation was successful and EGL_FALSE otherwise + * \error EGL_BAD_ATTRIBUTE if does not lie within expected range; + * EGL_BAD_MATCH if is not supported + * for the type of aSync object passed in + *//*-------------------------------------------------------------------*/ + EGLBoolean GetSyncAttrib(EGLint aAttribute, EGLint *aValue); + + /*-------------------------------------------------------------------*//*! + * \brief Returns the associated display Id + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLDisplay Display() const { return iDisplay; } + + /*-------------------------------------------------------------------*//*! + * \brief Returns the sync type + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLenum Type() const { return iSyncType; } +private: + const EGLSyncKHR iEglSync; + const EGLDisplay iDisplay; + const EGLenum iSyncType; + EGLenum iSyncState; + EGLBoolean iDestroyed; + EGLint iWaiters; + RMutex iSyncMutex; + RCondVar iSyncCondVar; + RFastLock& iFrontLock; + + static const EGLint KSupportedFlags; +}; + +class CGuestEGL; +NONSHARABLE_CLASS(CEglSyncExtension): public CBase + { +public: + /*-------------------------------------------------------------------*//*! + * \brief Factory function used to create a CEglSyncExtension instance + * \ingroup eglSync + * \param aEglInstance Reference to the Egl Instance implementation object + * \return a pointer to the extension instance if successful or NUL otherwise + *//*-------------------------------------------------------------------*/ + static CEglSyncExtension* Create(CGuestEGL& aEglInstance); + + /*-------------------------------------------------------------------*//*! + * \brief Public destructor + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + ~CEglSyncExtension(); +private: + + /*-------------------------------------------------------------------*//*! + * \brief Private initialisation method to be used by the factory method + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLBoolean Construct(); + + /*-------------------------------------------------------------------*//*! + * \brief Private constructor + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + CEglSyncExtension(CGuestEGL& aEglInstance); + +public: + /*-------------------------------------------------------------------*//*! + * \brief Create a aSync object for the specified display. + * \ingroup api + * \param aDisplay Identifier of the display which will own the aSync object + * \param type Type of the aSync object. EGL_SYNC_REUSABLE_KHR is only supported + * \param attrib_list Attribute-aValue list specifying attributes of the aSync + * object, terminated by an aAttribute entry EGL_NONE + * \return Handle for the created aSync object if successful, EGL_NO_SYNC_KHR otherwise + * \error EGL_BAD_DISPLAY if is not a name of a valid EGLDisplay; + * EGL_NOT_INITIALIZED if the display object associated + * with the has not been initialized; + * EGL_BAD_ATTRIBUTE if is neither NULL nor empty (containing only EGL_NONE) or + * if is not a supported type of aSync object; + * EGL_BAD_ALLOC if the memory allocation related to aSync object is not successful + * \note If is EGL_SYNC_REUSABLE_KHR, a reusable aSync object is created. + * In this case must be NULL or empty (containing only EGL_NONE). + * *//*-------------------------------------------------------------------*/ + static EGLSyncKHR eglCreateSyncKHR(EGLDisplay aDisplay, + EGLenum aType, + const EGLint* aAttribList); + + /*-------------------------------------------------------------------*//*! + * \brief Destroy a aSync object and free memory associated with it + * \ingroup api + * \param aDisplay Identifier of the display which owns the aSync object + * \param aSync Sync object handle. + * \return EGL_TRUE if deletion was successful and EGL_FALSE otherwise + * \error EGL_BAD_DISPLAY if is not a name of a valid EGLDisplay; + * EGL_NOT_INITIALIZED if the display object associated + * with the has not been initialized; + * EGL_BAD_PARAMETER if is not a valid aSync object for + * \note If any eglClientWaitSyncKHR commands are blocking on when + * eglDestroySyncKHR is called, they will be woken up, as if were signaled. + * If no errors are generated, will no longer be the handle of a valid aSync object. + *//*-------------------------------------------------------------------*/ + static EGLBoolean eglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync); + + /*-------------------------------------------------------------------*//*! + * \brief Blocks the calling thread until the specified aSync object + * is signaled, or until nanoseconds have passed. + * \ingroup api + * \param aDisplay Identifier of the display which owns the aSync object. + * \param aSync Sync object handle. + * \param aFlags If the EGL_FLUSH_COMMANDS_BIT_KHR bit is set in + * and is unsignaled when the function is called, then the equivalent + * of Flush() will be performed for the current API context. + * \param aTimeout The thread will be unblocked when is expired. + * If the is to zero, the function just test the current status + * of the aSync object. If the is set to EGL_FOREVER_KHR, then the + * function does not time out. For all other values, is adjusted to + * the closest aValue which may be substantially longer than one nanosecond. + * \return EGL_CONDITION_SATISFIED if was signaled before + * the timeout expired, which includes the case when was already + * signaled when eglClientWaitSyncKHR was called; EGL_TIMEOUT_EXPIRED_KHR if the + * specified timeout period expired before was signaled; + * EGL_FALSE if an error occurs. + * \error EGL_BAD_DISPLAY if is not a name of a valid EGLDisplay; + * EGL_NOT_INITIALIZED if the display object associated w + * ith the has not been initialized; + * EGL_BAD_PARAMETER if is not a valid aSync object for or + * if does not equal to 0 or EGL_SYNC_FLUSH_COMMAND_BIT_KHR + * Note\ More than one eglClientWaitSyncKHR may + * be outstanding on the same at any given time. + * When there are multiple threads blocked on the same and the aSync object is signaled, + * all such threads are released, but the order in which they are released is not defined. + * If a aSync object is destroyed while an eglClientWaitSyncKHR is blocking on that object, + * eglClientWaitSyncKHR will unblock and return immediately, just as if the aSync object + * had been signaled prior to being destroyed. + *//*-------------------------------------------------------------------*/ + static EGLint eglClientWaitSyncKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLint aFlags, + EGLTimeKHR aTimeout); + + /*-------------------------------------------------------------------*//*! + * \brief Signals or unsignals the reusable aSync object. + * \ingroup api + * \param aDisplay Identifier of the display which owns the aSync object. + * \param aSync Sync object handle. + * \param aMode Status of the aSync object. There are two possible states: + * EGL_SIGNALED_KHR and EGL_UNSIGNALED_KHR. + * \return EGL_TRUE if an operation was successful and EGL_FALSE otherwise. + *//*-------------------------------------------------------------------*/ + static EGLBoolean eglSignalSyncKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLenum aMode); + + /*-------------------------------------------------------------------*//*! + * \brief Query an aAttribute of the aSync object + * \ingroup api + * \param aDisplay Identifier of the display which owns the aSync object + * \param aSync Sync object handle. + * \param aAttribute An aAttribute to be retrieved. + * \param aValue Pointer to the aValue for the requested aAttribute + * which will be filled on function return. + * \return EGL_TRUE if an operation was successful and EGL_FALSE otherwise + * \error EGL_BAD_DISPLAY if is not a name of a valid EGLDisplay; + * EGL_NOT_INITIALIZED if the display object associated + * with the has not been initialized; + * EGL_BAD_PARAMETER if is not a valid aSync object for or if is not + * a valid pointer; EGL_BAD_ATTRIBUTE if does not lie within expected range; + * EGL_BAD_MATCH if is not supported for the type of aSync object passed in + *//*-------------------------------------------------------------------*/ + static EGLBoolean eglGetSyncAttribKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLint aAttribute, + EGLint* aValue); + + /*-------------------------------------------------------------------*//*! + * \brief Signals or unsignals the reusable aSync object. + * \ingroup api + * \param aDisplay Identifier of the display which owns the aSync object. + * \param aSync Sync object handle. + * \param aSync Status of the aSync object. There are two possible states: + * EGL_SIGNALED_KHR and EGL_UNSIGNALED_KHR. + * \return EGL_SUCCESS if an operation was successful; + * EGL_BAD_DISPLAY if is not a name of a valid EGLDisplay; + * EGL_NOT_INITIALIZED if the display object associated with the has not + * been initialized; EGL_BAD_PARAMETER if is not a valid aSync object for + * or if does not lie within expected range; + * EGL_BAD_MATCH if the type of is not EGL_SYNC_REUSABLE_KHR + * \note This function does not generate an error. + *//*-------------------------------------------------------------------*/ + static EGLint egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode); + +public: + /*-------------------------------------------------------------------*//*! + * \brief Initialisation request when a new display is created + * \ingroup eglSync + * \param aEglDisplay a display identifier + * \return EGL_SUCCESS if successful; + *//*-------------------------------------------------------------------*/ + TInt EglSyncDisplayCreate(EGLDisplay aDisplay); + + /*-------------------------------------------------------------------*//*! + * \brief Request to destroy all syncs associated with a display as preamble + * of destroying the specified display + * \ingroup eglSync + * \param aEglDisplay a display identifier + *//*-------------------------------------------------------------------*/ + void EglSyncDisplayDestroy(EGLDisplay aDisplay); + +private: + /*-------------------------------------------------------------------*//*! + * \brief Query and request to lock a specified display + * \ingroup eglSync + * \param aEglDisplay a display identifier + * \return EGL_SUCCESS if successful; + * EGL_BAD_DISPLAY is not a name of a valid EGLDisplay + * EGL_NOT_INITIALIZED if the display object associated + * with the has not been initialized + *//*-------------------------------------------------------------------*/ + EGLint FindAndLockDisplay(EGLDisplay aDisplay); + + /*-------------------------------------------------------------------*//*! + * \brief Releases the lock associated with a valid EGLDisplay + * \ingroup eglSync + * \param aEglDisplay a display identifier + *//*-------------------------------------------------------------------*/ + void ReleaseDisplayLock(EGLDisplay aDisplay); + +private: + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLSyncKHR EglCreateSyncKHR(EGLDisplay aDisplay, EGLenum aType, const EGLint* aAttribList); + + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLBoolean EglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync); + + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLint EglClientWaitSyncKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLint aFlags, + EGLTimeKHR aTimeout); + + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLBoolean EglSignalSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode); + + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLBoolean EglGetSyncAttribKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLint aAttribute, + EGLint* aValue); + + /*-------------------------------------------------------------------*//*! + * \brief Private implementation for public static interface + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + EGLint Egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode); + +private: + /*-------------------------------------------------------------------*//*! + * \brief Creates a sync and inserts it in the sync map + * \ingroup eglSync + * \param aEglDisplay the id of the associated display + * \param aType The sync type + * \return the id of the sync created + *//*-------------------------------------------------------------------*/ + EGLSyncKHR CreateSync(EGLDisplay aDisplay, EGLenum aType); + + /*-------------------------------------------------------------------*//*! + * \brief Destroy a sync associated with a display + * \ingroup eglSync + * \param aEglDisplay the id of the associated display + *//*-------------------------------------------------------------------*/ + void EglDestroySync(EGLDisplay aDisplay); + +private: + typedef RHashMap REglSyncHashMap; + + REglSyncHashMap iEglSyncMap; + RFastLock iEglSyncMapLock; + EGLint iEglSyncId; + CGuestEGL& iEglInstance; + }; + +#endif /* __GUEST_EGL_SYNC_H_ */ diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/inc/guestegl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/inc/guestegl.h Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,410 @@ +// 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 Header file + +#ifndef __GUEST__EGL_H +#define __GUEST__EGL_H + + +// CLASS DECLARATION +typedef enum + { + EPixmapTypeNone, + EPixmapTypeFbsBitmap, + EPixmapTypeSgImage, + } TSymbianPixmapTypeId; + + +typedef enum + { + ESurfaceTypeWindow = 0, + ESurfaceTypePbuffer = 1, + ESurfaceTypePixmapFbsBitmap = 2, + ESurfaceTypePixmapSgImage = 3, + } TEglSurfaceType; + + +class RSurfaceManager; +class CEglContext; + +// client side info about a surface +struct TSurfaceInfo + { + TSize iSize; + TEglSurfaceType iSurfaceType; //Surface type + EGLConfig iConfigId; + CFbsBitmap* iFbsBitmap; // Handle for CFbsBitmap +#ifdef FAISALMEMON_S4_SGIMAGE + RSgDrawable iSgHandle; // Handle for RSgImge - keeps image open + TSgDrawableId iSgId; // SgImage Id - to detect 2nd attempted surface using the same SgImage +#endif + EGLSurface iHostSurfaceId; + // Note: most member data is only used by Window surfaces + TSurfaceId iSurfaceId; /* iSurfaceMap; +//private: +// RMutex iContextMapLock; + RHashMap iContextMap; + }; + + +// prototype to help eglGetProcAddress() API +typedef void (*ProcPointer)(...); + + +// Collection of static functions for processing EGL Attribute Lists +class TAttribUtils + { +public: // definitions in eglattribs.cpp + static TInt AttribListLength(const EGLint* aAttribList); + static const EGLint* FindAttribValue(const EGLint* aAttribList, EGLint aAttrib); + // NB only use these on AttribLists with adequate space for editing + static EGLint* FindAttribValue(EGLint* aAttribList, EGLint aAttrib); + static void AppendAttribValue(EGLint* aAttribList, EGLint aAttrib, EGLint aValue); + static void RemoveAttrib(EGLint* aAttribList, EGLint aAttrib); +#ifdef _DEBUG + // definitions in egldebug.cpp + static void TraceAttribList(const EGLint* aAttribList); + static void TraceAttribNames(EGLint aAttrib, EGLint aValue, char** aAttrName, char** aValueName); + static void TraceGetAttrib(char* aApiName, char* aObjType, EGLDisplay aDisplay, EGLint aObject, EGLint aAttribute, EGLint *aValue, EGLBoolean aResult); + static void TraceSetAttrib(char* aApiName, char* aObjType, EGLDisplay aDisplay, EGLint aObject, EGLint aAttribute, EGLint aValue); +#endif + }; + + +// CEglContext represents an EGLContext on Host EGL +NONSHARABLE_CLASS(CEglContext) : public CBase + { +public: + // factory function + static CEglContext* Create(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, CEglContext* aShareContext, const EGLint* aAttribList); + EGLBoolean MakeCurrent(TEglThreadState& aThreadState, EGLSurface aDraw, EGLSurface aRead); + EGLBoolean QueryAttribute(TEglThreadState& aThreadState, EGLint aAttribute, EGLint* aValue); + // These functions return ETrue if they delete themselves + TBool Destroy(TEglThreadState& aThreadState); + TBool MakeNotCurrent(TEglThreadState& aThreadState); + EGLContext ShareContextFamily(); + inline EGLContext HostContext() { return iHostContext; } + inline EGLContext ClientContext() { return iHostContext; } + inline TBool IsDestroyed() { return iIsDestroyed; } + +private: + CEglContext(EGLDisplay aDisplay, EGLConfig aConfig, EGLContext aShareContextFamily, EGLenum aRenderingApi, EGLint aGlesClientVersion); + void Delete(TEglThreadState& aThreadState); + ~CEglContext(); +private: + RMutex iCtxMutex; + TBool iFirstUse; // for eglMakeCurrent + EGLContext iHostContext; // corresponding Host EGL Context + // info from eglCreateContext & eglMakeCurrent + EGLDisplay iDisplay; + EGLContext iShareContextFamily; + EGLConfig iConfigId; // Config id used to create context + EGLenum iRenderingApi; // set by current bound API at creation + EGLSurface iDrawSurface; // currently bound draw surface, if any + // for GL ES Contexts + EGLSurface iReadSurface; // currently bound read surface, if any + EGLint iGlesClientVersion; // set by EGL_CONTEXT_CLIENT_VERSION attribute at creation (default is 1) + // object lifetime management + TBool iIsDestroyed; + }; + + +NONSHARABLE_CLASS(CEglImage) : public CBase + { +public: + CEglImage(); + ~CEglImage(); +#ifdef FAISALMEMON_S4_SGIMAGE + inline void Create(TSgDrawableId aSgImageId, EGLDisplay aDisplay, TSgImageInfo& aSgImageInfo, TInt aPbufferHandle, VGHandle aVgHandle); + TSgDrawableId SgImageId() const; +#endif + inline void Duplicate(); + inline TBool OpenForVgImage(TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId); + inline TBool Close(); + inline TBool Destroy(); + inline TBool IsDestroyed() const; + inline TInt RefCount(); + inline EGLDisplay Display() const; + +private: +#ifdef FAISALMEMON_S4_SGIMAGE + RSgDrawable iSgHandle; // Client Handle + TSgImageInfo iSgImageInfo; +#endif + EGLDisplay iDisplay; + TInt iPbufferHandle; // Handle of the underlying Pbuffer, if any + VGHandle iVgHandle; // Handle of the underlying Host VgImage, if any + TInt iCreateCount; + TInt iOpenCount; + TBool iIsDestroyed; + }; + +const TInt KEglConfigSize = 29; + + +class XGuestEglInitialiser + { +public: + XGuestEglInitialiser(); + ~XGuestEglInitialiser(); + }; + + +/** + * CCGuestEGL + * + */ +NONSHARABLE_CLASS(CGuestEGL) : public CBase, public MEglManagementApi, + public MVgApiForEgl, public MGles11ApiForEgl, public MGles2ApiForEgl + { +public: + // Constructors and destructor + + /** + * Destructor. + */ + ~CGuestEGL(); + + /** + * Public constructor. + */ + static CGuestEGL* New(); + + // class MEglManagementApi - exported as a vtable via CVghwUtils for Open VG and Open GL ES to access EGL info + virtual TBool EglImageOpenForVgImage(EGLImageKHR aImage, TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId); + virtual void EglImageClose(EGLImageKHR aImage); + + + // Private interfaces for EGL to call into Open VG & Open GL ES + // class MVgApiForEgl - redirects via CVghwUtils to exported functions from Open VG + virtual ExtensionProcPointer guestGetVgProcAddress (const char *aProcName); + // class MGles11ApiForEgl - redirects via CVghwUtils to exported functions from Open GL ES 1.1 + virtual ExtensionProcPointer guestGetGles11ProcAddress (const char *aProcName); + // class MGles2ApiForEgl - redirects via CVghwUtils to exported functions from Open GL ES 2 + virtual ExtensionProcPointer guestGetGles2ProcAddress (const char *aProcName); + + + // public support functions for EGL C API + static EGLint CheckColorAttributes(const EGLint* aAttribList, EGLint aColorBufferType, EGLint aLuminanceBits, + EGLint aRedBits, EGLint aGreenBits, EGLint aBlueBits, EGLint aAlphaBits=0); + static void AppendColorAttributes(EGLint* aAttribList, EGLint aColorBufferType, EGLint aLuminanceBits, EGLint aRedBits, + EGLint aGreenBits, EGLint aBlueBits, EGLint aAlphaBits=0, TBool aSetVgPreMultAlpha=EFalse); + + const char *QueryExtensionList(); + + // ToDo probably remove this after EGL Sync refactoring + void SetError( EGLint aError ); + void DestroySurfaceInfo(EGLDisplay aDisplay, EGLSurface aSurface); + + // static functions directly implementing an EGL API + ProcPointer eglGetProcAddress(const char *aProcName); + + // functions directly implementing an EGL API + EGLBoolean eglBindTexImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer); + EGLBoolean eglChooseConfig(TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint *aAttribList, + EGLConfig *aConfigs, EGLint aConfigSize, EGLint *aNumConfig); + EGLBoolean eglCopyBuffers(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLNativePixmapType aTarget); + EGLContext eglCreateContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLContext aShareContext, const EGLint *aAttribList); + EGLImageKHR eglCreateImageKHR(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext, EGLenum aTarget, + EGLClientBuffer aBuffer, const EGLint *aAttribList); + EGLSurface eglCreatePbufferFromClientBuffer(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLenum aBufType, + EGLClientBuffer aBuffer, EGLConfig aConfig, const EGLint *aAttribList); + EGLSurface eglCreatePbufferSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const EGLint *aAttribList); + EGLSurface eglCreatePixmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLNativePixmapType aNativePixmap, const EGLint *aAttribList); + EGLSurface eglCreateWindowSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLNativeWindowType aNativeWindow, const EGLint *aAttribList); + EGLBoolean eglDestroyContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext); + EGLBoolean eglDestroyImageKHR(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLImageKHR aImage); + EGLBoolean eglDestroySurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface); + EGLBoolean eglGetConfigAttrib(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, + EGLint aAttribute, EGLint *aValue); + EGLBoolean eglGetConfigs(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig *aConfigs, + EGLint aConfigSize, EGLint *aNumConfig); + EGLContext eglGetCurrentContext(TEglThreadState& aThreadState); + EGLDisplay eglGetCurrentDisplay(TEglThreadState& aThreadState); + EGLSurface eglGetCurrentSurface(TEglThreadState& aThreadState, EGLint aReadDraw); + EGLDisplay eglGetDisplay(TEglThreadState& aThreadState, EGLNativeDisplayType aDisplayId); + EGLBoolean eglInitialize(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLint *aMajor, EGLint *aMinor); + EGLBoolean eglMakeCurrent(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aDraw, EGLSurface aRead, + EGLContext aContext); + EGLBoolean eglQueryContext(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext, EGLint aAttribute, EGLint *aValue); + const char* eglQueryString(EGLDisplay aDisplay, EGLint aName); + EGLBoolean eglQuerySurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aAttribute, + EGLint *aValue); + EGLBoolean eglReleaseTexImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer); + EGLBoolean eglSurfaceAttrib(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, + EGLint aAttribute, EGLint aValue); + EGLBoolean eglSwapBuffers(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface); + EGLBoolean eglSwapInterval(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLint aInterval); + EGLBoolean eglTerminate(TEglThreadState& aThreadState, EGLDisplay aDisplay); + EGLBoolean eglWaitClient(TEglThreadState& aThreadState); + +public: + // API supporting EGL sync extension + /*-------------------------------------------------------------------*//*! + * \brief Query and request to lock a specified display + * \ingroup eglSync + * \param aEglDisplay a display identifier + * \return EGL_SUCCESS if successful; + * EGL_BAD_DISPLAY is not a name of a valid EGLDisplay + * EGL_NOT_INITIALIZED if the display object associated + * with the has not been initialized + *//*-------------------------------------------------------------------*/ + EGLint FindAndLockDisplay(EGLDisplay aDisplay); + + /*-------------------------------------------------------------------*//*! + * \brief Releases the lock associated with a valid EGLDisplay + * \ingroup eglSync + * \param aEglDisplay a display identifier + *//*-------------------------------------------------------------------*/ + void ReleaseDisplayLock(EGLDisplay aDisplay); + + /*-------------------------------------------------------------------*//*! + * \brief Returns pointer to the EGL sync instance + * \ingroup eglSync + *//*-------------------------------------------------------------------*/ + CEglSyncExtension* EGLSyncExtension(); + +private: + /** + * private constructor, 2nd phase constructor + */ + CGuestEGL(); + void Create(); + void CloseSgResources(); + void OpenSgResources(); + + // private function with "EglInternalFunction_" prefix + TBool EglInternalFunction_CreateSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, EGLConfig aConfig, RWindow* aNativeWindow, TSurfaceInfo& aSurfaceInfo); + void EglInternalFunction_DestroyWindowSurface(TSurfaceInfo& aSurfaceInfo); + TUidPixelFormat EglInternalFunction_GetSymbianPixelFormat(const TSurfaceInfo& aSurfaceInfo); + EGLBoolean EglInternalFunction_CallSetSurfaceParams(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, TSurfaceInfo& aSurfaceInfo); + TBool EglInternalFunction_PixmapSurfacePreviouslyCreated(EGLNativePixmapType pixmap, TSymbianPixmapTypeId pixmapType); + static TSymbianPixmapTypeId EglInternalFunction_GetNativePixmapType(EGLNativePixmapType pixmap); + const char* EglInternalFunction_QueryExtensionList(); + TBool EglInternalFunction_IsValidNativePixmap(EGLNativePixmapType pixmap, TSymbianPixmapTypeId pixmapType); + EGLBoolean EglInternalFunction_SurfaceResized(TEglThreadState& aThreadState, TSurfaceInfo& aSurfaceInfo, EGLDisplay aDisplay, EGLSurface aSurface); + TSurfaceInfo* EglInternalFunction_GetPlatformSurface( EGLDisplay display, EGLSurface surface ); + void EglInternalFunction_AbortWindowInit(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface, TSurfaceInfo* ps, RWindow* window, CWsScreenDevice* screenDevice); + TBool EglInternalFunction_SwapWindowSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLSurface aSurface); + TInt EglInternalFunction_GetPitch( RWindow* aNativeWindow, TInt& aHorizontalPitch, TInt& aVerticalPitch ); + TBool EglInternalFunction_MetaGetConfigs( TEglThreadState& aThreadState, EGLConfig*& aConfigs, EGLint& aConfigCnt, EGLint*& aConfigAttribs, EGLint& aConfigAttribsLen, TMetaGetConfigsMode aFetchMode = EMetaGetConfigsSg ); + + // more private functions + + EGLint ConfigMatchesFbsBitmapPixmap(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const EGLint* aAttribList, TDisplayMode aMode); + EGLBoolean ChooseConfigForPixmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint* aAttribList, EGLConfig* aConfigs, EGLint aConfigSize, + EGLint* aNumConfig, const void* aPixmap); + EGLSurface CreateFbsBitmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, CFbsBitmap* aBitmap, const EGLint *aAttribList, TSurfaceInfo& aSurfaceInfo); + + EGLint ChooseConfigAttribsForFbsBitmap(TEglThreadState& aThreadState, const EGLint* aAttribList, const CFbsBitmap* aBitmap, EGLint** aNewList); + + EGLint ValidateEglImageTarget(EGLDisplay aDisplay, EGLContext aContext, EGLenum aTarget, + EGLClientBuffer aBuffer, const EGLint *aAttribList, TSymbianPixmapTypeId aTargetPixmapType); + + + TBool CreateDisplayInfo(EGLDisplay aDisplay); + TBool InitializeDisplayInfo(EGLDisplay aDisplay); + TBool IsDisplayInitialized(EGLDisplay aDisplay); + TBool DestroyDisplayInfo(EGLDisplay aDisplay); + +#ifdef FAISALMEMON_S4_SGIMAGE + EGLSurface CreateSgImageSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, const RSgImage* aSgImage, const EGLint *aAttribList, + TSurfaceInfo& aSurfaceInfo); + EGLImageKHR CreateNewEglImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, TSgDrawableId aSgId, TSgImageInfo aSgImageInfo); + EGLImageKHR DuplicateEglImageIfItExists(EGLDisplay aDisplay, TSgDrawableId aSgId); + EGLint ChooseConfigAttribsForSgImage(TEglThreadState& aThreadState, const EGLint* aAttribList, const RSgImage* aSgImage, EGLint** aNewList); + EGLBoolean ChooseConfigForNativeSgImagePixmapSurface(TEglThreadState& aThreadState, EGLDisplay aDisplay, const EGLint* aAttribList, EGLConfig* aConfigs, EGLint aConfigSize, + EGLint* aNumConfig, const EGLint* aPixmap); +#endif +private: + //new methods supporting EGL Sync extension + EGLint InitialiseExtensions(); + +private: + RReadWriteLock iDisplayMapLock; // protects the iDisplayMap for multi-threaded clients + RHashMap iDisplayMap; + + RMutex iEglImageLock; // protects the iEglImageArray for multi-threaded clients + RPointerArray iEglImageArray; // ToDo use a Unique Id for the index/handle, rather than the object address + +#ifdef FAISALMEMON_S4_SGIMAGE + EGLint* iSgConfigAttribs; + EGLint iSgConfigsAttribtCnt; + // ToDo (SgImage Design Spec 3.5) ARM EGL should maintain its own lists of native window handles, pixmap handles etc + + char* iEglExtnNameList; // supporting data for eglQueryString() + RSgDriver iSgDriver; +#endif + //data members supporting EGL Sync extension + CEglSyncExtension* iEglSyncExtension; + // vtable pointers populated from CVghwUtils - to access Open VG & GL ES internals, e.g. to support eglGetProcAddress + MVgApiForEgl* iVgApiForEgl; + MGles11ApiForEgl* iGles11ApiForEgl; + MGles2ApiForEgl* iGles2ApiForEgl; + }; + + +/* Execute host EGL functions that cannot fail + These functions do not set the flag to say that an EGL command has been executed since the last host eglGetError. + */ + +inline EGLContext ExecEglContextNoErrorCmd(TEglThreadState& aThreadState, EglRFC& aEglApiData) + { + aThreadState.ExecuteEglNeverErrorCmd(aEglApiData); + return (EGLContext) aEglApiData.ReturnValue(); + } + +inline EGLSurface ExecEglSurfaceNoErrorCmd(TEglThreadState& aThreadState, EglRFC& aEglApiData) + { + aThreadState.ExecuteEglNeverErrorCmd(aEglApiData); + return (EGLSurface) aEglApiData.ReturnValue(); + } + +inline EGLDisplay ExecEglDisplayNoErrorCmd(TEglThreadState& aThreadState, EglRFC& aEglApiData) + { + aThreadState.ExecuteEglNeverErrorCmd(aEglApiData); + return (EGLDisplay) aEglApiData.ReturnValue(); + } + + +#endif // __GUEST__EGL_H diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/rom/guestegl.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/rom/guestegl.iby Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,21 @@ +// 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: +// Rom configuration file for guest egl implementation + +#ifndef __GUEST_EGL_IBY__ +#define __GUEST_EGL_IBY__ + +file=ABI_DIR\BUILD_DIR\guestegl.dll sys\bin\libegl.dll + +#endif diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/eglapi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/eglapi.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,1165 @@ +// 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: +// Implementation of guest egl stub functions + +#include "eglapi.h" +#include + +/* + Only having the pointer as "Writeable Static Data" makes it very easy to tell if + initialisation has been done: the pointer is not NULL! + */ +CGuestEGL* guestEGL; +// Writeable Static Data - causes constructor to be called at load DLL time. +XGuestEglInitialiser GuestEglInitialiser; + + + +XGuestEglInitialiser::XGuestEglInitialiser() + { + EGL_TRACE("XGuestEglInitialiser::XGuestEglInitialiser() - guestEGL=0x%x", guestEGL); + if (!guestEGL) + { + // ensure VGHW Memory heap is created & channel to LDD is opened + CVghwUtils::InitStatics(); + // Multi-Threading safe creation of CGuestEGL instance + if (!guestEGL) + { + // guarantee that initialisation of the object is flushed to memory before the pointer is published + __e32_atomic_store_rel_ptr(&guestEGL, CGuestEGL::New()); + } + + // cast away volatile attribute + CGuestEGL* instance = (CGuestEGL*)guestEGL; + // cannot continue if alloc failed + EGLPANIC_ASSERT(guestEGL, EEglPanicCGuestEGLAllocFailed); + CVghwUtils::SetEglManagementApi(instance); + + CVghwUtils::CreateThreadState(); + } + } + + +XGuestEglInitialiser::~XGuestEglInitialiser() + { + EGL_TRACE("XGuestEglInitialiser::~XGuestEglInitialiser() - guestEGL=0x%x", guestEGL); + if (guestEGL) + { + delete guestEGL; + guestEGL = NULL; + } + CVghwUtils::DestroyStatics(); + } + + +_LIT(KEglPanicCategory, "Guest EGL"); + +void EglPanic(TEglPanic aPanicCode, char* aPanicName, char* aCondition, char* aFile, TInt aLine) + { + if (aPanicName && aCondition && aFile) + { + RDebug::Printf("Guest EGL DLL Panic %s for failed Assert (%s),\n\tat %s:%d", aPanicName, aCondition, aFile, aLine); + } + else if (aPanicName && aFile) + { + RDebug::Printf("Guest EGL DLL Panic %s at %s:%d", aPanicName, aFile, aLine); + } + else + { + RDebug::Printf("Guest EGL DLL Panic %d (line %d)", aPanicCode, aLine); + } + + User::Panic(KEglPanicCategory, aPanicCode); + } + + +extern "C" { +/* + Note: Comments at the start of each EGL api are adapted from the Khronos EGL 1.4 specification. + The text has been chosen/adapted to give a helpful overview of the function, and the errors + that it may generate. For more details see the full Khronos EGL specification. + */ + + +/* + Get details of the last EGL api error in this thread. + + Returns EGL_SUCCESS or an EGL_xxxx error constant. + */ +EXPORT_C EGLint eglGetError(void) + { + EGL_TRACE("eglGetError -->"); + + EGLint eglError = EGL_SUCCESS; + // threadState is non-null if an EGL api has been called in this thread + TEglThreadState* threadState = CVghwUtils::EglThreadState(); // do not create thread object for this API + if (threadState) + { // get error (may be from parameter checking in this DLL or from Host EGL) - fetching resets error to EGL_SUCCESS + eglError = threadState->EglError(); + } + EGL_TRACE("eglGetError returning eglError=0x%x <--", eglError); + return eglError; + } + +/* + Get display handle for display with requested properties. + + If display id is EGL_DEFAULT_DISPLAY, a default display is returned. + Multiple calls made to eglGetDisplay with the same display-id will + all return the same EGLDisplay handle. + If no display matching display id is available, EGL_NO_DISPLAY is + returned; no error condition is raised in this case. + */ +EXPORT_C EGLDisplay eglGetDisplay(EGLNativeDisplayType aDisplayId) + { + EGL_TRACE("eglGetDisplay Display Id=%d -->", aDisplayId); + + EGLDisplay display = EGL_NO_DISPLAY; + // Most likely eglGetDisplay is the first API called, so try initialising EGL instance first + CGuestEGL& instance = Instance(); + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + display = instance.eglGetDisplay(*threadState, aDisplayId); + } + EGL_TRACE("eglGetDisplay result Display=%d <--", display); + return display; + } + +/* + Initialize EGL on a display. + + EGL_TRUE is returned on success, and major and minor are updated with the major + and minor version numbers of the EGL implementation (for example, in an EGL + 1.2 implementation, the values of *major and *minor would be 1 and 2, respectively). + major and minor are not updated if they are specified as NULL. + 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. + */ +EXPORT_C EGLBoolean eglInitialize(EGLDisplay aDisplay, EGLint *aMajor, EGLint *aMinor) + { + EGL_TRACE("eglInitialize Display=%d, Major 0x%x, Minor 0x%x", aDisplay, aMajor, aMinor ); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + EGLBoolean success = EGL_FALSE; + if (threadState) + { + success = Instance().eglInitialize(*threadState, aDisplay, aMajor, aMinor); + } + EGL_TRACE("eglInitialize <- result=%d", success); + return success; + } + +/* + Marks all EGL-specific resources associated with the specified display + for deletion. + + If the dpy argument does not refer to a valid EGLDisplay, EGL_FALSE is + returned, and an EGL_BAD_DISPLAY error is generated. + */ +EXPORT_C EGLBoolean eglTerminate(EGLDisplay aDisplay) + { + EGL_TRACE("eglTerminate Display=%d", aDisplay); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglTerminate(*threadState, aDisplay); + } + return result; + } + +/* + Returns a pointer to a static, zero-terminated string describing some aspect + of the EGL implementation running on the specified display. name may be one + of EGL_CLIENT_APIS, EGL_EXTENSIONS, EGL_VENDOR, or EGL_VERSION. + + The EGL_CLIENT_APIS string describes which client rendering APIs are + supported. It is zero-terminated and contains a space-separated list of API + names, which must include at least one of ‘‘OpenGL’’, ‘‘OpenGL_ES’’ or + ‘‘OpenVG’’. + + The EGL_EXTENSIONS string describes which EGL extensions are supported + by the EGL implementation running on the specified display, and for the + current client API context. The string is zero terminated and contains a + space-separated list of extension names; extension names themselves do + not contain spaces. If there are no extensions to EGL, then the empty string + is returned. + + The format and contents of the EGL_VENDOR string is implementation dependent. + + The format of the EGL_VERSION string is: + + + On failure, NULL is returned. An EGL_NOT_INITIALIZED error is generated + if EGL is not initialized for dpy. An EGL_BAD_PARAMETER error is generated if + name is not one of the values described above. + */ +EXPORT_C const char* eglQueryString(EGLDisplay aDisplay, EGLint aName) + { + EGL_TRACE("eglQueryString Display=%d, Name=0x%x", aDisplay, aName); + + return Instance().eglQueryString(aDisplay, aName); + } + +/* + Get the list of all EGLConfigs that are available on the specified display. + + 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. + */ +EXPORT_C EGLBoolean eglGetConfigs(EGLDisplay aDisplay, EGLConfig *aConfigs, + EGLint aConfigSize, EGLint *aNumConfig) + { + EGL_TRACE("eglGetConfigs Display=%d, ConfigSize=%d , NumConfig=0x%x -->", aDisplay, aConfigSize, aNumConfig); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglGetConfigs(*threadState, aDisplay, aConfigs, aConfigSize, aNumConfig); + } + EGL_TRACE("eglGetConfigs hostResult=%d, NumConfig-%d <--", result, aNumConfig ? *aNumConfig : 0); + return result; + } + +/* + Get EGLConfigs that match a list of attributes. The return value and the meaning + of configs, config size, and num config are the same as for eglGetConfigs. + However, only configurations matching attrib list will be returned. + + On failure, EGL_FALSE is returned. An EGL_BAD_ATTRIBUTE error is generated + if attrib list contains an undefined EGL attribute or an attribute value that is + unrecognized or out of range. + */ +EXPORT_C EGLBoolean eglChooseConfig(EGLDisplay aDisplay, const EGLint *aAttribList, + EGLConfig *aConfigs, EGLint aConfigSize, EGLint *aNumConfig) + { + EGL_TRACE("eglChooseConfig Display=%d, AttribList=0x%x, Configs=0x%x, ConfigSize=%d, NumConfig=0x%x -->", + aDisplay, aAttribList, aConfigs, aConfigSize, aNumConfig); + EGL_TRACE_ATTRIB_LIST(aAttribList); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglChooseConfig(*threadState, aDisplay, aAttribList, aConfigs, aConfigSize, aNumConfig); + } + + EGL_TRACE("eglChooseConfig Result=%s, Num configs=%d, First config=%d <--", + result ? "success" : "fail", + aNumConfig ? *aNumConfig : 0, + (aConfigs && aNumConfig && (*aNumConfig > 0)) ? *aConfigs : -1); + return result; + } + +/* + Get the value of an EGLConfig attribute. + + On failure returns EGL_FALSE. If attribute + is not a valid attribute then EGL_BAD_ATTRIBUTE is generated. + */ +EXPORT_C EGLBoolean eglGetConfigAttrib(EGLDisplay aDisplay, EGLConfig aConfig, + EGLint aAttribute, EGLint *aValue) + { + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglGetConfigAttrib(*threadState, aDisplay, aConfig, aAttribute, aValue); + } + return result; + } + +/* + Creates an onscreen EGLSurface and returns a handle to it. Any EGL context created + with a compatible EGLConfig can be used to render into this surface. + + On failure returns EGL_NO_SURFACE. If the attributes of win do not correspond to + config, then an EGL_BAD_MATCH error is generated. If config does not support + rendering to windows (the EGL_SURFACE_TYPE attribute does not contain + EGL_WINDOW_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 win is not a valid + native window handle, then an EGL_BAD_NATIVE_WINDOW error should be generated. If + there is already an EGLConfig associated with win (as a result of a previous + eglCreateWindowSurface call), then an EGL_BAD_ALLOC error is generated. Finally, + if the implementation cannot allocate resources for the new EGL window, an + EGL_BAD_ALLOC error is generated. + */ +EXPORT_C EGLSurface eglCreateWindowSurface(EGLDisplay aDisplay, EGLConfig aConfig, + EGLNativeWindowType aWindow, const EGLint *aAttribList) + { + EGL_TRACE("eglCreateWindowSurface Display=%d, Config=%d, Window=0x%x -->", aDisplay, aConfig, aWindow); + + EGLSurface newSurface = EGL_NO_SURFACE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + newSurface = Instance().eglCreateWindowSurface(*threadState, aDisplay, aConfig, aWindow, aAttribList); + } + EGL_TRACE("eglCreateWindowSurface new Surface=0x%x <--", newSurface); + return newSurface; + } + +/* + Creates a single off-screen pbuffer surface and returns a handle to it. + + 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. In addition, an EGL_BAD_MATCH + error is generated if any of the following conditions are true: + * The EGL_TEXTURE_FORMAT attribute is not EGL_NO_TEXTURE, and EGL_WIDTH + and/or EGL_HEIGHT specify an invalid size (e.g., the texture size is + not a power of two, and the underlying OpenGL ES implementation does not + support non-power-of-two textures). + * The EGL_TEXTURE_FORMAT attribute is EGL_NO_TEXTURE, and EGL_TEXTURE_TARGET + is something other than EGL_NO_TEXTURE; or, EGL_TEXTURE_FORMAT is + something other than EGL_NO_TEXTURE, and EGL_TEXTURE_TARGET is + EGL_NO_TEXTURE. + Finally, an EGL_BAD_ATTRIBUTE error is generated if any of the EGL_- + TEXTURE_FORMAT, EGL_TEXTURE_TARGET, or EGL_MIPMAP_TEXTURE attributes + are specified, but config does not support OpenGL ES rendering (e.g. + the EGL_RENDERABLE_TYPE attribute does not include at least one of EGL_- + OPENGL_ES_BIT or EGL_OPENGL_ES2_BIT. + */ +EXPORT_C EGLSurface eglCreatePbufferSurface(EGLDisplay aDisplay, EGLConfig aConfig, const EGLint *aAttribList) + { + EGL_TRACE("eglCreatePbufferSurface Display=%d, Config=%d -->", aDisplay, aConfig); + EGL_TRACE_ATTRIB_LIST(aAttribList); + + EGLSurface newSurface = EGL_NO_SURFACE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + newSurface = Instance().eglCreatePbufferSurface(*threadState, aDisplay, aConfig, aAttribList); + } + EGL_TRACE("eglCreatePbufferSurface new Surface=0x%x <--", newSurface); + return newSurface; + } + +/* + Creates an offscreen EGLSurface and returns a handle to it. Any EGL context + created with a compatible EGLConfig can be used to render into this surface. + + To create a pixmap rendering surface, first create a native platform pixmap, + then select an EGLConfig matching the pixel format of that pixmap (calling + eglChooseConfig with an attribute list including EGL_MATCH_NATIVE_PIXMAP + returns only EGLConfigs matching the pixmap specified in the attribute list). + + 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. + */ +EXPORT_C EGLSurface eglCreatePixmapSurface(EGLDisplay aDisplay, EGLConfig aConfig, EGLNativePixmapType aPixmap, const EGLint *aAttribList) + { + EGL_TRACE("eglCreatePixmapSurface Display=%d, Config=%d, Pixmap=0x%x -->", aDisplay, aConfig, aPixmap); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + EGLSurface newSurface = EGL_NO_SURFACE; + if (threadState) + { + newSurface = Instance().eglCreatePixmapSurface(*threadState, aDisplay, aConfig, aPixmap, aAttribList); + } + EGL_TRACE("eglCreatePixmapSurface new Surface=0x%x <--", newSurface); + return newSurface; + } + +/* + Destroy an EGLSurface of any type (window, pbuffer, or pixmap). + + All resources associated with surface which were allocated by EGL are marked + for deletion as soon as possible. Following eglDestroySurface, the surface + and the handle referring to it are treated in the same fashion as a surface + destroyed by eglTerminate. + + Resources associated with surface but not allocated by EGL, such as native + windows, native pixmaps, or client API buffers, are not affected when the + surface is destroyed. Only storage actually allocated by EGL is marked for + deletion. Furthermore, resources associated with a pbuffer surface are not + released until all color buffers of that pbuffer bound to a OpenGL ES texture + object have been released. + + Returns EGL_FALSE on failure. An EGL_BAD_SURFACE error is generated if surface + is not a valid rendering surface. + */ +EXPORT_C EGLBoolean eglDestroySurface(EGLDisplay aDisplay, EGLSurface aSurface) + { + EGL_TRACE("eglDestroySurface Display=%d, Surface=0x%x", aDisplay, aSurface); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + EGLBoolean result = EGL_FALSE; + if (threadState) + { + result = Instance().eglDestroySurface(*threadState, aDisplay, aSurface); + } + return result; + } + +/* + Returns in value the value of attribute for surface. attribute must be set + to one of the attributes in table 3.5 of the EGL specification. + + 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. + */ +EXPORT_C EGLBoolean eglQuerySurface(EGLDisplay aDisplay, EGLSurface aSurface, EGLint aAttribute, EGLint *aValue) + { + EGL_TRACE("eglQuerySurface display=%d, surface=%d, attribute=%d", aDisplay, aSurface, aAttribute); + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + return Instance().eglQuerySurface(*threadState, aDisplay, aSurface, aAttribute, aValue); + } + return EGL_FALSE; + } + +/* + Set the current rendering API, this is set on a per-thread basis. + + api must specify one of the supported client APIs , either EGL_OPENVG_API + or EGL_OPENGL_ES_API. (EGL_OPENGL_API is not currently supported by Symbian.) + + Returns EGL_FALSE on failure. If api is not one of the values specified + above, or if the client API specified by api is not supported by the + implementation, an EGL_BAD_PARAMETER error is generated. + */ +EXPORT_C EGLBoolean eglBindAPI(EGLenum aApi) + { + EGL_TRACE("eglBindAPI 0x%x (%s)", aApi, (aApi == EGL_OPENGL_ES_API) ? "EGL_OPENGL_ES_API" : (aApi == EGL_OPENVG_API) ? "EGL_OPENVG_API" : "???"); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + EGLBoolean result = EGL_FALSE; + if (threadState) + { + if ( (aApi == EGL_OPENGL_ES_API) || (aApi == EGL_OPENVG_API) ) + { + threadState->SetEglBoundApi(aApi); + result = EGL_TRUE; + RemoteFunctionCallData rfcdata; EglRFC eglApiData(rfcdata); + eglApiData.Init(EglRFC::EeglBindAPI); + eglApiData.AppendEGLenum(aApi); + EGLBoolean hostResult = threadState->ExecEglBooleanCmd(eglApiData); + // confirm Host EGL matches what we think about the parameter + EGLPANIC_ASSERT_DEBUG(hostResult == result, EEglPanicTemp); + } + else + { + threadState->SetEglError(EGL_BAD_PARAMETER); + } + } + return result; + } + +/* + Get the current rendering API, this is set on a per-thread basis. + + The value returned will be one of the valid api parameters to eglBindAPI, + or EGL_NONE. + + The initial value of the current rendering API is EGL_OPENGL_ES_API. + Applications using multiple client APIs are responsible for ensuring + the current rendering API is correct before calling the functions + eglCreateContext, eglGetCurrentContext, eglGetCurrentDisplay, + eglGetCurrentSurface, eglMakeCurrent (when its ctx parameter is + EGL_NO_CONTEXT), eglWaitClient, or eglWaitNative. + */ +EXPORT_C EGLenum eglQueryAPI(void) + { + EGL_TRACE("eglQueryAPI"); + + EGLenum result = EGL_OPENGL_ES_API; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { // EGL threadState exists + result = threadState->EglBoundApi(); + threadState->SetEglError(EGL_SUCCESS); +#ifdef _DEBUG + // Debug build checks that local threadState is in sync with Host EGL state + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglQueryAPI); + threadState->ExecuteEglNeverErrorCmd(eglApiData); + EGLPANIC_ASSERT(result == (EGLenum)eglApiData.ReturnValue(), EEglPanicHostAndClientBoundApiOutOfSync); +#endif + } + return result; + } + +/* + Wait for client (Open GL ES, VG, ...) rendering to complete, before + using Symbian native rendering. + + Returns EGL_TRUE on success. If there is no current context for the current + rendering API, the function has no effect but still returns EGL_TRUE. If the + surface associated with the calling thread’s current context is no longer valid, + EGL_FALSE is returned and an EGL_BAD_CURRENT_SURFACE error is generated. + */ +EXPORT_C EGLBoolean eglWaitClient(void) + { + EGL_TRACE("eglWaitClient"); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglWaitClient(*threadState); + } + return result; + } + +/* + Return EGL to its state at thread initialization. + + EGL_TRUE is returned on success, and the following actions are taken: + * For each client API supported by EGL, if there is a currently bound context, + that context is released. This is equivalent to calling eglMakeCurrent + with ctx set to EGL_NO_CONTEXT and both draw and read set to EGL_NO_SURFACE. + * The current rendering API is reset to its value at thread initialization. + * Any additional implementation-dependent per-thread state maintained by + EGL is marked for deletion as soon as possible. + Returns EGL_FALSE on failure, there are no defined conditions under which + failure will occur. + */ +EXPORT_C EGLBoolean eglReleaseThread(void) + { + EGL_TRACE("eglReleaseThread -->"); + + TEglThreadState* threadState = CVghwUtils::EglThreadState(); // fetching pre-existing thread state, if any + if (threadState) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglReleaseThread); + threadState->ExecuteEglNeverErrorCmd(eglApiData); + + // release client side memory + CVghwUtils::ReleaseThreadState(); + } + + EGL_TRACE("eglReleaseThread <--"); + return EGL_TRUE; + } + +/* + Creates a single pbuffer surface bound to the specified buffer for part or + all of its buffer storage, and returns a handle to it. The width and height + of the pbuffer are determined by the width and height of buffer. + + Currently, the only client API resources which may be bound in this fashion + are OpenVG VGImage objects. + + 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. + */ +EXPORT_C EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay aDisplay, EGLenum aBufType, EGLClientBuffer aBuffer, + EGLConfig aConfig, const EGLint *aAttribList) + { + EGL_TRACE("eglCreatePbufferFromClientBuffer Display=%d, BufType=%d, Config=%d -->", aDisplay, aBufType, aConfig); + EGL_TRACE_ATTRIB_LIST(aAttribList); + + EGLSurface newSurface = EGL_NO_SURFACE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + newSurface = Instance().eglCreatePbufferFromClientBuffer(*threadState, aDisplay, aBufType, aBuffer, aConfig, aAttribList); + } + EGL_TRACE("eglCreateWindowSurface new Surface=0x%x <--", newSurface); + return newSurface; + } + +/* + Set an attribute for an EGLSurface. + + The specified attribute of surface is set to value. Attributes that can be + specified are EGL_MIPMAP_LEVEL, EGL_MULTISAMPLE_RESOLVE, and EGL_SWAP_BEHAVIOR. + + 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. + */ +EXPORT_C EGLBoolean eglSurfaceAttrib(EGLDisplay aDisplay, EGLSurface aSurface, + EGLint aAttribute, EGLint aValue) + { + EGL_TRACE("eglSurfaceAttrib Display=%d, Surface=0x%x, Attribute=0x%x, Value=%d", aDisplay, aSurface, aAttribute, aValue); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglSurfaceAttrib(*threadState, aDisplay, aSurface, aAttribute, aValue); + } + return result; + } + +/* + Defines a two-dimensional texture image. The texture image consists of the image + data in buffer for the specified surface, and need not be copied. Currently the + only value accepted for buffer is EGL_BACK_BUFFER, which indicates the buffer into + which OpenGL ES rendering is taking place (this is true even when using a + singlebuffered surface, such as a pixmap). In future versions of EGL, additional buffer + values may be allowed to bind textures to other buffers in an EGLSurface. + + eglBindTexImage is ignored if there is no current rendering context. + + 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. + */ +EXPORT_C EGLBoolean eglBindTexImage(EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer) + { + EGL_TRACE("eglBindTexImage Display=%d, Surface=0x%x, Buffer=%d", aDisplay, aSurface, aBuffer); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglBindTexImage(*threadState, aDisplay, aSurface, aBuffer); + } + return result; + } + +/* + The specified color buffer is released back to the surface. The surface is + made available for reading and writing when it no longer has any color + buffers bound as textures. + + 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. + */ +EXPORT_C EGLBoolean eglReleaseTexImage(EGLDisplay aDisplay, EGLSurface aSurface, EGLint aBuffer) + { + EGL_TRACE("eglReleaseTexImage Display=%d, Surface=0x%x, Buffer=%d", aDisplay, aSurface, aBuffer); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglReleaseTexImage(*threadState, aDisplay, aSurface, aBuffer); + } + return result; + } + +/* + Specifies the minimum number of video frame periods per buffer swap for + the window associated with the current context. The interval takes effect when + eglSwapBuffers is first called subsequent to the eglSwapInterval call. + + 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. + */ +EXPORT_C EGLBoolean eglSwapInterval(EGLDisplay aDisplay, EGLint aInterval) + { + EGL_TRACE("eglSwapInterval Display=%d, Interval=%d frames", aDisplay, aInterval); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglSwapInterval(*threadState, aDisplay, aInterval); + } + return result; + } + +/* + Create a rendering context for the current rendering API. + + If eglCreateContext succeeds, it initializes the context to the initial + state defined for the current rendering API, and returns a handle to it. + The context can be used to render to any compatible EGLSurface. Although + contexts are specific to a single client API , all contexts created in + EGL exist in a single namespace. This allows many EGL calls which manage + contexts to avoid use of the current rendering API. + + 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. + + If config is not a valid EGLConfig, or does not support the requested client + API , then an EGL_BAD_CONFIG error is generated (this includes requesting creation + of an OpenGL ES 1.x context when the EGL_RENDERABLE_TYPE attribute + of config does not contain EGL_OPENGL_ES_BIT, or creation of an OpenGL ES + 2.x context when the attribute does not contain EGL_OPENGL_ES2_BIT). + + If the OpenGL or OpenGL ES server context state for share context exists in + an address space that cannot be shared with the newly created context, if share - + context was created on a different display than the one referenced by config, or if + the contexts are otherwise incompatible (for example, one context being associated + with a hardware device driver and the other with a software renderer), then an + EGL_BAD_MATCH error is generated. If the server does not have enough resources + to allocate the new context, then an EGL_BAD_ALLOC error is generated. + */ +EXPORT_C EGLContext eglCreateContext(EGLDisplay aDisplay, EGLConfig aConfig, + EGLContext aShareContext, const EGLint *aAttribList) + { + EGL_TRACE("eglCreateContext Display=%d, Config=%d, ShareContext=%d -->", aDisplay, aConfig, aShareContext); + EGL_TRACE_ATTRIB_LIST(aAttribList); + + EGLContext result = EGL_NO_CONTEXT; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglCreateContext(*threadState, aDisplay, aConfig, aShareContext, aAttribList); + } + EGL_TRACE("eglCreateContext new context=%d <--", result); + return result; + } + +/* + Destroy a rendering context. + + All resources associated with ctx are marked for deletion as soon as possible. + Following eglDestroyContext, the context and the handle referring to it are + treated in the same fashion as a context destroyed by eglTerminate. + + Returns EGL_FALSE on failure. An EGL_BAD_CONTEXT error is generated if ctx is + not a valid context. + */ +EXPORT_C EGLBoolean eglDestroyContext(EGLDisplay aDisplay, EGLContext aContext) + { + EGL_TRACE("eglDestroyContext Display=%d, Context=%d", aDisplay, aContext); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglDestroyContext(*threadState, aDisplay, aContext); + } + return result; + } + +/* + Make a context current, binds ctx to the current rendering thread + and to the draw and read surfaces. + + For an OpenVG context, the same EGLSurface must be specified for both + draw and read. + + If the calling thread already has a current context of the same client + API type as ctx, then that context is flushed and marked as no longer + current. ctx is then made the current context for the calling thread. + + To release the current context without assigning a new one, set ctx to + EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE. The currently + bound context for the client API specified by the current rendering API + is flushed and marked as no longer current, and there will be no current + context for that client API after eglMakeCurrent returns. This is the + only case in which eglMakeCurrent respects the current rendering API. + In all other cases, the client API affected is determined by ctx. This + is the only case where an uninitialized display may be passed to + eglMakeCurrent. + + Returns EGL_FALSE on failure. Errors generated may include: + * If draw or read are not compatible with ctx, then an EGL_BAD_MATCH + error is generated. + * If ctx is current to some other thread, or if either draw or read are + bound to contexts in another thread, an EGL_BAD_ACCESS error is + generated. + * If binding ctx would exceed the number of current contexts of that + client API type supported by the implementation, an EGL_BAD_ACCESS + error is generated. + * If either draw or read are pbuffers created with eglCreatePbufferFrom- + ClientBuffer, and the underlying bound client API buffers are in use + by the client API that created them, an EGL_BAD_ACCESS error is + generated. + * If ctx is not a valid context, an EGL_BAD_CONTEXT error is generated. + * If either draw or read are not valid EGL surfaces, an EGL_BAD_SURFACE + error is generated. + * If a native window underlying either draw or read is no longer valid, + an EGL_BAD_NATIVE_WINDOW error is generated. + * If draw and read cannot fit into graphics memory simultaneously, an + EGL_BAD_MATCH error is generated. + * If the previous context of the calling thread has unflushed commands, + and the previous surface is no longer valid, an EGL_BAD_CURRENT_SURFACE + error is generated. + * If the ancillary buffers for draw and read cannot be allocated, an + EGL_BAD_ALLOC error is generated. + * If a power management event has occurred, an EGL_CONTEXT_LOST error + is generated. + * As with other commands taking EGLDisplay parameters, if dpy is not a + valid EGLDisplay handle, an EGL_BAD_DISPLAY error is generated. + Other errors may arise when the context state is inconsistent with the + surface state, as described in the EGL specification. + */ +EXPORT_C EGLBoolean eglMakeCurrent(EGLDisplay aDisplay, EGLSurface aDraw, EGLSurface aRead, EGLContext aContext) + { + EGL_TRACE("eglMakeCurrent Display=%d, DrawSurface=0x%x, ReadSurface=0x%x, Context=%d", aDisplay, aDraw, aRead, aContext); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + return Instance().eglMakeCurrent(*threadState, aDisplay, aDraw, aRead, aContext); + } + return EGL_FALSE; + } + +/* + Get the current context for the current rendering API. + + 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). + If the current context has been marked for deletion as a result of calling + eglTerminate or eglDestroyContext, the handle returned by eglGetCurrentContext + is not valid, and cannot be passed successfully to any other EGL function, + as discussed in section 3.2 of the EGL Specification. + */ +EXPORT_C EGLContext eglGetCurrentContext(void) + { + EGL_TRACE("eglGetCurrentContext -->"); + + EGLContext context = EGL_NO_SURFACE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + context = Instance().eglGetCurrentContext(*threadState); + } + EGL_TRACE("eglGetCurrentContext context=%d <--", context); + return context; + } + +/* + Get the surfaces used for rendering by a current context. + + readdraw is either EGL_READ or EGL_DRAW, to return respectively the read or + draw surfaces bound to the current context in the calling thread, for the + current rendering API. + + If there is no current context for the current rendering API, then + EGL_NO_SURFACE is returned (this is not an error). If readdraw is neither + EGL_READ nor EGL_DRAW, EGL_NO_SURFACE is returned and an EGL_BAD_PARAMETER + error is generated. If a current surface has been marked for deletion as + a result of calling eglTerminate or eglDestroySurface, the handle returned + by eglGetCurrentSurface is not valid, and cannot be passed successfully to + any other EGL function, as discussed in section 3.2 of the EGL Specification. + */ +EXPORT_C EGLSurface eglGetCurrentSurface(EGLint aReadDraw) + { + EGL_TRACE("eglGetCurrentSurface ReadDraw=%d -->", aReadDraw); + + EGLSurface surface = EGL_NO_SURFACE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + surface = Instance().eglGetCurrentSurface(*threadState, aReadDraw); + } + EGL_TRACE("eglGetCurrentSurface surface=0x%x <--", surface); + return surface; + } + +/* + Get the display associated with a current context. + + The display for the current context in the calling thread, for the current + rendering API, is returned. If there is no current context for the current + rendering API, EGL_NO_DISPLAY is returned (this is not an error). + + Note that EGL_NO_DISPLAY is used solely to represent an error condition, + and is not a valid EGLDisplay handle. Passing EGL_NO_DISPLAY to any command + taking an EGLDisplay parameter will generate either an EGL_BAD_DISPLAY + error if the EGL implementation validates EGLDisplay handles, or undefined + behavior as described at the end of section 3.1 of the EGL Specification. + */ +EXPORT_C EGLDisplay eglGetCurrentDisplay(void) + { + EGL_TRACE("eglGetCurrentDisplay -->"); + + EGLDisplay display = EGL_NO_DISPLAY; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + display = Instance().eglGetCurrentDisplay(*threadState); + } + EGL_TRACE("eglGetCurrentDisplay Display=%d <--", display); + return display; + } + +/* + Obtain the value of context attributes. + + Returns in value the value of attribute for ctx. attribute must be set to + EGL_CONFIG_ID, EGL_CONTEXT_CLIENT_TYPE, EGL_CONTEXT_CLIENT_VERSION, or + EGL_RENDER_BUFFER. + + 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. + */ +EXPORT_C EGLBoolean eglQueryContext(EGLDisplay aDisplay, EGLContext aContext, EGLint aAttribute, EGLint *aValue) + { + EGL_TRACE("eglQueryContext Display=%d, Context=%d, Attribute=0x%x, aValue=0x%x", aDisplay, aContext, aAttribute, aValue); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglQueryContext(*threadState, aDisplay, aContext, aAttribute, aValue); + } + EGL_TRACE_GET_ATTRIB("eglQueryContext", "context", aDisplay, aContext, aAttribute, aValue, result); + return result; + } + +/* + EGL function is for backwards compatibility only. + + Equivalent to: + EGLenum api = eglQueryAPI(); + eglBindAPI(EGL_OPENGL_ES_API); + eglWaitClient(); + eglBindAPI(api); + */ +EXPORT_C EGLBoolean eglWaitGL(void) + { + EGL_TRACE("eglWaitGL"); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglWaitGL); + result = threadState->ExecEglBooleanCmd(eglApiData); + } + return result; + } + +/* + Wait for Symbian native rendering to complete, before performing + client (Open GL ES, VG, ...) rendering. + + Returns EGL_TRUE on success. If there is no current context, + the function has no effect but still returns EGL_TRUE. If the surface does not support + native rendering (e.g. pbuffer and in most cases window surfaces), the function + has no effect but still returns EGL_TRUE. If the surface associated with the + calling thread’s current context is no longer valid, EGL_FALSE is returned and an + EGL_BAD_CURRENT_SURFACE error is generated. If engine does not denote a recognized + marking engine, EGL_FALSE is returned and an EGL_BAD_PARAMETER + error is generated. + */ +EXPORT_C EGLBoolean eglWaitNative(EGLint aEngine) + { + EGL_TRACE("eglWaitNative %d", aEngine); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglWaitNative); + eglApiData.AppendEGLint(aEngine); + result = threadState->ExecEglBooleanCmd(eglApiData); + + if ( EGL_CORE_NATIVE_ENGINE == aEngine ) + { + //Do native draw api sync + } + } + return result; + } + +/* + Post the color buffer to a window. + + If surface is a back-buffered window surface, then the color buffer is + copied to the native window associated with that surface. If surface is a + single-buffered window, pixmap, or pbuffer surface, eglSwapBuffers has no + effect. + + The contents of the color buffer of surface may be affected by + eglSwapBuffers, depending on the value of the EGL_SWAP_BEHAVIOR attribute + of surface. See section 3.5.6 of the EGL Specification. + + Returns EGL_FALSE on failure. If surface is not a valid EGL surface, an + EGL_BAD_SURFACE error is generated. If surface is not bound to the calling + thread’s current context, an EGL_BAD_SURFACE error is generated. If target is + not a valid native pixmap handle, an EGL_BAD_NATIVE_PIXMAP error should be + generated. If the format of target is not compatible with the color buffer, + or if the size of target is not the same as the size of the color buffer, and + there is no defined conversion between the source and target formats, an + EGL_BAD_MATCH error is generated. If called after a power management event + has occurred, a EGL_CONTEXT_LOST error is generated. If the native window + associated with surface is no longer valid, an EGL_ BAD_NATIVE_WINDOW error + is generated. + */ +EXPORT_C EGLBoolean eglSwapBuffers(EGLDisplay aDisplay, EGLSurface aSurface) + { + EGL_TRACE("eglSwapBuffers begin Display=%d, Surface=0x%x -->", aDisplay, aSurface); + + EGLBoolean result = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + result = Instance().eglSwapBuffers(*threadState, aDisplay, aSurface); + } + + EGL_TRACE("eglSwapBuffers success=%d <--", result); + return result; + } + +/* + Copy the color buffer to a native pixmap. + + The mapping of pixels in the color buffer to pixels in the pixmap is platform + dependent, since the native platform pixel coordinate system may differ from + that of client APIs. + + The color buffer of surface is left unchanged after calling eglCopyBuffers. + Returns EGL_FALSE on failure. If surface is not a valid EGL surface, an + EGL_BAD_SURFACE error is generated. If surface is not bound to the calling + thread’s current context, an EGL_BAD_SURFACE error is generated. If target is + not a valid native pixmap handle, an EGL_BAD_NATIVE_PIXMAP error should be + generated. If the format of target is not compatible with the color buffer, + or if the size of target is not the same as the size of the color buffer, and + there is no defined conversion between the source and target formats, an + EGL_BAD_MATCH error is generated. If called after a power management event + has occurred, a EGL_CONTEXT_LOST error is generated. If the egl + implementation does not support native pixmaps, an EGL_BAD_NATIVE_PIXMAP + error is generated. + */ +EXPORT_C EGLBoolean eglCopyBuffers(EGLDisplay aDisplay, EGLSurface aSurface, EGLNativePixmapType aTarget) + { + // Note: API supports CFbsBitmap native pixmap but not SgImage + EGL_TRACE("eglCopyBuffers Display=%d, Surface=0x%x, Target=0x%x", aDisplay, aSurface, aTarget); + + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { // EGL is initialized for thread + return Instance().eglCopyBuffers(*threadState, aDisplay, aSurface, aTarget); + } + return EGL_FALSE; + } + +/* + * eglCreateImageKHR supports Khronos EGL extension #8, "KHR_image_base" + * + * Supported values for target parameter: + * EGL_NATIVE_PIXMAP_KHR for Khronos EGL extension #9, "KHR_image_pixmap" + */ +EGLImageKHR eglCreateImageKHR(EGLDisplay aDisplay, EGLContext aContext, EGLenum aTarget, EGLClientBuffer aBuffer, const EGLint *aAttribList) + { + EGL_TRACE("eglCreateImageKHR Display=%d, Context=%d, Target=0x%x, Buffer=0x%x, AttribList=0x%x -->", + aDisplay, aContext, aTarget, aBuffer, aAttribList); + + EGLImageKHR image = NULL; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + image = Instance().eglCreateImageKHR(*threadState, aDisplay, aContext, aTarget, aBuffer, aAttribList); + } + EGL_TRACE("eglCreateImageKHR image=0x%x <--", image); + return image; + } + +/* + * eglDestroyImageKHR supports Khronos EGL extension #8, "KHR_image_base" + */ +EGLBoolean eglDestroyImageKHR(EGLDisplay aDisplay, EGLImageKHR aImage) + { + EGL_TRACE("eglDestroyImageKHR Display=%d, Image=0x%x -->", aDisplay, aImage); + + EGLBoolean success = EGL_FALSE; + TEglThreadState* threadState = CVghwUtils::CreateThreadState(); + if (threadState) + { + success = Instance().eglDestroyImageKHR(*threadState, aDisplay, aImage); + } + EGL_TRACE("eglDestroyImageKHR success=%d <--", success); + return success; + } + + +/* + Returns the address of the extension function named by procName. procName + must be a NULL-terminated string. The pointer returned should be cast to + a function pointer type matching the extension function’s definition in + that extension specification. + + A return value of NULL indicates that the specified function does not exist + for the implementation. + + A non-NULL return value for eglGetProcAddress does not guarantee that an + extension function is actually supported at runtime. The client must also make + a corresponding query, such as glGetString(GL_EXTENSIONS) for OpenGL and + OpenGL ES extensions; vgGetString(VG_EXTENSIONS) for OpenVG extensions; + or eglQueryString(dpy, EGL_EXTENSIONS) for EGL extensions, to determine if + an extension is supported by a particular client API context. + + Function pointers returned by eglGetProcAddress are independent of the display + and the currently bound context, and may be used by any context which supports + the extension. + + eglGetProcAddress may be queried for all of the following functions: + * All EGL and client API extension functions supported by the implementation + (whether those extensions are supported by the current context or not). + This includes any mandatory OpenGL ES extensions. + */ +EXPORT_C void (*eglGetProcAddress (const char *aProcname))(...) + { + EGL_TRACE("eglGetProcAddress"); + + if (aProcname) + { + return Instance().eglGetProcAddress(aProcname); + } + return NULL; + } + +} /* extern "C" */ diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/eglattribs.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/eglattribs.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,122 @@ +// 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 of attributes and attribute lists + +#include +#include "eglapi.h" + + + +TInt TAttribUtils::AttribListLength(const EGLint* aAttribList) + { + int length = 0; + if (aAttribList) + { + while (aAttribList[length] != EGL_NONE) + { + length += 2; + EGLPANIC_ASSERT_DEBUG(length < 100, EEglPanicAtribListLengthTooLong); + } + ++length; + } + return length; + } + +const EGLint* TAttribUtils::FindAttribValue(const EGLint* aAttribList, EGLint aAttrib) + { + EGLPANIC_ASSERT_DEBUG(aAttrib != EGL_NONE, EEglPanicTemp); + + if (aAttribList && (aAttrib != EGL_NONE) ) + { + TInt idx = 0; + while (aAttribList[idx] != EGL_NONE) + { + if (aAttribList[idx] == aAttrib) + { + return aAttribList + idx + 1; + } + idx += 2; + EGLPANIC_ASSERT_DEBUG(idx < 100, EEglPanicAtribListLengthTooLong); + } + } + return NULL; + } + +EGLint* TAttribUtils::FindAttribValue(EGLint* aAttribList, EGLint aAttrib) + { + EGLPANIC_ASSERT_DEBUG(aAttrib != EGL_NONE, EEglPanicTemp); + + if (aAttribList && (aAttrib != EGL_NONE) ) + { + TInt idx = 0; + while (aAttribList[idx] != EGL_NONE) + { + if (aAttribList[idx] == aAttrib) + { + return aAttribList + idx + 1; + } + idx += 2; + EGLPANIC_ASSERT_DEBUG(idx < 100, EEglPanicAtribListLengthTooLong); + } + } + return NULL; + } + +void TAttribUtils::AppendAttribValue(EGLint* aAttribList, EGLint aAttrib, EGLint aValue) + { + EGLPANIC_ASSERT_DEBUG(aAttrib != EGL_NONE, EEglPanicTemp); + + if (aAttribList && (aAttrib != EGL_NONE)) + { + TInt idx = 0; + while (aAttribList[idx] != EGL_NONE) + { + idx += 2; + EGLPANIC_ASSERT_DEBUG(idx < 100, EEglPanicAtribListLengthTooLong); + } + aAttribList[idx++] = aAttrib; + aAttribList[idx++] = aValue; + aAttribList[idx++] = EGL_NONE; + } + } + +void TAttribUtils::RemoveAttrib(EGLint* aAttribList, EGLint aAttrib) + { + EGLPANIC_ASSERT_DEBUG(aAttrib != EGL_NONE, EEglPanicTemp); + + if (aAttribList && (aAttrib != EGL_NONE) && (*aAttribList != EGL_NONE)) + { + TInt dstIdx = 0; + + while ( (aAttribList[dstIdx] != EGL_NONE) && (aAttribList[dstIdx] != aAttrib) ) + { + dstIdx += 2; + EGLPANIC_ASSERT_DEBUG(dstIdx < 100, EEglPanicAtribListLengthTooLong); + } + + if (aAttribList[dstIdx] == aAttrib) + { // attrib found + TInt srcIdx = dstIdx + 2; + while (aAttribList[srcIdx] != EGL_NONE) + { // copy up succeeding attrib / value pairs + aAttribList[dstIdx++] = aAttribList[srcIdx++]; + aAttribList[dstIdx++] = aAttribList[srcIdx++]; + EGLPANIC_ASSERT_DEBUG(dstIdx < 100, EEglPanicAtribListLengthTooLong); + } + aAttribList[dstIdx++] = EGL_NONE; + } + } + } + +// end of file eglattrib.cpp diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/eglcontext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/eglcontext.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,293 @@ +// 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: +// Implementation of guest egl context + +#include +#include "eglapi.h" + + + +// factory function +CEglContext* CEglContext::Create(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLConfig aConfig, CEglContext* aShareContext, const EGLint* aAttribList) + { + // ToDo validate aConfig + // ToDo validate aShareContext + + // which Khronos Graphics API is the Context for: Open GL ES, Open VG, ... + EGLenum api = aThreadState.EglBoundApi(); + // (in case supported APIs ever change) ensure the current API is valid + if (api == EGL_NONE) + { + aThreadState.SetEglError(EGL_BAD_MATCH); + return EGL_NO_CONTEXT; + } + + EGLint glesClientVersion = 1; + // validate AttribList parameter + if ( aAttribList && (*aAttribList != EGL_NONE) ) + { + TBool attribsOkay = EFalse; + // As of EGL 1.4 only Open GL ES api supports any attributes for eglCreateContext + if (api == EGL_OPENGL_ES_API) + { + // only supported attribute for Open GL ES is EGL_CONTEXT_CLIENT_VERSION + if ( (aAttribList[0] == EGL_CONTEXT_CLIENT_VERSION) && (aAttribList[2] == EGL_NONE) ) + { + glesClientVersion = aAttribList[1]; + // modify this code when GL ES 2 support is added + if (glesClientVersion == 1) + { + attribsOkay = ETrue; + } + } + } + if (!attribsOkay) + { + aThreadState.SetEglError(EGL_BAD_PARAMETER); + return EGL_NO_CONTEXT; + } + } + + // ToDo validate that aConfig supports this API (inc GL ES v2 versus v1) + EGLContext shareContextFamily = EGL_NO_CONTEXT; + if (aShareContext) + { + shareContextFamily = aShareContext->ShareContextFamily(); + } + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + CEglContext* self = new CEglContext(aDisplay, aConfig, shareContextFamily, api, glesClientVersion); + if (self == EGL_NO_CONTEXT) + { + aThreadState.SetEglError(EGL_BAD_ALLOC); + } + else + { + // call Host EGL, & set iHostContext + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglCreateContext); + eglApiData.AppendEGLDisplay(aDisplay); + eglApiData.AppendEGLConfig(aConfig); + eglApiData.AppendEGLContext(aShareContext ? aShareContext->HostContext() : EGL_NO_CONTEXT); + eglApiData.AppendEGLintVector(aAttribList, TAttribUtils::AttribListLength(aAttribList)); + self->iHostContext = aThreadState.ExecEglContextCmd(eglApiData); + if (self->iHostContext == EGL_NO_CONTEXT) + { // Host EGL error + delete self; + self = EGL_NO_CONTEXT; + } + } + CVghwUtils::SwitchFromVghwHeap(threadHeap); + return self; + } + + +CEglContext::CEglContext(EGLDisplay aDisplay, EGLConfig aConfig, EGLContext aShareContextFamily, EGLenum aRenderingApi, + EGLint aGlesClientVersion) : + iFirstUse(ETrue), iHostContext(EGL_NO_CONTEXT), iDisplay(aDisplay), iShareContextFamily(aShareContextFamily), + iConfigId(aConfig), iRenderingApi(aRenderingApi), iDrawSurface(EGL_NO_SURFACE), iReadSurface(EGL_NO_SURFACE), + iGlesClientVersion(aGlesClientVersion), iIsDestroyed(EFalse) + { + iCtxMutex.CreateLocal(EOwnerProcess); + } + + +void CEglContext::Delete(TEglThreadState& aThreadState) + { + EGLPANIC_ASSERT_DEBUG(iCtxMutex.IsHeld(), EEglPanicTemp); + + // tell Host EGL to destroy the Context now + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglDestroyContext); + eglApiData.AppendEGLDisplay(iDisplay); + eglApiData.AppendEGLContext(iHostContext); + EGLBoolean hostResult = aThreadState.ExecEglBooleanCmd(eglApiData); + EGLPANIC_ASSERT_DEBUG(hostResult, EEglPanicTemp); + + // free + iCtxMutex.Close(); + RHeap* threadHeap = CVghwUtils::SwitchToVghwHeap(); + delete this; + CVghwUtils::SwitchFromVghwHeap(threadHeap); + } + + +CEglContext::~CEglContext() + { + if (iCtxMutex.Handle()) + { + iCtxMutex.Close(); + } + } + + +EGLBoolean CEglContext::MakeCurrent(TEglThreadState& aThreadState, EGLSurface aDraw, EGLSurface aRead) + { + // ToDo support different number spaces for Host & Client EGL Surfaces + EGLBoolean hostResult = EGL_FALSE; + EGLint error = EGL_SUCCESS; + iCtxMutex.Wait(); + if (iIsDestroyed) + { + error = EGL_BAD_CONTEXT; + } + else + { + // ToDo validate aDraw & aRead are compatible with API + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init( EglRFC::EeglMakeCurrent ); + eglApiData.AppendEGLDisplay(iDisplay); + eglApiData.AppendEGLSurface(aDraw); + eglApiData.AppendEGLSurface(aRead); + eglApiData.AppendEGLContext(iHostContext); + hostResult = aThreadState.ExecEglBooleanCmd(eglApiData); + if (hostResult) + { + iDrawSurface = aDraw; + iReadSurface = aRead; + } + } + iCtxMutex.Signal(); + if (error != EGL_SUCCESS) + { // error in parameter checks + aThreadState.SetEglError(error); + } + return hostResult; + } + + +TBool CEglContext::Destroy(TEglThreadState& aThreadState) + { + iCtxMutex.Wait(); + iIsDestroyed = ETrue; + if ( (iDrawSurface == EGL_NO_SURFACE) && (iReadSurface == EGL_NO_SURFACE) ) + { // Context not in use + Delete(aThreadState); + return ETrue; + } + iCtxMutex.Signal(); + return EFalse; + } + + +TBool CEglContext::MakeNotCurrent(TEglThreadState& aThreadState) + { + iCtxMutex.Wait(); + iDrawSurface = EGL_NO_SURFACE; + iReadSurface = EGL_NO_SURFACE; + + if (iIsDestroyed) + { // Destroyed & no longer in use + Delete(aThreadState); + return ETrue; + } + iCtxMutex.Signal(); + return EFalse; + } + + +EGLContext CEglContext::ShareContextFamily() + { + EGLContext result = EGL_NO_CONTEXT; + // ToDo review - maybe just check Mutex is held + iCtxMutex.Wait(); + if (!iIsDestroyed) + { + if (iShareContextFamily) + { + result = iShareContextFamily; + } + else + { + result = iHostContext; + } + } + iCtxMutex.Signal(); + return result; + } + +// Valid attributes are: EGL_CONFIG_ID, EGL_CONTEXT_CLIENT_TYPE, EGL_CONTEXT_CLIENT_VERSION, or EGL_RENDER_BUFFER +EGLBoolean CEglContext::QueryAttribute(TEglThreadState& aThreadState, EGLint aAttribute, EGLint* aValue) + { + EGLint error = EGL_SUCCESS; + iCtxMutex.Wait(); + if (iIsDestroyed) + { + error = EGL_BAD_CONTEXT; + } + else + { + switch (aAttribute) + { + case EGL_CONFIG_ID: + *aValue = iConfigId; + break; + + case EGL_CONTEXT_CLIENT_TYPE: + *aValue = iRenderingApi; + break; + + case EGL_CONTEXT_CLIENT_VERSION: + *aValue = iGlesClientVersion; + break; + + case EGL_RENDER_BUFFER: + if (iDrawSurface == NULL) + { // context is not bound to any surface + *aValue = EGL_NONE; + } + else + // ToDo check the currently bound surface type to answer this + { + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglQueryContext); + eglApiData.AppendEGLDisplay(iDisplay); + eglApiData.AppendEGLContext(iHostContext); + eglApiData.AppendEGLint(aAttribute); + eglApiData.AppendEGLintVector(aValue, 1, RemoteFunctionCallData::EOut); + EGLBoolean hostResult = aThreadState.ExecEglBooleanCmd(eglApiData); + return hostResult; + } + break; + + default: + error = EGL_BAD_ATTRIBUTE; + break; + } + // Debug compare with Host EGL result +#ifdef _DEBUG + EGLint hostValue = 0; + RemoteFunctionCallData rfcdata; EglRFC eglApiData( rfcdata ); + eglApiData.Init(EglRFC::EeglQueryContext); + eglApiData.AppendEGLDisplay(iDisplay); + eglApiData.AppendEGLContext(iHostContext); + eglApiData.AppendEGLint(aAttribute); + eglApiData.AppendEGLintVector(&hostValue, 1, RemoteFunctionCallData::EOut); + EGLBoolean hostResult = aThreadState.ExecEglBooleanCmd(eglApiData); + if (error == EGL_SUCCESS) + { // Host EGl result should match ours + EGLPANIC_ASSERT(hostResult, EEglPanicTemp); + EGLPANIC_ASSERT(hostValue == *aValue, EEglPanicTemp); + } + else + { + EGLPANIC_ASSERT(!hostResult, EEglPanicTemp); + } +#endif + } + aThreadState.SetEglError(error); + iCtxMutex.Signal(); + return (error == EGL_SUCCESS); + } + +// end of file eglcontext.cpp diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/egldebug.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/egldebug.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,286 @@ +// 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 debugging support + +#include +#include "eglapi.h" + + +#ifdef _DEBUG + +// These functions help with verbose debug logging of EGL Attibutes + +// Try to get an attribute name string, and a description of the value - switch statements can be extended for later EGL versions +void TAttribUtils::TraceAttribNames(EGLint aAttrib, EGLint aValue, char** aAttrName, char** aValueName) + { + char* attrName = NULL; + char* valueName = NULL; + switch (aAttrib) + { + case EGL_BUFFER_SIZE: attrName = "EGL_BUFFER_SIZE"; break; + case EGL_ALPHA_SIZE: attrName = "EGL_ALPHA_SIZE"; break; + case EGL_BLUE_SIZE: attrName = "EGL_BLUE_SIZE"; break; + case EGL_GREEN_SIZE: attrName = "EGL_GREEN_SIZE"; break; + case EGL_RED_SIZE: attrName = "EGL_RED_SIZE"; break; + case EGL_DEPTH_SIZE: attrName = "EGL_DEPTH_SIZE"; break; + case EGL_STENCIL_SIZE: attrName = "EGL_STENCIL_SIZE"; break; + case EGL_CONFIG_CAVEAT: attrName = "EGL_CONFIG_CAVEAT"; + switch (aValue) + { + // Config attribute values + case EGL_SLOW_CONFIG: valueName = "EGL_SLOW_CONFIG"; break; + case EGL_NON_CONFORMANT_CONFIG: valueName = "EGL_NON_CONFORMANT_CONFIG"; break; + } + break; + case EGL_CONFIG_ID: attrName = "EGL_CONFIG_ID"; break; + case EGL_LEVEL: attrName = "EGL_LEVEL"; break; + case EGL_MAX_PBUFFER_HEIGHT: attrName = "EGL_MAX_PBUFFER_HEIGHT"; break; + case EGL_MAX_PBUFFER_PIXELS: attrName = "EGL_MAX_PBUFFER_PIXELS"; break; + case EGL_MAX_PBUFFER_WIDTH: attrName = "EGL_MAX_PBUFFER_WIDTH"; break; + case EGL_NATIVE_RENDERABLE: attrName = "EGL_NATIVE_RENDERABLE"; break; + case EGL_NATIVE_VISUAL_ID: attrName = "EGL_NATIVE_VISUAL_ID"; break; + case EGL_NATIVE_VISUAL_TYPE: attrName = "EGL_NATIVE_VISUAL_TYPE"; break; + case EGL_PRESERVED_RESOURCES: attrName = "EGL_PRESERVED_RESOURCES"; break; + case EGL_SAMPLES: attrName = "EGL_SAMPLES"; break; + case EGL_SAMPLE_BUFFERS: attrName = "EGL_SAMPLE_BUFFERS"; break; + case EGL_SURFACE_TYPE: attrName = "EGL_SURFACE_TYPE"; + switch(aValue & 7) + { + case 0: valueName = "* | EGL_NONE"; break; + case 1: valueName = "* | PBUFFER"; break; // EGL_PBUFFER_BIT + case 2: valueName = "* | PIXMAP"; break; // EGL_PIXMAP_BIT + case 3: valueName = "* | PIXMAP | PBUFFER"; break; + case 4: valueName = "* | WINDOW"; break; // EGL_WINDOW_BIT + case 5: valueName = "* | WINDOW | PBUFFER"; break; + case 6: valueName = "* | WINDOW | PIXMAP"; break; + case 7: valueName = "* | WINDOW | PIXMAP | PBUFFER"; break; + } + break; + case EGL_TRANSPARENT_TYPE: attrName = "EGL_TRANSPARENT_TYPE"; + if (aValue == EGL_TRANSPARENT_RGB) + valueName = "EGL_TRANSPARENT_RGB"; + break; + case EGL_TRANSPARENT_BLUE_VALUE: attrName = "EGL_TRANSPARENT_BLUE_VALUE"; break; + case EGL_TRANSPARENT_GREEN_VALUE: attrName = "EGL_TRANSPARENT_GREEN_VALUE"; break; + case EGL_TRANSPARENT_RED_VALUE: attrName = "EGL_TRANSPARENT_RED_VALUE"; break; + case EGL_BIND_TO_TEXTURE_RGB: attrName = "EGL_BIND_TO_TEXTURE_RGB"; break; + case EGL_BIND_TO_TEXTURE_RGBA: attrName = "EGL_BIND_TO_TEXTURE_RGBA"; break; + case EGL_MIN_SWAP_INTERVAL: attrName = "EGL_MIN_SWAP_INTERVAL"; break; + case EGL_MAX_SWAP_INTERVAL: attrName = "EGL_MAX_SWAP_INTERVAL"; break; + case EGL_LUMINANCE_SIZE: attrName = "EGL_LUMINANCE_SIZE"; break; + case EGL_ALPHA_MASK_SIZE: attrName = "EGL_ALPHA_MASK_SIZE"; break; + case EGL_COLOR_BUFFER_TYPE: attrName = "EGL_COLOR_BUFFER_TYPE"; + switch (aValue) + { + // EGL_COLOR_BUFFER_TYPE values + case EGL_RGB_BUFFER: valueName = "EGL_RGB_BUFFER"; break; + case EGL_LUMINANCE_BUFFER: valueName = "EGL_LUMINANCE_BUFFER"; break; + } + break; + case EGL_RENDERABLE_TYPE: attrName = "EGL_RENDERABLE_TYPE"; + switch(aValue) + { + case 0: valueName = "EGL_NONE"; break; + case 1: valueName = "GL-ES"; break; + case 2: valueName = "VG"; break; + case 3: valueName = "VG | GL-ES"; break; + case 4: valueName = "GL-ES2"; break; + case 5: valueName = "GL-ES2 | GL-ES"; break; + case 6: valueName = "GL-ES2 | VG"; break; + case 7: valueName = "GL-ES2 | VG | GL-ES"; break; + case 8: valueName = "GL"; break; + case 9: valueName = "GL | GL-ES"; break; + case 10: valueName = "GL | VG"; break; + case 11: valueName = "GL | VG | GL-ES"; break; + case 12: valueName = "GL | GL-ES2"; break; + case 13: valueName = "GL | GL-ES2 | GL-ES"; break; + case 14: valueName = "GL | GL-ES2 | VG"; break; + case 15: valueName = "GL | GL-ES2 | VG | GL-ES"; break; + } + break; + case EGL_MATCH_NATIVE_PIXMAP: attrName = "EGL_MATCH_NATIVE_PIXMAP"; break; // Pseudo-attribute (not queryable) + case EGL_CONFORMANT: attrName = "EGL_CONFORMANT"; break; + case EGL_HEIGHT: attrName = "EGL_HEIGHT"; break; + case EGL_WIDTH: attrName = "EGL_WIDTH"; break; + case EGL_LARGEST_PBUFFER: attrName = "EGL_LARGEST_PBUFFER"; break; + case EGL_TEXTURE_FORMAT: attrName = "EGL_TEXTURE_FORMAT"; + switch (aValue) + { + // config attribute values, for EGL_TEXTURE_FORMAT + case EGL_NO_TEXTURE: valueName = "EGL_NO_TEXTURE"; break; + case EGL_TEXTURE_RGB: valueName = "EGL_TEXTURE_RGB"; break; + case EGL_TEXTURE_RGBA: valueName = "EGL_TEXTURE_RGBA"; break; + case EGL_TEXTURE_2D: valueName = "EGL_TEXTURE_2D"; break; + } + break; + case EGL_TEXTURE_TARGET: attrName = "EGL_TEXTURE_TARGET"; break; + case EGL_MIPMAP_TEXTURE: attrName = "EGL_MIPMAP_TEXTURE"; break; + case EGL_MIPMAP_LEVEL: attrName = "EGL_MIPMAP_LEVEL"; break; + case EGL_RENDER_BUFFER: attrName = "EGL_RENDER_BUFFER"; + switch (aValue) + { + // EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets + case EGL_BACK_BUFFER: valueName = "EGL_BACK_BUFFER"; break; + case EGL_SINGLE_BUFFER: valueName = "EGL_SINGLE_BUFFER"; break; + } + break; + case EGL_VG_COLORSPACE: attrName = "EGL_VG_COLORSPACE"; + switch (aValue) + { + // OpenVG color spaces + case EGL_VG_COLORSPACE_sRGB: valueName = "EGL_VG_COLORSPACE_sRGB"; break; + case EGL_VG_COLORSPACE_LINEAR: valueName = "EGL_VG_COLORSPACE_LINEAR"; break; + } + break; + case EGL_VG_ALPHA_FORMAT: attrName = "EGL_VG_ALPHA_FORMAT"; + switch (aValue) + { + // OpenVG alpha formats + case EGL_VG_ALPHA_FORMAT_NONPRE: valueName = "EGL_VG_ALPHA_FORMAT_NONPRE"; break; + case EGL_VG_ALPHA_FORMAT_PRE: valueName = "EGL_VG_ALPHA_FORMAT_PRE"; break; + } + break; + case EGL_HORIZONTAL_RESOLUTION: attrName = "EGL_HORIZONTAL_RESOLUTION"; break; + case EGL_VERTICAL_RESOLUTION: attrName = "EGL_VERTICAL_RESOLUTION"; break; + case EGL_PIXEL_ASPECT_RATIO: attrName = "EGL_PIXEL_ASPECT_RATIO"; break; + case EGL_SWAP_BEHAVIOR: attrName = "EGL_SWAP_BEHAVIOR"; break; + case EGL_MULTISAMPLE_RESOLVE: attrName = "EGL_MULTISAMPLE_RESOLVE"; break; + default: // unknown value - maybe buggy data or a later EGL version. Debug prints include the hex anyway. + break; + } + + if (aValue == EGL_NONE) + valueName = "EGL_NONE"; + if (aAttrib == EGL_NONE) + attrName = "EGL_NONE"; + + *aAttrName = attrName; + *aValueName = valueName; + } + +// verbose debug logging of EGL Attibute Lists +void TAttribUtils::TraceAttribList(const EGLint* aAttribList) + { + int length = 0; + if (aAttribList) + { + while (aAttribList[length] != EGL_NONE) + { + char* attrName = NULL; + char* valueName = NULL; + // try to get an attribute name string, and a description of the value + TraceAttribNames(aAttribList[length], aAttribList[length+1], &attrName, &valueName); + // print attribute & value as numbers, and also print a string name/description if one could be determined + if (attrName) + { + if (valueName) + { + EGL_TRACE(" TraceAttribList aAttribList[%d]=0x%x (\"%s\"), aAttribList[%d]=0x%x (\"%s\")", + length, aAttribList[length], attrName, length+1, aAttribList[length+1], valueName); + } + else + { + EGL_TRACE(" TraceAttribList aAttribList[%d]=0x%x (\"%s\"), aAttribList[%d]=0x%x (%d)", + length, aAttribList[length], attrName, length+1, aAttribList[length+1], aAttribList[length+1]); + } + } + else + { + EGL_TRACE(" TraceAttribList aAttribList[%d]=0x%x, aAttribList[%d]=0x%x (%d)", + length, aAttribList[length], length+1, aAttribList[length+1], aAttribList[length+1]); + } + length += 2; + } + ++length; + } + } + +// verbose debug logging of EGL Get Attibute fn +void TAttribUtils::TraceGetAttrib(char* aApiName, char* aObjType, EGLDisplay aDisplay, EGLint aObject, EGLint aAttribute, EGLint *aValue, EGLBoolean aResult) + { + char* attrName = NULL; + char* valueName = NULL; + if (aResult) + { + // try to get an attribute name string, and a description of the value + TraceAttribNames(aAttribute, *aValue, &attrName, &valueName); + // print attribute & value as numbers, and also print a string name/description if one could be determined + if (attrName) + { + if (valueName) + { + EGL_TRACE("%s succeeded: aDisplay=%d, %s=%d, aAttrib=0x%x (\"%s\"), aValue=0x%x (\"%s\")", + aApiName, aDisplay, aObjType, aObject, aAttribute, attrName, *aValue, valueName); + } + else + { + EGL_TRACE("%s succeeded: aDisplay=%d, %s=%d, aAttrib=0x%x (\"%s\"), aValue=0x%x (%d)", + aApiName, aDisplay, aObjType, aObject, aAttribute, attrName, *aValue, *aValue); + } + } + else + { + EGL_TRACE("%s succeeded: aDisplay=%d, %s=%d, aAttrib=0x%x, aValue=0x%x (%d)", + aApiName, aDisplay, aObjType, aObject, aAttribute, *aValue, *aValue); + } + } + else + { + // try to get an attribute name string + TraceAttribNames(aAttribute, 0, &attrName, &valueName); + if (attrName) + { + EGL_TRACE("%s failed: aDisplay=%d, %s=%d, attribute=0x%x (\"%s\")", + aApiName, aDisplay, aObjType, aObject, aAttribute, attrName); + } + else + { + EGL_TRACE("%s failed: aDisplay=%d, %s=%d, attribute=0x%x", + aApiName, aDisplay, aObjType, aObject, aAttribute); + } + } + } + + +// verbose debug logging of EGL Get Attibute fn +void TAttribUtils::TraceSetAttrib(char* aApiName, char* aObjType, EGLDisplay aDisplay, EGLint aObject, EGLint aAttribute, EGLint aValue) + { + char* attrName = NULL; + char* valueName = NULL; + // try to get an attribute name string, and a description of the value + TraceAttribNames(aAttribute, aValue, &attrName, &valueName); + // print attribute & value as numbers, and also print a string name/description if one could be determined + if (attrName) + { + if (valueName) + { + EGL_TRACE("%s: aDisplay=%d, %s=%d, aAttrib=0x%x (\"%s\"), aValue=0x%x (\"%s\")", + aApiName, aDisplay, aObjType, aObject, aAttribute, attrName, aValue, valueName); + } + else + { + EGL_TRACE("%s: aDisplay=%d, %s=%d, aAttrib=0x%x (\"%s\"), aValue=0x%x (%d)", + aApiName, aDisplay, aObjType, aObject, aAttribute, attrName, aValue, aValue); + } + } + else + { + EGL_TRACE("%s: aDisplay=%d, %s=%d, aAttrib=0x%x, aValue=0x%x (%d)", + aApiName, aDisplay, aObjType, aObject, aAttribute, aValue, aValue); + } + } + + +#endif + diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/eglsgimage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/eglsgimage.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,369 @@ +// 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: +// Implementation of SgImage functions exported through eglGetProcAddress + + +#include "eglapi.h" + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// CEgLImage +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef FAISALMEMON_S4_SGIMAGE +CEglImage::CEglImage() : iSgHandle(), iDisplay(0), iSgImageInfo(), iPbufferHandle(0), iVgHandle(VG_INVALID_HANDLE), + iCreateCount(1), iOpenCount(0), iIsDestroyed(EFalse) + { + EGL_TRACE("CEglImage::CEglImage(0x%x)", this); + } + +CEglImage::~CEglImage() + { + EGL_TRACE("CEglImage::~CEglImage(0x%x) iCreateCount=%d, iOpenCount=%d", this, iCreateCount, iOpenCount); + EGLPANIC_ASSERT_DEBUG( (iCreateCount == 0) && (iOpenCount == 0), EEglPanicEglImageRefCountNonZero); + iSgHandle.Close(); + } + +// initialise member data +void CEglImage::Create(TSgDrawableId aSgImageId, EGLDisplay aDisplay, TSgImageInfo& aSgImageInfo, TInt aPbufferHandle, + VGHandle aVgHandle) + { + EGL_TRACE("CEglImage::Create iCreateCount=%d, iOpenCount=%d", iCreateCount, iOpenCount); + EGLPANIC_ASSERT_DEBUG(iCreateCount == 0, EEglPanicEglImageRefCountNonZero); + EGLPANIC_ASSERT_DEBUG(!iIsDestroyed, EEglPanicEglImageIsDestroyed); + EGLPANIC_ASSERT_DEBUG(aSgImageId != KSgNullDrawableId, EEglPanicTemp); + ++iCreateCount; + TInt err = iSgHandle.Open(aSgImageId); + EGLPANIC_ASSERT_DEBUG(err == KErrNone, EEglPanicTemp); + iDisplay = aDisplay; + iSgImageInfo = aSgImageInfo; + iVgHandle = aVgHandle; + iPbufferHandle = aPbufferHandle; + } + +// Duplicate open +void CEglImage::Duplicate() + { + EGL_TRACE("CEglImage::Duplicate iCreateCount=%d, iOpenCount=%d", iCreateCount, iOpenCount); + EGLPANIC_ASSERT_DEBUG( (iCreateCount > 0) && !iIsDestroyed, EEglPanicEglImageIsDestroyed); + ++iCreateCount; + } + + +// If successful increments reference count & returns ETrue. (Ultimtately called from e.g. vgCreateEGLImageTargetKHR.) +TBool CEglImage::OpenForVgImage(TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId) + { + EGL_TRACE("CEglImage::OpenForVgImage iCreateCount=%d, iOpenCount=%d", iCreateCount, iOpenCount); + if ( (iCreateCount > 0) && (iSgImageInfo.iUsage & ESgUsageBitOpenVgImage) ) + { + ++iOpenCount; + aSize = iSgImageInfo.iSizeInPixels; + aVgHandle = iVgHandle; + aSgImageId = iSgHandle.Id().iId; + return ETrue; + } + return EFalse; + } + +// If successful decrements reference count & returns ETrue. (Ultimtately called from e.g. vgDestroyImage.) +TBool CEglImage::Close() + { + EGL_TRACE("CEglImage::Close iCreateCount=%d, iOpenCount=%d", iCreateCount, iOpenCount); + if (iOpenCount > 0) + { + --iOpenCount; + if ( RefCount() == 0 ) + { + iSgHandle.Close(); + } + return ETrue; + } + return EFalse; + } + +// If not already destroyed: mark EglImage as destroyed, dec reference count, return ETrue. (Called from eglDestroyImageKHR.) +TBool CEglImage::Destroy() + { + EGL_TRACE("CEglImage::Destroy iCreateCount=%d, iOpenCount=%d", iCreateCount, iOpenCount); + if (!iIsDestroyed) + { + --iCreateCount; + if (iCreateCount == 0) + { + iIsDestroyed = ETrue; + if ( RefCount() == 0 ) + { + iSgHandle.Close(); + } + return ETrue; + } + } + return EFalse; + } + +// Reference Count: count of unbalanced Create() plus Open() calls. +TInt CEglImage::RefCount() + { + return iOpenCount + iCreateCount; + } + +TSgDrawableId CEglImage::SgImageId() const + { + return iSgHandle.Id(); + } + +EGLDisplay CEglImage::Display() const + { + return iDisplay; + } + +TBool CEglImage::IsDestroyed() const + { + return iIsDestroyed; + } +#else +void CEglImage::Duplicate() {} +TBool CEglImage::OpenForVgImage(TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId) {} +TBool CEglImage::Close() {} +TBool CEglImage::Destroy() {} +TBool CEglImage::IsDestroyed() const {} +TInt CEglImage::RefCount() {} +EGLDisplay CEglImage::Display() const {} +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// SgImage stuff in CGuestEGL +//////////////////////////////////////////////////////////////////////////////////////////////////// + + +EGLint CGuestEGL::ValidateEglImageTarget(EGLDisplay aDisplay, EGLContext aContext, EGLenum aTarget, + EGLClientBuffer aBuffer, const EGLint *aAttribList, TSymbianPixmapTypeId aTargetPixmapType) + { + if (!IsDisplayInitialized(aDisplay)) // ToDo just check display is valid, don't care if it is initialised + { + return EGL_BAD_DISPLAY; + } + if ( (aContext != EGL_NO_CONTEXT) || (aTarget != EGL_NATIVE_PIXMAP_KHR) ) + { + return EGL_BAD_PARAMETER; + } + aTargetPixmapType = EglInternalFunction_GetNativePixmapType((EGLNativePixmapType) aBuffer); + if ( (aTargetPixmapType != EPixmapTypeSgImage) || !EglInternalFunction_IsValidNativePixmap((EGLNativePixmapType) aBuffer, aTargetPixmapType) ) + { + return EGL_BAD_PARAMETER; + } + // ToDo check Attrib List is valid + return EGL_SUCCESS; + } + +#ifdef FAISALMEMON_S4_SGIMAGE +EGLImageKHR CGuestEGL::DuplicateEglImageIfItExists(EGLDisplay aDisplay, TSgDrawableId aSgId) + { // ToDo something smarter with a Hash Map ? + TInt imageCount = iEglImageArray.Count(); + for (TInt index = 0; index < imageCount; ++index) + { + CEglImage* imagePtr = iEglImageArray[index]; + if ( !imagePtr->IsDestroyed() && (imagePtr->SgImageId() == aSgId) && (imagePtr->Display() == aDisplay) ) + { + imagePtr->Duplicate(); + EGL_TRACE("CGuestEGL::DuplicateEglImageIfItExists SgImage already used for eglImage=0x%x", imagePtr); + return (EGLImageKHR)imagePtr; + } + } + return EGL_NO_IMAGE_KHR; + } + + + +EGLImageKHR CGuestEGL::CreateNewEglImage(TEglThreadState& aThreadState, EGLDisplay aDisplay, TSgDrawableId aSgId, TSgImageInfo aSgImageInfo) + { + RHeap* oldHeap = CVghwUtils::SwitchToVghwHeap(); + CEglImage* newImage = new CEglImage(); + if (newImage) + { + if (KErrNone != iEglImageArray.InsertInAddressOrder(newImage)) + { + delete newImage; + newImage = NULL; + } + } + CVghwUtils::SwitchFromVghwHeap(oldHeap); + if (newImage == NULL) + { + EGL_TRACE("CGuestEGL::CreateNewEglImage 1.a error creating new CEglImage"); + return EGL_NO_IMAGE_KHR; + } + + // success ... + EGL_TRACE("CGuestEGL::CreateNewEglImage 1.b Created new eglImage=0x%x", newImage); + TInt pbufferHandle; + TInt vgImageHandle; + TUint64 sgHandles; + EGLint hostResult = CVghwUtils::EglGetSgHandles(aSgId.iId, &sgHandles); + pbufferHandle = (TInt)(sgHandles&0xFFFFFFFF); + vgImageHandle = (TInt)((sgHandles>>32)&0xFFFFFFFF); + EGL_TRACE("CGuestEGL::CreateNewEglImage 2. CVghwUtils::EglGetSgHandles result=%d, pbufferHandle=0x%x, vgImageHandle=0x%x", + hostResult, pbufferHandle, vgImageHandle); + EGLPANIC_ASSERT(KErrNone == hostResult, EEglPanicTemp); + + newImage->Create(aSgId, aDisplay, aSgImageInfo, pbufferHandle, vgImageHandle); + + return (EGLImageKHR)newImage; + } + +#endif // FAISALMEMON_S4_SGIMAGE + + +/* + * eglCreateImageKHR supports Khronos EGL extension #8, "KHR_image_base" + * + * Supported values for target parameter: + * EGL_NATIVE_PIXMAP_KHR for Khronos EGL extension #9, "KHR_image_pixmap" + */ +EGLImageKHR CGuestEGL::eglCreateImageKHR(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLContext aContext, EGLenum aTarget, + EGLClientBuffer aBuffer, const EGLint *aAttribList) + { + // ToDo lock aDisplay + EGLImageKHR eglImage = EGL_NO_IMAGE_KHR; + iEglImageLock.Wait(); + TSymbianPixmapTypeId targetPixmapType = EPixmapTypeNone; + EGLint error = ValidateEglImageTarget(aDisplay, aContext, aTarget, aBuffer, aAttribList, targetPixmapType); + EGL_TRACE("CGuestEGL::eglCreateImageKHR 1. validate error=%d, targetPixmapType=%d", error, targetPixmapType); + + if (error == EGL_SUCCESS) + { + switch(targetPixmapType) + { + case EPixmapTypeSgImage: + { +#ifdef FAISALMEMON_S4_SGIMAGE + // try to lock SgImage from disappearing by opening a temporary handle + RSgImage* sgImagePtr = reinterpret_cast(aBuffer); + TSgDrawableId sgId = sgImagePtr->Id(); + RSgDrawable sgHandle; + TSgImageInfo imgInfo; + // ToDo ensure SgImage has correct suitable usage bits + if ( (sgId != KSgNullDrawableId) && (KErrNone == sgHandle.Open(sgId)) && (KErrNone == sgImagePtr->GetInfo(imgInfo)) ) + { + EGL_TRACE("CGuestEGL::eglCreateImageKHR 2. SgImage PixelFormat=%d; size=%d,%d; Usage=0x%x", + imgInfo.iPixelFormat, imgInfo.iSizeInPixels.iWidth, imgInfo.iSizeInPixels.iHeight, imgInfo.iUsage); + + // find / create CEglImage + if (error == EGL_SUCCESS) + { // SgImage may already be used for an EglImage + eglImage = DuplicateEglImageIfItExists(aDisplay, sgId); + if (eglImage == EGL_NO_IMAGE_KHR) + { // first use + eglImage = CreateNewEglImage(aThreadState, aDisplay, sgId, imgInfo); + if (eglImage == EGL_NO_IMAGE_KHR) + { + error = EGL_BAD_ALLOC; + } + } + } + } + else + { + error = EGL_BAD_PARAMETER; + } + sgHandle.Close(); +#endif + } + break; + + case EPixmapTypeFbsBitmap: + case EPixmapTypeNone: + default: // pixmap type not supported by this API + error = EGL_BAD_PARAMETER; + break; + } + } + + iEglImageLock.Signal(); + aThreadState.SetEglError(error); + + // we either failed or should have a non-NULL handle + EGLPANIC_ASSERT_DEBUG( (error != EGL_SUCCESS) || (eglImage != EGL_NO_IMAGE_KHR), EEglPanicTemp); + + return eglImage; + } + +/* + * eglDestroyImageKHR supports Khronos EGL extension #8, "KHR_image_base" + */ +EGLBoolean CGuestEGL::eglDestroyImageKHR(TEglThreadState& aThreadState, EGLDisplay aDisplay, EGLImageKHR aImage) + { + // ToDo lock aDisplay + EGLBoolean result = EGL_FALSE; + iEglImageLock.Wait(); + TInt index = iEglImageArray.FindInAddressOrder((CEglImage*)aImage); + if (index >= 0) + { + CEglImage* eglImage = iEglImageArray[index]; + if ( (eglImage->Display() && aDisplay) && eglImage->Destroy()) + { + result = EGL_TRUE; + if (eglImage->RefCount() == 0) + { + iEglImageArray.Remove(index); + delete eglImage; + } + } + } + iEglImageLock.Signal(); + + // set EGL Error appropriately + aThreadState.SetEglError( result ? EGL_SUCCESS : EGL_BAD_PARAMETER); + return result; + } + + +TBool CGuestEGL::EglImageOpenForVgImage(EGLImageKHR aImage, TSize& aSize, VGHandle& aVgHandle, TUint64& aSgImageId) + { + EGLBoolean result = EGL_FALSE; + iEglImageLock.Wait(); + TInt index = iEglImageArray.FindInAddressOrder((CEglImage*)aImage); + if (index >= 0) + { + CEglImage* eglImage = iEglImageArray[index]; + if (eglImage->OpenForVgImage(aSize, aVgHandle, aSgImageId)) + { + result = EGL_TRUE; + } + } + iEglImageLock.Signal(); + return result; + } + +void CGuestEGL::EglImageClose(EGLImageKHR aImage) + { + iEglImageLock.Wait(); + TInt index = iEglImageArray.FindInAddressOrder((CEglImage*)aImage); + if (index >= 0) + { + CEglImage* eglImage = iEglImageArray[index]; + if (eglImage->Close()) + { + if (eglImage->RefCount() == 0) + { + iEglImageArray.Remove(index); + delete eglImage; + } + } + } + iEglImageLock.Signal(); + } + +// end of file eglsgimage.cpp diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestegl/src/eglsync.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestegl/src/eglsync.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -0,0 +1,708 @@ +// 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: +// EGL sync implementation + +#include "eglapi.h" + +const EGLint CEglSync::KSupportedFlags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; + +// ToDo get rid of these macros +#define EGL_SET_ERROR(e) { Instance().SetError(e); } +#define TEST_AND_RET(c, r, t) { if (!(c)) { EGL_TRACE(t); return (r); } } +#define TEST_CLEANUP_RET(c, r, clnp, t) { if (!(c)) { clnp; EGL_TRACE(t); return (r); } } +#define CHECK_AND_RET(c, e, r, t) { if (!(c)) { EGL_SET_ERROR(e); EGL_TRACE(t); return (r); } } +#define CHECK_CLEANUP_RET(c, e, r, clnp, t) { if (!(c)) { EGL_SET_ERROR(e); clnp; EGL_TRACE(t); return (r); } } +#define RESET_EGL_ERROR() { EGL_SET_ERROR(EGL_SUCCESS); } + +// ToDo use EGL Panics & panic messages +void SyncPanic(TInt aPanic) + { + _LIT(KPanic, "EGL SYNC"); + User::Panic(KPanic, aPanic); + } + +CEglSync* CEglSync::Create(RFastLock& aFrontLock, EGLSyncKHR aSync, EGLDisplay aDisplay, EGLenum aType) + { + CEglSync* sync= new CEglSync(aFrontLock, aSync, aDisplay, aType); + TEST_AND_RET(sync != NULL, sync, "CEglSync::Create couldn't create the object"); + if (KErrNone == sync->Initialize()) + { + EGL_TRACE("CEglSync::Create OK aDisplay=%d aSync=%d aSyncType=0x%x", aDisplay, aSync, aType); + return sync; + } + else + { + EGL_TRACE("CEglSync::Create FAILED aDisplay=%d aSync=%d aSyncType=0x%x", aDisplay, aSync, aType); + delete sync; + return NULL; + } + } + +TInt CEglSync::Initialize() + { + TInt err = KErrNone; + err = iSyncMutex.CreateLocal(); + TEST_AND_RET(err == KErrNone, err, "CEglSync::Initialize failed to create mutex"); + err = iSyncCondVar.CreateLocal(); + TEST_AND_RET(err == KErrNone, err, "CEglSync::Initialize failed to create cond var"); + return err; + } + + +CEglSync::CEglSync(RFastLock& aFrontLock, EGLSyncKHR aSync, EGLDisplay aDisplay, EGLenum aType): +iEglSync(aSync), +iDisplay(aDisplay), +iSyncType(aType), +iSyncState(EGL_UNSIGNALED_KHR), +iDestroyed(EGL_FALSE), +iWaiters(0), +iFrontLock(aFrontLock) + { + + } + +CEglSync::~CEglSync() + { + iSyncMutex.Close(); + iSyncCondVar.Close(); + EGL_TRACE("CEglSync::~CEglSync iDisplay=%d iEglSync=%d", iDisplay, iEglSync); + } + +EGLBoolean CEglSync::DestroySyncReady() + { + EGL_TRACE("CEglSync::DestroySync iDisplay=%d iEglSync=%d iWaiters=%d", iDisplay, iEglSync, iWaiters); + iSyncMutex.Wait(); + if (iWaiters == 0) + { + EGL_TRACE("CEglSync::DestroySync READY TO DESTROY iDisplay=%d iEglSync=%d iWaiters=%d", iDisplay, iEglSync, iWaiters); + iDestroyed = EGL_TRUE; + return EGL_TRUE; + } + else if (!iDestroyed) + { + EGL_TRACE("CEglSync::DestroySync BROADCAST iDisplay=%d iEglSync=%d iWaiters=%d", iDisplay, iEglSync, iWaiters); + iSyncCondVar.Broadcast(); + } + iDestroyed = EGL_TRUE; + iSyncMutex.Signal(); + return EGL_FALSE; + } + + +EGLint CEglSync::SignalSync(EGLenum aMode) + { + EGL_TRACE("CEglSync::SignalSync aMode=%d", aMode); + + iSyncMutex.Wait(); + if (aMode != iSyncState) + { + iSyncState = aMode; + if (aMode == EGL_SIGNALED_KHR) + { + iSyncCondVar.Broadcast(); + } + } + + iSyncMutex.Signal(); + return EGL_SUCCESS; + } + +EGLint CEglSync::ClientWaitSync(EGLint aFlags, EGLTimeKHR aTimeout) + { + EGL_TRACE("CEglSync::ClientWaitSync aFlags=%d aTimeout=%d", aFlags, aTimeout); + + CHECK_CLEANUP_RET(!(aFlags & (~KSupportedFlags)), + EGL_BAD_PARAMETER, + EGL_FALSE, + iFrontLock.Signal();, + "CEglSync::ClientWaitSync bad flags parameter"); + + iSyncMutex.Wait(); + iFrontLock.Signal(); + + CHECK_CLEANUP_RET(!iDestroyed , + EGL_BAD_PARAMETER, + EGL_FALSE, + iSyncMutex.Signal();, + "CEglSync::ClientWaitSync sync already destroyed"); + + EGLint ret = (EGLint) EGL_FALSE; + if (iSyncState == EGL_UNSIGNALED_KHR) + { + if (aTimeout && (aFlags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) && (eglGetCurrentContext() != EGL_NO_CONTEXT)) + { + switch(eglQueryAPI()) + { + case EGL_OPENGL_ES_API: + //ToDo: make sure these cases are covered + //glFlush(); + break; + case EGL_OPENVG_API: + //ToDo: make sure these cases are covered + //vgFlush(); + break; + default: + SyncPanic(__LINE__); + } + } + + switch (aTimeout) + { + case 0: + ret = EGL_TIMEOUT_EXPIRED_KHR; + break; + + case EGL_FOREVER_KHR: + { + EGLint res = KErrNone; + ++iWaiters; + EGL_TRACE("CEglSync::ClientWaitSync iSyncCondVar.Wait"); + res = iSyncCondVar.Wait(iSyncMutex); + --iWaiters; + if (res == KErrNone) + { + ret = EGL_CONDITION_SATISFIED_KHR; + } + else + { + ret = EGL_FALSE; + } + break; + } + + default: + { + /* + * Since the supported range of timeout at function RCondVar::TimedWait(mutex, timeout) + * is 0 to KMaxTInt, looping mechanism below is used to support 64bit timeout. + */ + EGLint res = KErrTimedOut; + EGL_TRACE("CEglSync::ClientWaitSync iSyncCondVar.TimedWait"); + for(TInt64 timeoutMicroseconds = aTimeout/1000; (res == KErrTimedOut) && (timeoutMicroseconds > 0); timeoutMicroseconds -= KMaxTInt) + { + ++iWaiters; + res = iSyncCondVar.TimedWait(iSyncMutex, (timeoutMicroseconds > KMaxTInt) ? KMaxTInt:timeoutMicroseconds); + --iWaiters; + } + switch (res) + { + case KErrNone: + ret = EGL_CONDITION_SATISFIED_KHR; + break; + case KErrTimedOut: + ret = EGL_TIMEOUT_EXPIRED_KHR; + break; + default: + ret = EGL_FALSE; + break; + } + break; + } + } + } + else + { + ret = EGL_CONDITION_SATISFIED_KHR; + EGL_TRACE("CEglSync::ClientWaitSync sync in signalled state"); + } + if (iDestroyed && (iWaiters == 0)) + { + EGL_TRACE("CEglSync::ClientWaitSync sync autodestroyed"); + delete this; + } + else + { + EGL_TRACE("CEglSync::ClientWaitSync release sync mutex"); + iSyncMutex.Signal(); + } + EGL_TRACE("CEglSync::ClientWaitSync sync exit ret=0x%x", ret); + return ret; + } + +EGLBoolean CEglSync::GetSyncAttrib(EGLint aAttribute, EGLint *aValue) + { + EGL_TRACE("CEglSync::GetSyncAttrib aAttribute=0x%x aValue", aValue); + + CHECK_AND_RET(aValue, + EGL_BAD_PARAMETER, + EGL_FALSE, + "CEglSync::GetSyncAttrib undefined parameter aValue is NUL"); + + CHECK_AND_RET((aAttribute == EGL_SYNC_TYPE_KHR) || (aAttribute == EGL_SYNC_STATUS_KHR), + EGL_BAD_ATTRIBUTE, + EGL_FALSE, + "CEglSync::GetSyncAttrib unnexpected attribute parameter"); + + + iSyncMutex.Wait(); + EGLBoolean ret = EGL_FALSE; + switch(aAttribute) + { + case EGL_SYNC_TYPE_KHR: + { + *aValue = iSyncType; + ret = EGL_TRUE; + break; + } + case EGL_SYNC_STATUS_KHR: + { + *aValue = iSyncState; + ret = EGL_TRUE; + break; + } + default: + { + EGL_SET_ERROR(EGL_BAD_ATTRIBUTE); + } + } + iSyncMutex.Signal(); + return ret; + } + + +CEglSyncExtension* CEglSyncExtension::Create(CGuestEGL& aEglInstance) + { + EGL_TRACE("CEglSyncExtension::Create"); + CEglSyncExtension* eglSyncExt= new CEglSyncExtension(aEglInstance); + if (eglSyncExt && eglSyncExt->Construct()) + { + return eglSyncExt; + } + + delete eglSyncExt; + return NULL; + } + +EGLBoolean CEglSyncExtension::Construct() + { + if (iEglSyncMapLock.CreateLocal() == KErrNone) + { + EGL_TRACE("CEglSyncExtension::Construct OK"); + return EGL_TRUE; + } + + EGL_TRACE("CEglSyncExtension::Construct FAILED"); + return EGL_FALSE; + } + +CEglSyncExtension::CEglSyncExtension(CGuestEGL& aEglInstance): +iEglSyncMap(), +iEglSyncId(0), +iEglInstance(aEglInstance) + { + + } + +CEglSyncExtension::~CEglSyncExtension() + { + if (iEglSyncMapLock.Handle()) + { + iEglSyncMapLock.Wait(); + } + + EglDestroySync(EGL_NO_DISPLAY); + + iEglSyncMap.Close(); + iEglSyncMapLock.Close(); + } + +TInt CEglSyncExtension::EglSyncDisplayCreate(EGLDisplay aDisplay) + { + return KErrNone; + } + +void CEglSyncExtension::EglDestroySync(EGLDisplay aDisplay) + { + EGL_TRACE("CEglSyncExtension::EglDestroySync"); + REglSyncHashMap::TIter iter(iEglSyncMap); + + while (iter.NextKey()) + { + CEglSync* const* syncpp = NULL; + syncpp = iter.CurrentValue(); + if (syncpp && *syncpp && ((aDisplay == EGL_NO_DISPLAY) || (*syncpp)->Display() == aDisplay)) + { + const EGLint* key = iter.CurrentKey(); + EGLPANIC_ASSERT(key, EEglPanicTemp); + if (aDisplay != EGL_NO_DISPLAY) + { + // we expect that the map is to be closed after removing the elements + // therefore we can skip to remove the syncs from map + if (KErrNone != iEglSyncMap.Remove(*key)) + { + SyncPanic(__LINE__); + } + } + if ((*syncpp)->DestroySyncReady()) + { + delete *syncpp; + } + } + } + } + +void CEglSyncExtension::EglSyncDisplayDestroy(EGLDisplay aDisplay) + { + iEglSyncMapLock.Wait(); + EglDestroySync(aDisplay); + iEglSyncMapLock.Signal(); + } + +EGLSyncKHR CEglSyncExtension::EglCreateSyncKHR(EGLDisplay aDisplay, EGLenum aType, const EGLint* aAttribList) + { + EGL_TRACE("CEglSyncExtension::EglCreateSyncKHR aDisplay=%d, aType=%d", aDisplay, aType); + RESET_EGL_ERROR(); + + CHECK_AND_RET(aType == EGL_SYNC_REUSABLE_KHR, + EGL_BAD_ATTRIBUTE, + EGL_NO_SYNC_KHR, + "CEglSyncExtension::EglCreateSyncKHR unsupported sync type"); + + CHECK_AND_RET((aAttribList == NULL) || (*aAttribList == EGL_NONE), + EGL_BAD_ATTRIBUTE, + EGL_NO_SYNC_KHR, + "CEglSyncExtension::EglCreateSyncKHR invalid attribute list"); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + CHECK_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + EGL_NO_SYNC_KHR, + "CEglSyncExtension::EglCreateSyncKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + EGLSyncKHR dispRet = CreateSync(aDisplay, aType); + + iEglSyncMapLock.Signal(); + CVghwUtils::SwitchFromVghwHeap(callerHeap); + EGL_TRACE("CEglSyncExtension::EglCreateSyncKHR EXIT aDisplay=%d, sync=%d", aDisplay, dispRet); + return dispRet; + } + +EGLBoolean CEglSyncExtension::EglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync) + { + EGL_TRACE("CEglSyncExtension::EglDestroySyncKHR aDisplay=%d, aSync=%d", aDisplay, aSync); + + RESET_EGL_ERROR(); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + CHECK_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + EGL_FALSE, + "CEglSyncExtension::EglDestroySyncKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + CEglSync** sync = iEglSyncMap.Find((EGLint)aSync); + CHECK_CLEANUP_RET(sync && (*sync) && ((*sync)->Display() == aDisplay), + EGL_BAD_PARAMETER, + EGL_FALSE, + iEglSyncMapLock.Signal(), + "CEglSyncDisplayMap::EglDestroySyncKHR cannot find the sync"); + + if (KErrNone != iEglSyncMap.Remove((EGLint)aSync)) + { + SyncPanic(__LINE__); + } + + if ((*sync)->DestroySyncReady()) + { + delete *sync; + } + + iEglSyncMapLock.Signal(); + + CVghwUtils::SwitchFromVghwHeap(callerHeap); + EGL_TRACE("CEglSyncExtension::EglDestroySyncKHR EXIT aDisplay=%d, aSync=%d ret=%s", aDisplay, aSync, "EGL_TRUE"); + return EGL_TRUE; + } + +EGLBoolean CEglSyncExtension::EglSignalSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode) + { + EGL_TRACE("CEglSyncExtension::EglSignalSyncKHR aDisplay=%d, aSync=%d aMode=%d", aDisplay, aSync, aMode); + EGLBoolean ret = EGL_FALSE; + + RESET_EGL_ERROR(); + + CHECK_AND_RET((aMode == EGL_SIGNALED_KHR) || (aMode == EGL_UNSIGNALED_KHR), + EGL_BAD_PARAMETER, + ret, + "CEglSyncExtension::EglSignalSyncKHR unsupported sync mode"); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + CHECK_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + EGL_FALSE, + "CEglSyncExtension::EglSignalSyncKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + CEglSync** sync= iEglSyncMap.Find((EGLint)aSync); + + CHECK_CLEANUP_RET(sync && (*sync) && ((*sync)->Display()==aDisplay), + EGL_BAD_PARAMETER, + EGL_FALSE, + iEglSyncMapLock.Signal(); CVghwUtils::SwitchFromVghwHeap(callerHeap);, + "CEglSyncExtension::EglSignalSyncKHR cannot find the lock"); + + TEST_CLEANUP_RET((*sync)->Display() == EGL_SYNC_REUSABLE_KHR, + EGL_BAD_MATCH, + iEglSyncMapLock.Signal(); CVghwUtils::SwitchFromVghwHeap(callerHeap);, + "CEglSyncExtension::EglSignalSyncKHR bad sync type"); + + EGLint signalRet = (*sync)->SignalSync(aMode); + + if (signalRet != EGL_SUCCESS) + { + EGL_SET_ERROR(ret); + EGL_TRACE("CEglSyncExtension::EglSignalSyncKHR failed (%d)", ret); + ret = EGL_FALSE; + } + else + { + ret = EGL_TRUE; + } + + iEglSyncMapLock.Signal(); + CVghwUtils::SwitchFromVghwHeap(callerHeap); + EGL_TRACE("CEglSyncExtension::EglSignalSyncKHR EXIT aDisplay=%d, aSync=%d ret=%s", aDisplay, aSync, ret ? "EGL_TRUE":"EGL_FALSE"); + return ret; + } + +EGLint CEglSyncExtension::Egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode) + { + EGL_TRACE("CEglSyncExtension::EglPrivateSignalSyncKHR aDisplay=%d, aSync=%d aMode=%d", aDisplay, aSync, aMode); + + TEST_AND_RET((aMode == EGL_SIGNALED_KHR) || (aMode == EGL_UNSIGNALED_KHR), + EGL_BAD_PARAMETER, + "CEglSyncExtension::EglPrivateSignalSyncKHR unsupported sync mode"); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + TEST_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + "CEglSyncExtension::EglPrivateSignalSyncKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + CEglSync** sync= iEglSyncMap.Find((EGLint)aSync); + + TEST_CLEANUP_RET(sync && (*sync) && ((*sync)->Display()==aDisplay), + EGL_BAD_PARAMETER, + iEglSyncMapLock.Signal(); CVghwUtils::SwitchFromVghwHeap(callerHeap);, + "CEglSyncExtension::EglPrivateSignalSyncKHR cannot find the lock"); + + EGLint ret = (*sync)->SignalSync(aMode); + + if (ret != EGL_SUCCESS) + { + EGL_TRACE("CEglSyncExtension::EglPrivateSignalSyncKHR failed (%d)", ret); + } + + iEglSyncMapLock.Signal(); + CVghwUtils::SwitchFromVghwHeap(callerHeap); + EGL_TRACE("CEglSyncExtension::EglPrivateSignalSyncKHR EXIT aDisplay=%d, aSync=%d ret=%d", aDisplay, aSync, ret); + return ret; + } + +EGLint CEglSyncExtension::EglClientWaitSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout) + { + EGL_TRACE("CEglSyncExtension::EglClientWaitSyncKHR aDisplay=%d, aSync=%d aFlags=0x%x, aTimeout=%ld", aDisplay, aSync, aFlags, aTimeout); + + RESET_EGL_ERROR(); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + CHECK_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + EGL_FALSE, + "CEglSyncExtension::EglClientWaitSyncKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + CEglSync** sync= iEglSyncMap.Find((EGLint)aSync); + + CHECK_CLEANUP_RET(sync && (*sync) && ((*sync)->Display()==aDisplay), + EGL_BAD_PARAMETER, + EGL_FALSE, + iEglSyncMapLock.Signal(); CVghwUtils::SwitchFromVghwHeap(callerHeap);, + "CEglSyncExtension::EglClientWaitSyncKHR cannot find the sync"); + + EGLint ret = (*sync)->ClientWaitSync(aFlags, aTimeout); + + CVghwUtils::SwitchFromVghwHeap(callerHeap); + EGL_TRACE("CEglSyncExtension::EglClientWaitSyncKHR EXIT aDisplay=%d, aSync=%d ret=%d", aDisplay, aSync, ret); + return ret; + } + +EGLBoolean CEglSyncExtension::EglGetSyncAttribKHR(EGLDisplay aDisplay, + EGLSyncKHR aSync, + EGLint aAttribute, + EGLint* aValue) + { + EGL_TRACE("CEglSyncExtension::EglGetSyncAttribKHR aDisplay=%d, aSync=%d aAttribute=0x%x, aValue=0x%x", aDisplay, + aSync, + aAttribute, + aValue); + RESET_EGL_ERROR(); + + EGLint lockErr = FindAndLockDisplay(aDisplay); + + CHECK_AND_RET(lockErr == EGL_SUCCESS, + lockErr, + EGL_FALSE, + "CEglSyncExtension::EglGetSyncAttribKHR couldn't find and lock display"); + + RHeap* callerHeap = CVghwUtils::SwitchToVghwHeap(); + + iEglSyncMapLock.Wait(); + ReleaseDisplayLock(aDisplay); + + CEglSync** sync= iEglSyncMap.Find((EGLint)aSync); + + CHECK_CLEANUP_RET(sync && (*sync) && ((*sync)->Display()==aDisplay), + EGL_BAD_PARAMETER, + EGL_FALSE, + iEglSyncMapLock.Signal(); CVghwUtils::SwitchFromVghwHeap(callerHeap);, + "CEglSyncExtension::EglGetSyncAttribKHR cannot find the lock"); + + + EGLint ret = (*sync)->GetSyncAttrib(aAttribute, aValue); + + iEglSyncMapLock.Signal(); + + CVghwUtils::SwitchFromVghwHeap(callerHeap); + + EGL_TRACE("CEglSyncExtension::EglGetSyncAttribKHR EXIT aDisplay=%d, aSync=%d ret=%s", aDisplay, aSync, ret ? "EGL_TRUE":"EGL_FALSE"); + return ret; + } + +EGLint CEglSyncExtension::FindAndLockDisplay(EGLDisplay aDisplay) + { + return iEglInstance.FindAndLockDisplay(aDisplay); + } + +void CEglSyncExtension::ReleaseDisplayLock(EGLDisplay aDisplay) + { + iEglInstance.ReleaseDisplayLock(aDisplay); + } + +EGLSyncKHR CEglSyncExtension::CreateSync(EGLDisplay aDisplay, EGLenum aType) + { + CEglSync* sync = CEglSync::Create(iEglSyncMapLock, + (EGLSyncKHR)(++iEglSyncId), + aDisplay, + aType); + + CHECK_AND_RET(sync != NULL, + EGL_BAD_ALLOC, + EGL_NO_SYNC_KHR, + "CEglSyncDisplayMap::CreateSync failed to create sync"); + + TInt err = KErrNone; + err = iEglSyncMap.Insert(iEglSyncId, sync); + + CHECK_CLEANUP_RET(err == KErrNone, + EGL_BAD_ALLOC, + EGL_NO_SYNC_KHR, + delete sync, + "CEglSyncDisplayMap::CreateSync insert failed"); + + return (EGLSyncKHR)iEglSyncId; + } + +EGLSyncKHR CEglSyncExtension::eglCreateSyncKHR(EGLDisplay aDisplay, EGLenum aType, const EGLint* aAttribList) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_NO_SYNC_KHR, + "CEglSyncExtension::eglCreateSyncKHR extension instance not created"); + + return eglSyncInstance->EglCreateSyncKHR(aDisplay, aType, aAttribList); + } + +EGLBoolean CEglSyncExtension::eglDestroySyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_FALSE, + "CEglSyncExtension::eglDestroySyncKHR extension instance not created"); + + return eglSyncInstance->EglDestroySyncKHR(aDisplay, aSync); + } + +EGLint CEglSyncExtension::eglClientWaitSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aFlags, EGLTimeKHR aTimeout) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_FALSE, + "CEglSyncExtension::eglGetSyncAttribKHR extension instance not created"); + + return eglSyncInstance->EglClientWaitSyncKHR(aDisplay, aSync, aFlags, aTimeout); + } + +EGLBoolean CEglSyncExtension::eglSignalSyncKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_FALSE, + "CEglSyncExtension::eglSignalSyncKHR extension instance not created"); + + return eglSyncInstance->EglSignalSyncKHR(aDisplay, aSync, aMode); + } + + +EGLBoolean CEglSyncExtension::eglGetSyncAttribKHR(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLint aAttribute, EGLint* aValue) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_FALSE, + "CEglSyncExtension::eglGetSyncAttribKHR extension instance not created"); + + return eglSyncInstance->EglGetSyncAttribKHR(aDisplay, aSync, aAttribute, aValue); + } + +EGLint CEglSyncExtension::egl_Private_SignalSyncNOK(EGLDisplay aDisplay, EGLSyncKHR aSync, EGLenum aMode) + { + CEglSyncExtension* eglSyncInstance = Instance().EGLSyncExtension(); + CHECK_AND_RET(eglSyncInstance, + EGL_NOT_INITIALIZED, + EGL_NOT_INITIALIZED, + "CEglSyncExtension::egl_Private_SignalSyncNOK extension instance not created"); + + return eglSyncInstance->Egl_Private_SignalSyncNOK(aDisplay, aSync, aMode); + } 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; + } diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp --- a/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Fri Sep 03 10:14:54 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/virtualvideohwinterface.cpp Wed Sep 08 15:45:18 2010 +0100 @@ -25,7 +25,9 @@ // CONSTANTS +#ifdef PLATSIM_CONFIG _LIT( KVirtualVideoHwInterfacePanic, "DVirtualVideoHwInterface" ); +#endif // ============================ LOCAL DATA TYPES =============================== diff -r a4c94be9fb92 -r 220791dae4c4 guestrendering/vghwutils/inc/vghwutils.h --- a/guestrendering/vghwutils/inc/vghwutils.h Fri Sep 03 10:14:54 2010 +0100 +++ b/guestrendering/vghwutils/inc/vghwutils.h Wed Sep 08 15:45:18 2010 +0100 @@ -92,7 +92,7 @@ class MVgApiForEgl { public: - virtual ExtensionProcPointer platsimGetVgProcAddress (const char *aProcName) = 0; + virtual ExtensionProcPointer guestGetVgProcAddress (const char *aProcName) = 0; }; @@ -100,7 +100,7 @@ class MGles11ApiForEgl { public: - virtual ExtensionProcPointer platsimGetGles11ProcAddress (const char *aProcName) = 0; + virtual ExtensionProcPointer guestGetGles11ProcAddress (const char *aProcName) = 0; }; @@ -108,7 +108,7 @@ class MGles2ApiForEgl { public: - virtual ExtensionProcPointer platsimGetGles2ProcAddress (const char *aProcName) = 0; + virtual ExtensionProcPointer guestGetGles2ProcAddress (const char *aProcName) = 0; };