--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicscomposition/surfaceupdate/tsrc/tcompositionbackend.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,397 @@
+// Copyright (c) 2006-2009 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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code
+*/
+
+#include <e32std.h>
+#include "tcompositionbackend.h"
+#include <graphics/suerror.h>
+
+const TInt KNotificationsAtTime = 10; //how many notifications could be processed at a time, varies from 1...
+
+CTContentUpdateReceiver::CTContentUpdateReceiver(TInt aScreen) :
+ iScreen(aScreen), iVisible(ETrue)
+ {
+ RThread thread;
+ iReceiverThreadId = thread.Id();
+ }
+
+CTContentUpdateReceiver::~CTContentUpdateReceiver()
+ {
+ if(iPeriodic)
+ iPeriodic->Cancel();
+ delete iPeriodic;
+ iLock.Close();
+ iPriorityLock.Close();
+ }
+
+void CTContentUpdateReceiver::ConstructL()
+ {
+ TCallBack callback(CallBack);
+ callback.iPtr = this;
+ User::LeaveIfError(iLock.CreateLocal());
+ User::LeaveIfError(iPriorityLock.CreateLocal(0));
+ iPeriodic= CPeriodic::NewL(CPeriodic::EPriorityStandard);
+ iPeriodic->Start(TTimeIntervalMicroSeconds32(0),TTimeIntervalMicroSeconds32(KCompositionInterval), callback);
+ }
+
+CTContentUpdateReceiver* CTContentUpdateReceiver::NewL(TInt aScreen)
+ {
+ CTContentUpdateReceiver* receiver = new (ELeave) CTContentUpdateReceiver(aScreen);
+ CleanupStack::PushL(receiver);
+ receiver->ConstructL();
+ CleanupStack::Pop();
+ return receiver;
+ }
+
+TInt CTContentUpdateReceiver::Extension_(TUint aExtensionId, TAny*& aRetIface, TAny* a1)
+ {
+ switch (aExtensionId)
+ {
+ case MCompositionSurfaceUpdate::ETypeId:
+ aRetIface= static_cast<MCompositionSurfaceUpdate*>(this);
+ return KErrNone;
+
+ default: ;
+ }
+ return CExtensionContainer::Extension_(aExtensionId,aRetIface,a1);
+ }
+
+TInt CTContentUpdateReceiver::CallBack(TAny *aAny)
+ {
+ return (static_cast <CTContentUpdateReceiver*> (aAny))->CheckNewNotifications();
+ }
+
+void CTContentUpdateReceiver::Stop()
+ {
+ iLock.Wait();
+ iStop = ETrue;
+ iLock.Signal();
+ }
+
+EXPORT_C void CTContentUpdateReceiver::SetVisible(TBool aVisible)
+ {
+ iLock.Wait();
+ iVisible = aVisible;
+ iLock.Signal();
+ }
+
+TInt CTContentUpdateReceiver::CheckNewNotifications()
+ {
+ iLock.Wait();
+ if(iStop && (iNumberElements <= 0))
+ {
+ iLock.Signal();
+ CActiveScheduler::Stop();
+ return 0;//the return value is irrelevant for CPeriodic function
+ }
+ if(iSetInternalPriority)
+ {
+ TRAPD(res, DoSetInternalPriorityL());
+ iLock.Signal();
+ __ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
+ return 0;//the return value is irrelevant for CPeriodic function
+ }
+ TInt index = 0;
+ RThread thread;
+ TInt res = thread.Open(iThreadId);
+ __ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
+
+ //we will check only one limited amount of requests at the time
+ for(TInt iteration = 0; (iNumberElements > index) && (iteration < KNotificationsAtTime); iteration++)
+ {
+ if(iArray[index].iType == EReqDisplayed)
+ {
+ *(iArray[index].iTimeStamp) = User::FastCounter();
+ if(iCompositionOrder)
+ {
+ iCompositionOrder->SetOrder(EOrderComposition);
+ }
+ }
+ else if(iArray[index].iType == EReqDisplayedXTimes)
+ {
+ iArray[index].iDisplayedXTimes--;
+ if(iArray[index].iDisplayedXTimes > 0)
+ {
+ index++;
+ continue;
+ }
+ }
+ TRequestStatus* status = iArray[index].iStatus;
+ res = iVisible ? KErrNone : KErrNotVisible;
+ Remove(index);
+ thread.RequestComplete(status, res);
+ }
+ thread.Close();
+ iLock.Signal();
+ return 0;//the return value is irrelevant for CPeriodic function
+ }
+
+void CTContentUpdateReceiver::DoSetInternalPriorityL()
+ {
+ RThread thread;
+ User::LeaveIfError(thread.Open(iReceiverThreadId));
+ thread.SetPriority(iInternalPriority);
+ thread.Close();
+ TInt compositionInterval = KCompositionInterval;
+ CPeriodic::TPriority priority = CPeriodic::EPriorityStandard;
+ if(iInternalPriority < EPriorityNormal)
+ {
+ priority = CPeriodic::EPriorityIdle;
+ compositionInterval = KCompositionIntervalLong;
+ }
+ else if (iInternalPriority > EPriorityNormal)
+ {
+ priority = CPeriodic::EPriorityHigh;
+ compositionInterval = KCompositionIntervalShort;
+ }
+
+ TCallBack callback(CallBack);
+ callback.iPtr = this;
+ iPeriodic->Cancel();
+ delete iPeriodic;
+ iPeriodic= CPeriodic::NewL(priority);
+ iPeriodic->Start(TTimeIntervalMicroSeconds32(compositionInterval),TTimeIntervalMicroSeconds32(compositionInterval), callback);
+ iSetInternalPriority = EFalse;
+ iPriorityLock.Signal();
+ }
+
+EXPORT_C TInt CTContentUpdateReceiver::SetInternalPriority(TThreadPriority aInternalPriority)
+ {
+ iLock.Wait();
+ iInternalPriority = aInternalPriority;
+ iSetInternalPriority = ETrue;
+ iLock.Signal();
+
+ //wait for the priority changes takes place
+ iPriorityLock.Wait();
+ return KErrNone;
+ }
+
+void CTContentUpdateReceiver::ContentUpdated(const TSurfaceId& aId,
+ TInt aBuffer,
+ const TRegion* aRegion,
+ TRequestStatus* aStatusAvailable,
+ TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
+ TRequestStatus* aStatusDisplayedXTimes, TInt* aDisplayedXTimes)
+ {
+ (TAny)&aId;
+ (TAny)aBuffer;
+ (TAny)aRegion;
+
+ iLock.Wait();
+ if(iStop)
+ {
+ if(aStatusAvailable)
+ {
+ User::RequestComplete(aStatusAvailable, KErrDied);
+ }
+ if(aStatusDisplayed)
+ {
+ User::RequestComplete(aStatusDisplayed, KErrDied);
+ }
+ if(aStatusDisplayedXTimes)
+ {
+ User::RequestComplete(aStatusDisplayedXTimes, KErrDied);
+ }
+ iLock.Signal();
+ return;
+ }
+
+ RThread thread;
+ iThreadId = thread.Id();
+
+ if(aStatusAvailable)
+ {
+ Add(aStatusAvailable, EReqAvailable);
+ }
+ if(aStatusDisplayed)
+ {
+ Add(aStatusDisplayed, EReqDisplayed, 0, aTimeStamp);
+ }
+ if(aStatusDisplayedXTimes)
+ {
+ Add(aStatusDisplayedXTimes, EReqDisplayedXTimes, *aDisplayedXTimes);
+ }
+ iLock.Signal();
+ }
+
+/**
+ Add notification to the list. The function is called from the SUS thread.
+ The client of this API must use a lock mechanizm to preserve data integrity.
+*/
+TInt CTContentUpdateReceiver::Add(TRequestStatus *aStatus, RequestType aType,
+ TInt aDisplayedXTimes, TUint32* aTimeStamp)
+ {
+ TInt index = iNumberElements;
+ TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
+ if(index >= max)
+ return KErrOverflow;
+
+ iArray[index].iStatus = aStatus;
+ iArray[index].iType = aType;
+ iArray[index].iDisplayedXTimes = aDisplayedXTimes;
+ iArray[index].iTimeStamp = aTimeStamp;
+
+ iNumberElements++;
+ return KErrNone;
+ }
+
+/**
+ Remove notification from the list.
+ The function is called from the backend thread.
+ The client of this API must use a lock mechanizm to preserve data integrity.
+*/
+void CTContentUpdateReceiver::Remove(TInt aIndex)
+ {
+ TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
+ if((aIndex < 0) || (aIndex >= max))
+ return;
+
+ iNumberElements--;
+ if(aIndex < iNumberElements)
+ {
+ Mem::Move(&iArray[aIndex], &iArray[aIndex + 1], (iNumberElements - aIndex) * sizeof(RequestObject));
+ iArray[iNumberElements].iType= EReqEmpty;
+ }
+ else
+ {
+ iArray[aIndex].iType = EReqEmpty;
+ }
+ }
+
+TInt CTContentUpdateReceiver::ThreadFunction(TAny* aAny)
+ {
+ // get clean-up stack
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ RThread thread;
+ _LIT(KTestReceiver, "TestReceiver");
+ __ASSERT_ALWAYS(cleanup!=NULL, thread.Panic( KTestReceiver, KErrNoMemory));
+
+ // create an active scheduler and server
+ CActiveScheduler *pA = new CActiveScheduler;
+ __ASSERT_ALWAYS(pA != NULL, thread.Panic( KTestReceiver, KErrNoMemory));
+
+ //Install the active scheduler
+ CActiveScheduler::Install(pA);
+
+ CTContentUpdateReceiver *pCB = NULL;
+ TInt screen = * (static_cast <TInt*> (aAny));
+ TRAPD(err, pCB = CTContentUpdateReceiver::NewL(screen));
+ __ASSERT_ALWAYS(err == KErrNone, thread.Panic( KTestReceiver, err));
+
+ *(static_cast <CTContentUpdateReceiver**> (aAny)) = pCB;
+
+ // Let everyone know that we are ready to
+ // deal with requests.
+ RThread::Rendezvous(KErrNone);
+ // And start fielding requests from client(s).
+ CActiveScheduler::Start();
+
+ // Tidy up...
+ delete pCB;
+ delete pA;
+ delete cleanup;
+
+ return KErrNone;
+ }
+
+_LIT(KMaskBackend, "CompositionBackend_%d");
+const TUint KDefaultHeapSize=0x10000;
+
+EXPORT_C TInt StartTestUpdateReceiver(CTContentUpdateReceiver*& aReceiver, TInt aScreen)
+ {
+ RThread compositionThread;
+ TInt res = KErrGeneral;
+ TBuf<64> contentUpdateReceiverThreadName;
+ TBuf<64> contentUpdateReceiverThreadMask;
+
+ // Guarantee uniqueness of thread name by using timestamp
+ TTime tm;
+ TBuf<32> timeStamp;
+ tm.UniversalTime();
+ TRAP(res, tm.FormatL(timeStamp, _L("_%H%T%S%C")));
+ if(res != KErrNone)
+ {
+ return res;
+ }
+
+ contentUpdateReceiverThreadName.Format(KMaskBackend, aScreen);
+ contentUpdateReceiverThreadName.Append(timeStamp);
+ contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
+ contentUpdateReceiverThreadMask.Insert(0, _L("*"));
+ TFindThread findThread(contentUpdateReceiverThreadMask);
+ TFullName name;
+ // Need to check that the thread exists.
+ if (findThread.Next(name)!=KErrNone)
+ {
+ aReceiver = reinterpret_cast <CTContentUpdateReceiver*> (aScreen);
+
+ // Create the thread for the server.
+ res = compositionThread.Create(contentUpdateReceiverThreadName,
+ CTContentUpdateReceiver::ThreadFunction,
+ KDefaultStackSize,
+ KDefaultHeapSize,
+ KDefaultHeapSize,
+ (TAny*) &aReceiver
+ );
+
+ // The thread has been created OK so get it started - however
+ // we need to make sure that it has started before we continue.
+ if (res==KErrNone)
+ {
+ TRequestStatus rendezvousStatus;
+ compositionThread.SetPriority(EPriorityNormal);
+ compositionThread.Rendezvous(rendezvousStatus);
+ compositionThread.Resume();
+ User::WaitForRequest(rendezvousStatus);
+ res = rendezvousStatus.Int();
+ }
+ }
+ compositionThread.Close();
+ return res;
+ }
+
+EXPORT_C void CloseTestUpdateReceiver(CTContentUpdateReceiver* aReceiver)
+ {
+ if(!aReceiver)
+ return;
+
+ TBuf<64> contentUpdateReceiverThreadName;
+ contentUpdateReceiverThreadName.Format(KMaskBackend, aReceiver->Screen());
+ TBuf<64> contentUpdateReceiverThreadMask;
+ contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
+ contentUpdateReceiverThreadMask.Insert(0, _L("*"));
+ contentUpdateReceiverThreadMask.Append('*');
+ TFindThread findThread(contentUpdateReceiverThreadMask);
+ TFullName name;
+ RThread thread;
+ if((findThread.Next(name)!=KErrNone) ||
+ (thread.Open(findThread) != KErrNone))
+ {
+ thread.Close();
+ return;
+ }
+ TRequestStatus status;
+ thread.Logon(status);
+ if(aReceiver)
+ aReceiver->Stop();
+ User::WaitForRequest(status);
+ thread.Close();
+ }