vghwinterface/vghwdriver/ldd/src/devicereqhandler.cpp
author Matt Plumtree <matt.plumtree@nokia.com>
Wed, 06 Oct 2010 15:43:10 +0100
branchbug235_bringup_0
changeset 51 4f400a6ea71f
parent 5 guestrendering/guestvideodriver/ldd/src/devicereqhandler.cpp@65231b4e789a
permissions -rwxr-xr-x
Rearrange the package to put certain components into a new collection, vghwinterface. Remove unpopulated syborggraphicswrapper, as it will be integrated into the vghwapiwrapper (ne khronosapiwrapper).

// 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