--- /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 <e32debug.h>
+#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