--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vghwinterface/vghwdriver/ldd/src/devicereqhandler.cpp Wed Oct 06 15:43:10 2010 +0100
@@ -0,0 +1,1453 @@
+// 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:
+// Device Request Handler Implementation
+
+
+#include <platform.h>
+#include <assp.h>
+#include <kernel/kernel.h>
+#include <e32cmn.h>
+
+#include <graphics/devicereqhandler.h>
+#include <graphics/virtualvideohwinterface.h>
+#include <graphics/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 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" );
+#ifdef FAISALMEMON_S4_SGIMAGE
+ ReqHandlerExtension::SetReqHandler( this );
+#endif
+ }
+
+// -----------------------------------------------------------------------------
+// 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<TUint8*>(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<TUint8*>(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<RemoteFunctionCallData> 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;i<iSchedulerInitiatedTransactionIds.Count();++i )
+ {
+ if( iSchedulerInitiatedTransactionIds[i].iTransactionId == req->iRemoteFunctionCall.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<TUint8*>( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE );
+ TPckg<RemoteFunctionCallData> 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<TUint8*>( paramAddr ), VVI_PARAMETERS_OUTPUT_MEMORY_SIZE );
+ TPckg<RemoteFunctionCallData> 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<TUint8*>(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" );
+ 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
+ EGLSurface surface( EGL_NO_SURFACE );//The pbuffer surface to sync from, if needed
+ VGboolean syncNeeded = VG_FALSE;
+ if( sgId != NULL )
+ {
+ VVHW_TRACE( "DDeviceReqHandler::getVGSyncInOp SgImage-backing VGImage found" );
+ DSgResource* resource;
+ HBuf8* data = OpenSgImageMetaData( sgId, resource );
+ if( data )
+ {
+ TSgImageMetaData sginfo (((TPckgBuf<TSgImageMetaData>*) 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" );
+#ifdef FAISALMEMON_S4_SGIMAGE
+ 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
+#endif
+ VVHW_TRACE( "Pbuffer creation RequestComplete" );
+ break;
+ }
+ case DriverRFC::EDrvCreateVGImageSg:
+ {
+ VVHW_TRACE( "DDeviceReqHandler::ConsumeSchedulerInitiatedRequestResult : EDrvCreateVGImageSg" );
+#ifdef FAISALMEMON_S4_SGIMAGE
+ 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
+#endif
+ 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.");
+ }
+
+#ifdef FAISALMEMON_S4_SGIMAGE
+/**
+ * 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<TUint32> 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<RemoteFunctionCallData> 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<TUint32> 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<RemoteFunctionCallData> 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;
+ }
+#endif
+
+TInt DDeviceReqHandler::DestroySgImage( const TUint64 aId )
+ {
+ VVHW_TRACE("DDeviceReqHandler::DestroySgImage ->");
+
+#ifdef FAISALMEMON_S4_SGIMAGE
+ TBool allok = ETrue;
+ TAsyncRequest* req(0);
+ TPckg<TUint32> res( iOpReturn );
+ EGLSurface surface(0);
+ VGImage image(0);
+ DSgResource* resource;
+ HBuf8* data = OpenSgImageMetaData( aId, resource );
+ if( data )
+ {
+ TSgImageMetaData sginfo (((TPckgBuf<TSgImageMetaData>*) 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<RemoteFunctionCallData> 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<TSgImageMetaData>*) 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<TSgImageMetaData>*) 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<TSgImageMetaData>*) 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<TSgImageMetaData>*) 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;
+ }
+
+#ifdef FAISALMEMON_S4_SGIMAGE
+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
+ }
+#endif