Move GLES20 source into standard locations
Move Khronos headers into their respective components, to be exported by each.
Remove hostthreadadapter as nothing outside of the vghwapiwrapper, which now contains the code, needs it
// 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