diff -r d8d95053303a -r e8ccf068ac7f guestrendering/guestvideodriver/ldd/src/devicereqhandler.cpp --- a/guestrendering/guestvideodriver/ldd/src/devicereqhandler.cpp Fri Aug 20 18:02:40 2010 +0100 +++ b/guestrendering/guestvideodriver/ldd/src/devicereqhandler.cpp Wed Aug 25 17:57:53 2010 +0100 @@ -1,1439 +1,1451 @@ -/* - * ============================================================================= - * Name : devicereqhandler.cpp - * Part of : - * Description : Implementation of the class DDeviceReqHandler. - * Version : %version:6 % - * - * Copyright © 2008-2010 Nokia. All rights reserved. - * This material, including documentation and any related - * computer programs, is protected by copyright controlled by - * Nokia. All rights are reserved. Copying, including - * reproducing, storing, adapting or translating, any - * or all of this material requires the prior written consent of - * Nokia. This material also contains confidential - * information which may not be disclosed to others without the - * prior written consent of Nokia. - * ============================================================================= - */ - - -// INCLUDE FILES -#include -#include -#include -#include - -#include "devicereqhandler.h" -#include "virtualvideohwinterface.h" - -#include "virtualvideotracing.h" - -#include "remotefunctioncall.h" -#include "serializedfunctioncall.h" -#include "driverrfc.h" -#include "openvgrfc.h" //For the opcodes -#include "eglrfc.h" //For the opcodes -#include "opengles11rfc.h" //For the opcodes - - -using namespace PlatsimVideoDriver; - -// LOCAL DATA TYPES -TInt CmpTPbsIds(const TPbSId& a, const TPbSId& b) - { - if( a.iPbuffer == b.iPbuffer ) - return 0; - else - return b.iPbuffer - a.iPbuffer; - } - -TInt CmpTVGIsIds(const TVGISId& a, const TVGISId& b) - { - if( a.iVGImage == b.iVGImage ) - return 0; - else - return b.iVGImage - a.iVGImage; - } -/* - * Copies data from client space to the request buffer during serialisation - */ -class TDataFromClientSpaceCopier: public MDataCopier - { -public: - TDataFromClientSpaceCopier( DThread* aUserThread ): - iUserThread(aUserThread) - { - } - - TInt CopyData( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) - { - memcpy( aDest, aSource, aSize ); - return KErrNone; - } - - TInt CopyVector( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) - { - return Kern::ThreadRawRead( iUserThread, aSource, aDest, aSize ); - } - - DThread* iUserThread; - }; - -/* - * Copies data to client space from the request buffer during deserialisation - */ -class TDataToClientSpaceCopier: public MDataCopier - { -public: - TDataToClientSpaceCopier( DThread* aUserThread ): - iUserThread(aUserThread) - { - } - - TInt CopyData( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) - { - memcpy( aDest, aSource, aSize ); - return KErrNone; - } - - TInt CopyVector( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) - { - return Kern::ThreadRawWrite(iUserThread, aDest, aSource, aSize ); - } - - DThread* iUserThread; - }; - -// LOCAL FUNCTION DEFINITIONS - -// ----------------------------------------------------------------------------- -// ListRemoteFunctionCall -// ----------------------------------------------------------------------------- -// -inline void ListRemoteFunctionCall(RemoteFunctionCallData& call) - { -#if _DEBUG - VVHW_TRACE("RFC: %u %u %u %u %u %u %u", - call.Header().iOpCode, - call.Header().iTransactionId, - call.Header().iProcessId, - call.Header().iThreadId, - call.Header().iParameterCount, - call.Header().iOpType, - call.Header().iReturnValue); - - for ( TInt i = 0; i < call.Header().iParameterCount; i++) - { - RemoteFunctionCallData::TParam param = call.Parameters()[i]; - - TUint32 dir = param.iDir; - TUint32 type = param.iType; - - - if ( RemoteFunctionCallData::TParam::ESimple == param.iType ) - { - TUint32 datatype = param.iSimpleParam.iDataType; - VVHW_TRACE("RFC Simple Param %d: %u %u %u",i, dir, type, datatype ); - } - else if ( RemoteFunctionCallData::TParam::EVector == param.iType ) - { - TUint32 datatype = param.iVectorParam.iDataType; - TUint32 size = param.iVectorParam.iVectorLength; - VVHW_TRACE("RFC Vec Param %d: %u %u %u %u",i, dir, type, datatype, size ); - } - } -#endif // _DEBUG - } - - -// CONSTANTS -const TInt KDfcPriority = 1; - -// ============================= LOCAL FUNCTIONS =============================== - -// ----------------------------------------------------------------------------- -// Isr -// Interrupt service routine -// ----------------------------------------------------------------------------- -// -void Isr( TAny* aParam ) - { - DDeviceReqHandler* handler = ( DDeviceReqHandler* )aParam; - Interrupt::Disable( handler->InterruptId() ); - handler->Dfc().Add(); - } - -// ----------------------------------------------------------------------------- -// DfcFunc -// Function to call when HW has an interrupt -// ----------------------------------------------------------------------------- -// -void DfcFunc( TAny* aParam ) - { - DDeviceReqHandler* handler = ( DDeviceReqHandler* )aParam; - handler->ProcessDfc(); - } - -// ============================ MEMBER FUNCTIONS =============================== - - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::DDeviceReqHandler -// ----------------------------------------------------------------------------- -// -DDeviceReqHandler::DDeviceReqHandler( - DVirtualVideoHwInterface& aHwInterface, - TDfcQue* aQueue) : - iPbufferSgMapOrder ( &CmpTPbsIds ), - iVGImageSgMapOrder ( &CmpTVGIsIds ), - iCurrClientData(NULL), - iInitialized(EFalse), - iHwInterface( aHwInterface ), - iDfc( DfcFunc, (TAny*)this, aQueue, KDfcPriority ), - iInterruptId( 0 ), - iTransactionId( 1 ), - iRequestBuffer( *this, VVI_PARAMETERS_INPUT_MEMORY_SIZE ) - { - iDriverRfcProcessId = 0; - iDriverRfcThreadId = 0; - iOpType = 0; - iOpChainPhase = 0; - iInterruptId = VVI_IRQ; - VVHW_TRACE( "DDeviceReqHandler constructor" ); - VVHW_TRACE( "Called in process/thread %0x / %0x", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); - TInt err = Interrupt::Bind( iInterruptId, Isr, ( TAny* )this ); - if ( err != KErrNone ) - { - VVHW_TRACE( "Interrupt::Bind Error: %d", err ); - } - err = Interrupt::Enable( iInterruptId ); - if ( err != KErrNone ) - { - Interrupt::Unbind( iInterruptId ); - iInterruptId = 0; - VVHW_TRACE( "Interrupt::Enable Error: %d", err ); - } - iRequestBuffer.InitBuffer(); - //Register this object with the extension - VVHW_TRACE( "DDeviceReqHandler calling ReqHandlerExtension" ); - ReqHandlerExtension::SetReqHandler( this ); - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::~DDeviceReqHandler -// ----------------------------------------------------------------------------- -// -DDeviceReqHandler::~DDeviceReqHandler() - { - for( TInt i=0; i < iClientData.Count(); ++i ) - { - delete iClientData[i]; - } - iClientData.Close(); - Interrupt::Disable( iInterruptId ); - Interrupt::Unbind( iInterruptId ); - iInterruptId = 0; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::HandleClientShutdown -// ----------------------------------------------------------------------------- -// -TInt DDeviceReqHandler::HandleClientShutdown( TUint aProcessId, TUint aThreadId ) - { - VVHW_TRACE("DDeviceReqHandler::HandleClientShutdown"); - TInt err( KErrNone ); - TAsyncRequest* req = AllocRequest( NULL, NULL, NULL, NULL, TAsyncRequest::ERTDriver ); - - if ( req ) - { - DriverRFC drfc( req->iRemoteFunctionCall ); - drfc.Init( DriverRFC::EDrvClientShutdown, RemoteFunctionCallData::EOpRequest ); - req->iRemoteFunctionCall.SetTransactionId( ++iTransactionId ); - req->iRemoteFunctionCall.SetThreadInformation( aProcessId, aThreadId ); - iPendingRequestRoot.AppendToLast( req ); - TInt ret = ProcessNextPendingRequest(); - while ( KErrNone == ret ) - { - ret = ProcessNextPendingRequest(); - } - } - else - { - err = KErrNoMemory; - } - return err; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::ProcessNextPendingRequest -// ----------------------------------------------------------------------------- -// -TInt DDeviceReqHandler::ProcessNextPendingRequest() - { - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest"); - TInt err( KErrNone ); - TAsyncRequest* req = iPendingRequestRoot.iNext; - if ( !req ) - { - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest !req"); - return KErrUnderflow; - } - //Try to serve the client from here, or do some sgImage specific stuff - TInt mode = InterpretRequest( req ); - switch( mode ) - { - case ENormal: - { - //Nothing, process as normal - break; - } - case EHandled: - { - //Already handled, remove and signal complete - req->RemoveFromList( &iPendingRequestRoot ); - Kern::RequestComplete( req->iAsyncClient, req->iStatus, KErrNone ); - ReleaseRequest( req ); - return KErrNone;//Change to "err" if you add lines above this that may set it to something else - } - case EQueued: - { - //To be removed from the usual queues, but not deleted (released) or completed - req->RemoveFromList( &iPendingRequestRoot ); - return KErrNone; - } - default: - { - break; - } - } - - if ( TAsyncRequest::ERTCommandLoad == req->iCommandLoadRequest ) - { - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands"); - TInt loaderr( KErrNone ); - TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); - - if ( len < 0 ) - { - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands len < 0"); - return KErrUnderflow;; - } - - if ( !iRequestBuffer.CheckForSpace( len ) ) - { - //Not enough space - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands No space"); - return KErrNoMemory; - } - - req->RemoveFromList( &iPendingRequestRoot ); - - const TUint32 base( iRequestBuffer.AllocateBytes( len ) ); - - //Next, serialize the call to the HW memory - const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); - - TPtr8 ptr(reinterpret_cast(paramAddr), 0, len ); - - //Read the RemoveFunctionCall - loaderr = Kern::ThreadDesRead( req->iAsyncClient, req->iA1, ptr, 0, 0 ); - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands ThreadDesRead %d", loaderr); - - if ( KErrNone == loaderr ) - { - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands CommitBytes"); - iRequestBuffer.CommitBytes( base, len ); - iHwInterface.IssueCommand( VVI_EXECUTE ); - } - Kern::RequestComplete( req->iAsyncClient, req->iStatus, loaderr ); - ReleaseRequest( req ); - } - else //ERTRequest or ERTDriver - { -#if _DEBUG - ListRemoteFunctionCall( req->iRemoteFunctionCall ); -#endif - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest req %u tid %u opcode %u", - req, req->iRemoteFunctionCall.Header().iTransactionId, - req->iRemoteFunctionCall.Header().iOpCode ); - const TUint32 serializedLength( req->iRemoteFunctionCall.SerialisedLength() ); - if ( !iRequestBuffer.CheckForSpace( serializedLength ) ) - { - //Not enough space - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest No space"); - return KErrOverflow; - } - - req->RemoveFromList( &iPendingRequestRoot ); - - if ( RemoteFunctionCallData::EOpRequestWithReply == req->iRemoteFunctionCall.Header().iOpType ) - { - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest 3"); - iSerializedRequestRoot.AppendToLast( req ); - } - TDataFromClientSpaceCopier datacopier( req->iAsyncClient ); - SerializedFunctionCall sfc( req->iRemoteFunctionCall ); - - if ( TAsyncRequest::ERTRequest == req->iCommandLoadRequest ) - { - sfc.SetDataCopier( &datacopier ); - } - - const TUint32 base( iRequestBuffer.AllocateBytes( serializedLength ) ); - - //Next, serialize the call to the HW memory - const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); - - TInt len = sfc.WriteToBuffer( reinterpret_cast(paramAddr), - VVI_PARAMETERS_INPUT_MEMORY_SIZE - 1 - base ); - - sfc.SetDataCopier( NULL ); - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest Write at index %u with length %u", base, len ); - iRequestBuffer.CommitBytes( base, serializedLength ); - - iHwInterface.IssueCommand( VVI_EXECUTE ); - - if ( RemoteFunctionCallData::EOpRequest == req->iRemoteFunctionCall.Header().iOpType ) - { - if ( TAsyncRequest::ERTRequest == req->iCommandLoadRequest ) - { - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest RequestComplete"); - Kern::RequestComplete( req->iAsyncClient, req->iStatus, KErrNone ); - } - ReleaseRequest( req ); - } - } - VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest DONE"); - return err; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::HandleLoadCommands -// ----------------------------------------------------------------------------- -// -TInt DDeviceReqHandler::HandleLoadCommands( - DThread*& aUserThread, - TRequestStatus* aStatus, - TAny* aA1 ) - { - VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands"); - TInt err( KErrNone ); - TAsyncRequest* req = AllocRequest( aStatus, aUserThread, aA1, NULL, TAsyncRequest::ERTCommandLoad ); - - if ( req ) - { - TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); - - if ( len < 0 ) - { - err = len;//TODO: this sucks - ReleaseRequest( req ); - return err; - } - - iPendingRequestRoot.AppendToLast( req ); - TInt ret = ProcessNextPendingRequest(); - while ( KErrNone == ret ) - { - ret = ProcessNextPendingRequest(); - } - } - else - { - err = KErrNoMemory; - } - - return err; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::HandleExecuteAsync -// ----------------------------------------------------------------------------- -// -TInt DDeviceReqHandler::HandleExecuteAsync( - DThread*& aUserThread, - TRequestStatus* aStatus, - TAny* a1 ) - { - VVHW_TRACE("DDeviceReqHandler::HandleExecuteAsync"); - TInt err( KErrNone ); - TAsyncRequest* req = AllocRequest( aStatus, aUserThread, a1, NULL ); - - if ( req ) - { - TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); - - if ( len < 0 ) - { - err = len; - ReleaseRequest( req ); - return err; - } - - TPckg rcallbuf( req->iRemoteFunctionCall ); - - //Read the RemoteFunctionCall - err = Kern::ThreadDesRead( req->iAsyncClient, req->iA1, rcallbuf, 0, 0 ); - - if ( KErrNone != err ) - { - ReleaseRequest( req ); - return err; - } - - req->iRemoteFunctionCall.SetTransactionId( ++iTransactionId ); - - iPendingRequestRoot.AppendToLast( req ); - TInt ret = ProcessNextPendingRequest(); - while ( KErrNone == ret ) - { - ret = ProcessNextPendingRequest(); - } - } - else - { - err = KErrNoMemory; - } - VVHW_TRACE("DDeviceReqHandler::HandleExecuteAsync <-"); - return err; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::ProcessDfc -// ----------------------------------------------------------------------------- -// -void DDeviceReqHandler::ProcessDfc() - { - VVHW_TRACE("DDeviceReqHandler::ProcessDfc"); - TUint32 error( 0 ); - iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegError, error ); - - TUint32 transactionId; - iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegRequestId, transactionId ); - - TAsyncRequest* req = iSerializedRequestRoot.iNext; - VVHW_TRACE( "DDeviceReqHandler::ProcessDfc req %u transactionid %u", req, transactionId ); - - - if ( req && transactionId == req->iRemoteFunctionCall.Header().iTransactionId ) - { - req->RemoveFromList( &iSerializedRequestRoot ); - - //Check if the request was scheduler-initiated - TBool driverInitiated(EFalse); - if( iSchedulerInitiatedTransactionIds.Count() > 0 ) - { - for( int i=0;iiRemoteFunctionCall.Header().iTransactionId ) - { - driverInitiated = ETrue; - //This will be used in the "consume" function later on in many cases - iSchedulerInitiatedTransactionData = iSchedulerInitiatedTransactionIds[i].iTransactionData; - iSchedulerInitiatedTransactionIds.Remove( i ); - break; - } - } - } - - if( driverInitiated ) - { - //This branch is for the purpose of handling commands that have been initiated from (this) - //Command Scheduler, and not a client thread. So far no cases exists, where this would - //imply notifying a (client) DLL, so RequestComplete does not have to be called here (this could change later). - //Parse result and write vectors back to client space - if ( 0 == error ) - { - //Parse result and write vectors back to client space - TDataToClientSpaceCopier datacopier2( req->iAsyncClient ); - RemoteFunctionCallData rfc; - SerializedFunctionCall sfc( rfc ); - sfc.SetDataCopier( &datacopier2 ); - const TLinAddr paramAddr( iHwInterface.OutputParametersAddress() ); - VVHW_TRACE("DDeviceReqHandler::ProcessDfc parse"); - sfc.ParseBuffer( reinterpret_cast( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE ); - TPckg resultbuf( rfc ); - req->iRemoteFunctionCall = resultbuf();//Get the object; its in the same address space - VVHW_TRACE("DDeviceReqHandler::ProcessDfc ThreadDesWrite err=%d (data len=%d)", error, resultbuf.Length()); - sfc.SetDataCopier( NULL ); - } - - error = ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); - ConsumeSchedulerInitiatedRequestResult( req ); - } - else - { - TInt desWriteError = KErrNone; - if ( 0 == error ) - { - //Parse result and write vectors back to client space - // TODO for performance only write back result & output vectors, not whole request buffer - TDataToClientSpaceCopier datacopier2( req->iAsyncClient ); - RemoteFunctionCallData rfc; - SerializedFunctionCall sfc( rfc ); - sfc.SetDataCopier( &datacopier2 ); - const TLinAddr paramAddr( iHwInterface.OutputParametersAddress() ); - VVHW_TRACE("DDeviceReqHandler::ProcessDfc parse"); - sfc.ParseBuffer( reinterpret_cast( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE ); - TPckg resultbuf( rfc ); - desWriteError = Kern::ThreadDesWrite( req->iAsyncClient, req->iA1, resultbuf, 0, 0 ); - VVHW_TRACE("DDeviceReqHandler::ProcessDfc ThreadDesWrite err=%d (data len=%d)",desWriteError, resultbuf.Length()); - sfc.SetDataCopier( NULL ); - } - - Kern::RequestComplete( req->iAsyncClient, req->iStatus, desWriteError ); - ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); - ReleaseRequest( req ); - } - } - else - { - ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); - } - VVHW_TRACE("DDeviceReqHandler::ProcessDfc ProcessNextPendingRequest"); - - TInt ret = ProcessNextPendingRequest(); - while ( KErrNone == ret ) - { - ret = ProcessNextPendingRequest(); - } - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::AllocRequest -// ----------------------------------------------------------------------------- -// -DDeviceReqHandler::TAsyncRequest* DDeviceReqHandler::AllocRequest( TRequestStatus* aStatus, - DThread* aAsyncClient, - TAny* aA1, - TAny* aA2, - DDeviceReqHandler::TAsyncRequest::TRequestType aRequestType ) - { - TAsyncRequest* req( NULL ); - if ( iFreeCount ) - { - req = iFreeListRoot.iNext; - req->RemoveFromList( &iFreeListRoot ); - req->Init( aStatus, aAsyncClient, aA1, aA2, aRequestType ); - iFreeCount--; - } - else - { - VVHW_TRACE("DDeviceReqHandler::AllocRequest new"); - req = new TAsyncRequest( aStatus, aAsyncClient, aA1, aA2, aRequestType ); - } - return req; - } - -// ----------------------------------------------------------------------------- -// DDeviceReqHandler::ReleaseRequest -// ----------------------------------------------------------------------------- -// -void DDeviceReqHandler::ReleaseRequest( DDeviceReqHandler::TAsyncRequest* aReq ) - { - if ( iFreeCount > KMaxFreeRequests ) - { - VVHW_TRACE("DDeviceReqHandler::AllocRequest delete"); - delete aReq; - } - else - { - aReq->AppendToList( &iFreeListRoot ); - iFreeCount++; - } - } - - - -void DDeviceReqHandler::RemoveClientData( const TUint32 aProcId, const TUint32 aThreadId ) - { - VVHW_TRACE("DDeviceReqHandler::RemoveClientData (%d/%d)", aProcId, aThreadId ); - TPerThreadData* data( NULL ); - for( TInt i=0; i < iClientData.Count(); ++i ) - { - if( iClientData[i]->sameThread( aProcId, aThreadId ) ) - { - data = iClientData[i]; - iClientData.Remove(i); - if( data == iCurrClientData ) - { - iCurrClientData = 0; - } - delete data; - break; - } - } - } - -TBool DDeviceReqHandler::InitiateRequestWithReply( TAsyncRequest* aRec, TAny* aTransactionData ) - { - VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply" ); - if( iDriverRfcThreadId == 0 || iDriverRfcProcessId == 0 ) - { - iDriverRfcProcessId = Kern::CurrentProcess().iId; - iDriverRfcThreadId = Kern::CurrentThread().iId; - } - //iReqIssueMutex.Wait(); - const TUint32 serializedLength( aRec->iRemoteFunctionCall.SerialisedLength() ); - if ( !iRequestBuffer.CheckForSpace( serializedLength ) ) - { - return EFalse; - } - ++iTransactionId; - aRec->iRemoteFunctionCall.SetTransactionId( iTransactionId ); - aRec->iRemoteFunctionCall.SetOperationType( RemoteFunctionCallData::EOpRequestWithReply ); - aRec->iAsyncClient = &(Kern::CurrentThread()); - aRec->iRemoteFunctionCall.SetThreadInformation( iDriverRfcProcessId, iDriverRfcThreadId ); - - iSchedulerInitiatedTransactionIds.Append( TTransactionInfo( iTransactionId, aTransactionData ) ); - VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply ids len=%d transaction id = %u proc/thread = %u / %u api/op = %0x / %0x", iSchedulerInitiatedTransactionIds.Count(), iTransactionId, Kern::CurrentProcess().iId, Kern::CurrentThread().iId, aRec->iRemoteFunctionCall.Header().iApiUid, aRec->iRemoteFunctionCall.Header().iOpCode ); - if( aRec->iRemoteFunctionCall.Header().iApiUid ) - { - VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply request's api is SERIALISED_DRIVER_API_UID" ); - } - - iSerializedRequestRoot.AppendToLast( aRec );//we need the result, so add to the dfc handled requests - TDataFromClientSpaceCopier datacopier( aRec->iAsyncClient ); - SerializedFunctionCall sfc( aRec->iRemoteFunctionCall ); - - sfc.SetDataCopier( &datacopier );//We know this is a "request" (precondition) - const TUint32 base( iRequestBuffer.AllocateBytes( serializedLength ) ); - //Next, serialize the call to the HW memory - const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); - TInt len = sfc.WriteToBuffer( reinterpret_cast(paramAddr), VVI_PARAMETERS_INPUT_MEMORY_SIZE - 1 - base ); - VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply len = %d", len); - sfc.SetDataCopier( NULL ); - iRequestBuffer.CommitBytes( base, serializedLength ); - iHwInterface.IssueCommand( VVI_EXECUTE ); - VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply issued"); - return ETrue; - } - -/** - * This routine adds extra info about the sgImage's pbuffer handle for syncing, - * when that is required. - * 1. checks the sgImage handle, and if it's not NULL, then - * 2. Get the sgImage's metadata - * 3. Check if the vgImage is "dirty", and if yes, - * then append the pbuffer handle as a parameter to the call - * 4. Set the pbuffer "dirty", if aSetBufferDirty is ETrue - */ - -void DDeviceReqHandler::getVGSyncInOp( TAsyncRequest* aReq, TInt aSgHandleIndexInReq, TBool aSetBufferDirty ) - { - VVHW_TRACE( "DDeviceReqHandler::getVGSyncInOp" ); - EGLSurface surface( EGL_NO_SURFACE );//The pbuffer surface to sync from, if needed - VGboolean syncNeeded = VG_FALSE; - OpenVgRFC call( aReq->iRemoteFunctionCall ); - TUint64 sgId(NULL); - - if( call.Data().Header().iParameterCount > aSgHandleIndexInReq ) - { - call.GetTUint64( sgId, aSgHandleIndexInReq ); - } - else - { - return;//No sgImage handle appended on the client side, just exit - } - - if( sgId != NULL ) - { - VVHW_TRACE( "DDeviceReqHandler::getVGSyncInOp SgImage-backing VGImage found" ); - DSgResource* resource; - HBuf8* data = OpenSgImageMetaData( sgId, resource ); - if( data ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - - if( !sginfo.iVGImageClean ) - { - //set the sync bit as clean now. - sginfo.iVGImageClean = ETrue; - //Additional info for the host side to use - syncNeeded = VG_TRUE; - surface = sginfo.iPbufferHandle; - } - if( aSetBufferDirty ) - { - sginfo.iPbufferClean = EFalse; - } - resource->SetMetaData( *data ); - delete data;//delete the copy of the metadata descriptor - } - } - if( syncNeeded ) - { - call.AppendParam ( (int)surface ); - } - } - - -void DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult( TAsyncRequest* aReq ) - { - const TUint32 proc_id( aReq->iRemoteFunctionCall.Header().iProcessId ); - const TUint32 thread_id( aReq->iRemoteFunctionCall.Header().iThreadId ); - const TUint32 apicode( aReq->iRemoteFunctionCall.Header().iApiUid ); - const TUint32 opcode( aReq->iRemoteFunctionCall.Header().iOpCode ); - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult: process/thread id : %d / %d", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult: process/thread id : %d / %d API/opcode = %0x/%0x", proc_id, thread_id, apicode, opcode ); - TPerThreadData* data(0); - for( TInt i=0; i < iClientData.Count(); ++i ) - { - if( iClientData[i]->sameThread( proc_id, thread_id )) - { - data = iClientData[i]; - break; - } - } - - switch ( apicode ) - { - case SERIALISED_DRIVER_API_UID: - { - switch( opcode ) - { - case DriverRFC::EDrvCreatePbufferSg: - { - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult : EDrvCreatePbufferSg" ); - if( iSchedulerInitiatedTransactionData ) - { - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle = aReq->iRemoteFunctionCall.Header().iReturnValue; - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult pbuffer=%u", ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle ); - } - TPbSId obj ( ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle, - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId ); - iPbufferSgMap.InsertInOrder( obj, iPbufferSgMapOrder ); - VVHW_TRACE( "pbuffer creation RequestComplete. Inserted (%u, %u) into sg map. Notify thread %u, request status %u", - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle, - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId, - aReq->iAsyncClient, - aReq->iStatus ); - *(aReq->iStatus) = 0;//REquestComplete doesn't work - VVHW_TRACE( "Pbuffer creation RequestComplete" ); - break; - } - case DriverRFC::EDrvCreateVGImageSg: - { - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult : EDrvCreateVGImageSg" ); - if( iSchedulerInitiatedTransactionData ) - { - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle = aReq->iRemoteFunctionCall.Header().iReturnValue; - } - TVGISId obj ( ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle, - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId ); - iVGImageSgMap.InsertInOrder( obj, iVGImageSgMapOrder ); - VVHW_TRACE( "pbuffer creation RequestComplete. Inserted (%u, %u) into sg map. Notify thread %u, request status %u", - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle, - ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId, - aReq->iAsyncClient, - aReq->iStatus ); - *(aReq->iStatus) = 0;//REquestComplete doesn't work - VVHW_TRACE( "VGImage creation RequestComplete" ); - break; - } - case DriverRFC::EDrvDeleteSgImage: - { - *(aReq->iStatus) = 0; - } - case DriverRFC::EDrvSyncVGImageFromPBuffer: - { - ((TAsyncRequest*)iSchedulerInitiatedTransactionData)->AppendToList( (TAsyncRequest*)(&iPendingRequestRoot) ); - break; - } - default: - { - break; - } - } - } - case SERIALISED_OPENVG_API_UID: - { - switch( opcode ) - { - case OpenVgRFC::EvgGetError: - { - VVHW_TRACE("OpenVgRFC::EvgGetError"); - data->iErrorVG = aReq->iRemoteFunctionCall.Header().iReturnValue; - data->iErrUpdatedVG = EFalse;//TODO: ETrue - break; - } - default:{break;} - } - break; - } - case SERIALISED_EGL_API_UID: - { - switch( opcode ) - { - case EglRFC::EeglGetError: - { - VVHW_TRACE("EglRFC::EeglGetError"); - data->iErrorEGL = aReq->iRemoteFunctionCall.Header().iReturnValue; - data->iErrUpdatedEGL = EFalse;//TODO: ETrue - break; - } - default: - {break;} - } - break; - } - case SERIALISED_OPENGLES_1_1_API_UID: - { - switch( opcode ) - { - case OpenGlES11RFC::EglGetError: - { - VVHW_TRACE("OpenGlES11RFC::EglGetError"); - data->iErrorGLES = aReq->iRemoteFunctionCall.Header().iReturnValue; - data->iErrUpdatedGLES = EFalse;//TODO: ETrue - } - default:{break;} - } - break; - } - default:{break;} - } - - VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult return value: %d", aReq->iRemoteFunctionCall.Header().iReturnValue ); - if( data ) - { - VVHW_TRACE("errors EGL/VG/GLES=%0x/%0x/%0x", data->iErrorEGL, data->iErrorVG, data->iErrorGLES ); - } - //Delete the request object, as it is no longer needed - aReq->iStatus = 0; - aReq->iAsyncClient = 0; - delete aReq; - VVHW_TRACE("DDeviceReqHandle::ConsumeSchedulerInitiatedRequestResult done."); - } - -/** - * DDeviceReqHandler::CreateSgImagePbuffer +/* + * ============================================================================= + * Name : devicereqhandler.cpp + * Part of : + * Description : Implementation of the class DDeviceReqHandler. + * Version : %version:6 % + * + * Copyright © 2008-2010 Nokia. All rights reserved. + * This material, including documentation and any related + * computer programs, is protected by copyright controlled by + * Nokia. All rights are reserved. Copying, including + * reproducing, storing, adapting or translating, any + * or all of this material requires the prior written consent of + * Nokia. This material also contains confidential + * information which may not be disclosed to others without the + * prior written consent of Nokia. + * ============================================================================= + */ + + +// INCLUDE FILES +#include +#include +#include +#include + +#include +#include +#include + +#include "remotefunctioncall.h" +#include "serializedfunctioncall.h" +#include "driverrfc.h" +#include "openvgrfc.h" //For the opcodes +#include "eglrfc.h" //For the opcodes +#include "opengles11rfc.h" //For the opcodes + + +using namespace GuestVideoDriver; + +// LOCAL DATA TYPES +TInt CmpTPbsIds(const TPbSId& a, const TPbSId& b) + { + if( a.iPbuffer == b.iPbuffer ) + return 0; + else + return b.iPbuffer - a.iPbuffer; + } + +TInt CmpTVGIsIds(const TVGISId& a, const TVGISId& b) + { + if( a.iVGImage == b.iVGImage ) + return 0; + else + return b.iVGImage - a.iVGImage; + } +/* + * Copies data from client space to the request buffer during serialisation + */ +class TDataFromClientSpaceCopier: public MDataCopier + { +public: + TDataFromClientSpaceCopier( DThread* aUserThread ): + iUserThread(aUserThread) + { + } + + TInt CopyData( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) + { + memcpy( aDest, aSource, aSize ); + return KErrNone; + } + + TInt CopyVector( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) + { + return Kern::ThreadRawRead( iUserThread, aSource, aDest, aSize ); + } + + DThread* iUserThread; + }; + +/* + * Copies data to client space from the request buffer during deserialisation + */ +class TDataToClientSpaceCopier: public MDataCopier + { +public: + TDataToClientSpaceCopier( DThread* aUserThread ): + iUserThread(aUserThread) + { + } + + TInt CopyData( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) + { + memcpy( aDest, aSource, aSize ); + return KErrNone; + } + + TInt CopyVector( TUint8* aDest, const TUint8* aSource, TUint32 aSize ) + { + return Kern::ThreadRawWrite(iUserThread, aDest, aSource, aSize ); + } + + DThread* iUserThread; + }; + +// LOCAL FUNCTION DEFINITIONS + +// ----------------------------------------------------------------------------- +// ListRemoteFunctionCall +// ----------------------------------------------------------------------------- +// +inline void ListRemoteFunctionCall(RemoteFunctionCallData& call) + { +#if _DEBUG + VVHW_TRACE("RFC: %u %u %u %u %u %u %u", + call.Header().iOpCode, + call.Header().iTransactionId, + call.Header().iProcessId, + call.Header().iThreadId, + call.Header().iParameterCount, + call.Header().iOpType, + call.Header().iReturnValue); + + for ( TInt i = 0; i < call.Header().iParameterCount; i++) + { + RemoteFunctionCallData::TParam param = call.Parameters()[i]; + + TUint32 dir = param.iDir; + TUint32 type = param.iType; + + + if ( RemoteFunctionCallData::TParam::ESimple == param.iType ) + { + TUint32 datatype = param.iSimpleParam.iDataType; + VVHW_TRACE("RFC Simple Param %d: %u %u %u",i, dir, type, datatype ); + } + else if ( RemoteFunctionCallData::TParam::EVector == param.iType ) + { + TUint32 datatype = param.iVectorParam.iDataType; + TUint32 size = param.iVectorParam.iVectorLength; + VVHW_TRACE("RFC Vec Param %d: %u %u %u %u",i, dir, type, datatype, size ); + } + } +#endif // _DEBUG + } + + +// CONSTANTS +const TInt KDfcPriority = 1; + +// ============================= LOCAL FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// Isr +// Interrupt service routine +// ----------------------------------------------------------------------------- +// +void Isr( TAny* aParam ) + { + DDeviceReqHandler* handler = ( DDeviceReqHandler* )aParam; + Interrupt::Disable( handler->InterruptId() ); + handler->Dfc().Add(); + } + +// ----------------------------------------------------------------------------- +// DfcFunc +// Function to call when HW has an interrupt +// ----------------------------------------------------------------------------- +// +void DfcFunc( TAny* aParam ) + { + DDeviceReqHandler* handler = ( DDeviceReqHandler* )aParam; + handler->ProcessDfc(); + } + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::DDeviceReqHandler +// ----------------------------------------------------------------------------- +// +DDeviceReqHandler::DDeviceReqHandler( + DVirtualVideoHwInterface& aHwInterface, + TDfcQue* aQueue) : + iPbufferSgMapOrder ( &CmpTPbsIds ), + iVGImageSgMapOrder ( &CmpTVGIsIds ), + iCurrClientData(NULL), + iInitialized(EFalse), + iHwInterface( aHwInterface ), + iDfc( DfcFunc, (TAny*)this, aQueue, KDfcPriority ), + iInterruptId( 0 ), + iTransactionId( 1 ), + iRequestBuffer( *this, VVI_PARAMETERS_INPUT_MEMORY_SIZE ) + { + iDriverRfcProcessId = 0; + iDriverRfcThreadId = 0; + iOpType = 0; + iOpChainPhase = 0; + iInterruptId = VVI_IRQ; + VVHW_TRACE( "DDeviceReqHandler constructor" ); + VVHW_TRACE( "Called in process/thread %0x / %0x", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); + TInt err = Interrupt::Bind( iInterruptId, Isr, ( TAny* )this ); + if ( err != KErrNone ) + { + VVHW_TRACE( "Interrupt::Bind Error: %d", err ); + } + err = Interrupt::Enable( iInterruptId ); + if ( err != KErrNone ) + { + Interrupt::Unbind( iInterruptId ); + iInterruptId = 0; + VVHW_TRACE( "Interrupt::Enable Error: %d", err ); + } + iRequestBuffer.InitBuffer(); + //Register this object with the extension + VVHW_TRACE( "DDeviceReqHandler calling ReqHandlerExtension" ); + ReqHandlerExtension::SetReqHandler( this ); + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::~DDeviceReqHandler +// ----------------------------------------------------------------------------- +// +DDeviceReqHandler::~DDeviceReqHandler() + { + for( TInt i=0; i < iClientData.Count(); ++i ) + { + delete iClientData[i]; + } + iClientData.Close(); + Interrupt::Disable( iInterruptId ); + Interrupt::Unbind( iInterruptId ); + iInterruptId = 0; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::HandleClientShutdown +// ----------------------------------------------------------------------------- +// +TInt DDeviceReqHandler::HandleClientShutdown( TUint aProcessId, TUint aThreadId ) + { + VVHW_TRACE("DDeviceReqHandler::HandleClientShutdown"); + TInt err( KErrNone ); + TAsyncRequest* req = AllocRequest( NULL, NULL, NULL, NULL, TAsyncRequest::ERTDriver ); + + if ( req ) + { + DriverRFC drfc( req->iRemoteFunctionCall ); + drfc.Init( DriverRFC::EDrvClientShutdown, RemoteFunctionCallData::EOpRequest ); + req->iRemoteFunctionCall.SetTransactionId( ++iTransactionId ); + req->iRemoteFunctionCall.SetThreadInformation( aProcessId, aThreadId ); + iPendingRequestRoot.AppendToLast( req ); + TInt ret = ProcessNextPendingRequest(); + while ( KErrNone == ret ) + { + ret = ProcessNextPendingRequest(); + } + } + else + { + err = KErrNoMemory; + } + return err; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::ProcessNextPendingRequest +// ----------------------------------------------------------------------------- +// +TInt DDeviceReqHandler::ProcessNextPendingRequest() + { + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest"); + TInt err( KErrNone ); + TAsyncRequest* req = iPendingRequestRoot.iNext; + if ( !req ) + { + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest !req"); + return KErrUnderflow; + } + //Try to serve the client from here, or do some sgImage specific stuff + TInt mode = InterpretRequest( req ); + switch( mode ) + { + case ENormal: + { + //Nothing, process as normal + break; + } + case EHandled: + { + //Already handled, remove and signal complete + req->RemoveFromList( &iPendingRequestRoot ); + Kern::RequestComplete( req->iAsyncClient, req->iStatus, KErrNone ); + ReleaseRequest( req ); + return KErrNone;//Change to "err" if you add lines above this that may set it to something else + } + case EQueued: + { + //To be removed from the usual queues, but not deleted (released) or completed + req->RemoveFromList( &iPendingRequestRoot ); + return KErrNone; + } + default: + { + break; + } + } + + if ( TAsyncRequest::ERTCommandLoad == req->iCommandLoadRequest ) + { + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands"); + TInt loaderr( KErrNone ); + TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); + + if ( len < 0 ) + { + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands len < 0"); + return KErrUnderflow;; + } + + if ( !iRequestBuffer.CheckForSpace( len ) ) + { + //Not enough space + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands No space"); + return KErrNoMemory; + } + + req->RemoveFromList( &iPendingRequestRoot ); + + const TUint32 base( iRequestBuffer.AllocateBytes( len ) ); + + //Next, serialize the call to the HW memory + const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); + + TPtr8 ptr(reinterpret_cast(paramAddr), 0, len ); + + //Read the RemoveFunctionCall + loaderr = Kern::ThreadDesRead( req->iAsyncClient, req->iA1, ptr, 0, 0 ); + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands ThreadDesRead %d", loaderr); + + if ( KErrNone == loaderr ) + { + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands CommitBytes"); + iRequestBuffer.CommitBytes( base, len ); + iHwInterface.IssueCommand( VVI_EXECUTE ); + } + Kern::RequestComplete( req->iAsyncClient, req->iStatus, loaderr ); + ReleaseRequest( req ); + } + else //ERTRequest or ERTDriver + { +#if _DEBUG + ListRemoteFunctionCall( req->iRemoteFunctionCall ); +#endif + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest req %u tid %u opcode %u", + req, req->iRemoteFunctionCall.Header().iTransactionId, + req->iRemoteFunctionCall.Header().iOpCode ); + const TUint32 serializedLength( req->iRemoteFunctionCall.SerialisedLength() ); + if ( !iRequestBuffer.CheckForSpace( serializedLength ) ) + { + //Not enough space + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest No space"); + return KErrOverflow; + } + + req->RemoveFromList( &iPendingRequestRoot ); + + if ( RemoteFunctionCallData::EOpRequestWithReply == req->iRemoteFunctionCall.Header().iOpType ) + { + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest 3"); + iSerializedRequestRoot.AppendToLast( req ); + } + TDataFromClientSpaceCopier datacopier( req->iAsyncClient ); + SerializedFunctionCall sfc( req->iRemoteFunctionCall ); + + if ( TAsyncRequest::ERTRequest == req->iCommandLoadRequest ) + { + sfc.SetDataCopier( &datacopier ); + } + + const TUint32 base( iRequestBuffer.AllocateBytes( serializedLength ) ); + + //Next, serialize the call to the HW memory + const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); + + TInt len = sfc.WriteToBuffer( reinterpret_cast(paramAddr), + VVI_PARAMETERS_INPUT_MEMORY_SIZE - 1 - base ); + + sfc.SetDataCopier( NULL ); + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest Write at index %u with length %u", base, len ); + iRequestBuffer.CommitBytes( base, serializedLength ); + + iHwInterface.IssueCommand( VVI_EXECUTE ); + + if ( RemoteFunctionCallData::EOpRequest == req->iRemoteFunctionCall.Header().iOpType ) + { + if ( TAsyncRequest::ERTRequest == req->iCommandLoadRequest ) + { + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest RequestComplete"); + Kern::RequestComplete( req->iAsyncClient, req->iStatus, KErrNone ); + } + ReleaseRequest( req ); + } + } + VVHW_TRACE("DDeviceReqHandler::ProcessNextPendingRequest DONE"); + return err; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::HandleLoadCommands +// ----------------------------------------------------------------------------- +// +TInt DDeviceReqHandler::HandleLoadCommands( + DThread*& aUserThread, + TRequestStatus* aStatus, + TAny* aA1 ) + { + VVHW_TRACE("DDeviceReqHandler::HandleLoadCommands"); + TInt err( KErrNone ); + TAsyncRequest* req = AllocRequest( aStatus, aUserThread, aA1, NULL, TAsyncRequest::ERTCommandLoad ); + + if ( req ) + { + TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); + + if ( len < 0 ) + { + err = len;//TODO: this sucks + ReleaseRequest( req ); + return err; + } + + iPendingRequestRoot.AppendToLast( req ); + TInt ret = ProcessNextPendingRequest(); + while ( KErrNone == ret ) + { + ret = ProcessNextPendingRequest(); + } + } + else + { + err = KErrNoMemory; + } + + return err; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::HandleExecuteAsync +// ----------------------------------------------------------------------------- +// +TInt DDeviceReqHandler::HandleExecuteAsync( + DThread*& aUserThread, + TRequestStatus* aStatus, + TAny* a1 ) + { + VVHW_TRACE("DDeviceReqHandler::HandleExecuteAsync"); + TInt err( KErrNone ); + TAsyncRequest* req = AllocRequest( aStatus, aUserThread, a1, NULL ); + + if ( req ) + { + TInt len = Kern::ThreadGetDesLength( req->iAsyncClient, req->iA1 ); + + if ( len < 0 ) + { + err = len; + ReleaseRequest( req ); + return err; + } + + TPckg rcallbuf( req->iRemoteFunctionCall ); + + //Read the RemoteFunctionCall + err = Kern::ThreadDesRead( req->iAsyncClient, req->iA1, rcallbuf, 0, 0 ); + + if ( KErrNone != err ) + { + ReleaseRequest( req ); + return err; + } + + req->iRemoteFunctionCall.SetTransactionId( ++iTransactionId ); + + iPendingRequestRoot.AppendToLast( req ); + TInt ret = ProcessNextPendingRequest(); + while ( KErrNone == ret ) + { + ret = ProcessNextPendingRequest(); + } + } + else + { + err = KErrNoMemory; + } + VVHW_TRACE("DDeviceReqHandler::HandleExecuteAsync <-"); + return err; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::ProcessDfc +// ----------------------------------------------------------------------------- +// +void DDeviceReqHandler::ProcessDfc() + { + VVHW_TRACE("DDeviceReqHandler::ProcessDfc"); + TUint32 error( 0 ); + iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegError, error ); + + TUint32 transactionId; + iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegRequestId, transactionId ); + + TAsyncRequest* req = iSerializedRequestRoot.iNext; + VVHW_TRACE( "DDeviceReqHandler::ProcessDfc req %u transactionid %u", req, transactionId ); + + + if ( req && transactionId == req->iRemoteFunctionCall.Header().iTransactionId ) + { + req->RemoveFromList( &iSerializedRequestRoot ); + + //Check if the request was scheduler-initiated + TBool driverInitiated(EFalse); + if( iSchedulerInitiatedTransactionIds.Count() > 0 ) + { + for( int i=0;iiRemoteFunctionCall.Header().iTransactionId ) + { + driverInitiated = ETrue; + //This will be used in the "consume" function later on in many cases + iSchedulerInitiatedTransactionData = iSchedulerInitiatedTransactionIds[i].iTransactionData; + iSchedulerInitiatedTransactionIds.Remove( i ); + break; + } + } + } + + if( driverInitiated ) + { + //This branch is for the purpose of handling commands that have been initiated from (this) + //Command Scheduler, and not a client thread. So far no cases exists, where this would + //imply notifying a (client) DLL, so RequestComplete does not have to be called here (this could change later). + //Parse result and write vectors back to client space + if ( 0 == error ) + { + //Parse result and write vectors back to client space + TDataToClientSpaceCopier datacopier2( req->iAsyncClient ); + RemoteFunctionCallData rfc; + SerializedFunctionCall sfc( rfc ); + sfc.SetDataCopier( &datacopier2 ); + const TLinAddr paramAddr( iHwInterface.OutputParametersAddress() ); + VVHW_TRACE("DDeviceReqHandler::ProcessDfc parse"); + sfc.ParseBuffer( reinterpret_cast( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE ); + TPckg resultbuf( rfc ); + req->iRemoteFunctionCall = resultbuf();//Get the object; its in the same address space + VVHW_TRACE("DDeviceReqHandler::ProcessDfc ThreadDesWrite err=%d (data len=%d)", error, resultbuf.Length()); + sfc.SetDataCopier( NULL ); + } + + error = ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); + ConsumeSchedulerInitiatedRequestResult( req ); + } + else + { + TInt desWriteError = KErrNone; + if ( 0 == error ) + { + //Parse result and write vectors back to client space + // TODO for performance only write back result & output vectors, not whole request buffer + TDataToClientSpaceCopier datacopier2( req->iAsyncClient ); + RemoteFunctionCallData rfc; + SerializedFunctionCall sfc( rfc ); + sfc.SetDataCopier( &datacopier2 ); + const TLinAddr paramAddr( iHwInterface.OutputParametersAddress() ); + VVHW_TRACE("DDeviceReqHandler::ProcessDfc parse"); + sfc.ParseBuffer( reinterpret_cast( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE ); + TPckg resultbuf( rfc ); + desWriteError = Kern::ThreadDesWrite( req->iAsyncClient, req->iA1, resultbuf, 0, 0 ); + VVHW_TRACE("DDeviceReqHandler::ProcessDfc ThreadDesWrite err=%d (data len=%d)",desWriteError, resultbuf.Length()); + sfc.SetDataCopier( NULL ); + } + + Kern::RequestComplete( req->iAsyncClient, req->iStatus, desWriteError ); + ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); + ReleaseRequest( req ); + } + } + else + { + ResetAndEnableInterrupt( DVirtualVideoHwInterface::EInterruptNewDataAvailable ); + } + VVHW_TRACE("DDeviceReqHandler::ProcessDfc ProcessNextPendingRequest"); + + TInt ret = ProcessNextPendingRequest(); + while ( KErrNone == ret ) + { + ret = ProcessNextPendingRequest(); + } + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::AllocRequest +// ----------------------------------------------------------------------------- +// +DDeviceReqHandler::TAsyncRequest* DDeviceReqHandler::AllocRequest( TRequestStatus* aStatus, + DThread* aAsyncClient, + TAny* aA1, + TAny* aA2, + DDeviceReqHandler::TAsyncRequest::TRequestType aRequestType ) + { + TAsyncRequest* req( NULL ); + if ( iFreeCount ) + { + req = iFreeListRoot.iNext; + req->RemoveFromList( &iFreeListRoot ); + req->Init( aStatus, aAsyncClient, aA1, aA2, aRequestType ); + iFreeCount--; + } + else + { + VVHW_TRACE("DDeviceReqHandler::AllocRequest new"); + req = new TAsyncRequest( aStatus, aAsyncClient, aA1, aA2, aRequestType ); + } + return req; + } + +// ----------------------------------------------------------------------------- +// DDeviceReqHandler::ReleaseRequest +// ----------------------------------------------------------------------------- +// +void DDeviceReqHandler::ReleaseRequest( DDeviceReqHandler::TAsyncRequest* aReq ) + { + if ( iFreeCount > KMaxFreeRequests ) + { + VVHW_TRACE("DDeviceReqHandler::AllocRequest delete"); + delete aReq; + } + else + { + aReq->AppendToList( &iFreeListRoot ); + iFreeCount++; + } + } + + + +void DDeviceReqHandler::RemoveClientData( const TUint32 aProcId, const TUint32 aThreadId ) + { + VVHW_TRACE("DDeviceReqHandler::RemoveClientData (%d/%d)", aProcId, aThreadId ); + TPerThreadData* data( NULL ); + for( TInt i=0; i < iClientData.Count(); ++i ) + { + if( iClientData[i]->sameThread( aProcId, aThreadId ) ) + { + data = iClientData[i]; + iClientData.Remove(i); + if( data == iCurrClientData ) + { + iCurrClientData = 0; + } + delete data; + break; + } + } + } + +TBool DDeviceReqHandler::InitiateRequestWithReply( TAsyncRequest* aRec, TAny* aTransactionData ) + { + VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply" ); + if( iDriverRfcThreadId == 0 || iDriverRfcProcessId == 0 ) + { + iDriverRfcProcessId = Kern::CurrentProcess().iId; + iDriverRfcThreadId = Kern::CurrentThread().iId; + } + //iReqIssueMutex.Wait(); + const TUint32 serializedLength( aRec->iRemoteFunctionCall.SerialisedLength() ); + if ( !iRequestBuffer.CheckForSpace( serializedLength ) ) + { + return EFalse; + } + ++iTransactionId; + aRec->iRemoteFunctionCall.SetTransactionId( iTransactionId ); + aRec->iRemoteFunctionCall.SetOperationType( RemoteFunctionCallData::EOpRequestWithReply ); + aRec->iAsyncClient = &(Kern::CurrentThread()); + aRec->iRemoteFunctionCall.SetThreadInformation( iDriverRfcProcessId, iDriverRfcThreadId ); + + iSchedulerInitiatedTransactionIds.Append( TTransactionInfo( iTransactionId, aTransactionData ) ); + VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply ids len=%d transaction id = %u proc/thread = %u / %u api/op = %0x / %0x", iSchedulerInitiatedTransactionIds.Count(), iTransactionId, Kern::CurrentProcess().iId, Kern::CurrentThread().iId, aRec->iRemoteFunctionCall.Header().iApiUid, aRec->iRemoteFunctionCall.Header().iOpCode ); + if( aRec->iRemoteFunctionCall.Header().iApiUid ) + { + VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply request's api is SERIALISED_DRIVER_API_UID" ); + } + + iSerializedRequestRoot.AppendToLast( aRec );//we need the result, so add to the dfc handled requests + TDataFromClientSpaceCopier datacopier( aRec->iAsyncClient ); + SerializedFunctionCall sfc( aRec->iRemoteFunctionCall ); + + sfc.SetDataCopier( &datacopier );//We know this is a "request" (precondition) + const TUint32 base( iRequestBuffer.AllocateBytes( serializedLength ) ); + //Next, serialize the call to the HW memory + const TLinAddr paramAddr( iHwInterface.InputParametersAddress() + base ); + TInt len = sfc.WriteToBuffer( reinterpret_cast(paramAddr), VVI_PARAMETERS_INPUT_MEMORY_SIZE - 1 - base ); + VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply len = %d", len); + sfc.SetDataCopier( NULL ); + iRequestBuffer.CommitBytes( base, serializedLength ); + iHwInterface.IssueCommand( VVI_EXECUTE ); + VVHW_TRACE("DDeviceReqHandler::InitiateRequestWithReply issued"); + return ETrue; + } + +/** + * This routine adds extra info about the sgImage's pbuffer handle for syncing, + * when that is required. + * 1. checks the sgImage handle, and if it's not NULL, then + * 2. Get the sgImage's metadata + * 3. Check if the vgImage is "dirty", and if yes, + * then append the pbuffer handle as a parameter to the call + * 4. Set the pbuffer "dirty", if aSetBufferDirty is ETrue + */ + +void DDeviceReqHandler::getVGSyncInOp( TAsyncRequest* aReq, TInt aSgHandleIndexInReq, TBool aSetBufferDirty ) + { + VVHW_TRACE( "DDeviceReqHandler::getVGSyncInOp" ); + EGLSurface surface( EGL_NO_SURFACE );//The pbuffer surface to sync from, if needed + VGboolean syncNeeded = VG_FALSE; + OpenVgRFC call( aReq->iRemoteFunctionCall ); + TUint64 sgId(NULL); + + if( call.Data().Header().iParameterCount > aSgHandleIndexInReq ) + { + call.GetTUint64( sgId, aSgHandleIndexInReq ); + } + else + { + return;//No sgImage handle appended on the client side, just exit + } + +#ifdef FAISALMEMON_S4_SGIMAGE + if( sgId != NULL ) + { + VVHW_TRACE( "DDeviceReqHandler::getVGSyncInOp SgImage-backing VGImage found" ); + DSgResource* resource; + HBuf8* data = OpenSgImageMetaData( sgId, resource ); + if( data ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + + if( !sginfo.iVGImageClean ) + { + //set the sync bit as clean now. + sginfo.iVGImageClean = ETrue; + //Additional info for the host side to use + syncNeeded = VG_TRUE; + surface = sginfo.iPbufferHandle; + } + if( aSetBufferDirty ) + { + sginfo.iPbufferClean = EFalse; + } + resource->SetMetaData( *data ); + delete data;//delete the copy of the metadata descriptor + } + } + if( syncNeeded ) + { + call.AppendParam ( (int)surface ); + } +#endif + } + + +void DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult( TAsyncRequest* aReq ) + { + const TUint32 proc_id( aReq->iRemoteFunctionCall.Header().iProcessId ); + const TUint32 thread_id( aReq->iRemoteFunctionCall.Header().iThreadId ); + const TUint32 apicode( aReq->iRemoteFunctionCall.Header().iApiUid ); + const TUint32 opcode( aReq->iRemoteFunctionCall.Header().iOpCode ); + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult: process/thread id : %d / %d", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult: process/thread id : %d / %d API/opcode = %0x/%0x", proc_id, thread_id, apicode, opcode ); + TPerThreadData* data(0); + for( TInt i=0; i < iClientData.Count(); ++i ) + { + if( iClientData[i]->sameThread( proc_id, thread_id )) + { + data = iClientData[i]; + break; + } + } + + switch ( apicode ) + { + case SERIALISED_DRIVER_API_UID: + { + switch( opcode ) + { + case DriverRFC::EDrvCreatePbufferSg: + { + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult : EDrvCreatePbufferSg" ); + if( iSchedulerInitiatedTransactionData ) + { + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle = aReq->iRemoteFunctionCall.Header().iReturnValue; + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult pbuffer=%u", ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle ); + } + TPbSId obj ( ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle, + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId ); + iPbufferSgMap.InsertInOrder( obj, iPbufferSgMapOrder ); + VVHW_TRACE( "pbuffer creation RequestComplete. Inserted (%u, %u) into sg map. Notify thread %u, request status %u", + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iPbufferHandle, + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId, + aReq->iAsyncClient, + aReq->iStatus ); + *(aReq->iStatus) = 0;//REquestComplete doesn't work + VVHW_TRACE( "Pbuffer creation RequestComplete" ); + break; + } + case DriverRFC::EDrvCreateVGImageSg: + { + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult : EDrvCreateVGImageSg" ); + if( iSchedulerInitiatedTransactionData ) + { + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle = aReq->iRemoteFunctionCall.Header().iReturnValue; + } + TVGISId obj ( ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle, + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId ); + iVGImageSgMap.InsertInOrder( obj, iVGImageSgMapOrder ); + VVHW_TRACE( "pbuffer creation RequestComplete. Inserted (%u, %u) into sg map. Notify thread %u, request status %u", + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iVGImageHandle, + ((TSgImageMetaData*)iSchedulerInitiatedTransactionData)->iSgId, + aReq->iAsyncClient, + aReq->iStatus ); + *(aReq->iStatus) = 0;//REquestComplete doesn't work + VVHW_TRACE( "VGImage creation RequestComplete" ); + break; + } + case DriverRFC::EDrvDeleteSgImage: + { + *(aReq->iStatus) = 0; + } + case DriverRFC::EDrvSyncVGImageFromPBuffer: + { + ((TAsyncRequest*)iSchedulerInitiatedTransactionData)->AppendToList( (TAsyncRequest*)(&iPendingRequestRoot) ); + break; + } + default: + { + break; + } + } + } + case SERIALISED_OPENVG_API_UID: + { + switch( opcode ) + { + case OpenVgRFC::EvgGetError: + { + VVHW_TRACE("OpenVgRFC::EvgGetError"); + data->iErrorVG = aReq->iRemoteFunctionCall.Header().iReturnValue; + data->iErrUpdatedVG = EFalse;//TODO: ETrue + break; + } + default:{break;} + } + break; + } + case SERIALISED_EGL_API_UID: + { + switch( opcode ) + { + case EglRFC::EeglGetError: + { + VVHW_TRACE("EglRFC::EeglGetError"); + data->iErrorEGL = aReq->iRemoteFunctionCall.Header().iReturnValue; + data->iErrUpdatedEGL = EFalse;//TODO: ETrue + break; + } + default: + {break;} + } + break; + } + case SERIALISED_OPENGLES_1_1_API_UID: + { + switch( opcode ) + { + case OpenGlES11RFC::EglGetError: + { + VVHW_TRACE("OpenGlES11RFC::EglGetError"); + data->iErrorGLES = aReq->iRemoteFunctionCall.Header().iReturnValue; + data->iErrUpdatedGLES = EFalse;//TODO: ETrue + } + default:{break;} + } + break; + } + default:{break;} + } + + VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult return value: %d", aReq->iRemoteFunctionCall.Header().iReturnValue ); + if( data ) + { + VVHW_TRACE("errors EGL/VG/GLES=%0x/%0x/%0x", data->iErrorEGL, data->iErrorVG, data->iErrorGLES ); + } + //Delete the request object, as it is no longer needed + aReq->iStatus = 0; + aReq->iAsyncClient = 0; + delete aReq; + VVHW_TRACE("DDeviceReqHandle::ConsumeSchedulerInitiatedRequestResult done."); + } + +/** + * DDeviceReqHandler::CreateSgImagePbuffer * @param aInfo the info - */ -void DDeviceReqHandler::CreateSgImagePbuffer( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread ) - { - //eglCreatePbufferSurface - // - VVHW_TRACE("DDeviceReqHandler::CreateSgImagePbuffer ->"); - if( !iCurrClientData ) - {return;} - TBool allok = ETrue; - TAsyncRequest* req(0); - TPckg res( iOpReturn ); - *aStatus = KRequestPending; - VVHW_TRACE("DDeviceReqHandler::CreateSgImagePbuffer request from thread %u, requeststatus %u", aThread, aStatus ); - req = AllocRequest( aStatus, aThread, NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); - if( req ) - { - DriverRFC call( req->iRemoteFunctionCall ); - call.Init( DriverRFC::EDrvCreatePbufferSg ); - - call.AppendEGLint ( aInfo.iSizeInPixels.iWidth ); - call.AppendEGLint ( aInfo.iSizeInPixels.iHeight ); - call.AppendEGLint ( aInfo.iPixelFormat ); - - TPckg data( req->iRemoteFunctionCall ); - req->iA1 = (TAny*)( &data ); - allok = InitiateRequestWithReply( req, (TAny*)(&aInfo) ); - } - if( !allok ) - { - //request not sent, or something else went wrong. Tell the client its over - //TODO: somehow dispose of the pbuffer that might have been created - } - while( *(aStatus) == KRequestPending ) - { - NKern::Sleep( 20 ); - } - VVHW_TRACE("DDeviceReqHandler::CreateSgImagePBuffer <-"); - return; - } - -void DDeviceReqHandler::CreateSgImageVGImage( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread ) - { - //eglCreatePbufferSurface - // - VVHW_TRACE("DDeviceReqHandler::CreateSgImageVGImage ->"); - if( !iCurrClientData ) - {return;} - TBool allok = ETrue; - TAsyncRequest* req(0); - TPckg res( iOpReturn ); - *aStatus = KRequestPending; - //make a request for the vgImage - req = AllocRequest( aStatus, aThread, NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); - if( req ) - { - DriverRFC call( req->iRemoteFunctionCall ); - call.Init( DriverRFC::EDrvCreateVGImageSg ); - - call.AppendEGLint ( aInfo.iSizeInPixels.iWidth ); - call.AppendEGLint ( aInfo.iSizeInPixels.iHeight ); - call.AppendEGLint ( aInfo.iPixelFormat ); - - TPckg data( req->iRemoteFunctionCall ); - req->iA1 = (TAny*)(&data); - allok = InitiateRequestWithReply( req, (TAny*)(&aInfo) ); - } - if( !allok ) - { - //request not sent, or something else went wrong. Tell the client its over - //TODO: somehow dispose of the image that might have been created - //Kern::RequestComplete( aStatus, KErrGeneral ); - } - while( *(aStatus) == KRequestPending ) - { - NKern::Sleep( 20 ); - } - VVHW_TRACE("DDeviceReqHandler::CreateSgImageVGImage <-"); - return; - } - - - - -TInt DDeviceReqHandler::DestroySgImage( const TUint64 aId ) - { - VVHW_TRACE("DDeviceReqHandler::DestroySgImage ->"); - TBool allok = ETrue; - TAsyncRequest* req(0); - TPckg res( iOpReturn ); - EGLSurface surface(0); - VGImage image(0); - - DSgResource* resource; - HBuf8* data = OpenSgImageMetaData( aId, resource ); - if( data ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - surface = sginfo.iPbufferHandle; - //TODO: are there other cases: e.g. can the vgimage be destroyed without destroying the surface? - if( sginfo.iUsage || ESgUsageBitOpenVgImage ) - { - image = sginfo.iVGImageHandle; - } - delete data; - } - TRequestStatus status = KRequestPending; - //make a request for the vgImage - req = AllocRequest( &status, &Kern::CurrentThread(), NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); - allok = (req?EFalse:ETrue); - if( req ) - { - DriverRFC call( req->iRemoteFunctionCall ); - call.Init( DriverRFC::EDrvDeleteSgImage ); - - call.AppendEGLSurface( surface ); - call.AppendVGParam ( image ); - - TPckg data( req->iRemoteFunctionCall ); - req->iA1 = (TAny*)(&data); - allok = InitiateRequestWithReply( req, 0 ); - } - if( !allok ) - { - //TODO - } - while( status == KRequestPending ) - { - NKern::Sleep( 20 ); - } - VVHW_TRACE("DDeviceReqHandler::DestroySgImage <-"); - return 1; - } - - -DDeviceReqHandler::TRequestMode DDeviceReqHandler::InterpretRequest( TAsyncRequest* aReq ) - { - TRequestMode alreadyProcessed( ENormal );//processed here? The return value - const TUint32 proc_id( aReq->iRemoteFunctionCall.Header().iProcessId ); - const TUint32 thread_id( aReq->iRemoteFunctionCall.Header().iThreadId ); - const TUint32 apicode( aReq->iRemoteFunctionCall.Header().iApiUid ); - const TUint32 opcode( aReq->iRemoteFunctionCall.Header().iOpCode ); - - VVHW_TRACE( "DDeviceReqHandler::InterpretRequest in the process/thread %0x / %0x", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); - - TBool ErrUpdatedVG = EFalse;//is the error updated during this function call - TBool ErrUpdatedEGL = EFalse;//is the error updated during this function call - TBool ErrUpdatedGLES = EFalse;//is the error updated during this function call - //Get a data object to work with - //(either a previously used client data object, or create a new one) - TPerThreadData* data(NULL); - if( iCurrClientData && - iCurrClientData->sameThread( proc_id, thread_id )) - { - //the same client as previously - data = iCurrClientData; - } - else - { - //Check if this client is already known - for( TInt i=0; i < iClientData.Count(); ++i ) - { - if( iClientData[i]->sameThread( proc_id, thread_id )) - { - data = iClientData[i]; - break; - } - } - if( !data ) - { - data = new TPerThreadData( aReq->iStatus, aReq->iAsyncClient, proc_id, thread_id ); - iClientData.Append( data ); - } - if( iCurrClientData ) - { - VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: SWITCHING CONTEXT: %d / %d -> %d / %d", - iCurrClientData->iProcessId, - iCurrClientData->iThreadId, - proc_id, - thread_id ); - //Some other things need to be done here as well, as per 5.2 in the "Implementing SgImage" design doc - //TODO: currently the context switch does not need to be done on this level - } - //Context switched, or no previous client. Current set to new current. - iCurrClientData = data; - } - //Invariant: "data" and "iCurrClient" are the same and not null after this line - VVHW_TRACE("DDeviceReqHandler::InterpretRequest: number of clients = %d", iClientData.Count() ); - - - iCurrClientData->iCurrApiUid = apicode; - iCurrClientData->iCurrOpCode = opcode; - VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: process/thread id : %d / %d API/opcode = %d/%0x", proc_id, thread_id, apicode, opcode ); - - - switch ( apicode ) - { - case SERIALISED_DRIVER_API_UID: - { - VVHW_TRACE("Driver request (must be a shutdown for %d / %d)", proc_id, thread_id ); - if( opcode == DriverRFC::EDrvClientShutdown ) - { - RemoveClientData( proc_id, thread_id ); - } - break; - } - case SERIALISED_OPENVG_API_UID: - { - VVHW_TRACE("OpenVG request" ); - switch( opcode ) - { - case OpenVgRFC::EvgGetError: - { - break; - } - //We need to catch all the operations that create or access VGImage buffers - case OpenVgRFC::EvgChildImage: - { - VVHW_TRACE("vgChildImage" ); - break; - } - case OpenVgRFC::EvgDestroyImage: - { - VVHW_TRACE("vgDestroyImage" ); - break; - } - case OpenVgRFC::EvgFinish: - { - VVHW_TRACE("vgFinish" ); - //A sync is required if there are any native pixmaps backing surfaces in the current context - break; - } - /* - The sgImage ID is a 64-bit value, it has to be serialised as 2 32-bit values, thus occupying - 2 parameter slots each. The sgImage ID position is thus the second last + last parameters in the - parameter list - */ - case OpenVgRFC::EvgClearImage: - { - VVHW_TRACE("vgClearImage" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); - break; - } - case OpenVgRFC::EvgImageSubData: - { - VVHW_TRACE("vgImageSubData" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); - break; - } - case OpenVgRFC::EvgGetPixels: - { - VVHW_TRACE("vgGetPixels" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); - break; - } - case OpenVgRFC::EvgSetPixels: - { - VVHW_TRACE("vgSetPixels" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); - break; - } - case OpenVgRFC::EvgCopyImage: - { - VVHW_TRACE("vgCopyImage" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); - break; - } - case OpenVgRFC::EvgDrawImage: - { - VVHW_TRACE("vgDrawImage" ); - break; - } - case OpenVgRFC::EvgColorMatrix: - { - VVHW_TRACE("vgColorMatrix" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgConvolve: - { - VVHW_TRACE("vgConvolve" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgSeparableConvolve: - { - VVHW_TRACE("vgSeparableConvolve" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgGaussianBlur: - { - VVHW_TRACE("vgGaussianBlur" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgLookup: - { - VVHW_TRACE("vgLookup" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgLookupSingle: - { - VVHW_TRACE("vgLookupSingle" ); - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst - getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src - break; - } - case OpenVgRFC::EvgPathBounds: - { - VVHW_TRACE("vgPathBounds" ); - break; - } - default: - { - break; - } - } - break; - } - case SERIALISED_EGL_API_UID: - { - VVHW_TRACE("EGL request" ); - switch( opcode ) - { - case EglRFC::EeglMetaSgGetHandles: - { - VVHW_TRACE("EglRFC::EeglMetaSgGetHandles" ); - EglRFC call( aReq->iRemoteFunctionCall ); - TUint64 id(0); - EGLint* handles; - EGLint handles_size; - - call.GetTUint64( id, 0 ); - call.GetEGLintVectorData( handles, handles_size, 2 ); - DSgResource* resource; - VVHW_TRACE("EglRFC::EeglMetaSgGetHandles openSgImageMetaData" ); - HBuf8* data = OpenSgImageMetaData( id, resource ); - if( data && handles_size >= 2 ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - handles[0] = sginfo.iPbufferHandle; - handles[1] = sginfo.iVGImageHandle; - call.SetReturnValue( (int)EGL_TRUE ); - } - else - { - call.SetReturnValue( (int)EGL_FALSE ); - } - alreadyProcessed = EHandled; - break; - } - case EglRFC::EeglCreateContext: - { - //if no share_context specified, pass the sgImage pool context - VVHW_TRACE("eglCreateContext" ); - break; - } - case EglRFC::EeglMakeCurrent: - { - EGLDisplay dpy; - EGLSurface draw; - EGLSurface read; - EGLContext ctx; - EGLint syncRequirement(0);//no sync = 0 - - EglRFC call( aReq->iRemoteFunctionCall ); - call.GetEGLDisplay( dpy, 0 ); - call.GetEGLSurface( draw, 1 ); - call.GetEGLSurface( read, 2 ); - call.GetEGLContext( ctx, 3 ); - VGImage img = 0; - - TPbSId obj ( draw, 0 ); - - TInt sgIdIndex = iPbufferSgMap.FindInOrder( obj, iPbufferSgMapOrder ); - if( sgIdIndex != KErrNotFound ) - { - DSgResource* resource; - HBuf8* data = OpenSgImageMetaData( iPbufferSgMap[sgIdIndex].iSgId, resource ); - if( data ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - - if( !sginfo.iPbufferClean ) - { - img = sginfo.iVGImageHandle; - //sync with the underlying pbuffer surface - syncRequirement = syncRequirement | KSyncDrawSurface; - call.AppendEGLint( img ); - } - delete data; - } - } - obj.iPbuffer = read; - obj.iSgId = 0; - - sgIdIndex = iPbufferSgMap.FindInOrder( obj, iPbufferSgMapOrder ); - if( sgIdIndex != KErrNotFound ) - { - DSgResource* resource; - HBuf8* data = OpenSgImageMetaData( iPbufferSgMap[sgIdIndex].iSgId, resource ); - if( data ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - - if( !sginfo.iPbufferClean ) - { - img = sginfo.iVGImageHandle; - //sync with the underlying pbuffer surface - syncRequirement = syncRequirement | KSyncReadSurface; - } - delete data; - } - } - call.AppendEGLint( syncRequirement ); - call.AppendEGLint( img ); - - VVHW_TRACE("eglMakeCurrent %u", iCurrClientData->iContext ); - break; - } - case EglRFC::EeglMakeCurrentSg: - { - VVHW_TRACE("eglMakeCurrentSg" ); - break; - } - case EglRFC::EeglCreatePixmapSurfaceSg: - { - alreadyProcessed = EHandled;//This will be handled here - - TUint64 sgId; - EglRFC call( aReq->iRemoteFunctionCall ); - call.GetTUint64( sgId, 0 );//get the sgImage id - - DSgResource* resource; - HBuf8* data = OpenSgImageMetaData( sgId, resource ); - if( data ) - { - TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); - resource->SetMetaData( (*data) ); - aReq->iRemoteFunctionCall.SetReturnValue( sginfo.iPbufferHandle ); - delete data; - } - else - { - aReq->iRemoteFunctionCall.SetReturnValue( EGL_NO_SURFACE ); - } - //Find the sgimage's pbuffer surface, then return that - VVHW_TRACE( "EeglCreatePixmapSurfaceSg" ); - break; - } - case EglRFC::EeglCreatePbufferFromClientBuffer: - { - //if a sgImage-backing VGImage handle is passed here, then fail with EGL_BAD_ACCESS - - VVHW_TRACE("eglCreatePbufferFromClientBuffer" ); - break; - } - case EglRFC::EeglGetError: - { - VVHW_TRACE("eglGetError" ); - break; - } - default: - { - break; - } - }//switch opcode (EGL) - - break; - } - case SERIALISED_OPENGLES_1_1_API_UID: - { - VVHW_TRACE("OpenGLES request" ); - switch( opcode ) - { - case OpenGlES11RFC::EglGetError: - { - //Get the GLES error - } - default: - { - break; - } - } - break; - } - default: - { - break; - } - }//switch apicode - //VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: opcode : %d ", data->iCurrOpCode ); - if( iCurrClientData )//This could have been removed, in a call to RemoveClientData - { - iCurrClientData->iErrUpdatedVG = ErrUpdatedVG; - iCurrClientData->iErrUpdatedEGL = ErrUpdatedEGL; - iCurrClientData->iErrUpdatedGLES = ErrUpdatedGLES; - } - return alreadyProcessed; - } - -HBuf8* DDeviceReqHandler::OpenSgImageMetaData( const TUint64 aId, DSgResource*& aResource ) - { - VVHW_TRACE("DDeviceReqHandler::OpenSgImageMetaData 0x%lx", aId ); - aResource = 0; - HBuf8* data(0); - TInt sgOpenErr( KErrNone ); - - sgOpenErr = SgExtension::FindAndOpenResource( aId, aResource );//Open the sgimage resource - VVHW_TRACE(" sgOpenErr %d", sgOpenErr); - if( sgOpenErr == KErrNone ) - { - data = HBuf8::New( aResource->GetMetaDataSize() ); - if( data ) - { - aResource->GetMetaData( (*data) ); - } - } - return data;//If there was a problem, this is zero. Ownership belongs to caller - } + */ +void DDeviceReqHandler::CreateSgImagePbuffer( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread ) + { + //eglCreatePbufferSurface + // + VVHW_TRACE("DDeviceReqHandler::CreateSgImagePbuffer ->"); + if( !iCurrClientData ) + {return;} + TBool allok = ETrue; + TAsyncRequest* req(0); + TPckg res( iOpReturn ); + *aStatus = KRequestPending; + VVHW_TRACE("DDeviceReqHandler::CreateSgImagePbuffer request from thread %u, requeststatus %u", aThread, aStatus ); + req = AllocRequest( aStatus, aThread, NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); + if( req ) + { + DriverRFC call( req->iRemoteFunctionCall ); + call.Init( DriverRFC::EDrvCreatePbufferSg ); + + call.AppendEGLint ( aInfo.iSizeInPixels.iWidth ); + call.AppendEGLint ( aInfo.iSizeInPixels.iHeight ); + call.AppendEGLint ( aInfo.iPixelFormat ); + + TPckg data( req->iRemoteFunctionCall ); + req->iA1 = (TAny*)( &data ); + allok = InitiateRequestWithReply( req, (TAny*)(&aInfo) ); + } + if( !allok ) + { + //request not sent, or something else went wrong. Tell the client its over + //TODO: somehow dispose of the pbuffer that might have been created + } + while( *(aStatus) == KRequestPending ) + { + NKern::Sleep( 20 ); + } + VVHW_TRACE("DDeviceReqHandler::CreateSgImagePBuffer <-"); + return; + } + +void DDeviceReqHandler::CreateSgImageVGImage( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread ) + { + //eglCreatePbufferSurface + // + VVHW_TRACE("DDeviceReqHandler::CreateSgImageVGImage ->"); + if( !iCurrClientData ) + {return;} + TBool allok = ETrue; + TAsyncRequest* req(0); + TPckg res( iOpReturn ); + *aStatus = KRequestPending; + //make a request for the vgImage + req = AllocRequest( aStatus, aThread, NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); + if( req ) + { + DriverRFC call( req->iRemoteFunctionCall ); + call.Init( DriverRFC::EDrvCreateVGImageSg ); + + call.AppendEGLint ( aInfo.iSizeInPixels.iWidth ); + call.AppendEGLint ( aInfo.iSizeInPixels.iHeight ); + call.AppendEGLint ( aInfo.iPixelFormat ); + + TPckg data( req->iRemoteFunctionCall ); + req->iA1 = (TAny*)(&data); + allok = InitiateRequestWithReply( req, (TAny*)(&aInfo) ); + } + if( !allok ) + { + //request not sent, or something else went wrong. Tell the client its over + //TODO: somehow dispose of the image that might have been created + //Kern::RequestComplete( aStatus, KErrGeneral ); + } + while( *(aStatus) == KRequestPending ) + { + NKern::Sleep( 20 ); + } + VVHW_TRACE("DDeviceReqHandler::CreateSgImageVGImage <-"); + return; + } + + + + +TInt DDeviceReqHandler::DestroySgImage( const TUint64 aId ) + { + VVHW_TRACE("DDeviceReqHandler::DestroySgImage ->"); + TBool allok = ETrue; + TAsyncRequest* req(0); + TPckg res( iOpReturn ); + EGLSurface surface(0); + VGImage image(0); + +#ifdef FAISALMEMON_S4_SGIMAGE + DSgResource* resource; + HBuf8* data = OpenSgImageMetaData( aId, resource ); + if( data ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + surface = sginfo.iPbufferHandle; + //TODO: are there other cases: e.g. can the vgimage be destroyed without destroying the surface? + if( sginfo.iUsage || ESgUsageBitOpenVgImage ) + { + image = sginfo.iVGImageHandle; + } + delete data; + } + TRequestStatus status = KRequestPending; + //make a request for the vgImage + req = AllocRequest( &status, &Kern::CurrentThread(), NULL, (TAny*)(&res), TAsyncRequest::ERTRequest ); + allok = (req?EFalse:ETrue); + if( req ) + { + DriverRFC call( req->iRemoteFunctionCall ); + call.Init( DriverRFC::EDrvDeleteSgImage ); + + call.AppendEGLSurface( surface ); + call.AppendVGParam ( image ); + + TPckg data( req->iRemoteFunctionCall ); + req->iA1 = (TAny*)(&data); + allok = InitiateRequestWithReply( req, 0 ); + } + if( !allok ) + { + //TODO + } + while( status == KRequestPending ) + { + NKern::Sleep( 20 ); + } +#endif + + VVHW_TRACE("DDeviceReqHandler::DestroySgImage <-"); + return 1; + } + + +DDeviceReqHandler::TRequestMode DDeviceReqHandler::InterpretRequest( TAsyncRequest* aReq ) + { + TRequestMode alreadyProcessed( ENormal );//processed here? The return value + const TUint32 proc_id( aReq->iRemoteFunctionCall.Header().iProcessId ); + const TUint32 thread_id( aReq->iRemoteFunctionCall.Header().iThreadId ); + const TUint32 apicode( aReq->iRemoteFunctionCall.Header().iApiUid ); + const TUint32 opcode( aReq->iRemoteFunctionCall.Header().iOpCode ); + + VVHW_TRACE( "DDeviceReqHandler::InterpretRequest in the process/thread %0x / %0x", Kern::CurrentProcess().iId, Kern::CurrentThread().iId ); + + TBool ErrUpdatedVG = EFalse;//is the error updated during this function call + TBool ErrUpdatedEGL = EFalse;//is the error updated during this function call + TBool ErrUpdatedGLES = EFalse;//is the error updated during this function call + //Get a data object to work with + //(either a previously used client data object, or create a new one) + TPerThreadData* data(NULL); + if( iCurrClientData && + iCurrClientData->sameThread( proc_id, thread_id )) + { + //the same client as previously + data = iCurrClientData; + } + else + { + //Check if this client is already known + for( TInt i=0; i < iClientData.Count(); ++i ) + { + if( iClientData[i]->sameThread( proc_id, thread_id )) + { + data = iClientData[i]; + break; + } + } + if( !data ) + { + data = new TPerThreadData( aReq->iStatus, aReq->iAsyncClient, proc_id, thread_id ); + iClientData.Append( data ); + } + if( iCurrClientData ) + { + VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: SWITCHING CONTEXT: %d / %d -> %d / %d", + iCurrClientData->iProcessId, + iCurrClientData->iThreadId, + proc_id, + thread_id ); + //Some other things need to be done here as well, as per 5.2 in the "Implementing SgImage" design doc + //TODO: currently the context switch does not need to be done on this level + } + //Context switched, or no previous client. Current set to new current. + iCurrClientData = data; + } + //Invariant: "data" and "iCurrClient" are the same and not null after this line + VVHW_TRACE("DDeviceReqHandler::InterpretRequest: number of clients = %d", iClientData.Count() ); + + + iCurrClientData->iCurrApiUid = apicode; + iCurrClientData->iCurrOpCode = opcode; + VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: process/thread id : %d / %d API/opcode = %d/%0x", proc_id, thread_id, apicode, opcode ); + + + switch ( apicode ) + { + case SERIALISED_DRIVER_API_UID: + { + VVHW_TRACE("Driver request (must be a shutdown for %d / %d)", proc_id, thread_id ); + if( opcode == DriverRFC::EDrvClientShutdown ) + { + RemoveClientData( proc_id, thread_id ); + } + break; + } + case SERIALISED_OPENVG_API_UID: + { + VVHW_TRACE("OpenVG request" ); + switch( opcode ) + { + case OpenVgRFC::EvgGetError: + { + break; + } + //We need to catch all the operations that create or access VGImage buffers + case OpenVgRFC::EvgChildImage: + { + VVHW_TRACE("vgChildImage" ); + break; + } + case OpenVgRFC::EvgDestroyImage: + { + VVHW_TRACE("vgDestroyImage" ); + break; + } + case OpenVgRFC::EvgFinish: + { + VVHW_TRACE("vgFinish" ); + //A sync is required if there are any native pixmaps backing surfaces in the current context + break; + } + /* + The sgImage ID is a 64-bit value, it has to be serialised as 2 32-bit values, thus occupying + 2 parameter slots each. The sgImage ID position is thus the second last + last parameters in the + parameter list + */ + case OpenVgRFC::EvgClearImage: + { + VVHW_TRACE("vgClearImage" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); + break; + } + case OpenVgRFC::EvgImageSubData: + { + VVHW_TRACE("vgImageSubData" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); + break; + } + case OpenVgRFC::EvgGetPixels: + { + VVHW_TRACE("vgGetPixels" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); + break; + } + case OpenVgRFC::EvgSetPixels: + { + VVHW_TRACE("vgSetPixels" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); + break; + } + case OpenVgRFC::EvgCopyImage: + { + VVHW_TRACE("vgCopyImage" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 ); + break; + } + case OpenVgRFC::EvgDrawImage: + { + VVHW_TRACE("vgDrawImage" ); + break; + } + case OpenVgRFC::EvgColorMatrix: + { + VVHW_TRACE("vgColorMatrix" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgConvolve: + { + VVHW_TRACE("vgConvolve" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgSeparableConvolve: + { + VVHW_TRACE("vgSeparableConvolve" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgGaussianBlur: + { + VVHW_TRACE("vgGaussianBlur" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgLookup: + { + VVHW_TRACE("vgLookup" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgLookupSingle: + { + VVHW_TRACE("vgLookupSingle" ); + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-4 );//dst + getVGSyncInOp( aReq, aReq->iRemoteFunctionCall.Header().iParameterCount-2 );//src + break; + } + case OpenVgRFC::EvgPathBounds: + { + VVHW_TRACE("vgPathBounds" ); + break; + } + default: + { + break; + } + } + break; + } + case SERIALISED_EGL_API_UID: + { + VVHW_TRACE("EGL request" ); + switch( opcode ) + { + case EglRFC::EeglMetaSgGetHandles: + { + VVHW_TRACE("EglRFC::EeglMetaSgGetHandles" ); + EglRFC call( aReq->iRemoteFunctionCall ); + TUint64 id(0); + EGLint* handles; + EGLint handles_size; + + call.GetTUint64( id, 0 ); + call.GetEGLintVectorData( handles, handles_size, 2 ); +#ifdef FAISALMEMON_S4_SGIMAGE + DSgResource* resource; + VVHW_TRACE("EglRFC::EeglMetaSgGetHandles openSgImageMetaData" ); + HBuf8* data = OpenSgImageMetaData( id, resource ); + if( data && handles_size >= 2 ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + handles[0] = sginfo.iPbufferHandle; + handles[1] = sginfo.iVGImageHandle; + call.SetReturnValue( (int)EGL_TRUE ); + } + else + { + call.SetReturnValue( (int)EGL_FALSE ); + } + alreadyProcessed = EHandled; +#endif + break; + } + case EglRFC::EeglCreateContext: + { + //if no share_context specified, pass the sgImage pool context + VVHW_TRACE("eglCreateContext" ); + break; + } + case EglRFC::EeglMakeCurrent: + { + EGLDisplay dpy; + EGLSurface draw; + EGLSurface read; + EGLContext ctx; + EGLint syncRequirement(0);//no sync = 0 + + EglRFC call( aReq->iRemoteFunctionCall ); + call.GetEGLDisplay( dpy, 0 ); + call.GetEGLSurface( draw, 1 ); + call.GetEGLSurface( read, 2 ); + call.GetEGLContext( ctx, 3 ); + VGImage img = 0; + + TPbSId obj ( draw, 0 ); + + TInt sgIdIndex = iPbufferSgMap.FindInOrder( obj, iPbufferSgMapOrder ); + if( sgIdIndex != KErrNotFound ) + { +#ifdef FAISALMEMON_S4_SGIMAGE + DSgResource* resource; + HBuf8* data = OpenSgImageMetaData( iPbufferSgMap[sgIdIndex].iSgId, resource ); + if( data ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + + if( !sginfo.iPbufferClean ) + { + img = sginfo.iVGImageHandle; + //sync with the underlying pbuffer surface + syncRequirement = syncRequirement | KSyncDrawSurface; + call.AppendEGLint( img ); + } + delete data; + } +#endif + } + obj.iPbuffer = read; + obj.iSgId = 0; + + sgIdIndex = iPbufferSgMap.FindInOrder( obj, iPbufferSgMapOrder ); + if( sgIdIndex != KErrNotFound ) + { +#ifdef FAISALMEMON_S4_SGIMAGE + DSgResource* resource; + HBuf8* data = OpenSgImageMetaData( iPbufferSgMap[sgIdIndex].iSgId, resource ); + if( data ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + + if( !sginfo.iPbufferClean ) + { + img = sginfo.iVGImageHandle; + //sync with the underlying pbuffer surface + syncRequirement = syncRequirement | KSyncReadSurface; + } + delete data; + } +#endif + } + call.AppendEGLint( syncRequirement ); + call.AppendEGLint( img ); + + VVHW_TRACE("eglMakeCurrent %u", iCurrClientData->iContext ); + break; + } + case EglRFC::EeglMakeCurrentSg: + { + VVHW_TRACE("eglMakeCurrentSg" ); + break; + } + case EglRFC::EeglCreatePixmapSurfaceSg: + { + alreadyProcessed = EHandled;//This will be handled here + + TUint64 sgId; + EglRFC call( aReq->iRemoteFunctionCall ); + call.GetTUint64( sgId, 0 );//get the sgImage id + +#ifdef FAISALMEMON_S4_SGIMAGE + DSgResource* resource; + HBuf8* data = OpenSgImageMetaData( sgId, resource ); + if( data ) + { + TSgImageMetaData sginfo (((TPckgBuf*) data)->operator ()()); + resource->SetMetaData( (*data) ); + aReq->iRemoteFunctionCall.SetReturnValue( sginfo.iPbufferHandle ); + delete data; + } + else + { + aReq->iRemoteFunctionCall.SetReturnValue( EGL_NO_SURFACE ); + } + //Find the sgimage's pbuffer surface, then return that +#endif + VVHW_TRACE( "EeglCreatePixmapSurfaceSg" ); + break; + } + case EglRFC::EeglCreatePbufferFromClientBuffer: + { + //if a sgImage-backing VGImage handle is passed here, then fail with EGL_BAD_ACCESS + + VVHW_TRACE("eglCreatePbufferFromClientBuffer" ); + break; + } + case EglRFC::EeglGetError: + { + VVHW_TRACE("eglGetError" ); + break; + } + default: + { + break; + } + }//switch opcode (EGL) + + break; + } + case SERIALISED_OPENGLES_1_1_API_UID: + { + VVHW_TRACE("OpenGLES request" ); + switch( opcode ) + { + case OpenGlES11RFC::EglGetError: + { + //Get the GLES error + } + default: + { + break; + } + } + break; + } + default: + { + break; + } + }//switch apicode + //VVHW_TRACE( "DDeviceReqHandler::InterpretRequest: opcode : %d ", data->iCurrOpCode ); + if( iCurrClientData )//This could have been removed, in a call to RemoveClientData + { + iCurrClientData->iErrUpdatedVG = ErrUpdatedVG; + iCurrClientData->iErrUpdatedEGL = ErrUpdatedEGL; + iCurrClientData->iErrUpdatedGLES = ErrUpdatedGLES; + } + return alreadyProcessed; + } + +HBuf8* DDeviceReqHandler::OpenSgImageMetaData( const TUint64 aId, DSgResource*& aResource ) + { + VVHW_TRACE("DDeviceReqHandler::OpenSgImageMetaData 0x%lx", aId ); + aResource = 0; + HBuf8* data(0); + TInt sgOpenErr( KErrNone ); + + sgOpenErr = SgExtension::FindAndOpenResource( aId, aResource );//Open the sgimage resource + VVHW_TRACE(" sgOpenErr %d", sgOpenErr); + if( sgOpenErr == KErrNone ) + { + data = HBuf8::New( aResource->GetMetaDataSize() ); + if( data ) + { + aResource->GetMetaData( (*data) ); + } + } + return data;//If there was a problem, this is zero. Ownership belongs to caller + }