diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/AlfDecoderServerClient/src/alfcompositionclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/AlfDecoderServerClient/src/alfcompositionclient.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1141 @@ +/* +* Copyright (c) 2006 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: +* +*/ + +#include +#include + +#include +#include +#include +#include "graphics/surfacemanager.h" +#include "graphics/surface.h" +#include "graphics/surfaceupdateclient.h" +#include "graphics/suerror.h" // KAllScreens + +#include "graphics/surfaceconfiguration.h" // TSurfaceConfiguration + +#include "alflogger.h" + +// --------------------------------------------------------------------------- +// CAlfCompositionClientBaseData::NewL +// --------------------------------------------------------------------------- +// +CAlfCompositionClientBase::CAlfCompositionClientBaseData* + CAlfCompositionClientBase::CAlfCompositionClientBaseData::NewL( + TInt aBufferSize, + RAlfBridgerClient* aClient) + { + CAlfCompositionClientBaseData* me = new (ELeave) CAlfCompositionClientBaseData(); + CleanupStack::PushL(me); + me->ConstructL(aBufferSize, aClient); + CleanupStack::Pop(); + return me; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionClientBaseData::ConstructL +// --------------------------------------------------------------------------- +// +void CAlfCompositionClientBase::CAlfCompositionClientBaseData::ConstructL(TInt /*aBufferSize*/, RAlfBridgerClient* aClient) + { + if (!aClient) + { + iClient = new (ELeave) RAlfBridgerClient(); + iOwnsClient = ETrue; + User::LeaveIfError(iClient->Connect()); + } + else + { + iClient = aClient; + } + } + +// --------------------------------------------------------------------------- +// ~CAlfCompositionClientBaseData +// --------------------------------------------------------------------------- +// +CAlfCompositionClientBase::CAlfCompositionClientBaseData::~CAlfCompositionClientBaseData() + { + if (iOwnsClient && iClient) + { + iClient->Close(); + delete iClient; + } + if (iDeleted) + { + *iDeleted = ETrue; + } + } +// --------------------------------------------------------------------------- +// RequestEventL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionClientBase::RequestEventL(TInt aBufferSize, RAlfBridgerClient* aClient) + { + if (!IsActive()) + { + if (!iData) + { + iData = CAlfCompositionClientBaseData::NewL(aBufferSize, aClient); + } + SetActive(); + iData->iClient->SendAsynchronous(KAlfCompOpRequestEvent,TIpcArgs(&iData->iBuffer), iStatus); + } + } + +// --------------------------------------------------------------------------- +// SendEvent +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionClientBase::SendEvent(TInt aOp, const TAny* aEventData, TInt aEventSize) + { + // Todo, should support batching / asynch + if (!iData) + { + TRAPD(err, iData = CAlfCompositionClientBaseData::NewL(aEventSize, 0)) // basically zero buffer would do + if (err) + { + return err; + } + } + + TPtrC8 ptr(reinterpret_cast(aEventData), aEventSize); + + return iData->iClient->SendSynch(aOp, ptr); + } + +// --------------------------------------------------------------------------- +// HandleEventL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionClientBase::HandleEventL(TInt /*aEventType*/, TAny* /*aEventData*/) + { + } + +// --------------------------------------------------------------------------- +// NullBoolPtr +// --------------------------------------------------------------------------- +// +void NullBoolPtr(TAny* ptr) + { + TBool** boolptr = static_cast(ptr); + *boolptr = 0; + } + +// --------------------------------------------------------------------------- +// RunL +// --------------------------------------------------------------------------- +// +void CAlfCompositionClientBase::RunL() + { + TInt status = iStatus.Int(); + User::LeaveIfError(status); + TBool deleted = EFalse; + iData->iDeleted = &deleted; + CleanupStack::PushL(TCleanupItem(NullBoolPtr, &iData->iDeleted)); + HandleEventL(status, (void*)iData->iBuffer.Ptr()); + CleanupStack::PopAndDestroy(); + if (!deleted) // just small precaution if client deletes itself on callback + { + RequestEventL(sizeof(TInt)); + } + } + +// --------------------------------------------------------------------------- +// DoCancel +// --------------------------------------------------------------------------- +// +void CAlfCompositionClientBase::DoCancel() + { + if (iData) + { + iData->iClient->SendSynch(KAlfCompOpCancelEventRequest, TIpcArgs(Handle()) ); + } + } + +// --------------------------------------------------------------------------- +// RunError +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionClientBase::RunError(TInt aError) + { + RDebug::Print(_L("CAlfCompositionClientBase::RunError( %d )"),aError); + if ( aError == KErrServerTerminated ) + { + RDebug::Print(_L("CAlfCompositionClientBase::RunError - ALF server has died. Everything is lost. Halting.")); + USER_INVARIANT(); + } + return KErrNone; + } + +// --------------------------------------------------------------------------- +// ~CAlfCompositionClientBase +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionClientBase::~CAlfCompositionClientBase() + { + Cancel(); + delete iData; + iData = NULL; + } + +// --------------------------------------------------------------------------- +// SetHandleL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionClientBase::SetHandleL(TInt aHandle) + { + User::LeaveIfError(aHandle); + if (!iData) + { + iData = CAlfCompositionClientBaseData::NewL(sizeof(TInt),0);// basically zero buffer would do + } + iData->iHandle = aHandle; + } + +// --------------------------------------------------------------------------- +// Handle +// --------------------------------------------------------------------------- +// +TInt CAlfCompositionClientBase::Handle() const + { + return iData?iData->iHandle:0; + } + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionCntrlClient* CAlfCompositionCntrlClient::NewL(RAlfBridgerClient* aClient, MAlfCompositionController* aController) + { + CAlfCompositionCntrlClient* me = new (ELeave) CAlfCompositionCntrlClient(aController); + me->RequestEventL(60, aClient); // magic, extent with options + me->SendEvent(KAlfCompositionWServReady,0,0); + return me; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionCntrlClient::~CAlfCompositionCntrlClient() + { + iHostBindingsHash.Close(); + iHostPermittedOpsHash.Close(); + } + +// --------------------------------------------------------------------------- +// HandleEventL +// --------------------------------------------------------------------------- +// +void CAlfCompositionCntrlClient::HandleEventL(TInt aEventType, TAny* aEventData) + { + __ASSERT_DEBUG(iController, USER_INVARIANT()); + + if (aEventType == KAlfCompositionLowOnGraphicsMemory && iController) + { + iController->LowOnGraphicsMemory(); + return; + } + + if (aEventType == KAlfCompositionGoodOnGraphicsMemory && iController) + { + iController->GraphicsMemoryGood(); + return; + } + + TInt* ptr = static_cast(aEventData); + TInt target; + + // find out if target is a host (is binded to some other target) + TInt bindedTarget = 0; + TInt* tempbind = iHostBindingsHash.Find(*ptr); + if(tempbind) + bindedTarget = *tempbind; + TInt32 permittedOps = 0; + if(bindedTarget) + { + target = bindedTarget; + TInt32* tempOps = iHostPermittedOpsHash.Find(*ptr); + if(tempOps) + permittedOps = *tempOps; + } + else + { + target = *ptr; + } + + // SetTargetL is always sent before the actual command. + iController->SetTargetL(target); // When this is composition + + switch (aEventType) + { + case KAlfCompOpCreateToken: + { + break; + } + case KAlfCompOpBindSourceToToken: + { + RDebug::Print(_L("ptr0: %d, Target %d, Flags %d, combinedtarget"), ptr[0], ptr[1], ptr[2]); + if( ptr[1] != 0) // add binding information for new host to given target with permitted operations + { + iHostBindingsHash.Insert(*ptr, ptr[1]); + iHostPermittedOpsHash.Insert(*ptr, ptr[2]); + } + else // remove old host bindings when the host is being deleted. + { + iHostBindingsHash.Remove(*ptr); + iHostPermittedOpsHash.Remove(*ptr); + } + break; + } + case KAlfCompOpCreateSource: + { + iController->CreateTargetL(target, ptr[2], ptr[3]); + break; + } + case KAlfCompOpEnableAlpha: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeAlpha) + { + iController->EnableAlpha(ptr[1]); + } + break; + } + case KAlfCompOpSetOpacity: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeOpacity) + { + TReal32* opacity = /*static_cast<*/(TReal32*)(++ptr); + iController->SetOpacity(*opacity); + } + break; + } + case KAlfCompOpSetRotation: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeRotation) + { + iController->SetRotation(ptr[1]); + } + break; + } + case KAlfCompOpSetZOrder: + { + TInt newToken = 0; + if( ptr[3] != KErrNotFound) + { + newToken = iController->SetOrder(target,ptr[1],ptr[2],ETrue); // top, below, combineTargets + } + else + { + newToken = iController->SetOrder(target,ptr[1],ptr[2],EFalse); // top, below, combineTargets + } + TInt array[] = {ptr[0], newToken, ptr[3]}; // caller session, newToken, secretKey + SendEvent(KAlfCompositionTargetCreated, array, sizeof(array)); + break; + } + + case KAlfCompOpSetExtent: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeExtent) + { + TRect rect(ptr[1],ptr[2],ptr[3],ptr[4]); + TSurfaceId surfaceId; + surfaceId.iInternal[0] = ptr[6]; + surfaceId.iInternal[1] = ptr[7]; + surfaceId.iInternal[2] = ptr[8]; + surfaceId.iInternal[3] = ptr[9]; + iController->SetExtentSurfaceId(surfaceId); + iController->SetExtent(rect, ptr[5]); // rect, screen + } + break; + } + case KAlfCompOpSetSRect: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeExtent) + { + TRect rect(ptr[1],ptr[2],ptr[3],ptr[4]); + iController->SetSourceRect(rect); + } + break; + } + case KAlfComOpSetBackgroundAnim: + { + if ( !bindedTarget || permittedOps & CAlfCompositionHost::EAlfAllowChangeBackgroundAnim) + { + iController->SetIsBackgroundAnim(ptr[1]); + } + break; + } + case KAlfCompOpSessionClosed: + { + iController->DeleteTarget(target); + break; + } + + default: + break; + } + } + +// --------------------------------------------------------------------------- +// RunError +// --------------------------------------------------------------------------- +// +TInt CAlfCompositionCntrlClient::RunError(TInt aError) + { + CAlfCompositionClientBase::RunError(aError); + // reactivate + TRAPD(err, RequestEventL(60)); // magic, extent with options + return err; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAlfCompositionSource::CAlfCompositionSourceData):public CBase + { + public: + static CAlfCompositionSourceData* NewL() + { + CAlfCompositionSourceData* me = new (ELeave) CAlfCompositionSourceData(); + CleanupStack::PushL(me); + // jada + CleanupStack::Pop(); + return me; + } + + ~CAlfCompositionSourceData() + { + if (iDeleted) + { + *iDeleted = ETrue; + } + iObservers.Reset(); + } + + TBool* iDeleted; + TSurfaceId iSurfaceId; + RPointerArray iObservers; + }; + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionSource* CAlfCompositionSource::NewL(RWindow& aClientWindow) + { + CAlfCompositionSource* me = new (ELeave) CAlfCompositionSource(); + CleanupStack::PushL(me); + me->ConstructL(aClientWindow); + CleanupStack::Pop(me); + return me; + } + +// --------------------------------------------------------------------------- +// ~CAlfCompositionSource +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionSource::~CAlfCompositionSource() + { + delete iData; + iData = NULL; + } +// --------------------------------------------------------------------------- +// ConstructL +// --------------------------------------------------------------------------- +// +void CAlfCompositionSource::ConstructL(TInt aWsHandle, TInt aGroupHandle, TInt aScreenNumber) + { + iData = CAlfCompositionSourceData::NewL(); + RDebug::Print(_L("CAlfCompositionClientBase::ConstructL - %d"), iData ); + + User::LeaveIfError( SendEvent(KAlfCompositionSourceScreenNumber, &aScreenNumber, sizeof(TInt))); + + TInt array[] = { 0, aWsHandle, aGroupHandle}; + TInt handle = SendEvent(KAlfCompOpCreateSource, array, sizeof(array)); + SetHandleL(handle); + } + +void CAlfCompositionSource::ConstructL(RWindow& aClientWindow) + { + ConstructL(aClientWindow.ClientHandle(), aClientWindow.WindowGroupId(), aClientWindow.ScreenNumber()); + TSurfaceConfiguration surfaceConfigs; + User::LeaveIfError(aClientWindow.GetBackgroundSurface(surfaceConfigs)); + surfaceConfigs.GetSurfaceId(iData->iSurfaceId); + if(iData->iSurfaceId.IsNull()) + { + __ALFLOGSTRING( "CAlfCompositionSource::NewL - Window does not have background surface set - Leaving"); + User::Leave(KErrNotFound); + } + } + +// --------------------------------------------------------------------------- +// CreatePermissionToken +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::CreatePermissionToken(TInt aKey, TInt aPermissionFlags) + { + TInt array[] = {aKey, aPermissionFlags}; + return SendEvent(KAlfCompOpCreateToken, array, sizeof(array)); + } + +// --------------------------------------------------------------------------- +// EnableAlpha +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::EnableAlpha(TBool aEnable) + { + return SendEvent(KAlfCompOpEnableAlpha, &aEnable, sizeof(TInt)); + } + +// --------------------------------------------------------------------------- +// SetOpacity +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::SetOpacity(TReal32 aOpacity) __SOFTFP + { + return SendEvent(KAlfCompOpSetOpacity, &aOpacity, sizeof(TReal32)); + } + +// --------------------------------------------------------------------------- +// SetRotation +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::SetRotation(TInt aRotationInDegrees) + { + return SendEvent(KAlfCompOpSetRotation, &aRotationInDegrees, sizeof(TInt)); + } + +// --------------------------------------------------------------------------- +// SetZOrder +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::SetZOrder(const CAlfCompositionClientBase& aNode, TBool aAbove, TInt aKey) + { + TInt array[] = {aNode.Handle(), aAbove, aKey}; + return SendEvent(KAlfCompOpSetZOrder, array, sizeof(array)); + } + +// --------------------------------------------------------------------------- +// SetExtent +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::SetExtent(const TRect& aRect, TInt aScreen) + { + TInt array[] = {aRect.iTl.iX,aRect.iTl.iY,aRect.iBr.iX,aRect.iBr.iY, aScreen, + iData->iSurfaceId.iInternal[0], iData->iSurfaceId.iInternal[1], iData->iSurfaceId.iInternal[2], + iData->iSurfaceId.iInternal[3]}; + return SendEvent(KAlfCompOpSetExtent, array, sizeof(array)); + } + +// --------------------------------------------------------------------------- +// SetSourceRect +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionSource::SetSourceRect(const TRect& aRect) + { + TInt array[] = {aRect.iTl.iX,aRect.iTl.iY,aRect.iBr.iX,aRect.iBr.iY}; + return SendEvent(KAlfCompOpSetSRect, array, sizeof(array)); + } + +// --------------------------------------------------------------------------- +// AddCompositionObserverL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionSource::AddCompositionObserverL(MAlfCompositionObserver& aObserver, TInt aScreenNumber) + { + if (iData->iObservers.Count() == 1 || aScreenNumber != 0) + { // TODO: support only single observer for now + // because we can't currently handle deletion of an observer + // during handle event properly (if there were more than one observers present) + User::Leave(KErrNotSupported); + } + + TInt index = iData->iObservers.Find(&aObserver); + if (index == KErrNotFound) + { + iData->iObservers.AppendL(&aObserver); + } + RequestEventL(sizeof(TInt)); // enable notifications if not active yet + } + +// --------------------------------------------------------------------------- +// RemoveObserver +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionSource::RemoveObserver(MAlfCompositionObserver& aObserver) + { + TInt index = iData->iObservers.Find(&aObserver); + if (index != KErrNotFound) + { + iData->iObservers.Remove(index); + } + } + +// --------------------------------------------------------------------------- +// SetIsBackgroundAnim +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionSource::SetIsBackgroundAnim(TBool aIsBg) + { + SendEvent(KAlfComOpSetBackgroundAnim, &aIsBg, sizeof(TBool)); + } + +// --------------------------------------------------------------------------- +// EnableKeyboard +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionSource::EnableKeyboard(TBool aEnable, TInt aScreen) + { + TInt array[] = {aEnable, aScreen}; + SendEvent(KAlfCompOpEnableKb, array, sizeof(array)); + } + +// --------------------------------------------------------------------------- +// HandleEventL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionSource::HandleEventL(TInt aEventType, TAny* aEventData) + { + switch (aEventType) + { + case KAlfCompositionFrameReady: + { + for (TInt i = 0; i < iData->iObservers.Count(); i++) + { + iData->iObservers[i]->FrameReady(*static_cast(aEventData)); // todo multiple screens + } + break; + } + case KAlfCompositionLowOnGraphicsMemory: + { + for (TInt i = 0; i < iData->iObservers.Count(); i++) + { + iData->iObservers[i]->RunningLowOnGraphicsMemory(); // todo multiple screens + } + break; + } + case KAlfCompositionTargetHidden: + { + for (TInt i = 0; i < iData->iObservers.Count(); i++) + { + iData->iObservers[i]->CompositionTargetHidden(); // todo multiple screens + } + break; + } + case KAlfCompositionGoodOnGraphicsMemory: + { + TInt count = iData->iObservers.Count(); + for (TInt i = 0; i < count; i++) + { + iData->iObservers[i]->GraphicsMemoryGood(); + } + break; + } + case KAlfCompositionTargetVisible: + { + for (TInt i = 0; i < iData->iObservers.Count(); i++) + { + iData->iObservers[i]->CompositionTargetVisible(); // todo multiple screens + } + break; + } + + default: + break; + } + } + +// --------------------------------------------------------------------------- +// CAlfCompositionHost::NewL +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionHost* CAlfCompositionHost::NewL(TInt aToken, TInt aKey) + { + CAlfCompositionHost* me = new (ELeave) CAlfCompositionHost(); + CleanupStack::PushL(me); + me->ConstructL(aToken, aKey); + CleanupStack::Pop(); + return me; + } + +// --------------------------------------------------------------------------- +// ConstructL +// --------------------------------------------------------------------------- +// +void CAlfCompositionHost::ConstructL(TInt aToken, TInt aKey) + { + iData = CAlfCompositionSourceData::NewL(); + RDebug::Print(_L("CAlfCompositionClientBase::ConstructL - %d"), iData ); + + TInt array[] = { 0, aToken, aKey }; + TInt result = SendEvent(KAlfCompOpBindSourceToToken, array, sizeof(array)); + User::LeaveIfError(result); + SetHandleL(result); + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +NONSHARABLE_CLASS( CSurfaceUpdateCallback ) : public CActive + { + public: + + public: + CSurfaceUpdateCallback( CAlfCompositionPixelSource& aPixelSource, TInt aBufferNumber, + TInt aPriority): CActive(aPriority), iPixelSource(aPixelSource), + iBufferNumber(aBufferNumber) { CActiveScheduler::Add(this); }; + ~CSurfaceUpdateCallback() { Cancel(); }; + public: + + void SetActive() {iStatus = KRequestPending; CActive::SetActive();}; + + void RunL() + { + if( iStatus == KErrNone ) + { + SetActive(); + if( !iPixelSource.DrawFrameL(iStatus, iBufferNumber) ) + { + __ALFLOGSTRING( "CSurfaceUpdateCallBack::RunL - DrawFrameL returned EFalse -> Pause"); + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + Cancel(); + } + } + else + { + __ALFLOGSTRING1("CSurfaceUpdateCallBack::RunL %d", iStatus.Int()); + iPixelSource.Suspend(); + } + + + }; + void DoCancel() { }; + + private: // Data + CAlfCompositionPixelSource& iPixelSource; + TInt iBufferNumber; + }; + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +NONSHARABLE_CLASS(CAlfCompositionPixelSource::CAlfCompositionPixelSourceData):public CBase + { + public: + + enum TPixelSourceStatus + { + EActive = 0, // drawing loop running + EPaused = 1, // drawing paused but resources are still reserved + ESuspended = 2 // drawing suspended and surface related resources freed until activated again + }; + + static CAlfCompositionPixelSourceData* NewL(MAlfBufferProvider& aProvider) + { + CAlfCompositionPixelSourceData* me = new (ELeave) CAlfCompositionPixelSourceData(aProvider); + return me; + } + + + CAlfCompositionPixelSourceData(MAlfBufferProvider& aProvider) : + iProvider( aProvider), iSourceStatus(ESuspended) {iSurfaceId.CreateNullId();} + + ~CAlfCompositionPixelSourceData() + { + if(iWindow && iSourceStatus != ESuspended) + { + iWindow->RemoveBackgroundSurface(ETrue); + } + + if(iSourceStatus != ESuspended) + { + iSurfaceUpdateSession.CancelAllUpdateNotifications(); + } + + iSurfaceUpdateSession.Close(); + + if(iSurfaceManager) + { + iSurfaceManager->CloseSurface(iSurfaceId); + iSurfaceManager->Close(); + delete iSurfaceManager; + } + + if(iSurfaceChunk) + { + iSurfaceChunk->Close(); + delete iSurfaceChunk; + } + + if(iSurfaceUpdateWaiter && iSurfaceUpdateWaiter->IsActive()) + { + iSurfaceUpdateWaiter->Cancel(); + } + delete iSurfaceUpdateWaiter; + + } + MAlfBufferProvider& iProvider; + + TPixelSourceStatus iSourceStatus; + + RSurfaceUpdateSession iSurfaceUpdateSession; + TSurfaceId iSurfaceId; + RSurfaceManager* iSurfaceManager; + RChunk* iSurfaceChunk; + + // Not owned + RWindow* iWindow; + + TUint8* iSurfaceBuffer; + + CSurfaceUpdateCallback* iSurfaceUpdateWaiter; + + TInt iCurrentBuffer; + + TRect iSurfaceRect; + }; + + + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::NewL +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionPixelSource* CAlfCompositionPixelSource::NewL(MAlfBufferProvider& aProvider, RWindow* aWindow) + { + CAlfCompositionPixelSource* me = new (ELeave) CAlfCompositionPixelSource(); + CleanupStack::PushL(me); + me->ConstructL(aProvider, aWindow); + CleanupStack::Pop(me); + return me; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::ActivateL +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionPixelSource::ActivateL() + { + if( !iData->iWindow && iData->iSurfaceId.IsNull() ) + { + User::Leave(KErrNotReady); + } + + if( iData->iSourceStatus == CAlfCompositionPixelSourceData::ESuspended ) + { + MAlfBufferProvider::TBufferCreationAttributes& creationAttribs = iData->iProvider.BufferAttributes(); + + iData->iSurfaceRect = TRect(TPoint(0,0), TSize(creationAttribs.iWidth, creationAttribs.iHeight)); + + ConstructSurfaceL(creationAttribs); + + iData->iWindow->SetBackgroundSurface(iData->iSurfaceId); + + TInt array[] = { 0, iData->iWindow->ClientHandle(), iData->iWindow->WindowGroupId() }; + TInt handle = SendEvent(KAlfCompOpCreateSource, array, sizeof(array)); + CAlfCompositionClientBase::SetHandleL( handle ); + + User::LeaveIfError( iData->iSurfaceUpdateSession.Connect() ); + } + + if( iData->iSourceStatus != CAlfCompositionPixelSourceData::EActive ) + { + if( !iData->iSurfaceUpdateWaiter ) + { + iData->iSurfaceUpdateWaiter = new (ELeave) CSurfaceUpdateCallback( *this, 0, CActive::EPriorityIdle ); + } + + iData->iSurfaceUpdateWaiter->SetActive(); + TRequestStatus* status = &iData->iSurfaceUpdateWaiter->iStatus; + User::RequestComplete(status, KErrNone); + + iData->iProvider.OnActivation(); + iData->iSourceStatus = CAlfCompositionPixelSourceData::EActive; + } + + // do nothing if content was already active + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::Suspend +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfCompositionPixelSource::Suspend() + { + if(iData->iSourceStatus != CAlfCompositionPixelSourceData::ESuspended) + { + iData->iProvider.ContextAboutToSuspend(); + + TInt error = SendEvent(KAlfCompOpSessionClosed,0,0); + + // todo: what if error != KErrNone + + FreeSurface(); + + if(iData->iSurfaceUpdateWaiter && iData->iSurfaceUpdateWaiter->IsActive()) + { + iData->iSurfaceUpdateWaiter->Cancel(); + } + + + iData->iSourceStatus = CAlfCompositionPixelSourceData::ESuspended; + } + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::CAlfCompositionPixelSource +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfCompositionPixelSource::~CAlfCompositionPixelSource() + { + Suspend(); + delete iData; + iData = NULL; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::SetExtent +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfCompositionPixelSource::SetExtent(const TRect& aRect, TInt aScreen) + { + TInt error = KErrNone; + if(iData->iSurfaceId.IsNull() && !iData->iWindow) + { + //create surface as client did not supply window + MAlfBufferProvider::TBufferCreationAttributes& creationAttribs = iData->iProvider.BufferAttributes(); + + iData->iSurfaceRect = TRect(TPoint(0,0), TSize(creationAttribs.iWidth, creationAttribs.iHeight)); + + TRAP(error, ConstructSurfaceL(creationAttribs) ); + + if( error == KErrNone ) + { + error = iData->iSurfaceUpdateSession.Connect(); + iData->iSourceStatus = CAlfCompositionPixelSourceData::EPaused; + } + } + + if( error == KErrNone ) + { + TInt array[] = {aRect.iTl.iX,aRect.iTl.iY,aRect.iBr.iX,aRect.iBr.iY, aScreen, + iData->iSurfaceId.iInternal[0], iData->iSurfaceId.iInternal[1], iData->iSurfaceId.iInternal[2], + iData->iSurfaceId.iInternal[3]}; + error = SendEvent(KAlfCompOpSetExtent, array, sizeof(array)); + } + return error; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::ConstructL +// --------------------------------------------------------------------------- +// +void CAlfCompositionPixelSource::ConstructL(MAlfBufferProvider& aProvider, RWindow* aWindow) + { + iData = CAlfCompositionPixelSourceData::NewL( aProvider ); + TInt screenNumber = KErrNotFound; + if( aWindow ) + { + iData->iWindow = aWindow; + screenNumber = aWindow->ScreenNumber(); + } + else // let's just initialize baseclass and wait for client to call SetExtent + { + iData->iWindow = NULL; + } + // construct the base class + CAlfCompositionSource::ConstructL(0, 0, screenNumber); + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::ConstructSurfaceL +// --------------------------------------------------------------------------- +// +void CAlfCompositionPixelSource::ConstructSurfaceL(MAlfBufferProvider::TBufferCreationAttributes& aCreationAttributes) + { + TSize size(aCreationAttributes.iWidth, aCreationAttributes.iHeight); + + TUidPixelFormat surfaceFormat = EUidPixelFormatUnknown; + switch (aCreationAttributes.iFormat) + { + case MAlfBufferProvider::ESourceFormatRGB_565: + surfaceFormat = EUidPixelFormatRGB_565; + break; + case MAlfBufferProvider::ESourceFormatXRGB_8888: + surfaceFormat = EUidPixelFormatXRGB_8888; + break; + case MAlfBufferProvider::ESourceFormatARGB_8888: + surfaceFormat = EUidPixelFormatARGB_8888; + break; + case MAlfBufferProvider::ESourceFormatARGB_8888_PRE: + surfaceFormat = EUidPixelFormatARGB_8888_PRE; + break; + default: + User::Leave( KErrNotSupported ); + break; + } + + TInt err = KErrNone; + if(!iData->iSurfaceManager) + { + iData->iSurfaceManager = new RSurfaceManager(); + User::LeaveIfNull(iData->iSurfaceManager); + + err = iData->iSurfaceManager->Open(); + User::LeaveIfError(err); + + RSurfaceManager::TSurfaceCreationAttributesBuf attributes; + attributes().iPixelFormat = surfaceFormat; + attributes().iSize = size; + attributes().iBuffers = 1; + attributes().iStride = aCreationAttributes.iStride; + attributes().iAlignment = aCreationAttributes.iAlignment; + attributes().iContiguous = ETrue; + attributes().iMappable = ETrue; + + // Create surface + err = iData->iSurfaceManager->CreateSurface(attributes, iData->iSurfaceId); + User::LeaveIfError(err); + } + + if(!iData->iSurfaceChunk) + { + // Map to chunk + iData->iSurfaceChunk = new RChunk(); + User::LeaveIfNull(iData->iSurfaceChunk); + err = iData->iSurfaceManager->MapSurface(iData->iSurfaceId, *iData->iSurfaceChunk); + User::LeaveIfError(err); + } + + // Get the info from the surfaceManager + RSurfaceManager::TInfoBuf info; + err = iData->iSurfaceManager->SurfaceInfo(iData->iSurfaceId, info); + User::LeaveIfError(err); + RSurfaceManager::TSurfaceInfoV01 surfaceInfo = info(); + aCreationAttributes.iStride = surfaceInfo.iStride; + + TInt offset = 0; + iData->iSurfaceManager->GetBufferOffset(iData->iSurfaceId, 0, offset); + + // Store pointer to the pixel data + iData->iSurfaceBuffer = iData->iSurfaceChunk->Base() + offset; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::FreeSurface +// --------------------------------------------------------------------------- +// +void CAlfCompositionPixelSource::FreeSurface() + { + if(iData->iWindow && iData->iSourceStatus != CAlfCompositionPixelSourceData::ESuspended) + { + iData->iWindow->RemoveBackgroundSurface(ETrue); + iData->iWindow->Session()->Flush(); + } + + if(iData->iSourceStatus != CAlfCompositionPixelSourceData::ESuspended) + { + iData->iSurfaceUpdateSession.CancelAllUpdateNotifications(); + } + iData->iSurfaceUpdateSession.Close(); + + if(iData->iSurfaceManager) + { + iData->iSurfaceManager->CloseSurface(iData->iSurfaceId); + iData->iSurfaceManager->Close(); + delete iData->iSurfaceManager; + iData->iSurfaceManager = NULL; + } + + iData->iSurfaceId = TSurfaceId::CreateNullId(); + + if(iData->iSurfaceChunk) + { + iData->iSurfaceChunk->Close(); + delete iData->iSurfaceChunk; + iData->iSurfaceChunk = NULL; + } + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::Buffer +// --------------------------------------------------------------------------- +// +TUint8* CAlfCompositionPixelSource::Buffer(TInt /*aBufferNumber*/) + { + return iData->iSurfaceBuffer; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::DrawFrameL +// --------------------------------------------------------------------------- +// +TBool CAlfCompositionPixelSource::DrawFrameL(TRequestStatus& aStatus, TInt aBufferNumber) + { + // Region indicates the currently visible region of the surface. The information is not yet available. + RRegion region; + region.AddRect(iData->iSurfaceRect); + TUint8* buffer = Buffer(aBufferNumber); + TBool draw = iData->iProvider.ProduceNewFrameL(region, buffer); + if(draw) + { + iData->iSurfaceUpdateSession.NotifyWhenAvailable(aStatus); + + iData->iSurfaceUpdateSession.SubmitUpdate(KAllScreens, iData->iSurfaceId, aBufferNumber); + } + else + { + iData->iSourceStatus = CAlfCompositionPixelSourceData::EPaused; + } + region.Close(); + return draw; + } + +// --------------------------------------------------------------------------- +// CAlfCompositionPixelSource::HandleEventL +// --------------------------------------------------------------------------- +// +void CAlfCompositionPixelSource::HandleEventL(TInt aEventType, TAny* aEventData) + { + switch (aEventType) + { + case KAlfCompositionFrameReady: + { + // do nothing for now + } + break; + case KAlfCompositionLowOnGraphicsMemory: + case KAlfCompositionTargetHidden: + { + // suspend drawing + Suspend(); + } + break; + default: + break; + } + // call base class + CAlfCompositionSource::HandleEventL( aEventType, aEventData ); + } + +//end of file