diff -r 8f2c3e21aac9 -r 4d1fe4a7ce83 graphics_plat/guestvideodriver_api/ldd/inc/devicereqhandler.h --- /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 +#include +#include + +#include //TSgImageMetaData +#include "sgextension.h"//For SgExtension + +#include "guestvideodriverprotocol.h" +#include "virtualvideohwinterface.h" +#include "remotefunctioncall.h" +#include "requestbuffer.h" +#include "reqhandlerextension.h" + +#include //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 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 iPbufferSgMapOrder; + TLinearOrder iVGImageSgMapOrder; + //map pbuffer surface handles -> sgImage ID + RArray iPbufferSgMap; + RArray iVGImageSgMap; + //The data structs for storing per process&thread information + RPointerArray iClientData; + //The current client + TPerThreadData* iCurrClientData; + RArray 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