diff -r 013716db5021 -r d8d95053303a guestrendering/guestvideodriver/api/src/guestvideodriver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/guestrendering/guestvideodriver/api/src/guestvideodriver.cpp Fri Aug 20 18:02:40 2010 +0100 @@ -0,0 +1,254 @@ +// 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: +// Guest Video Driver Implementation + +#include +#include +#include +#include + +#include +#include +#include + +#include "remotefunctioncall.h" +#include "serializedfunctioncall.h" + +// tracing +#ifdef _DEBUG +#include + #define UTIL_TRACE(fmt, args...) RDebug::Printf(fmt, ##args) + #define DRVRPANIC_ASSERT(condition, panic) if (!(condition)) { DriverPanic(panic, #condition, __LINE__); } + #define DRVRPANIC_ASSERT_DEBUG(condition, panic) if (!(condition)) { DriverPanic(panic, #condition, __LINE__); } +#else + #define UTIL_TRACE(fmt, args...) + #define DRVRPANIC_ASSERT(condition, panic) if (!(condition)) { DriverPanic(panic, NULL, __LINE__); } + #define DRVRPANIC_ASSERT_DEBUG(condition, panic) +#endif + +//Max supported request size +const TUint32 KMaxRequestSize( VVI_PARAMETERS_INPUT_MEMORY_SIZE ); + +typedef enum + { + EDriverPanicSendBufferFailed=1, + EDriverPanicInvalidOperationType, + EDriverPanicOperationDataTooBig, + EDriverPanicDriverAlreadyOpen, + EDriverPanicCreateDriverChannelFailed, + EDriverPanicCreateThreadLockFailed, + EDriverPanicSendBufferFnDoesNotHaveThreadLock, + EDriverPanicBufferCommandFnDoesNotHaveThreadLock, + EDriverPanicDriverNotOpenForExecuteCommandFn, + EDriverPanicRequestStatusErrorInExecuteCommandFn, // 10 + EDriverPanicBufferWriteFailed, + } TDriverPanic; + +_LIT(KDriverPanicCategory, "Guest VidDrv"); + +void DriverPanic(TDriverPanic aPanicCode, char* aCondition, TInt aLine) + { + UTIL_TRACE("Guest Video Driver Panic %d for failed Assert (%s), at guestvideodriver.cpp:%d", aPanicCode, aCondition, aLine); + + User::Panic(KDriverPanicCategory, aPanicCode); + } + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::RGuestVideoDriver +// ----------------------------------------------------------------------------- +// +EXPORT_C RGuestVideoDriver::RGuestVideoDriver() : iIsOpen(EFalse), iProcessId(0) + { + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::Open +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RGuestVideoDriver::Open() + { + UTIL_TRACE("RGuestVideoDriver::Open start iProcessId=0x%x, iIsOpen=%d", iProcessId, iIsOpen); + DRVRPANIC_ASSERT(iIsOpen == EFalse, EDriverPanicDriverAlreadyOpen); + iProcessId = RProcess().Id(); + TInt error = iThreadLock.CreateLocal(EOwnerProcess); + DRVRPANIC_ASSERT_DEBUG( error == KErrNone, EDriverPanicCreateThreadLockFailed); + if (!error) + { + error = DoCreate( + GuestVideoDriver::KDeviceName, + TVersion( GuestVideoDriver::KMajorVer, + GuestVideoDriver::KMinorVer, + GuestVideoDriver::KBuildVer ), + KNullUnit, + NULL, + NULL); + DRVRPANIC_ASSERT_DEBUG( error == KErrNone, EDriverPanicCreateDriverChannelFailed); + if (!error) + { + iIsOpen = ETrue; + } + } + UTIL_TRACE("RGuestVideoDriver::Open end iProcessId=0x%x, error=%d", iProcessId, error); + return error; + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::~RGuestVideoDriver +// ----------------------------------------------------------------------------- +// +EXPORT_C RGuestVideoDriver::~RGuestVideoDriver() + { + UTIL_TRACE("RGuestVideoDriver::~RGuestVideoDriver iProcessId=0x%x", iProcessId); + iThreadLock.Close(); + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::ExecuteCommand +// Syncrhonous version with local buffering +// ----------------------------------------------------------------------------- +// +EXPORT_C void RGuestVideoDriver::ExecuteCommand(RemoteFunctionCallData& aRequestData) + { + DRVRPANIC_ASSERT(iIsOpen, EDriverPanicDriverNotOpenForExecuteCommandFn); + DRVRPANIC_ASSERT( (RemoteFunctionCallData::EOpRequestWithReply == aRequestData.Header().iOpType) || + (RemoteFunctionCallData::EOpRequest == aRequestData.Header().iOpType), + EDriverPanicInvalidOperationType); + + //Set thread and process id + aRequestData.SetThreadInformation(iProcessId, RThread().Id()); + TBool sendNow = (RemoteFunctionCallData::EOpRequest != aRequestData.Header().iOpType); + if (!sendNow) + { + iThreadLock.Wait(); + while (!BufferCommand(aRequestData)) + { + // Flush any queued commands & retry + if (iBuffer.Length()) + { + SendBuffer(); + } + else + { // Too big for buffer + sendNow = ETrue; + break; + } + } + iThreadLock.Signal(); + } + + if (sendNow) + { + // Maintain order of operations by flushing queue + iThreadLock.Wait(); + if (iBuffer.Length()) + { + SendBuffer(); + } + iThreadLock.Signal(); + + TRequestStatus status; + TPckg data(aRequestData); + DRVRPANIC_ASSERT(data().SerialisedLength() <= KMaxRequestSize, EDriverPanicOperationDataTooBig); + UTIL_TRACE("RGuestVideoDriver::ExecuteCommand direct send, req length=%d", data().SerialisedLength()); + DoRequest(GuestVideoDriver::ERequestExecuteCommand, status, (TAny*)&data); + User::WaitForRequest(status); + // status <> 0 if write of reply data failed + DRVRPANIC_ASSERT_DEBUG(status.Int() == KErrNone, EDriverPanicRequestStatusErrorInExecuteCommandFn); + } + } + +// Flush video Command buffer +EXPORT_C void RGuestVideoDriver::Flush() + { + iThreadLock.Wait(); + if (iIsOpen && iBuffer.Length()) + { + SendBuffer(); + } + iThreadLock.Signal(); + } + + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::BufferCommand +// ----------------------------------------------------------------------------- +// +TBool RGuestVideoDriver::BufferCommand( RemoteFunctionCallData& aRequestData ) + { + DRVRPANIC_ASSERT_DEBUG(iThreadLock.IsHeld(), EDriverPanicBufferCommandFnDoesNotHaveThreadLock); + TBool result = EFalse; + SerializedFunctionCall data( aRequestData ); + + const TUint32 len = aRequestData.SerialisedLength(); + const TInt alignmentAdjIndex( RemoteFunctionCallData::AlignIndex( iBuffer.Length(), 4 ) ); + + if ( (alignmentAdjIndex + len) < iBuffer.MaxLength() ) + { + //There is enough space left on local buffer + iBuffer.SetLength( alignmentAdjIndex + len ); + TPtrC8 serialisedDataPtr = iBuffer.Right( len ); + TInt wlen = data.WriteToBuffer( const_cast(serialisedDataPtr.Ptr()), len, 0 ); + DRVRPANIC_ASSERT(wlen == len, EDriverPanicBufferWriteFailed); + result = ETrue; + } + + UTIL_TRACE("RGuestVideoDriver::BufferCommand length=%d, Req len=%d, result=%d", + iBuffer.Length(), len, result); + return result; + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::MapToHWAddress +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RGuestVideoDriver::MapToHWAddress( const TInt aChunkHandle, TUint32& aHWAddress ) + { + TPckgBuf handle( aChunkHandle ); + TPckg address( aHWAddress ); + return DoControl( GuestVideoDriver::ERequestMapAddress, (TAny*)&handle, (TAny*)&address ); + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::EglGetSgHandles +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RGuestVideoDriver::EglGetSgHandles( const TUint64 aId, TUint64 *aSgHandles ) + { + TPckg sgId( aId ); + TPckg sgHandles( *aSgHandles ); + return DoControl( GuestVideoDriver::ERequestSgHandles, (TAny*)&sgId, (TAny*)&sgHandles ); + } + +// ----------------------------------------------------------------------------- +// RGuestVideoDriver::SendBuffer +// ----------------------------------------------------------------------------- +// +void RGuestVideoDriver::SendBuffer() + { + UTIL_TRACE("RGuestVideoDriver::SendBuffer length=%d", iBuffer.Length()); + DRVRPANIC_ASSERT_DEBUG(iThreadLock.IsHeld(), EDriverPanicSendBufferFnDoesNotHaveThreadLock); + TRequestStatus status; + + DoRequest(GuestVideoDriver::ERequestLoadCommands, status, (TAny*)&iBuffer); + + User::WaitForRequest( status ); + + iBuffer.Zero(); + UTIL_TRACE("RGuestVideoDriver::SendBuffer status=%d", status.Int()); + // Commands expecting a reply should never come through here, so status should always be KErrNone + DRVRPANIC_ASSERT(status.Int() == KErrNone, EDriverPanicSendBufferFailed); + }