diff -r ac96196b945c -r 15986eb6c500 windowing/windowserver/nga/SERVER/SERVER.CPP --- 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 #include #include #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 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; screenNumberClearScreenUpdateObserver(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; }