/*
* 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 <alfdecoderserverclient.h>
#include <alfstreamerconsts.h>
#include <uiacceltk/HuiUtil.h>
#include <coemain.h>
#include <alf/alfcompositionclient.h>
#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<const TUint8*>(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<TBool**>(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<TInt*>(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<MAlfCompositionObserver> 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<TInt*>(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