diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/ServerCore/Src/alfstreamerbridge.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/ServerCore/Src/alfstreamerbridge.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,549 @@ +/* +* Copyright (c) 2008 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: Interthread synchronization object +* +*/ + + + +#include +#include +#include "alfstreamerbridge.h" +#include "alfstreamerserver.h" +#include "alflogger.h" + +#ifdef ALF_DEBUG_TRACK_DRAWING +#include "alfcommanddebug.h" +#endif + + +// #define EGL_TALKS_TO_WINDOW_SERVER + +// --------------------------------------------------------------------------- +// constructor +// +// --------------------------------------------------------------------------- +// + +// The priority is EActivePriorityWsEvents+1 instead of CActive::EPriorityHigh to prevent a deadlock +// when AlfredServerThread calling iWsSession.GetEvent(event); from inside CCoeEnv::RunL() while +// wserv was waiting inside CWindowServer::CDefaultAnimationScheduler::DoRedrawNow for Alf to +// complete the TRequestStatus passed to CAlfRenderStage::End. + +CAlfStreamerBridge::CAlfStreamerBridge(MAlfStreamerListener* aObserver):CActive(EActivePriorityWsEvents+1),iObserver(aObserver), iBatchObserver(0), iThread(RThread().Id()) + { + CActiveScheduler::Add(this); + iStatus = KRequestPending; + SetActive(); + TInt err = iQueueSema.CreateLocal(); + + if (err) + { + // Device startup ends here. + __ALFLOGSTRING("Stop the music, we are running without synchronization"); + User::Panic(_L("UI Accelerator"), 1); + } + } + +// --------------------------------------------------------------------------- +// NewL +// +// --------------------------------------------------------------------------- +// +CAlfStreamerBridge* CAlfStreamerBridge::NewL( MAlfStreamerListener* aObserver ) + { + CAlfStreamerBridge* self = new(ELeave)CAlfStreamerBridge( aObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// ConstructL +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::ConstructL() + { + iDataBuf.Create( KInitialVariableBufferSize ); + iDataBuf.SetLength(0); + iStreamerServer = NULL; +#ifdef ALF_DEBUG_TRACK_DRAWING + iCommandDebugger = CAlfCommandDebug::NewL(); +#endif + CHuiEnv::Static()->iSwapObserver = this; + } + +// --------------------------------------------------------------------------- +// destructor +// +// --------------------------------------------------------------------------- +// +CAlfStreamerBridge::~CAlfStreamerBridge() + { + CHuiEnv::Static()->iSwapObserver = 0; + iDataBuf.Close(); + iQueueSema.Close(); +#ifdef ALF_DEBUG_TRACK_DRAWING + delete iCommandDebugger; +#endif + } + +// --------------------------------------------------------------------------- +// SetBatchObserver +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::SetBatchObserver(MAlfBatchObs* aBatchObserver) + { + iBatchObserver = aBatchObserver; + } + +// --------------------------------------------------------------------------- +// Activate +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::Activate() + { + iStatus = KRequestPending; + SetActive(); + } + +// --------------------------------------------------------------------------- +// Trigger +// +// --------------------------------------------------------------------------- +// +TInt CAlfStreamerBridge::Trigger(TInt aStatus) + { + TInt err = KErrNone; + if (!iVarDataAddedButNotPosted) + { + iQueueSema.Wait(); + } + iVarDataAddedButNotPosted = EFalse; // after this point, data may just be lost if posting fails + __ALFLOGSTRING2("CAlfStreamerBridge::Trigger status %d, own request status %d", aStatus, iStatus.Int() ); + if (IsActive() && iStatus == KRequestPending) + { + RThread t; + TInt err = t.Open(iThread); + if (err) + { + __ALFLOGSTRING1( "CAlfStreamerBridge::Trigger() ignore RThread::Open() error: %d", err ); + } + TRequestStatus* status = &iStatus; + __ALFLOGSTRING("CAlfStreamerBridge::Trigger - completing CAlfStreamerBridge"); + t.RequestComplete(status, aStatus); + t.Close(); + } + else + { +#ifdef _DEBUG + if ( IsActive() ) + { + __ALFLOGSTRING("CAlfStreamerBridge::Trigger - already active"); + } + __ALFLOGSTRING("CAlfStreamerBridge::Trigger - appending data"); +#endif + err = iQueue.Append(aStatus); + } + + iQueueSema.Signal(); + __ALFLOGSTRING1("CAlfStreamerBridge::Trigger request status %d", iStatus.Int() ); + return err; + } + +// --------------------------------------------------------------------------- +// AddData +// +// --------------------------------------------------------------------------- +// +TInt CAlfStreamerBridge::AddData( TAlfDecoderServerBindings aOp,TInt aI1,TInt aI2 ,TAny* aPtr ) + { + if (iSwapActive && aOp == EAlfRequestCommitBatch) + { + __ALFLOGSTRING("CAlfStreamerBridge::AddData() just release window server"); + iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE); + return KErrNone; + } + + TInt err = KErrNotFound; + { +#ifdef ALF_DEBUG_TRACK_DRAWING + iCommandDebugger->SetDescription( aOp, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); + __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %S, iQueue.Length = %d", &iCommandDebugger->Text(), iQueue.Count()); + #else + __ALFLOGSTRING2("CAlfStreamerBridge::AddData op %d, iQueue.Length = %d", aOp, iQueue.Count()); + #endif + err = KErrNone; + for(TInt i = 0; i < iMessages.Count(); i++ ) + { + if (iMessages[i].IsEmpty()) + { + iMessages[i].Set(aOp,aI1,aI2,aPtr); + err = Trigger(i); + return err; + } + } + + // No existing (empty) cell was available for recycling, add new cell to array + TAlfBridgerData data; + data.Set(aOp,aI1,aI2,aPtr); + err = iMessages.Append(data); + } + if (!err) + { + err = Trigger(iMessages.Count()-1); + } + else + { + iQueueSema.Signal(); + } + return err; + } + +// --------------------------------------------------------------------------- +// GetData +// +// Note, that this method frees the message entry for reuse. +// --------------------------------------------------------------------------- +// +TAlfBridgerData CAlfStreamerBridge::GetData(TInt aIndex) + { + TAlfBridgerData data; + ASSERT(aIndex <= iMessages.Count()-1); + data = iMessages[aIndex]; + return data; + } + +void CAlfStreamerBridge::PrepareSwap() + { +#ifdef EGL_TALKS_TO_WINDOW_SERVER + __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, flush the queue"); + iSwapActive = ETrue; + if (iStatus.Int() >=0 && iMessages.Count() > iStatus.Int() ) + { + Cancel(); // remove from scheduler + RunL(); // run manually (and activate) + } + __ALFLOGSTRING("CAlfStreamerBridge:: Prepare swap, the queue emptied"); +#endif //#ifdef EGL_TALKS_TO_WINDOW_SERVER + } + +void CAlfStreamerBridge::SwapComplete() + { +#ifdef EGL_TALKS_TO_WINDOW_SERVER + __ALFLOGSTRING("CAlfStreamerBridge:: Swap buffers complete"); + iSwapActive = EFalse; +#endif // #ifdef EGL_TALKS_TO_WINDOW_SERVER + + } + +#ifdef EGL_TALKS_TO_WINDOW_SERVER +void CAlfStreamerBridge::ReleaseWindowServer(TBool aRelease) + { + __ALFLOGSTRING1("CAlfStreamerBridge::ReleaseWindowServer: %d",aRelease); + if (aRelease) + { + iMakeCurrentActive = ETrue; + if (iBatchObserver && !iSwapActive) + { + iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER); + } + } + else + { + iMakeCurrentActive = EFalse; + } +#else +void CAlfStreamerBridge::ReleaseWindowServer(TBool) + { +#endif + } + +void CAlfStreamerBridge::SetWgIdArray(TInt* aArray) + { + iWgArray = aArray; + } + +EXPORT_C TUid CAlfStreamerBridge::FindAppUidForWgId(TInt aWgId) + { + if (iWgArray) + {TInt* ptr = iWgArray; + for (TInt i=0; i<39; i=i+2) // magic + { + if (ptr[i] == aWgId) + { + return TUid::Uid(ptr[i+1]); + } + if (!ptr[i]) + { + break; + } + } + } + return KNullUid; + } + +EXPORT_C TInt CAlfStreamerBridge::FindWgForAppUid(TUid aAppUid) + { + if (iWgArray) + {TInt* ptr = iWgArray; + for (TInt i=0; i<39; i=i+2) // magic + { + if (ptr[i+1] == aAppUid.iUid) + { + return ptr[i]; + } + if (!ptr[i]) + { + break; + } + } + } + return 0; + } + +// --------------------------------------------------------------------------- +// RunL +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::RunL() + { + TInt operation = iMessages[iStatus.Int()].iOp; + +#ifdef ALF_DEBUG_TRACK_DRAWING + iCommandDebugger->SetDescription( operation, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); + __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %S", &iCommandDebugger->Text() ); +#else + __ALFLOGSTRING1("CAlfStreamerBridge::RunL: First op %d", operation); +#endif + switch ( operation ) + { + // Just call back to Alf decoder thread + case EAlfRequestCommitBatch: + case EAlfRequestCommandReadNotification: + case EAlfReleaseTemporaryChunk: + { + if (iBatchObserver) + { + iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 ); + } + iMessages[iStatus.Int()].ResetEntry(); + break; + } + default: + { + // Handle command + __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback"); + iObserver->HandleCallback(iStatus.Int()); + + // For "getters" also call back to Alf decoder thread + if ((operation > EAlfDSGetCommandsStart) && (operation < EAlfDSGetCommandsEnd)) + { + if (iBatchObserver) + { + iBatchObserver->BridgerCallback( operation, iMessages[iStatus.Int()].iInt1 ); + } + } + + iMessages[iStatus.Int()].ResetEntry(); // mark the cell free + } + } + + // Todo: is this kind of burst mode ok, it should be.. + iQueueSema.Wait(); + while (iQueue.Count()) + { + TInt operation2 = iMessages[iQueue[0]].iOp; +#ifdef ALF_DEBUG_TRACK_DRAWING + iCommandDebugger->SetDescription( operation2, R_ALF_BRIDGE_COMMAND_DESCRIPTION_ARRAY ); + __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %S", &iCommandDebugger->Text() ); +#else + __ALFLOGSTRING1("CAlfStreamerBridge:: Queue op %d", operation2 ); +#endif + switch ( operation2 ) + { + case EAlfRequestCommitBatch: + case EAlfRequestCommandReadNotification: + case EAlfReleaseTemporaryChunk: + { + if (iBatchObserver) + { + __ALFLOGSTRING("CAlfStreamerBridge:: calling BATCH observer callback"); + iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 ); + } + iMessages[iQueue[0]].ResetEntry(); + break; + } + default: + { + // Handle command + __ALFLOGSTRING("CAlfStreamerBridge:: calling observer callback"); + iObserver->HandleCallback(iQueue[0]); + + // For "getters" also call back to Alf decoder thread + if ((operation2 > EAlfDSGetCommandsStart) && (operation2 < EAlfDSGetCommandsEnd)) + { + if (iBatchObserver) + { + iBatchObserver->BridgerCallback( operation2, iMessages[iQueue[0]].iInt1 ); + } + } + iMessages[iQueue[0]].ResetEntry(); // mark the cell free + } + } + iQueue.Remove(0); + } + if ( !iItemsInBuffer ) + { + iDataBuf.SetLength(0); + } + + __ALFLOGSTRING1("CAlfStreamerBridge::RunL - activating", iItemsInBuffer); + Activate(); + iQueueSema.Signal(); + __ALFLOGSTRING1("CAlfStreamerBridge::RunL - really really ending", iItemsInBuffer); + } + +// --------------------------------------------------------------------------- +// DoCancel +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::DoCancel() + { + if (iBatchObserver) + { + iBatchObserver->BridgerCanceled(); + } + } + +// --------------------------------------------------------------------------- +// StartNewBlock +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::StartNewBlock() + { + // Queue marker. Basically we could use one new member to assert that there can + // be only one marker + __ALFLOGSTRING1("CAlfStreamerBridge:: Request command read notification, swap active: %d", iSwapActive ); + if ( iSwapActive || iMakeCurrentActive ) + { + __ALFLOGSTRING("CAlfStreamerBridge::StartNewBlock() just release window server"); + iBatchObserver->BridgerCallback(KRELEASEWINDOWSERVER,KRELEASEDBEFOREQUEUE); + return; + } + AddData(EAlfRequestCommitBatch,0,0,0); + } + +// --------------------------------------------------------------------------- +// RequestCommandReadNotification +// +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::RequestCommandReadNotification( TInt aLastReadOffset, TAlfDecoderServerBindings aCommand ) + { + AddData( aCommand, aLastReadOffset, 0, 0); + } + +// --------------------------------------------------------------------------- +// AppendVarDataL +// +// Note, that memory allocation is done only if current buffer is not large enough +// to add an item. +// TODO: The buffers added are not the buffer in optimal way. +// --------------------------------------------------------------------------- +// +EXPORT_C const TAny* CAlfStreamerBridge::AppendVarDataL( TInt aSize, TInt& aIndex ) + { + iQueueSema.Wait(); + // Make sure the length of the allocated data is always divisible by 8 + if ( aSize % 8 != 0 ) + { + __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, size not multiple of 8: %d", aSize ); + aSize = aSize + ( 8 - aSize % 8 ); + } + if ( iDataBuf.Length() + aSize >= iDataBuf.MaxLength() ) + { + TRAPD(err, iDataBuf.ReAllocL( iDataBuf.MaxLength() + KInitialVariableBufferSize )); + if ( err ) + { + __ALFLOGSTRING("CAlfStreamerBridge::AppendVarDataL, realloc failed"); + iQueueSema.Signal(); + return NULL; + } + __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL, new max size: %d", iDataBuf.MaxLength() ); + } + aIndex = iDataBuf.Length(); + iDataBuf.SetLength( iDataBuf.Length() + aSize); + iItemsInBuffer++; + __ALFLOGSTRING1("CAlfStreamerBridge::AppendVarDataL: buflength %d", iDataBuf.Length()); + iVarDataAddedButNotPosted = ETrue; + return iDataBuf.MidTPtr( aIndex ).Ptr(); + } + +// --------------------------------------------------------------------------- +// GetVarDataL +// +// Note, that data is not removed at any point. However it should not be accessed again +// with this method, because that would confuse iItemsInBuffer counter. +// --------------------------------------------------------------------------- +// +const TAny* CAlfStreamerBridge::GetVarDataL( TInt aIndex ) + { + ASSERT( aIndex >= 0 && aIndex < iDataBuf.MaxLength() ); + ASSERT( iItemsInBuffer ); + iItemsInBuffer--; + return iDataBuf.MidTPtr( aIndex ).Ptr(); + } + +EXPORT_C const TAny* CAlfStreamerBridge::AppendEffectsDataL( TInt aSize, TInt& aIndex ) + { + return AppendVarDataL( aSize, aIndex ); + } + +// --------------------------------------------------------------------------- +// GetVarDataL +// +// Note, that data is not removed at any point. However it should not be accessed again +// with this method, because that would confuse iItemsInBuffer counter. +// --------------------------------------------------------------------------- +// +const TAny* CAlfStreamerBridge::GetEffectsDataL( TInt aIndex ) + { + return GetVarDataL(aIndex); + } + +// --------------------------------------------------------------------------- +// SetStreamerServer +// --------------------------------------------------------------------------- +// +void CAlfStreamerBridge::SetStreamerServer( CAlfStreamerServer& aStreamerServer ) + { + iStreamerServer = &aStreamerServer; + } + +// --------------------------------------------------------------------------- +// StreamerServer +// --------------------------------------------------------------------------- +// +CAlfStreamerServer* CAlfStreamerBridge::StreamerServer() + { + return iStreamerServer; + }