--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics_plat/guestvideodriver_api/ldd/inc/devicereqhandler.h Fri Aug 13 15:11:40 2010 +0100
@@ -0,0 +1,594 @@
+// Copyright (c) 2002-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:
+//
+
+
+#ifndef DEVICEREQHANDLER_H
+#define DEVICEREQHANDLER_H
+
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <e32cmn.h>
+
+#include <sgresource/sgcommon.h>//TSgImageMetaData
+#include "sgextension.h"//For SgExtension
+
+#include "guestvideodriverprotocol.h"
+#include "virtualvideohwinterface.h"
+#include "remotefunctioncall.h"
+#include "requestbuffer.h"
+#include "reqhandlerextension.h"
+
+#include <EGL/egltypes.h>//For EGLint
+
+class RSgImage;//we only need pointers anyways
+
+using namespace GuestVideoDriver;
+
+
+//Container class for the mapping from pbuffers to sgimages
+class TPbSId
+ {
+ public:
+ TInt iPbuffer;
+ TUint64 iSgId;
+ TPbSId( TInt aP, TUint64 aId ) : iPbuffer( aP ), iSgId( aId ){}
+ };
+class TVGISId
+ {
+ public:
+ TInt iVGImage;
+ TUint64 iSgId;
+ TVGISId( TInt aI, TUint64 aId ) : iVGImage( aI ), iSgId( aId ){}
+ };
+
+/**
+ * Class for handling requests to the Video driver.
+ */
+class DDeviceReqHandler : public DBase, MReqHandlerCallback , protected MRequestBufferBookKeepingWriter
+ {
+public:
+ enum TRequestMode
+ {
+ ENormal, //to be issued by the normal route
+ EHandled, //already completed (in the scheduler)
+ EQueued //queued into another outstanding request
+ };
+ enum TOpChainType
+ {//for performing a series of operations in sequence
+ EOpInit = 1
+ };
+ enum { KMaxFreeRequests = 20 };
+
+ struct SgImageMetaInfo
+ {
+ TUint32 iSgImagePointer;
+ };
+ /*
+ * Stores data belonging to a client thread
+ */
+ struct TPerThreadData
+ {
+ TRequestStatus* iStatus;
+ DThread* iAsyncClient;//asynchronous client
+ TUint32 iProcessId;
+ TUint32 iThreadId;
+
+ TUint32 iCurrApiUid;//5.2 in "Implementing sgImage on Guest EGL"
+ TUint32 iCurrOpCode;//Not required
+
+ TBool iErrUpdatedGLES;
+ TBool iErrUpdatedVG;
+ TBool iErrUpdatedEGL;
+ TUint32 iErrorGLES;//The error for the previous GLES call
+ TUint32 iErrorVG;//The error for the previous VG call
+ TUint32 iErrorEGL;//The error for the previous EGL call
+
+ EGLContext iContext;//The last set context
+
+
+ RArray<SgImageMetaInfo> iImageInfo;
+
+
+ TBool sameThread( TUint32 aProcId, TUint32 aThreadId )
+ {
+ return ( ( aProcId == iProcessId && aThreadId == iThreadId ) ? ETrue : EFalse );
+ }
+ TPerThreadData( TRequestStatus* aStatus, DThread* aAsyncClient, TUint32 aProcId, TUint32 aThreadId ) :
+ iStatus( aStatus),
+ iAsyncClient(aAsyncClient),
+ iProcessId( aProcId ),
+ iThreadId( aThreadId ),
+ iErrUpdatedGLES(EFalse),
+ iErrUpdatedVG(EFalse),
+ iErrUpdatedEGL(EFalse)
+ {}
+ };
+
+ struct TTransactionInfo
+ {
+ public:
+ TUint32 iTransactionId;
+ //this must be valid for the whole duration of the transaction, and is now owned here
+ TAny* iTransactionData;
+ TTransactionInfo( TUint32 aTransactionId, TAny* aTransactionData = 0 ) :
+ iTransactionId( aTransactionId ),
+ iTransactionData( aTransactionData )
+ {}
+ };
+
+ /*
+ * Stores an async request before serialisation
+ */
+ struct TAsyncRequest
+ {
+ enum TRequestType
+ {
+ ERTDriver,
+ ERTRequest,
+ ERTCommandLoad
+ };
+
+ TAsyncRequest( TRequestStatus* aStatus,
+ DThread* aAsyncClient,
+ TAny* aA1,
+ TAny* aA2,
+ TRequestType aCommandLoadRequest ):
+ iStatus( aStatus ),
+ iAsyncClient( aAsyncClient ),
+ iA1( aA1 ),
+ iA2( aA2 ),
+ iCommandLoadRequest( aCommandLoadRequest ),
+ iNext( NULL )
+ {
+ }
+
+ void Init(TRequestStatus* aStatus,
+ DThread* aAsyncClient,
+ TAny* aA1,
+ TAny* aA2,
+ TRequestType aCommandLoadRequest )
+ {
+ iStatus = aStatus;
+ iAsyncClient = aAsyncClient;
+ iA1 = aA1;
+ iA2 = aA2;
+ iCommandLoadRequest = aCommandLoadRequest;
+ iNext = NULL;
+ }
+
+ void AppendToList( TAsyncRequest* iPrev )
+ {
+ if ( iPrev->iNext )
+ {
+ this->iNext = iPrev->iNext;
+ }
+ iPrev->iNext = this;
+ }
+
+ void RemoveFromList( TAsyncRequest* iPrev )
+ {
+ if ( iPrev->iNext == this )
+ {
+ iPrev->iNext = this->iNext;
+ }
+ this->iNext = NULL;
+ }
+
+ //Current request status
+ TRequestStatus* iStatus;
+
+ //Current asynchronous client
+ DThread* iAsyncClient;
+
+ TAny* iA1;
+ TAny* iA2;
+
+ TRequestType iCommandLoadRequest;
+
+ RemoteFunctionCallData iRemoteFunctionCall;
+
+ //Link for linked list
+ TAsyncRequest* iNext;
+ };
+
+ struct TAsyncRequestRoot: public TAsyncRequest
+ {
+ TAsyncRequestRoot():
+ TAsyncRequest( NULL, NULL, NULL, NULL, ERTRequest )
+ {
+ }
+
+ void AppendToLast( TAsyncRequest* aReq )
+ {
+ TAsyncRequest* last( this );
+ TAsyncRequest* next( iNext );
+ while ( next )
+ {
+ last = next;
+ next = next->iNext;
+ }
+ aReq->AppendToList( last );
+ }
+
+ void DeleteAll()
+ {
+ TAsyncRequest* next( iNext );
+ while ( next )
+ {
+ TAsyncRequest* nextToDel( next );
+ next = next->iNext;
+ delete nextToDel;
+ }
+ }
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param aHwInterface
+ * Interface to the hardware
+ * @param aQueue
+ * Deferred function call queue
+ * @param aMdaifSvTable
+ * MDAIF shared variable table
+ */
+ DDeviceReqHandler(
+ DVirtualVideoHwInterface& aHwInterface,
+ TDfcQue* aQueue );
+
+ /**
+ * Destructor.
+ */
+ virtual ~DDeviceReqHandler();
+
+ /**
+ * Handles a command execution
+ *
+ * @param aUserThread
+ * Thread making the request
+ * @param aStatus
+ * Request status to be used in request completion.
+ * @param a1
+ * Request parameter 1
+ */
+ TInt HandleExecuteAsync(
+ DThread*& aUserThread,
+ TRequestStatus* aStatus,
+ TAny* a1);
+
+ /**
+ * Handles a command buffering
+ *
+ * @param aUserThread
+ * Thread making the request
+ * @param a1
+ * Request parameter 1
+ */
+ TInt HandleLoadCommands(
+ DThread*& aUserThread,
+ TRequestStatus* aStatus,
+ TAny* a1 );
+
+ TInt HandleClientShutdown( TUint aProcessId, TUint aThreadId );
+
+public: // Called from Dfc context
+
+ /**
+ * Directs hardware interrupts to appropriate functions.
+ */
+ void ProcessDfc();
+
+public: // Inline functions
+
+ /**
+ * Returns current interrupt ID.
+ *
+ * @return
+ * Interrupt ID.
+ */
+ inline TInt InterruptId() { return iInterruptId; }
+
+ /**
+ * Returns hardware interface.
+ *
+ * @return
+ * Hardware interface reference.
+ */
+ inline DVirtualVideoHwInterface& HwInterface() { return iHwInterface; }
+
+ /**
+ * Returns DFC.
+ *
+ * @return
+ * Reference to TDfc object.
+ */
+ inline TDfc& Dfc() { return iDfc; }
+
+ /**
+ * Returns current interrupt ID.
+ *
+ * @param aInterrupt
+ * Interrupt to be reset.
+ * @return
+ * KErrNone - Successful
+ * System wide errorcodes in error situations.
+ */
+ inline TInt ResetAndEnableInterrupt(
+ DVirtualVideoHwInterface::TInterrupt aInterrupt )
+ {
+ iHwInterface.ResetInterruptStatus( aInterrupt );
+ Interrupt::Clear( InterruptId() );
+ return Interrupt::Enable( iInterruptId );
+ }
+
+ /**
+ * Process next request from ring buffer
+ */
+ TInt ProcessNextPendingRequest();
+
+protected: // Ring buffer book keaping routines
+ void IncrementInputWriteCount( TUint32 aWriteCount )
+ {
+ TUint32 inputBufferWriteCount = GetWriteCount() + aWriteCount;
+ iHwInterface.SetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferWriteCount,
+ inputBufferWriteCount );
+ }
+
+ TUint32 GetInputWriteCount()
+ {
+ TUint32 inputBufferWriteCount;
+ iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferWriteCount,
+ inputBufferWriteCount );
+ return inputBufferWriteCount;
+ }
+
+ TUint32 GetInputReadCount()
+ {
+ TUint32 inputBufferReadCount;
+ iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferReadCount,
+ inputBufferReadCount );
+ return inputBufferReadCount;
+ }
+
+ TUint32 InputBufferTail()
+ {
+ TUint32 val;
+ iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferTail,
+ val );
+ return val;
+ }
+
+ TUint32 InputBufferHead()
+ {
+ TUint32 val;
+ iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferHead,
+ val );
+ return val;
+ }
+
+ void SetInputBufferTail( TUint32 aIndex )
+ {
+ iHwInterface.SetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferTail,
+ aIndex );
+ }
+
+ void SetInputBufferHead( TUint32 aIndex )
+ {
+ iHwInterface.SetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferHead,
+ aIndex );
+ }
+
+protected: // From MRequestBufferBookKeeping
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ void IncrementWriteCount( TUint32 aWriteCount ){ IncrementInputWriteCount( aWriteCount ); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ TUint32 GetWriteCount(){ return GetInputWriteCount(); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ TUint32 GetReadCount(){ return GetInputReadCount(); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ TUint32 BufferTail(){ return InputBufferTail(); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ TUint32 BufferHead(){ return InputBufferHead(); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ void SetBufferHead( TUint32 aIndex ){ SetInputBufferHead( aIndex ); }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ TUint32 MaxTailIndex()
+ {
+ TUint32 val;
+ iHwInterface.GetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferMaxTail,
+ val );
+ return val;
+ }
+
+ /**
+ * See MRequestBufferBookKeepingWriter
+ */
+ void SetMaxTailIndex( TUint32 aIndex )
+ {
+ iHwInterface.SetRegisterValue( DVirtualVideoHwInterface::ERegInputBufferMaxTail,
+ aIndex );
+ }
+
+protected: //Command Scheduling functions
+ /**
+ * DDeviceReqHandler::InterpretRequest
+ * This function is the focal point of the implementation
+ * of the 1st paragraph of 3.4 in the "Implementing SgImage" design doc.
+ * This function therefore intercepts and interprets SOME EGL,VG (and, in the future GLES)
+ * calls.
+ *
+ * @param aReq the request
+ *
+ * @return TBool has the call already been processed? If true, then no further processing
+ * is required for that call (doesn't have to be sent host-side).
+ */
+ DDeviceReqHandler::TRequestMode InterpretRequest( TAsyncRequest* aReq );
+
+
+ void ConsumeSchedulerInitiatedRequestResult( TAsyncRequest* aReq );
+
+ /**
+ * RemoveClientData
+ * @param aProcId
+ * @param aThreadId
+ */
+ void RemoveClientData( const TUint32 aProcId, const TUint32 aThreadId );
+ /**
+ * Initiate a request to the host side from the scheduler (this)
+ * This is needed so that the scheduler can make requests that are not
+ * directly client-originated.
+ */
+ TBool InitiateRequestWithReply( TAsyncRequest* req, TAny* aTransactionData = 0 );
+
+ /**
+ * Helper function for getting the stored client data for the proc/thread, if present
+ * @return TPerThreadData object, or NULL, if no object was found with the right proc/thread id
+ */
+ TPerThreadData* GetClientData( const TUint32 aProcId, const TUint32 aThreadId );
+
+ /**
+ * getVGSync
+ * Check if the VGImage is sg image backing, and if it's sync flag is set to dirty.
+ * If both above conditions are met, add the required parameters to the hostside call
+ * so that the hostside can proceed to making the sync.
+ *
+ */
+ DDeviceReqHandler::TRequestMode DDeviceReqHandler::getVGSync( VGImage aImg, TAsyncRequest* aReq );
+
+ /**
+ *
+ * @param aReq the request to add the additional info to
+ * @param aImageIndexInReq the index of the vg image in the rfc call. This will
+ * be used to determine what the sgImage is, and find the sync bit
+ * @param aSetBufferDirty: set the buffer dirty in any case
+ * @param aAddFalseForOther. All sync operations are prepared to handle two vgimages, thus need to have another
+ * value to read. Set this to ETrue if you are not going to add another real sync operation.
+ */
+ void getVGSyncInOp( TAsyncRequest* aReq, TInt aSgHandleIndexInReq, TBool aSetBufferDirty = EFalse );
+
+public:
+ HBuf8* OpenSgImageMetaData( const TUint64 aId, DSgResource*& aResource );
+ void CreateSgImagePbuffer( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread );
+ void CreateSgImageVGImage( const TSgImageMetaData& aInfo, TRequestStatus* aStatus, DThread* aThread );
+ TInt DestroySgImage( const TUint64 aId );
+ void ContinueInit( TAsyncRequest* aReq );
+
+
+
+
+private: //Request management
+ TInt iOpType;
+ TInt iOpChainPhase;//just a running nummber
+ TInt iOpReturn;//return value from host side calls
+ TRequestStatus iOpStatus;//dummy request status
+ /*
+ * Allocates a new request data structure
+ */
+ TAsyncRequest* AllocRequest( TRequestStatus* aStatus,
+ DThread* aAsyncClient,
+ TAny* aA1,
+ TAny* aA2,
+ TAsyncRequest::TRequestType aRequestType = TAsyncRequest::ERTRequest );
+
+
+
+ /*
+ * Releases a request data structure
+ */
+ void ReleaseRequest( TAsyncRequest* aReq );
+
+ /*
+ * Free request data structures
+ */
+ TAsyncRequestRoot iFreeListRoot;
+
+ /*
+ * Number of free request data structures
+ */
+ TInt iFreeCount;
+
+private:
+
+ TLinearOrder<TPbSId> iPbufferSgMapOrder;
+ TLinearOrder<TVGISId> iVGImageSgMapOrder;
+ //map pbuffer surface handles -> sgImage ID
+ RArray<TPbSId> iPbufferSgMap;
+ RArray<TVGISId> iVGImageSgMap;
+ //The data structs for storing per process&thread information
+ RPointerArray<TPerThreadData> iClientData;
+ //The current client
+ TPerThreadData* iCurrClientData;
+ RArray<TTransactionInfo> iSchedulerInitiatedTransactionIds;
+ TAny* iSchedulerInitiatedTransactionData;
+ // The process- and thread ids to use in driver rfcs
+ // This is needed as the calling thread may be different, while we still want the same
+ // state to remain on the hostside.
+ TUint32 iDriverRfcProcessId;
+ TUint32 iDriverRfcThreadId;
+ //Is egl initialized or not. If not, then it needs to be done before processing any other command
+ TBool iInitialized;
+
+ /// Interface to the hardware.
+ DVirtualVideoHwInterface& iHwInterface;
+
+ /// DFC.
+ TDfc iDfc;
+
+ /// Current interrupt ID.
+ TInt iInterruptId;
+
+ /// Kernel address of the shared chunk.
+ TLinAddr iChunkKernelAddress;
+
+ /// Size of the chunk.
+ TUint32 iChunkSize;
+
+ //Request lists
+ TAsyncRequestRoot iSerializedRequestRoot;
+ TAsyncRequestRoot iPendingRequestRoot;
+
+ /*
+ * Current transaction id
+ */
+ TUint32 iTransactionId;
+
+ /*
+ * Ring buffer for requests
+ */
+ RequestBufferWriter iRequestBuffer;
+
+ };
+
+#endif // DEVICEREQHANDLER_H