--- a/windowing/windowserver/nga/SERVER/SERVER.CPP Mon Mar 15 12:45:41 2010 +0200
+++ b/windowing/windowserver/nga/SERVER/SERVER.CPP Wed Mar 31 23:34:07 2010 +0300
@@ -19,7 +19,6 @@
#include "panics.h"
#include "wstop.h"
#include "EVENT.H"
-#include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
#include <bitdraw.h>
#include <hal.h>
#include "inifile.h"
@@ -107,6 +106,8 @@
void OnActive();
void ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen);
void DoRedrawNow(MWsScreen& aScreen);
+ void DoRedrawNow(MWsScreen& aScreen, MWsAnimationScheduler::MScreenUpdateObserver& aObserver);
+ void ClearScreenUpdateObserver(const MWsAnimationScheduler::MScreenUpdateObserver& aObserver);
private:
static TBool OnIdleCallBack(TAny* aAny);
void ScheduleUpdate (TInt aScreenNumber, TBool aForce);
@@ -142,6 +143,8 @@
~CScreenState();
void SetActive ();
+ void WaitForRedraws(MWsAnimationScheduler::MScreenUpdateObserver& aObserver, TInt aNumRedraws);
+ void ClearScreenUpdateObserver(const MWsAnimationScheduler::MScreenUpdateObserver& aObserver);
CPeriodic* iUpdateOn;
TTime iExpectedTickTime;
TScreenUpdateDetails iScreenUpdateDetails;
@@ -151,6 +154,8 @@
private:
CScreenState (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal);
void ConstructL ();
+ void ReleaseRemainingClients();
+ void ReleaseClientsWaitingFor(TUint aCurrentFrame);
void RunL();
void DoCancel()
@@ -158,6 +163,18 @@
TRequestStatus* tmpTRS = &iStatus;
User::RequestComplete(tmpTRS, KErrNone);
};
+ class TWaitingClient
+ {
+ public:
+ TWaitingClient(MWsAnimationScheduler::MScreenUpdateObserver& aObserver, TInt aTargetFrame)
+ : iObserver(aObserver), iTargetFrame(aTargetFrame)
+ {
+ }
+ MWsAnimationScheduler::MScreenUpdateObserver& iObserver;
+ TUint iTargetFrame;
+ };
+ TUint iFrameCount;
+ RArray<TWaitingClient> iWaitingClients;
};
// If using the default animation scheduler on a device, these two numbers may be worth tweaking in the inifile
@@ -275,6 +292,7 @@
void CWindowServer::CDefaultAnimationScheduler::CScreenState::ConstructL ()
{
iUpdateOn = CPeriodic::NewL(EComposeCompletePriority);
+ iWaitingClients.ReserveL(8);
CActiveScheduler::Add(this);
}
@@ -283,19 +301,91 @@
CActive::Cancel();
iInvalidated.Close();
delete iUpdateOn;
+ TInt i = iWaitingClients.Count();
+ while(i--)
+ {
+ iWaitingClients[i].iObserver.ScreenUpdateComplete(KErrAbort);
+ }
+ iWaitingClients.Close();
}
void CWindowServer::CDefaultAnimationScheduler::CScreenState::SetActive()
{
CActive::SetActive ();
}
-
+
+/**
+This function is called from CWsClient d'tor to make sure we will not hang on to any deleted objects.
+*/
+void CWindowServer::CDefaultAnimationScheduler::CScreenState::ClearScreenUpdateObserver(const MWsAnimationScheduler::MScreenUpdateObserver& aObserver)
+ {
+ const TInt count = iWaitingClients.Count();
+ for(TInt i = count-1 ; i >= 0; i--)
+ {
+ if( &aObserver == &(iWaitingClients[i].iObserver) )
+ {
+ TWaitingClient& client = iWaitingClients[i];
+ client.iObserver.ScreenUpdateComplete(KErrCancel);
+ iWaitingClients.Remove(i);
+ }
+ }
+ }
+
+void CWindowServer::CDefaultAnimationScheduler::CScreenState::WaitForRedraws(MWsAnimationScheduler::MScreenUpdateObserver& aObserver, TInt aNumRedraws)
+ {
+ const TUint targetFrame = iFrameCount + aNumRedraws;
+ TWaitingClient request(aObserver, targetFrame);
+ TInt err = iWaitingClients.Append(request);
+ if(err != KErrNone)
+ {
+ //If OOM and already have 8 waiting clients we will not accept a 9th client
+ aObserver.ScreenUpdateComplete(KErrNoMemory);
+ }
+ }
+
+void CWindowServer::CDefaultAnimationScheduler::CScreenState::ReleaseRemainingClients()
+ {
+ const TInt count = iWaitingClients.Count();
+ for(TInt i = count-1; i >= 0; i--)
+ {
+ TWaitingClient& client = iWaitingClients[i];
+ client.iObserver.ScreenUpdateComplete(KErrNone);
+ iWaitingClients.Remove(i);
+ }
+ }
+
+void CWindowServer::CDefaultAnimationScheduler::CScreenState::ReleaseClientsWaitingFor(TUint aCurrentFrame)
+ {
+ const TInt count = iWaitingClients.Count();
+ for(TInt i = count-1; i >= 0; i--)
+ {
+ TWaitingClient& client = iWaitingClients[i];
+ if(aCurrentFrame >= client.iTargetFrame)
+ {
+ client.iObserver.ScreenUpdateComplete(KErrNone);
+ iWaitingClients.Remove(i);
+ }
+ }
+ }
+
/**
-Invoked when the rendering pipline signals that it is ready to recieve updated.
+Invoked when the rendering pipline signals that it is ready to recieve updates.
*/
void CWindowServer::CDefaultAnimationScheduler::CScreenState::RunL()
{
+ iFrameCount++;
+
+ //Complete any clients waiting for this frame
+ ReleaseClientsWaitingFor(iFrameCount);
+
iScreenUpdateDetails.iScheduler->ProcessUpdateCompletion (iScreenUpdateDetails.iScreenNumber);
+
+ if(!IsActive())
+ {
+ //No further pending frames, release all remaining clients
+ ReleaseRemainingClients();
+ }
+
}
void CWindowServer::CDefaultAnimationScheduler::ProcessUpdateCompletion (TInt aScreenNumber)
@@ -310,6 +400,49 @@
ScheduleUpdate (aScreenNumber, ETrue);
}
+void CWindowServer::CDefaultAnimationScheduler::DoRedrawNow(MWsScreen& aScreen, MWsAnimationScheduler::MScreenUpdateObserver& aObserver)
+ {
+ TInt screenNumber = ScreenNumber (aScreen);
+ TInt redrawCount = 0;
+
+ // redrawCount is the number of times we should wait for redraws to complete.
+ // If a redraw is not currently active then we need to wait (at most) once: for
+ // any outstanding scheduled update to complete.
+ // If a redraw is currently active then we need to wait (at most) twice: once for
+ // the current update to complete, and once for any outstanding scheduled update to complete.
+ if (!iScreenState[screenNumber]->IsActive())
+ {
+ // No animation in progress, so force a redraw of due updates.
+ ScheduleUpdate(screenNumber, ETrue);
+
+ // If there is still nothing drawing, set redrawCount to zero to make sure we do not wait.
+ if (!iScreenState[screenNumber]->IsActive())
+ {
+ redrawCount = 0;
+ aObserver.ScreenUpdateComplete(KErrNone);
+ }
+ else
+ {
+ redrawCount = 1;
+ iScreenState[screenNumber]->WaitForRedraws(aObserver, redrawCount);
+ }
+ }
+ else
+ {
+ redrawCount = 2;
+ iScreenState[screenNumber]->WaitForRedraws(aObserver, redrawCount);
+ }
+ }
+
+void CWindowServer::CDefaultAnimationScheduler::ClearScreenUpdateObserver(const MWsAnimationScheduler::MScreenUpdateObserver& aObserver)
+ {
+ const TInt count = iScreenState.Count();
+ for(TInt screenNumber=0; screenNumber<count; screenNumber++)
+ {
+ iScreenState[screenNumber]->ClearScreenUpdateObserver(aObserver);
+ }
+ }
+
/**
Switch to deactivate animation or drawing (based on setting of iInactivityBehaviour).
See InvokeDueAnimation().
@@ -366,7 +499,7 @@
{
TInt screenNumber = ScreenNumber (aScreen);
TInt redrawCount = 0;
-
+
// redrawCount is the number of times we should wait for redraws to complete.
// If a redraw is not currently active then we need to wait (at most) once: for
// any outstanding scheduled update to complete.
@@ -735,8 +868,7 @@
iDrawerMasterIndex.Close();
delete iDefaultAnimationScheduler;
- iDefaultAnimationScheduler = NULL; //might be called from clients during server destruction
- iCustomAnimationScheduler = NULL; // not owned
+ iDefaultAnimationScheduler = NULL; //might be called from clients during server destruction
}
void CWindowServer::ConstructL()
@@ -799,37 +931,23 @@
/**
Custom Animation Scheduler
*/
-TBool CWindowServer::SetCustomAnimationScheduler(MWsAnimationScheduler* aScheduler)
+TBool CWindowServer::SetCustomAnimationScheduler(MWsAnimationScheduler* /*aScheduler*/)
{
- if(!iCustomAnimationScheduler && aScheduler)
- {
- iCustomAnimationScheduler = aScheduler;
- return ETrue;
- }
return EFalse;
}
TBool CWindowServer::HasCustomAnimationScheduler() const
{
- return !!iCustomAnimationScheduler;
+ return EFalse;
}
-TBool CWindowServer::ClearCustomAnimationScheduler(MWsAnimationScheduler* aCurrentScheduler)
+TBool CWindowServer::ClearCustomAnimationScheduler(MWsAnimationScheduler* /*aCurrentScheduler*/)
{
- if(iCustomAnimationScheduler && (iCustomAnimationScheduler == aCurrentScheduler))
- {
- iCustomAnimationScheduler = NULL;
- return ETrue;
- }
return EFalse;
}
MWsAnimationScheduler* CWindowServer::AnimationScheduler()
{
- if(iCustomAnimationScheduler)
- {
- return iCustomAnimationScheduler;
- }
return iDefaultAnimationScheduler;
}