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