mRunning( FALSE ),
mUpdateRenderRunCount( 0 ),
mDestroyUpdateRenderThread( FALSE ),
+ mUpdateRenderThreadCanSleep( FALSE ),
+ mPendingRequestUpdate( FALSE ),
mNewSurface( NULL ),
mPostRendering( FALSE )
{
RunUpdateRenderThread( CONTINUOUS, false /* No animation progression */ );
}
+
+ ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition );
+ mPendingRequestUpdate = TRUE;
}
void CombinedUpdateRenderController::RequestUpdateOnce()
{
ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
mUpdateRenderRunCount = numberOfCycles;
+ mUpdateRenderThreadCanSleep = FALSE;
mUseElapsedTimeAfterWait = useElapsedTime;
LOG_COUNTER_EVENT( "mUpdateRenderRunCount: %d, mUseElapsedTimeAfterWait: %d", mUpdateRenderRunCount, mUseElapsedTimeAfterWait );
mUpdateRenderThreadWaitCondition.Notify( lock );
bool CombinedUpdateRenderController::IsUpdateRenderThreadPaused()
{
ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
- return mUpdateRenderRunCount != CONTINUOUS; // Report paused if NOT continuously running
+ return ( mUpdateRenderRunCount != CONTINUOUS ) || // Report paused if NOT continuously running
+ mUpdateRenderThreadCanSleep; // Report paused if sleeping
}
void CombinedUpdateRenderController::ProcessSleepRequest()
--mUpdateRequestCount;
}
- // Only sleep if our update-request count is 0
+ // Can sleep if our update-request count is 0
+ // Update/Render thread can choose to carry on updating if it determines more update/renders are required
if( mUpdateRequestCount == 0 )
{
LOG_EVENT( "Going to sleep" );
- PauseUpdateRenderThread();
+ ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
+ mUpdateRenderThreadCanSleep = TRUE;
}
}
LOG_UPDATE_RENDER( "THREAD INITIALISED" );
bool useElapsedTime = true;
+ bool updateRequired = true;
- while( UpdateRenderReady( useElapsedTime ) )
+ while( UpdateRenderReady( useElapsedTime, updateRequired ) )
{
LOG_UPDATE_RENDER_TRACE;
! renderStatus.NeedsUpdate() )
{
mSleepTrigger->Trigger();
+ updateRequired = false;
LOG_UPDATE_RENDER( "Sleep Triggered" );
}
+ else
+ {
+ updateRequired = true;
+ }
//////////////////////////////
// FRAME TIME
mEnvironmentOptions.UnInstallLogFunction();
}
-bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime )
+bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bool updateRequired )
{
useElapsedTime = true;
ConditionalWait::ScopedLock updateLock( mUpdateRenderThreadWaitCondition );
- while( ! mUpdateRenderRunCount && // Should try to wait if event-thread has paused the Update/Render thread
+ while( ( ! mUpdateRenderRunCount || // Should try to wait if event-thread has paused the Update/Render thread
+ ( mUpdateRenderThreadCanSleep && ! updateRequired && ! mPendingRequestUpdate ) ) && // Ensure we wait if we're supposed to be sleeping AND do not require another update
! mDestroyUpdateRenderThread && // Ensure we don't wait if the update-render-thread is supposed to be destroyed
! mNewSurface ) // Ensure we don't wait if we need to replace the surface
{
+ LOG_UPDATE_RENDER( "WAIT: mUpdateRenderRunCount: %d", mUpdateRenderRunCount );
+ LOG_UPDATE_RENDER( " mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
+ LOG_UPDATE_RENDER( " mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread );
+ LOG_UPDATE_RENDER( " mNewSurface: %d", mNewSurface );
+
mUpdateRenderThreadWaitCondition.Wait( updateLock );
if( ! mUseElapsedTimeAfterWait )
}
}
- mUseElapsedTimeAfterWait = FALSE;
+ LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderRunCount: %d", mUpdateRenderRunCount );
+ LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
+ LOG_COUNTER_UPDATE_RENDER( "mDestroyUpdateRenderThread: %d", mDestroyUpdateRenderThread );
+ LOG_COUNTER_UPDATE_RENDER( "mNewSurface: %d", mNewSurface );
- LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderRunCount: %d", mUpdateRenderRunCount );
+ mUseElapsedTimeAfterWait = FALSE;
+ mUpdateRenderThreadCanSleep = FALSE;
+ mPendingRequestUpdate = FALSE;
// If we've been asked to run Update/Render cycles a finite number of times then decrement so we wait after the
// requested number of cycles
/**
* Called by the Update/Render Thread which ensures a wait if required.
*
- * @param[out] useElapsedTime If true when returned, then the actual elapsed time will be used for animation.
- * If false when returned, then there should NOT be any animation progression in the next Update.
+ * @param[out] useElapsedTime If true when returned, then the actual elapsed time will be used for animation.
+ * If false when returned, then there should NOT be any animation progression in the next Update.
+ * @param[in] updateRequired Whether another update is required.
* @return false, if the thread should stop.
*/
- bool UpdateRenderReady( bool& useElapsedTime );
+ bool UpdateRenderReady( bool& useElapsedTime, bool updateRequired );
/**
* Checks to see if the surface needs to be replaced.
volatile int mUpdateRenderRunCount; ///< The number of times Update/Render cycle should run. If -1, then will run continuously (set by the event-thread, read by v-sync-thread).
volatile unsigned int mDestroyUpdateRenderThread; ///< Whether the Update/Render thread be destroyed (set by the event-thread, read by the update-render-thread).
+ volatile unsigned int mUpdateRenderThreadCanSleep; ///< Whether the Update/Render thread can sleep (set by the event-thread, read by the update-render-thread).
+ volatile unsigned int mPendingRequestUpdate; ///< Is set as soon as an RequestUpdate is made and unset when the next update happens (set by the event-thread and update-render thread, read by the update-render-thread).
+ ///< Ensures we do not go to sleep if we have not processed the most recent update-request.
volatile unsigned int mUseElapsedTimeAfterWait; ///< Whether we should use the elapsed time after waiting (set by the event-thread, read by the update-render-thread).