Simplified ThreadController 98/44198/15
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 1 Jul 2015 16:51:34 +0000 (17:51 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 13 Aug 2015 16:49:12 +0000 (17:49 +0100)
Change-Id: I779591ba17b1789be8832500991631212c34ecbd

26 files changed:
adaptors/base/render-thread.cpp
adaptors/base/render-thread.h
adaptors/base/thread-controller.cpp
adaptors/base/thread-controller.h
adaptors/base/thread-synchronization-debug.h [new file with mode: 0644]
adaptors/base/thread-synchronization.cpp
adaptors/base/thread-synchronization.h
adaptors/base/update-thread.cpp
adaptors/base/update-thread.h
adaptors/base/vsync-notifier.cpp
adaptors/base/vsync-notifier.h
adaptors/common/adaptor-impl.cpp
adaptors/common/gl/gl-implementation.h
adaptors/devel-api/adaptor-framework/render-surface.h
adaptors/integration-api/wayland/ecore-wl-render-surface.h
adaptors/integration-api/wayland/pixmap-render-surface.h
adaptors/integration-api/x11/ecore-x-render-surface.h
adaptors/integration-api/x11/pixmap-render-surface.h
adaptors/wayland/pixmap-render-surface-wl.cpp
adaptors/wayland/window-render-surface-wl.cpp
adaptors/wayland/window-render-surface.h
adaptors/x11/pixmap-render-surface-x.cpp
adaptors/x11/window-render-surface-x.cpp
adaptors/x11/window-render-surface.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h

index 2b4b350..a61e52f 100644 (file)
@@ -84,7 +84,7 @@ bool ReplaceSurfaceRequest::GetReplaceCompleted()
 RenderThread::RenderThread( ThreadSynchronization& sync,
                             AdaptorInternalServices& adaptorInterfaces,
                             const EnvironmentOptions& environmentOptions )
-: mThreadSync( sync ),
+: mThreadSynchronization( sync ),
   mCore( adaptorInterfaces.GetCore() ),
   mGLES( adaptorInterfaces.GetGlesInterface() ),
   mEglFactory( &adaptorInterfaces.GetEGLFactoryInterface()),
@@ -161,78 +161,60 @@ void RenderThread::Stop()
 
 bool RenderThread::Run()
 {
-  // install a function for logging
+  DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run\n");
+
+  // Install a function for logging
   mEnvironmentOptions.InstallLogFunction();
 
   InitializeEgl();
 
-  bool running( true );
-
   Dali::Integration::RenderStatus renderStatus;
+  RenderRequest* request = NULL;
 
-  uint64_t currentTime( 0 );
-
-  // render loop, we stay inside here when rendering
-  while( running )
+  // Render loop, we stay inside here when rendering
+  while( mThreadSynchronization.RenderReady( request ) )
   {
-    // Sync with update thread and get any outstanding requests from ThreadSynchronization
-    DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 1 - RenderSyncWithUpdate()\n");
-    RenderRequest* request = NULL;
-    running = mThreadSync.RenderSyncWithUpdate( request );
-
-    DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 2 - Process requests\n");
+    DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 1 - RenderReady\n");
 
     // Consume any pending events to avoid memory leaks
+    DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 2 - ConsumeEvents\n");
     mDisplayConnection->ConsumeEvents();
 
-    bool processRequests = true;
-    bool requestProcessed = false;
-    while( processRequests && running)
+    // Check if we've got a request from the main thread (e.g. replace surface)
+    if( request )
     {
-      // Check if we've got any requests from the main thread (e.g. replace surface)
-      requestProcessed = ProcessRequest( request );
-
-      // perform any pre-render operations
-      DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 3 - PreRender\n");
-      bool preRendered = PreRender(); // Returns false if no surface onto which to render
-      if( preRendered )
-      {
-        processRequests = false;
-      }
-      else
-      {
-        // Block until new surface... - cleared by ReplaceSurface code in ThreadController
-        running = mThreadSync.RenderSyncWithRequest(request);
-      }
+      // Process the request, we should NOT render when we have a request
+      DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 3 - Process requests\n");
+      ProcessRequest( request );
     }
-
-    if( running )
+    else
     {
-       // Render
-      DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 4 - Core.Render()\n");
-      mCore.Render( renderStatus );
-
-      // Notify the update-thread that a render has completed
-      DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 5 - Sync.RenderFinished()\n");
-      mThreadSync.RenderFinished( renderStatus.NeedsUpdate(), requestProcessed );
-
-      uint64_t newTime( mThreadSync.GetTimeMicroseconds() );
-
-      // perform any post-render operations
-      if ( renderStatus.HasRendered() )
+      // No request to process so we render
+      if( PreRender() ) // Returns false if no surface onto which to render
       {
-        DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 6 - PostRender()\n");
-        PostRender( static_cast< unsigned int >(newTime - currentTime) );
+        // Render
+        DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 3 - Core.Render()\n");
+
+        mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::RENDER_START );
+        mCore.Render( renderStatus );
+        mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::RENDER_END );
+
+        // Perform any post-render operations
+        if ( renderStatus.HasRendered() )
+        {
+          DALI_LOG_INFO( gRenderLogFilter, Debug::Verbose, "RenderThread::Run. 4 - PostRender()\n");
+          PostRender();
+        }
       }
-
-      currentTime = newTime;
     }
+
+    request = NULL; // Clear the request if it was set, no need to release memory
   }
 
-  // shut down egl
+  // Shut down EGL
   ShutdownEgl();
 
-  // install a function for logging
+  // Uninstall the logging function
   mEnvironmentOptions.UnInstallLogFunction();
 
   return true;
@@ -264,10 +246,8 @@ void RenderThread::InitializeEgl()
 
 }
 
-bool RenderThread::ProcessRequest( RenderRequest* request )
+void RenderThread::ProcessRequest( RenderRequest* request )
 {
-  bool processedRequest = false;
-
   if( request != NULL )
   {
     switch(request->GetType())
@@ -278,12 +258,11 @@ bool RenderThread::ProcessRequest( RenderRequest* request )
         ReplaceSurfaceRequest* replaceSurfaceRequest = static_cast<ReplaceSurfaceRequest*>(request);
         ReplaceSurface( replaceSurfaceRequest->GetSurface() );
         replaceSurfaceRequest->ReplaceCompleted();
-        processedRequest = true;
+        mThreadSynchronization.RenderInformSurfaceReplaced();
         break;
       }
     }
   }
-  return processedRequest;
 }
 
 void RenderThread::ReplaceSurface( RenderSurface* newSurface )
@@ -296,13 +275,7 @@ void RenderThread::ReplaceSurface( RenderSurface* newSurface )
 
   mDisplayConnection->InitializeEgl(*mEGL);
 
-  bool contextLost = newSurface->ReplaceEGLSurface(*mEGL);
-  if( contextLost )
-  {
-    DALI_LOG_WARNING("Context lost\n");
-    mCore.ContextDestroyed();
-    mCore.ContextCreated();
-  }
+  newSurface->ReplaceEGLSurface(*mEGL);
 
   // use the new surface from now on
   mSurface = newSurface;
@@ -339,15 +312,15 @@ bool RenderThread::PreRender()
   return success;
 }
 
-void RenderThread::PostRender( unsigned int timeDelta )
+void RenderThread::PostRender()
 {
   // Inform the gl implementation that rendering has finished before informing the surface
-  mGLES.PostRender(timeDelta);
+  mGLES.PostRender();
 
   if( mSurface )
   {
     // Inform the surface that rendering this frame has finished.
-    mSurface->PostRender( *mEGL, mGLES, mDisplayConnection, timeDelta, mSurfaceReplaced );
+    mSurface->PostRender( *mEGL, mGLES, mDisplayConnection, mSurfaceReplaced );
   }
   mSurfaceReplaced = false;
 }
index 174e505..370afe0 100644 (file)
@@ -158,9 +158,8 @@ private: // Render thread side helpers
   /**
    * Check if main thread made any requests, e.g. ReplaceSurface
    * Called from render thread
-   * @return true if a request was processed, false otherwise.
    */
-  bool ProcessRequest(RenderRequest* request);
+  void ProcessRequest( RenderRequest* request );
 
   /**
    * Replaces the rendering surface
@@ -186,9 +185,8 @@ private: // Render thread side helpers
   /**
    * Called after core has rendered the scene
    * Called from render thread
-   * @param[in] timeDelta Time since PostRender was last called in microseconds
    */
-  void PostRender( unsigned int timeDelta );
+  void PostRender();
 
   /**
    * Helper for the thread calling the entry function.
@@ -202,7 +200,7 @@ private: // Render thread side helpers
 
 private: // Data
 
-  ThreadSynchronization&        mThreadSync;             ///< Used to synchronize the all threads
+  ThreadSynchronization&        mThreadSynchronization;  ///< Used to synchronize the all threads
   Dali::Integration::Core&      mCore;                   ///< Dali core reference
   Integration::GlAbstraction&   mGLES;                   ///< GL abstraction reference
   EglFactoryInterface*          mEglFactory;             ///< Factory class to create EGL implementation
index d612b2b..ad31ad8 100644 (file)
@@ -61,27 +61,25 @@ ThreadController::~ThreadController()
   delete mThreadSync;
 }
 
-void ThreadController::Start()
+void ThreadController::Initialize()
 {
   // Notify the synchronization object before starting the threads
-  mThreadSync->Start();
+  mThreadSync->Initialise();
 
+  // We want to the threads to be set up before they start
   mUpdateThread->Start();
   mRenderThread->Start();
   mVSyncNotifier->Start();
 }
 
-void ThreadController::Pause()
+void ThreadController::Start()
 {
-  mThreadSync->Pause();
-
-  // if update thread is napping, wake it up to get it to pause in correct place
-  mThreadSync->UpdateRequested();
+  mThreadSync->Start();
 }
 
-void ThreadController::ResumeFrameTime()
+void ThreadController::Pause()
 {
-  mThreadSync->ResumeFrameTime();
+  mThreadSync->Pause();
 }
 
 void ThreadController::Resume()
@@ -101,15 +99,13 @@ void ThreadController::Stop()
 
 void ThreadController::RequestUpdate()
 {
-  mThreadSync->UpdateRequested();
+  mThreadSync->UpdateRequest();
 }
 
 void ThreadController::RequestUpdateOnce()
 {
-  // we may be sleeping
-  mThreadSync->UpdateRequested();
   // if we are paused, need to allow one update
-  mThreadSync->UpdateWhilePaused();
+  mThreadSync->UpdateOnce();
 }
 
 void ThreadController::ReplaceSurface( RenderSurface* newSurface )
@@ -124,25 +120,12 @@ void ThreadController::ReplaceSurface( RenderSurface* newSurface )
   mThreadSync->ReplaceSurface( newSurface );
 }
 
-void ThreadController::NewSurface( RenderSurface* newSurface )
-{
-  // This API shouldn't be used when there is a current surface, but check anyway.
-  RenderSurface* currentSurface = mAdaptorInterfaces.GetRenderSurfaceInterface();
-  if( currentSurface )
-  {
-    currentSurface->StopRender();
-  }
-
-  mThreadSync->NewSurface( newSurface );
-}
-
 void ThreadController::SetRenderRefreshRate(unsigned int numberOfVSyncsPerRender )
 {
   mNumberOfVSyncsPerRender = numberOfVSyncsPerRender;
   mThreadSync->SetRenderRefreshRate(numberOfVSyncsPerRender);
 }
 
-
 } // namespace Adaptor
 
 } // namespace Internal
index df29660..0413815 100644 (file)
@@ -54,6 +54,11 @@ public:
   ~ThreadController();
 
   /**
+   * Initializes the thread controller
+   */
+  void Initialize();
+
+  /**
    * @copydoc Dali::Adaptor::Start()
    */
   void Start();
@@ -74,12 +79,6 @@ public:
   void Stop();
 
   /**
-   * Ensure the frame time values are reset before the next call to Core::Update()
-   * following a Resume application state change.
-   */
-  void ResumeFrameTime();
-
-  /**
    * Called by the adaptor when core requires another update
    */
   void RequestUpdate();
@@ -97,13 +96,6 @@ public:
   void ReplaceSurface( RenderSurface* surface );
 
   /**
-   * Provides a new surface. Should be used if the old surface has been lost
-   * for any reason.
-   * @param surface new surface
-   */
-  void NewSurface( RenderSurface* surface );
-
-  /**
    * @copydoc Dali::Adaptor::SetRenderRefreshRate()
    */
   void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
diff --git a/adaptors/base/thread-synchronization-debug.h b/adaptors/base/thread-synchronization-debug.h
new file mode 100644 (file)
index 0000000..d314291
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef __DALI_INTERNAL_THREAD_SYNCHRONIZATION_DEBUG_H__
+#define __DALI_INTERNAL_THREAD_SYNCHRONIZATION_DEBUG_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Adaptor
+{
+
+namespace
+{
+#ifdef DEBUG_ENABLED
+
+#define ENABLE_LOG_IN_COLOR 1
+#define ENABLE_VSYNC_COUNTER_LOGGING 1
+#define ENABLE_UPDATE_COUNTER_LOGGING 1
+#define ENABLE_VSYNC_THREAD_LOGGING 1
+#define ENABLE_UPDATE_THREAD_LOGGING 1
+#define ENABLE_RENDER_THREAD_LOGGING 1
+#define ENABLE_EVENT_LOGGING 1
+
+Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, true, "LOG_THREAD_SYNC" );
+
+#define LOG_THREAD_SYNC(level, color, format, args...) \
+    if( gLogFilter && gLogFilter->IsEnabledFor( level ) ) { Dali::Integration::Log::LogMessage( Dali::Integration::Log::DebugInfo, "%s" format "%s\n", color, ## args, COLOR_CLEAR ); }
+
+#define LOG_THREAD_SYNC_TRACE(color) \
+    Dali::Integration::Log::TraceObj debugTraceObj( ( gLogFilter && gLogFilter->IsEnabledFor( Debug::Concise ) ) ? gLogFilter : NULL, "%s%s%s", color, __FUNCTION__, COLOR_CLEAR )
+
+#define LOG_THREAD_SYNC_TRACE_FMT(color, format, args...) \
+    Dali::Integration::Log::TraceObj debugTraceObj( ( gLogFilter && gLogFilter->IsEnabledFor( Debug::Concise ) ) ? gLogFilter : NULL, "%s%s: " format "%s", color, __FUNCTION__, ## args, COLOR_CLEAR )
+
+#else // DEBUG_ENABLED
+
+#define LOG_THREAD_SYNC(color, format, args...)
+#define LOG_THREAD_SYNC_TRACE(color)
+#define LOG_THREAD_SYNC_TRACE_FMT(color, format, args...)
+
+#endif // DEBUG_ENABLED
+
+#ifdef ENABLE_LOG_IN_COLOR
+#define COLOR_RED            "\033[31m"
+#define COLOR_YELLOW         "\033[33m"
+#define COLOR_BLUE           "\033[34m"
+#define COLOR_LIGHT_RED      "\033[91m"
+#define COLOR_LIGHT_YELLOW   "\033[93m"
+#define COLOR_LIGHT_BLUE     "\033[94m"
+#define COLOR_WHITE          "\033[97m"
+#define COLOR_CLEAR          "\033[0m"
+#else
+#define COLOR_RED
+#define COLOR_YELLOW
+#define COLOR_BLUE
+#define COLOR_LIGHT_RED
+#define COLOR_LIGHT_YELLOW
+#define COLOR_LIGHT_BLUE
+#define COLOR_WHITE
+#define COLOR_CLEAR
+#endif
+
+#ifdef ENABLE_VSYNC_COUNTER_LOGGING
+#define LOG_VSYNC_COUNTER_VSYNC(format, args...)    LOG_THREAD_SYNC(Debug::Verbose, COLOR_LIGHT_RED, "%s: " format, __FUNCTION__, ## args)
+#define LOG_VSYNC_COUNTER_UPDATE(format, args...)   LOG_THREAD_SYNC(Debug::Verbose, COLOR_LIGHT_YELLOW, "%s: " format, __FUNCTION__, ## args)
+#else
+#define LOG_VSYNC_COUNTER_VSYNC(format, args...)
+#define LOG_VSYNC_COUNTER_UPDATE(format, args...)
+#endif
+
+#ifdef ENABLE_UPDATE_COUNTER_LOGGING
+#define LOG_UPDATE_COUNTER_UPDATE(format, args...)  LOG_THREAD_SYNC(Debug::Verbose, COLOR_YELLOW, "%s: " format, __FUNCTION__, ## args)
+#define LOG_UPDATE_COUNTER_RENDER(format, args...)  LOG_THREAD_SYNC(Debug::Verbose, COLOR_LIGHT_BLUE, "%s: " format, __FUNCTION__, ## args)
+#else
+#define LOG_UPDATE_COUNTER_UPDATE(format, args...)
+#define LOG_UPDATE_COUNTER_RENDER(format, args...)
+#endif
+
+#ifdef ENABLE_VSYNC_THREAD_LOGGING
+#define LOG_VSYNC(format, args...)             LOG_THREAD_SYNC(Debug::General, COLOR_RED, "%s: " format, __FUNCTION__, ## args)
+#define LOG_VSYNC_TRACE                        LOG_THREAD_SYNC_TRACE(COLOR_RED)
+#define LOG_VSYNC_TRACE_FMT(format, args...)   LOG_THREAD_SYNC_TRACE_FMT(COLOR_RED, format, ## args)
+#else
+#define LOG_VSYNC(format, args...)
+#define LOG_VSYNC_TRACE
+#define LOG_VSYNC_TRACE_FMT(format, args...)
+#endif
+
+#ifdef ENABLE_UPDATE_THREAD_LOGGING
+#define LOG_UPDATE(format, args...)            LOG_THREAD_SYNC(Debug::General, COLOR_YELLOW, "%s: " format, __FUNCTION__, ## args)
+#define LOG_UPDATE_TRACE                       LOG_THREAD_SYNC_TRACE(COLOR_YELLOW)
+#define LOG_UPDATE_TRACE_FMT(format, args...)  LOG_THREAD_SYNC_TRACE_FMT(COLOR_YELLOW, format, ## args)
+#else
+#define LOG_UPDATE(format, args...)
+#define LOG_UPDATE_TRACE
+#define LOG_UPDATE_TRACE_FMT(format, args...)
+#endif
+
+#ifdef ENABLE_RENDER_THREAD_LOGGING
+#define LOG_RENDER(format, args...)            LOG_THREAD_SYNC(Debug::General, COLOR_BLUE, "%s: " format, __FUNCTION__, ## args)
+#define LOG_RENDER_TRACE                       LOG_THREAD_SYNC_TRACE(COLOR_BLUE)
+#define LOG_RENDER_TRACE_FMT(format, args...) LOG_THREAD_SYNC_TRACE_FMT(COLOR_BLUE, format, ## args)
+#else
+#define LOG_RENDER(format, args...)
+#define LOG_RENDER_TRACE
+#define LOG_RENDER_TRACE_FMT(format, args...)
+#endif
+
+#ifdef ENABLE_EVENT_LOGGING
+#define LOG_EVENT(format, args...)             LOG_THREAD_SYNC(Debug::Concise, COLOR_WHITE, "%s: " format, __FUNCTION__, ## args)
+#define LOG_EVENT_TRACE                        LOG_THREAD_SYNC_TRACE(COLOR_WHITE)
+#define LOG_EVENT_TRACE_FMT(format, args...)   LOG_THREAD_SYNC_TRACE_FMT(COLOR_WHITE, format, ## args)
+#else
+#define LOG_EVENT(format, args...)
+#define LOG_EVENT_TRACE
+#define LOG_EVENT_TRACE_FMT(format, args...)
+#endif
+} // unnamed namespace
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_THREAD_SYNCHRONIZATION_DEBUG_H__
index 07b2b65..8a27ecb 100644 (file)
 // CLASS HEADER
 #include "thread-synchronization.h"
 
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-
 // INTERNAL INCLUDES
 #include <base/interfaces/adaptor-internal-services.h>
+#include <base/thread-synchronization-debug.h>
 
 namespace Dali
 {
@@ -36,30 +34,36 @@ namespace Adaptor
 namespace
 {
 const unsigned int TIME_PER_FRAME_IN_MICROSECONDS = 16667;
-const unsigned int MICROSECONDS_PER_SECOND( 1000000 );
-const unsigned int INPUT_EVENT_UPDATE_PERIOD( MICROSECONDS_PER_SECOND / 90 ); // period between ecore x event updates
-
+const int TOTAL_THREAD_COUNT = 3;
+const unsigned int TRUE = 1u;
+const unsigned int FALSE = 0u;
 } // unnamed namespace
 
-ThreadSynchronization::ThreadSynchronization( AdaptorInternalServices& adaptorInterfaces,
-                                                          unsigned int numberOfVSyncsPerRender)
-: mMaximumUpdateCount( adaptorInterfaces.GetCore().GetMaximumUpdateCount()),
-  mNumberOfVSyncsPerRender( numberOfVSyncsPerRender ),
-  mUpdateReadyCount( 0u ),
-  mRunning( false ),
-  mUpdateRequired( false ),
-  mPaused( false ),
-  mUpdateRequested( false ),
-  mAllowUpdateWhilePaused( false ),
-  mVSyncSleep( false ),
-  mSyncFrameNumber( 0u ),
-  mSyncSeconds( 0u ),
-  mSyncMicroseconds( 0u ),
-  mFrameTime( adaptorInterfaces.GetPlatformAbstractionInterface() ),
+ThreadSynchronization::ThreadSynchronization( AdaptorInternalServices& adaptorInterfaces, unsigned int numberOfVSyncsPerRender)
+: mFrameTime( adaptorInterfaces.GetPlatformAbstractionInterface() ),
   mNotificationTrigger( adaptorInterfaces.GetProcessCoreEventsTrigger() ),
   mPerformanceInterface( adaptorInterfaces.GetPerformanceInterface() ),
   mReplaceSurfaceRequest(),
-  mReplaceSurfaceRequested( false )
+  mUpdateThreadWaitCondition(),
+  mRenderThreadWaitCondition(),
+  mVSyncThreadWaitCondition(),
+  mEventThreadWaitCondition(),
+  mMaximumUpdateCount( adaptorInterfaces.GetCore().GetMaximumUpdateCount()),
+  mNumberOfVSyncsPerRender( numberOfVSyncsPerRender ),
+  mTryToSleepCount( 0u ),
+  mState( State::STOPPED ),
+  mVSyncAheadOfUpdate( 0u ),
+  mUpdateAheadOfRender( 0u ),
+  mNumberOfThreadsStarted( 0u ),
+  mUpdateThreadResuming( FALSE ),
+  mVSyncThreadRunning( FALSE ),
+  mVSyncThreadStop( FALSE ),
+  mRenderThreadStop( FALSE ),
+  mRenderThreadReplacingSurface( FALSE ),
+  mEventThreadSurfaceReplaced( FALSE ),
+  mVSyncThreadInitialised( FALSE ),
+  mRenderThreadInitialised( FALSE ),
+  mRenderThreadSurfaceReplaced( FALSE )
 {
 }
 
@@ -67,411 +71,743 @@ ThreadSynchronization::~ThreadSynchronization()
 {
 }
 
-void ThreadSynchronization::Start()
-{
-  mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
-  mRunning = true;
-}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// EVENT THREAD
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-void ThreadSynchronization::Stop()
+void ThreadSynchronization::Initialise()
 {
-  mRunning = false;
-
-  // Wake if sleeping
-  UpdateRequested();
-
-  // we may be paused so need to resume
-  Resume();
+  LOG_EVENT_TRACE;
 
-  // Notify all condition variables, so if threads are waiting
-  // they can break out, and check the running status.
-  mUpdateFinishedCondition.notify_one();
-  mRenderFinishedCondition.notify_one();
-  mVSyncSleepCondition.notify_one();
-  mVSyncReceivedCondition.notify_one();
-  mRenderRequestSleepCondition.notify_one();
-
-  mFrameTime.Suspend();
+  ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+  if( mState == State::STOPPED )
+  {
+    LOG_EVENT( "INITIALISING" );
+    mState = State::INITIALISING;
+  }
 }
 
-void ThreadSynchronization::Pause()
+void ThreadSynchronization::Start()
 {
-  mPaused = true;
-
-  AddPerformanceMarker( PerformanceInterface::PAUSED );
-  mFrameTime.Suspend();
-}
+  LOG_EVENT_TRACE;
 
-void ThreadSynchronization::ResumeFrameTime()
-{
-  mFrameTime.Resume();
-}
+  bool start = false;
+  {
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    if( mState == State::INITIALISING )
+    {
+      start = true;
+    }
+  }
 
-void ThreadSynchronization::Resume()
-{
-  mPaused = false;
-  mVSyncSleep = false;
+  // Not atomic, but does not matter here as we just want to ensure we only start from State::INITIALISING
+  if( start )
+  {
+    LOG_EVENT( "STARTING" );
+    mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
 
-  mPausedCondition.notify_one();
-  mVSyncSleepCondition.notify_one();
+    {
+      ConditionalWait::ScopedLock lock( mEventThreadWaitCondition );
+      while( mNumberOfThreadsStarted < TOTAL_THREAD_COUNT )
+      {
+        mEventThreadWaitCondition.Wait( lock );
+      }
+    }
 
-  AddPerformanceMarker( PerformanceInterface::RESUME);
+    {
+      ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+      mState = State::RUNNING;
+    }
+    mUpdateThreadWaitCondition.Notify();
+  }
 }
 
-void ThreadSynchronization::UpdateRequested()
+void ThreadSynchronization::Stop()
 {
-  mUpdateRequested = true;
+  LOG_EVENT_TRACE;
 
-  // Wake update thread if sleeping
-  mUpdateSleepCondition.notify_one();
-}
+  bool stop = false;
+  {
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    if( mState != State::STOPPED )
+    {
+      stop = true;
+      mState = State::STOPPED;
+    }
+  }
 
-void ThreadSynchronization::UpdateWhilePaused()
-{
+  // Not atomic, but does not matter here as we just want to ensure we do not stop more than once
+  if( stop )
   {
-    boost::unique_lock< boost::mutex > lock( mMutex );
+    LOG_EVENT( "STOPPING" );
 
-    mAllowUpdateWhilePaused = true;
-  }
+    // Notify update-thread so that it continues and sets up the other threads to stop as well
+    mUpdateThreadWaitCondition.Notify();
 
-  // wake vsync if sleeping
-  mVSyncSleepCondition.notify_one();
-  // Wake update if sleeping
-  mUpdateSleepCondition.notify_one();
-  // stay paused but notify the pause condition
-  mPausedCondition.notify_one();
+    mFrameTime.Suspend();
+  }
 }
 
-bool ThreadSynchronization::ReplaceSurface( RenderSurface* newSurface )
+void ThreadSynchronization::Pause()
 {
-  bool result=false;
+  LOG_EVENT_TRACE;
 
-  UpdateRequested();
-  UpdateWhilePaused();
+  bool addPerformanceMarker = false;
   {
-    boost::unique_lock< boost::mutex > lock( mMutex );
+    // Only pause if we're RUNNING or SLEEPING
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    if( ( mState == State::RUNNING ) ||
+        ( mState == State::SLEEPING ) )
+    {
+      LOG_EVENT( "PAUSING" );
 
-    mReplaceSurfaceRequest.SetSurface(newSurface);
-    mReplaceSurfaceRequested = true;
+      mState = State::PAUSED;
 
-    mRenderRequestFinishedCondition.wait(lock); // wait unlocks the mutex on entry, and locks again on exit.
+      mUpdateThreadResuming = FALSE;
 
-    mReplaceSurfaceRequested = false;
-    result = mReplaceSurfaceRequest.GetReplaceCompleted();
+      mFrameTime.Suspend();
+
+      addPerformanceMarker = true;
+    }
   }
 
-  return result;
+  if( addPerformanceMarker )
+  {
+    // Can lock so we do not want to have a lock when calling this to avoid deadlocks
+    AddPerformanceMarker( PerformanceInterface::PAUSED );
+  }
 }
 
-bool ThreadSynchronization::NewSurface( RenderSurface* newSurface )
+void ThreadSynchronization::Resume()
 {
-  bool result=false;
+  LOG_EVENT_TRACE;
 
-  UpdateRequested();
-  UpdateWhilePaused();
+  // Only resume if we're PAUSED
+  bool resume = false;
   {
-    boost::unique_lock< boost::mutex > lock( mMutex );
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    if( mState == State::PAUSED )
+    {
+      resume = true;
+      mState = State::RUNNING;
+      mUpdateThreadResuming = TRUE;
+    }
+  }
 
-    mReplaceSurfaceRequest.SetSurface(newSurface);
-    mReplaceSurfaceRequested = true;
+  // Not atomic, but does not matter here as we just want to ensure we only resume if we're paused
+  if( resume )
+  {
+    LOG_EVENT( "RESUMING" );
 
-    // Unlock the render thread sleeping on requests
-    mRenderRequestSleepCondition.notify_one();
+    mFrameTime.Resume();
 
-    // Lock event thread until request has been processed
-    mRenderRequestFinishedCondition.wait(lock);// wait unlocks the mutex on entry, and locks again on exit.
+    // Start up Update thread again
+    mUpdateThreadWaitCondition.Notify();
 
-    mReplaceSurfaceRequested = false;
-    result = mReplaceSurfaceRequest.GetReplaceCompleted();
+    // Can lock so we do not want to have a lock when calling this to avoid deadlocks
+    AddPerformanceMarker( PerformanceInterface::RESUME);
   }
-
-  return result;
 }
 
-
-void ThreadSynchronization::UpdateReadyToRun()
+void ThreadSynchronization::UpdateRequest()
 {
-  bool wokenFromPause( false );
+  LOG_EVENT_TRACE;
 
-  // atomic check first to avoid mutex lock in 99.99% of cases
-  if( mPaused )
+  bool update = false;
   {
-    boost::unique_lock< boost::mutex > lock( mMutex );
-
-    // wait while paused
-    while( mPaused && !mAllowUpdateWhilePaused )
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    if( mState == State::SLEEPING )
     {
-      // this will automatically unlock mMutex
-      mPausedCondition.wait( lock );
-
-      wokenFromPause = true;
+      mState = State::RUNNING;
+      update = true;
     }
+    mTryToSleepCount = 0;
   }
 
-  if ( !wokenFromPause )
+  if( update )
   {
-    // Wait for the next Sync
-    WaitSync();
+    LOG_EVENT( "UPDATE REQUEST" );
+    mUpdateThreadWaitCondition.Notify();
   }
+}
+
+void ThreadSynchronization::UpdateOnce()
+{
+  LOG_EVENT_TRACE;
+  LOG_EVENT( "UPDATE ONCE" );
 
-  AddPerformanceMarker( PerformanceInterface::UPDATE_START );
+  mUpdateThreadWaitCondition.Notify();
 }
 
-bool ThreadSynchronization::UpdateSyncWithRender( bool notifyEvent, bool& renderNeedsUpdate )
+void ThreadSynchronization::ReplaceSurface( RenderSurface* newSurface )
 {
-  AddPerformanceMarker( PerformanceInterface::UPDATE_END );
+  LOG_EVENT_TRACE;
 
-  // Do the notifications first so the event thread can start processing them
-  if( notifyEvent && mRunning )
+  State::Type previousState( State::STOPPED );
   {
-    // Tell the event-thread to wake up (if asleep) and send a notification event to Core
-    mNotificationTrigger.Trigger();
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    previousState = mState;
+    mState = State::REPLACING_SURFACE;
   }
 
-  boost::unique_lock< boost::mutex > lock( mMutex );
+  {
+    ConditionalWait::ScopedLock lock( mEventThreadWaitCondition );
+    mEventThreadSurfaceReplaced = FALSE;
+  }
 
-  // Another frame was prepared for rendering; increment counter
-  ++mUpdateReadyCount;
-  DALI_ASSERT_DEBUG( mUpdateReadyCount <= mMaximumUpdateCount );
+  {
+    ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+    mReplaceSurfaceRequest.SetSurface( newSurface );
+    mRenderThreadReplacingSurface = TRUE;
+  }
 
-  // Notify the render-thread that an update has completed
-  mUpdateFinishedCondition.notify_one();
+  // Notify the RenderThread in case it's waiting
+  mRenderThreadWaitCondition.Notify();
 
-  // The update-thread must wait until a frame has been rendered, when mMaximumUpdateCount is reached
-  while( mRunning && ( mMaximumUpdateCount == mUpdateReadyCount ) )
   {
-    // Wait will atomically add the thread to the set of threads waiting on
-    // the condition variable mRenderFinishedCondition and unlock the mutex.
-    mRenderFinishedCondition.wait( lock );
-  }
+    ConditionalWait::ScopedLock lock( mEventThreadWaitCondition );
+
+    // Wait for RenderThread to replace the surface
+    while( ! mEventThreadSurfaceReplaced )
+    {
+      LOG_EVENT( "Waiting for Surface to be Replaced" );
 
-  renderNeedsUpdate = mUpdateRequired;
+      mEventThreadWaitCondition.Wait( lock );
+    }
+  }
 
-  // Flag is used to during UpdateThread::Stop() to exit the update/render loops
-  return mRunning;
+  {
+    ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+    mState = previousState;
+  }
+  mUpdateThreadWaitCondition.Notify();
 }
 
-void ThreadSynchronization::UpdateWaitForAllRenderingToFinish()
+void ThreadSynchronization::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
 {
-  boost::unique_lock< boost::mutex > lock( mMutex );
+  LOG_EVENT_TRACE;
+  LOG_EVENT( "SET RENDER REFRESH RATE" );
 
-  // Wait for all of the prepared frames to be rendered
-  while ( mRunning && ( 0u != mUpdateReadyCount ) && !mUpdateRequested )
-  {
-    // Wait will atomically add the thread to the set of threads waiting on
-    // the condition variable mRenderFinishedCondition and unlock the mutex.
-    mRenderFinishedCondition.wait( lock );
-  }
+  mNumberOfVSyncsPerRender = numberOfVSyncsPerRender;
 }
 
-bool ThreadSynchronization::UpdateTryToSleep()
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// UPDATE THREAD
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool ThreadSynchronization::UpdateReady( bool notifyEvent, bool runUpdate, float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds )
 {
-  if ( !mUpdateRequired && !mUpdateRequested )
+  LOG_UPDATE_TRACE;
+
+  State::Type state = State::STOPPED;
   {
-    // there's nothing to update in the scene, so wait for render to finish processing
-    UpdateWaitForAllRenderingToFinish();
+    ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+    state = mState;
   }
 
-  boost::mutex sleepMutex;
-  boost::unique_lock< boost::mutex > lock( sleepMutex );
-
-  while( mRunning && !mUpdateRequired && !mUpdateRequested )
+  switch( state )
   {
-    //
-    // Going to sleep
-    //
+    case State::STOPPED:
+    {
+      StopAllThreads();
+      return false; // Stop update-thread
+    }
 
-    // 1. put VSync thread to sleep.
-    mVSyncSleep = true;
+    case State::INITIALISING:
+    {
+      UpdateInitialising();
+      break;
+    }
 
-    // 2. inform frame time
-    mFrameTime.Sleep();
+    case State::PAUSED:
+    {
+      LOG_UPDATE_TRACE_FMT( "PAUSED" );
 
-    // 3. block thread and wait for wakeup event
-    mUpdateSleepCondition.wait( lock );
+      // Just pause the VSyncThread, locks so we shouldn't have a scoped-lock when calling this
+      PauseVSyncThread();
+    }
+    // No break, fall through
 
-    //
-    // Woken up
-    //
+    case State::RUNNING:
+    {
+      LOG_UPDATE_TRACE_FMT( "RUNNING" );
+
+      if( IsUpdateThreadResuming() )
+      {
+        LOG_UPDATE( "Restarting VSyncThread" );
+
+        {
+          ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+          mUpdateThreadResuming = FALSE;
+        }
+
+        // Restart the VSyncThread, locks so we shouldn't have a scoped-lock when calling this
+        RunVSyncThread();
+      }
+
+      if( notifyEvent )
+      {
+        LOG_UPDATE( "Notify Event Thread" );
+
+        // Do the notifications first so the event thread can start processing them
+        // Tell the event-thread to wake up (if asleep) and send a notification event to Core
+        mNotificationTrigger.Trigger();
+      }
+
+      // Inform render thread
+      {
+        ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+        ++mUpdateAheadOfRender;
+        LOG_UPDATE_COUNTER_UPDATE( "updateAheadOfRender(%d)", mUpdateAheadOfRender );
+      }
+      mRenderThreadWaitCondition.Notify();
+
+      // Wait if we've reached the maximum-ahead-of-render count.
+      while( MaximumUpdateAheadOfRenderReached() )
+      {
+        LOG_UPDATE( "Maximum Update Ahead of Render: WAIT" );
+
+        mRenderThreadWaitCondition.Notify(); // Notify the render thread in case it was waiting
+
+        {
+          // Ensure we did not stop while we were waiting previously.
+          ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+          if( mState == State::STOPPED )
+          {
+            break; // Break out of while loop
+          }
+          mUpdateThreadWaitCondition.Wait( updateLock );
+        }
+      }
+
+      // Ensure we have had at least 1 V-Sync before we continue
+      // Ensure we didn't stop while we were previously waiting
+      {
+        ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+        if( ( mState != State::STOPPED ) &&
+            ( mVSyncAheadOfUpdate == 0 ) )
+        {
+          LOG_VSYNC_COUNTER_UPDATE( " vSyncAheadOfUpdate(%d) WAIT", mVSyncAheadOfUpdate );
+          mUpdateThreadWaitCondition.Wait( updateLock );
+        }
+        else
+        {
+          LOG_VSYNC_COUNTER_UPDATE( " vSyncAheadOfUpdate(%d)", mVSyncAheadOfUpdate );
+        }
+        mVSyncAheadOfUpdate = 0;
+      }
+
+      // Try to sleep if we do not require any more updates
+      UpdateTryToSleep( runUpdate );
+
+      break;
+    }
 
-    // 1. inform frame timer
-    mFrameTime.WakeUp();
+    case State::SLEEPING:
+    case State::REPLACING_SURFACE:
+    {
+      break;
+    }
+  }
 
-    // 2. wake VSync thread.
-    mVSyncSleep = false;
-    mVSyncSleepCondition.notify_one();
+  // Ensure we didn't stop while we were waiting
+  if( IsUpdateThreadStopping() )
+  {
+    // Locks so we shouldn't have a scoped-lock when calling this
+    StopAllThreads();
+    return false; // Stop update-thread
   }
 
-  mUpdateRequested = false;
+  // Just wait if we're replacing the surface as the render-thread is busy
+  UpdateWaitIfReplacingSurface();
 
-  return mRunning;
+  mFrameTime.PredictNextSyncTime( lastFrameDeltaSeconds, lastSyncTimeMilliseconds, nextSyncTimeMilliseconds );
+
+  return true; // Keep update-thread running
 }
 
-bool ThreadSynchronization::RenderSyncWithRequest(RenderRequest*& requestPtr)
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// RENDER THREAD
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool ThreadSynchronization::RenderReady( RenderRequest*& requestPtr )
 {
-  boost::unique_lock< boost::mutex > lock( mMutex );
+  LOG_RENDER_TRACE;
 
-  // Wait for a replace surface request
-  mRenderRequestSleepCondition.wait(lock);
+  if( ! IsRenderThreadReplacingSurface() ) // Call to this function locks so should not be called if we have a scoped-lock
+  {
+    if( ! mRenderThreadInitialised )
+    {
+      LOG_RENDER( "Initialised" );
+
+      mRenderThreadInitialised = TRUE;
 
-  // write any new requests
-  if( mReplaceSurfaceRequested )
+      // Notify event thread that this thread is up and running, this locks so we should have a scoped-lock
+      NotifyThreadInitialised();
+    }
+    else
+    {
+      if( mRenderThreadSurfaceReplaced )
+      {
+        mRenderThreadSurfaceReplaced = FALSE;
+      }
+      else
+      {
+        // decrement update-ahead-of-render
+        ConditionalWait::ScopedLock renderLock( mRenderThreadWaitCondition );
+        --mUpdateAheadOfRender;
+      }
+    }
+
+    // Check if we've had an update, if we haven't then we just wait
+    // Ensure we do not wait if we're supposed to stop
+    {
+      ConditionalWait::ScopedLock renderLock( mRenderThreadWaitCondition );
+      if( mUpdateAheadOfRender <= 0 && ! mRenderThreadStop )
+      {
+        LOG_UPDATE_COUNTER_RENDER( "updateAheadOfRender(%d) WAIT", mUpdateAheadOfRender );
+        mRenderThreadWaitCondition.Wait( renderLock );
+      }
+      else
+      {
+        LOG_UPDATE_COUNTER_RENDER( "updateAheadOfRender(%d)", mUpdateAheadOfRender );
+      }
+    }
+  }
+  else
   {
+    LOG_RENDER( "Just Rendered, now Replacing surface" );
+
+    // ... also decrement update-ahead-of-render
+    ConditionalWait::ScopedLock renderLock( mRenderThreadWaitCondition );
+    --mUpdateAheadOfRender;
+  }
+
+  // We may have been asked to replace the surface while we were waiting so check again here
+  if( IsRenderThreadReplacingSurface() )
+  {
+    // Replacing surface
+    LOG_RENDER( "REPLACE SURFACE" );
+
+    ConditionalWait::ScopedLock renderLock( mRenderThreadWaitCondition );
     requestPtr = &mReplaceSurfaceRequest;
+    mRenderThreadReplacingSurface = FALSE;
+    mRenderThreadSurfaceReplaced = FALSE;
   }
-  mReplaceSurfaceRequested = false;
-  return mRunning;
+
+  return IsRenderThreadRunning(); // Call to this function locks so should not be called if we have a scoped-lock
 }
 
-bool ThreadSynchronization::RenderSyncWithUpdate(RenderRequest*& requestPtr)
+void ThreadSynchronization::RenderInformSurfaceReplaced()
 {
-  boost::unique_lock< boost::mutex > lock( mMutex );
+  LOG_RENDER_TRACE;
 
-  // Wait for update to produce a buffer, or for the mRunning state to change
-  while ( mRunning && ( 0u == mUpdateReadyCount ) )
+  mRenderThreadSurfaceReplaced = TRUE;
   {
-    // Wait will atomically add the thread to the set of threads waiting on
-    // the condition variable mUpdateFinishedCondition and unlock the mutex.
-    mUpdateFinishedCondition.wait( lock );
+    ConditionalWait::ScopedLock lock( mEventThreadWaitCondition );
+    mEventThreadSurfaceReplaced = TRUE;
   }
+  mEventThreadWaitCondition.Notify();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// V-SYNC THREAD
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool ThreadSynchronization::VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender )
+{
+  LOG_VSYNC_TRACE;
 
-  if( mRunning )
   {
-    AddPerformanceMarker( PerformanceInterface::RENDER_START );
+    ConditionalWait::ScopedLock vSyncLock( mVSyncThreadWaitCondition );
+    if( numberOfVSyncsPerRender != mNumberOfVSyncsPerRender )
+    {
+      numberOfVSyncsPerRender = mNumberOfVSyncsPerRender; // save it back
+      mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
+    }
+
+    if( validSync )
+    {
+      mFrameTime.SetSyncTime( frameNumber );
+    }
   }
 
-  // write any new requests
-  if( mReplaceSurfaceRequested )
+  if( ! mVSyncThreadInitialised )
   {
-    requestPtr = &mReplaceSurfaceRequest;
+    LOG_VSYNC( "Initialised" );
+
+    mVSyncThreadInitialised = TRUE;
+
+    // Notify event thread that this thread is up and running, this locks so we should have a scoped-lock
+    NotifyThreadInitialised();
+  }
+  else
+  {
+    // Increment v-sync-ahead-of-update count and inform update-thread
+    {
+      ConditionalWait::ScopedLock lock( mUpdateThreadWaitCondition );
+      ++mVSyncAheadOfUpdate;
+      LOG_VSYNC_COUNTER_VSYNC( " vSyncAheadOfUpdate(%d)", mVSyncAheadOfUpdate );
+    }
+    mUpdateThreadWaitCondition.Notify();
+  }
+
+  // Ensure update-thread has set us to run before continuing
+  // Ensure we do not wait if we're supposed to stop
+  {
+    ConditionalWait::ScopedLock vSyncLock( mVSyncThreadWaitCondition );
+    while( ! mVSyncThreadRunning && ! mVSyncThreadStop )
+    {
+      LOG_VSYNC( "WAIT" );
+      mVSyncThreadWaitCondition.Wait( vSyncLock );
+    }
   }
-  mReplaceSurfaceRequested = false;
 
-  // Flag is used to during UpdateThread::Stop() to exit the update/render loops
-  return mRunning;
+  return IsVSyncThreadRunning(); // Call to this function locks so should not be called if we have a scoped-lock
 }
 
-void ThreadSynchronization::RenderFinished( bool updateRequired, bool requestProcessed )
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// ALL THREADS: Performance Marker
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ThreadSynchronization::AddPerformanceMarker( PerformanceInterface::MarkerType type )
 {
+  if( mPerformanceInterface )
   {
-    boost::unique_lock< boost::mutex > lock( mMutex );
+    mPerformanceInterface->AddMarker( type );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// PRIVATE METHODS
+//
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    // Set the flag to say if update needs to run again.
-    mUpdateRequired = updateRequired;
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Called by ALL Threads
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    // A frame has been rendered; decrement counter
-    --mUpdateReadyCount;
-    DALI_ASSERT_DEBUG( mUpdateReadyCount < mMaximumUpdateCount );
+void ThreadSynchronization::NotifyThreadInitialised()
+{
+  {
+    ConditionalWait::ScopedLock lock( mEventThreadWaitCondition );
+    ++mNumberOfThreadsStarted;
   }
+  mEventThreadWaitCondition.Notify();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Called by Update Thread
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void ThreadSynchronization::UpdateInitialising()
+{
+  LOG_UPDATE_TRACE;
 
-  // Notify the update-thread that a render has completed
-  mRenderFinishedCondition.notify_one();
+  // Notify event thread that this thread is up and running, locks so we shouldn't have a scoped-lock when calling this
+  NotifyThreadInitialised();
 
-  if( requestProcessed )
+  // Wait for first thread-sync point
   {
-    // Notify the event thread that a request has completed
-    mRenderRequestFinishedCondition.notify_one();
+    ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+
+    while( mState == State::INITIALISING )
+    {
+      mUpdateThreadWaitCondition.Wait( updateLock );
+    }
   }
 
-  AddPerformanceMarker( PerformanceInterface::RENDER_END );
+  // Locks so we shouldn't have a scoped-lock when calling this
+  RunVSyncThread();
 }
 
-void ThreadSynchronization::WaitSync()
+void ThreadSynchronization::UpdateTryToSleep( bool runUpdate )
 {
-  // Block until the start of a new sync.
-  // If we're experiencing slowdown and are behind by more than a frame
-  // then we should wait for the next frame
+  LOG_UPDATE_TRACE;
 
-  unsigned int updateFrameNumber = mSyncFrameNumber;
+  if( ! runUpdate )
+  {
+    LOG_UPDATE( "TryToSleep" );
+
+    if( ++mTryToSleepCount >= 3 )
+    {
+      LOG_UPDATE( "Going to sleep" );
 
-  boost::unique_lock< boost::mutex > lock( mMutex );
+      // Locks so we shouldn't have a scoped-lock when calling this
+      PauseVSyncThread();
 
-  while ( mRunning && ( updateFrameNumber == mSyncFrameNumber ) )
+      // Render thread will automatically wait as it relies on update-ahead-of-render count
+
+      // Change the state
+      {
+        ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+
+        // Ensure we weren't stopped while we have been processing
+        if( mState != State::STOPPED )
+        {
+          mState = State::SLEEPING;
+        }
+      }
+
+      // Inform FrameTime that we're going to sleep
+      mFrameTime.Sleep();
+
+      // Wait while we're SLEEPING
+      {
+        ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+        while( mState == State::SLEEPING )
+        {
+          mUpdateThreadWaitCondition.Wait( updateLock );
+        }
+      }
+
+      ////////////////////////
+      // WAKE UP
+      ////////////////////////
+
+      LOG_UPDATE( "Waking Up" );
+
+      // Clear V-Sync-ahead-of-update-count
+      {
+        ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+        mVSyncAheadOfUpdate = 0;
+      }
+
+      // Restart the v-sync-thread, locks so we shouldn't have a scoped-lock
+      RunVSyncThread();
+
+      // Reset try-to-sleep count
+      mTryToSleepCount = 0;
+
+      // Inform frame timer that we've woken up
+      mFrameTime.WakeUp();
+    }
+  }
+  else
   {
-    // Wait will atomically add the thread to the set of threads waiting on
-    // the condition variable mVSyncReceivedCondition and unlock the mutex.
-    mVSyncReceivedCondition.wait( lock );
+    mTryToSleepCount = 0;
   }
-
-  // reset update while paused flag
-  mAllowUpdateWhilePaused = false;
 }
 
-bool ThreadSynchronization::VSyncNotifierSyncWithUpdateAndRender( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender )
+void ThreadSynchronization::UpdateWaitIfReplacingSurface()
 {
-  // This may have changed since the last sync. Update VSyncNotifier's copy here if so.
-  if( numberOfVSyncsPerRender != mNumberOfVSyncsPerRender )
+  bool replacingSurface = false;
   {
-    numberOfVSyncsPerRender = mNumberOfVSyncsPerRender; // save it back
-    mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
+    ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+    replacingSurface = ( mState == State::REPLACING_SURFACE );
   }
-
-  if( validSync )
+  while( replacingSurface )
   {
-    mFrameTime.SetSyncTime( frameNumber );
-  }
-
-  boost::unique_lock< boost::mutex > lock( mMutex );
+    LOG_UPDATE_TRACE_FMT( "REPLACING SURFACE" );
 
-  mSyncFrameNumber = frameNumber;
-  mSyncSeconds = seconds;
-  mSyncMicroseconds = microseconds;
+    // Locks so should not be called while we have a scoped-lock
+    PauseVSyncThread();
 
-  mVSyncReceivedCondition.notify_all();
+    // One last check before we actually wait in case the state has changed since we checked earlier
+    {
+      ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+      replacingSurface = ( mState == State::REPLACING_SURFACE );
+      if( replacingSurface )
+      {
+        mUpdateThreadWaitCondition.Wait( updateLock );
+      }
+    }
 
-  AddPerformanceMarker( PerformanceInterface::VSYNC );
+    {
+      ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+      mVSyncAheadOfUpdate = 0;
+    }
 
-  while( mRunning && // sleep on condition variable WHILE still running
-         !mAllowUpdateWhilePaused &&             // AND NOT allowing updates while paused
-         ( mVSyncSleep || mPaused ) )            // AND sleeping OR paused
-  {
-    // Wait will atomically add the thread to the set of threads waiting on
-    // the condition variable mVSyncSleepCondition and unlock the mutex.
-    mVSyncSleepCondition.wait( lock );
+    // Locks so should not be called while we have a scoped-lock
+    RunVSyncThread();
   }
+}
+
+bool ThreadSynchronization::IsUpdateThreadResuming()
+{
+  ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+  return mUpdateThreadResuming;
+}
 
-  return mRunning;
+bool ThreadSynchronization::IsUpdateThreadStopping()
+{
+  ConditionalWait::ScopedLock updateLock( mUpdateThreadWaitCondition );
+  return ( mState == State::STOPPED );
 }
 
-unsigned int ThreadSynchronization::GetFrameNumber() const
+bool ThreadSynchronization::MaximumUpdateAheadOfRenderReached()
 {
-  return mSyncFrameNumber;
+  ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+  return mUpdateAheadOfRender >= mMaximumUpdateCount;
 }
 
-uint64_t ThreadSynchronization::GetTimeMicroseconds()
+void ThreadSynchronization::StopAllThreads()
 {
-  uint64_t currentTime(0);
+  LOG_UPDATE_TRACE;
 
-  {
-    boost::unique_lock< boost::mutex > lock( mMutex );
+  // Lock so we shouldn't have a scoped-lock when calling these methods
+  StopVSyncThread();
+  StopRenderThread();
+}
 
-    currentTime = mSyncSeconds;
-    currentTime *= MICROSECONDS_PER_SECOND;
-    currentTime += mSyncMicroseconds;
+void ThreadSynchronization::RunVSyncThread()
+{
+  {
+    ConditionalWait::ScopedLock lock( mVSyncThreadWaitCondition );
+    mVSyncThreadRunning = TRUE;
   }
+  mVSyncThreadWaitCondition.Notify();
+}
 
-  return currentTime;
+void ThreadSynchronization::PauseVSyncThread()
+{
+  ConditionalWait::ScopedLock lock( mVSyncThreadWaitCondition );
+  mVSyncThreadRunning = FALSE;
 }
 
-void ThreadSynchronization::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
+void ThreadSynchronization::StopVSyncThread()
 {
-  mNumberOfVSyncsPerRender = numberOfVSyncsPerRender;
+  {
+    ConditionalWait::ScopedLock lock( mVSyncThreadWaitCondition );
+    mVSyncThreadStop = TRUE;
+  }
+  mVSyncThreadWaitCondition.Notify();
 }
 
-inline void ThreadSynchronization::AddPerformanceMarker( PerformanceInterface::MarkerType type )
+void ThreadSynchronization::StopRenderThread()
 {
-  if( mPerformanceInterface )
   {
-    mPerformanceInterface->AddMarker( type );
+    ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+    mRenderThreadStop = TRUE;
   }
+  mRenderThreadWaitCondition.Notify();
 }
 
-void ThreadSynchronization::PredictNextSyncTime(
-  float& lastFrameDeltaSeconds,
-  unsigned int& lastSyncTimeMilliseconds,
-  unsigned int& nextSyncTimeMilliseconds )
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Called by V-Sync Thread
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool ThreadSynchronization::IsVSyncThreadRunning()
 {
-  mFrameTime.PredictNextSyncTime( lastFrameDeltaSeconds, lastSyncTimeMilliseconds, nextSyncTimeMilliseconds );
+  ConditionalWait::ScopedLock lock( mVSyncThreadWaitCondition );
+  return ! mVSyncThreadStop;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Called by Render Thread
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+bool ThreadSynchronization::IsRenderThreadRunning()
+{
+  ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+  return ! mRenderThreadStop;
+}
+
+bool ThreadSynchronization::IsRenderThreadReplacingSurface()
+{
+  ConditionalWait::ScopedLock lock( mRenderThreadWaitCondition );
+  return mRenderThreadReplacingSurface;
 }
 
 } // namespace Adaptor
index 18f59ba..5f2ebfc 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
-#define __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
+#ifndef __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
+#define __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
 
 /*
  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  */
 
 // EXTERNAL INCLUDES
-#include <stdint.h>
-#include <boost/thread.hpp>
-#include <boost/thread/condition_variable.hpp>
 
 // INTERNAL INCLUDES
 #include <base/interfaces/performance-interface.h>
+#include <base/conditional-wait.h>
 #include <trigger-event-interface.h>
 #include <base/frame-time.h>
 #include <base/render-thread.h>
@@ -34,14 +32,6 @@ namespace Dali
 
 class RenderSurface;
 
-namespace Integration
-{
-
-class Core;
-class PlatformAbstraction;
-
-} // namespace Integration
-
 namespace Internal
 {
 
@@ -73,217 +63,331 @@ public:
    */
   ~ThreadSynchronization();
 
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the Event Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
   /**
-   * Start the threads
+   * Initialises the ThreadSynchronisation class. The expectation is that this function will be
+   * called when all threads are about to be set up and that Start will be called when
+   * the the scene is actually prepared and ready to be displayed. This way our first update
+   * will have the actual scene we require.
+   *
+   * @note Should only be called by the Event Thread.
+   */
+  void Initialise();
+
+  /**
+   * Starts running all threads. This waits until all threads are up and running.
+   *
+   * @pre A call to Initialise has been made.
+   *
+   * @note Should only be called by the Event Thread.
    */
   void Start();
 
   /**
-   * Stop the threads
+   * Stop the threads.
+   *
+   * @note Should only be called by the Event Thread.
    */
   void Stop();
 
   /**
-   * Pause the controller (and threads)
+   * Pause the controller (and threads).
+   *
+   * @note Should only be called by the Event Thread.
    */
   void Pause();
 
   /**
-   * Resume the controller (and threads)
+   * Resume the controller (and threads).
+   *
+   * @note Should only be called by the Event Thread.
    */
   void Resume();
 
   /**
-   * Resume the frame time predictor
-   */
-  void ResumeFrameTime();
-
-  /**
    * Wake update thread if sleeping. If the update thread is not sleeping
-   * this becomes a noop.
+   * this becomes a no-op.
    * Called when an update is requested by Core.
    * i.e. when a batch of messages have been queued for the next update.
+   *
+   * @note Should only be called by the Event Thread.
    */
-  void UpdateRequested();
+  void UpdateRequest();
 
   /**
    * Update once (even if paused)
+   *
+   * @note Should only be called by the Event Thread.
    */
-  void UpdateWhilePaused();
+  void UpdateOnce();
 
   /**
    * Inform the render thread that there is a new surface, and that
    * it should replace the current surface.
+   *
    * @param[in] newSurface The new surface for rendering.
+   *
+   * @note Should only be called by the Event Thread.
    */
-  bool ReplaceSurface( RenderSurface* newSurface );
+  void ReplaceSurface( RenderSurface* newSurface );
 
   /**
-   * Inform the render thread that there is a new surface. Should be used
-   * after SurfaceLost() has been used to inform RenderThread that the surface
-   * has gone.
+   * Set the refresh rate for rendering
    *
-   * @param[in] newSurface The new surface for rendering.
+   * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
+   *
+   * @note Should only be called by the Event Thread.
    */
-  bool NewSurface( RenderSurface* newSurface );
+  void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the Update Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Called by Update thread before it runs the update. This is the point where we can pause
+   * Called by Update thread when it is ready to run the update.
+   *
+   * @param[in] notifyEvent Whether the event thread should be woken up.
+   * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
+   * @param[out] lastFrameDeltaSeconds The delta, in seconds (with float precision), between the last two renders.
+   * @param[out] lastSyncTimeMilliseconds The time, in milliseconds, of the last Sync.
+   * @param[out] nextSyncTimeMilliseconds The estimated time, in milliseconds, at the next Sync.
+   * @return true if updating should continue, false if the update-thread should quit.
+   *
+   * @note Should only be called by the Update thread.
    */
-  void UpdateReadyToRun();
+  bool UpdateReady( bool notifyEvent, bool runUpdate, float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the Render Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Called after an update has completed, to inform render-thread a buffer is ready to render.
-   * The function also waits for a free buffer to become available before returning.
-   * @pre Called by update thread only.
-   * @param[in] notifyEvent Whether the event thread should be woken up.
-   * @param[out] renderNeedsUpdate Whether the render task requires another update.
-   * @return True if updating should continue, false if the update-thread should quit.
+   * Called by the Render thread when it is ready to render.
+   *
+   * @param[in] request Pointer to set if there are any requests. This does not need to be freed by the caller.
+   *
+   * @note Should only be called by the Render thread.
+   * @note If there is a request, then the Render thread should NOT perform a Render and only process the request
    */
-  bool UpdateSyncWithRender( bool notifyEvent, bool& renderNeedsUpdate );
+  bool RenderReady( RenderRequest*& request );
 
   /**
-   * Called by update thread to wait for all rendering to finish.
-   * Used by update to check the status of the final render before pausing.
-   * @pre Called by update thread only.
+   * Called by the Render thread to inform the synchronization class that the surface has been replaced.
+   *
+   * @note Should only be called by the Render thread.
    */
-  void UpdateWaitForAllRenderingToFinish();
+  void RenderInformSurfaceReplaced();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by the V-Sync Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Try block the update-thread when there's nothing to update.
-   * @return True if updating should continue, false if the update-thread should quit.
+   * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
+   *
+   * @param[in] validSync True if the sync was valid (@see VSyncMonitor::DoSync)
+   * @param[in] frameNumber The current frame number
+   * @param[in] seconds The current time
+   * @param[in] microseconds The current time
+   * @param[out] numberOfVSyncsPerRender The number of frames per render.
+   * @return true if VSync monitoring/notifications should continue.
+   *
+   * @note Should only be called by the VSync thread.
+   * @note The first call to this method should be BEFORE the actual VSync so a thread-sync point can be established (and startup time is not delayed).
    */
-  bool UpdateTryToSleep();
+  bool VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by ALL Threads
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Block the render thread whilst waiting for requests e.g. providing a new
-   * surface.
-   * @param[in] request Pointer to set if there are any requests
+   * Helper to add a performance marker to the performance server (if it's active)
+   * @param type performance marker type
    */
-  bool RenderSyncWithRequest(RenderRequest*& request );
+  void AddPerformanceMarker( PerformanceInterface::MarkerType type );
+
+private:
+
+  // Undefined copy constructor.
+  ThreadSynchronization( const ThreadSynchronization& );
+
+  // Undefined assignment operator.
+  ThreadSynchronization& operator=( const ThreadSynchronization& );
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by ALL Threads
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Called by the render-thread to wait for a buffer to read from and then render.
-   * @pre Called by render thread only.
-   * @param[in] request Pointer to set if there are any requests
-   * @return True if rendering should continue, false if the render-thread should quit.
+   * Called by the update, render & v-sync thread when they up and running.
+   * This will lock the mutex in mEventThreadWaitCondition.
    */
-  bool RenderSyncWithUpdate( RenderRequest*& request);
+  inline void NotifyThreadInitialised();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by Update Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Called by the render thread after it renders a frame.
-   * Used to notify the update-thread that a frame has been rendered.
-   * @pre Called by render thread only.
-   * @param[in] updateRequired Whether a further update is required.
-   * @param[in] requestProcessed True if a render request was processed this frame
+   * Called by the update-thread when the state is State::INITIALISING.
+   * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
    */
-  void RenderFinished( bool updateRequired, bool requestProcessed );
+  void UpdateInitialising();
 
   /**
-   * Called by the render/update threads to wait for a Synchronization
+   * Called by the update thread to attempt to sleep.
+   * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
    */
-  void WaitSync();
+  void UpdateTryToSleep( bool runUpdate );
 
   /**
-   * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
-   * @param[in] validSync True if the sync was valid (@see VSyncMonitor::DoSync)
-   * @param[in] frameNumber The current frame number
-   * @param[in] seconds The current time
-   * @param[in] microseconds The current time
-   * @param[out] numberOfVSyncsPerRender The number of frames per render.
-   * @return true if VSync monitoring/notifications should continue.
+   * Called by the update thread to wait while the render-surface is being replaced.
+   * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
    */
-  bool VSyncNotifierSyncWithUpdateAndRender( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
+  void UpdateWaitIfReplacingSurface();
 
   /**
-   * Sets the expected minimum frame time interval.
-   * @param[in]  interval  The interval in microseconds.
+   * Called by the update thread to check if we're just resuming.
+   * This will lock the mutex in mUpdateThreadWaitCondition.
    */
-  void SetMinimumFrameTimeInterval( unsigned int timeInterval );
+  inline bool IsUpdateThreadResuming();
 
   /**
-   * Predicts when the next render time will occur.
+   * Called by the update thread to check if the update thread should be running.
+   * This will lock the mutex in mUpdateThreadWaitCondition.
    *
-   * @param[out]  lastFrameDeltaSeconds      The delta, in seconds (with float precision), between the last two renders.
-   * @param[out]  lastSyncTimeMilliseconds  The time, in milliseconds, of the last Sync.
-   * @param[out]  nextSyncTimeMilliseconds  The estimated time, in milliseconds, at the next Sync.
-   *
-   * @note Should only be called once per tick, from the update thread.
+   * @return True if we're stopping, false otherwise.
    */
-  void PredictNextSyncTime( float& lastFrameDeltaSeconds,
-                            unsigned int& lastSyncTimeMilliseconds,
-                            unsigned int& nextSyncTimeMilliseconds );
+  inline bool IsUpdateThreadStopping();
 
   /**
-   * Retrieves the last sync frame number.
-   * This is a count of the number of synchronised update/render
-   * frames, not a count of hardware VSync frames.
+   * Called by the update thread to check if we've filled all update buffers.
+   * This will lock the mutex in mRenderThreadWaitCondition.
    *
-   * @return The sync frame number.
+   * @return True if all update buffers are full.
    */
-  unsigned int GetFrameNumber() const;
+  inline bool MaximumUpdateAheadOfRenderReached();
 
   /**
-   * Retrieves the time (in microseconds) at the last VSync
-   * @return The VSync timestamp in microseconds.
+   * Called by the update thread when we are about to stop.
+   * This will call other functions which lock various conditional wait mutexes.
    */
-  uint64_t GetTimeMicroseconds();
+  inline void StopAllThreads();
 
   /**
-   * Set the refresh rate for rendering
-   * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
+   * Runs the V-Sync Thread.
+   * This will lock the mutex in mVSyncThreadWaitCondition.
    */
-  void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
+  inline void RunVSyncThread();
 
-private:
+  /**
+   * Pauses the V-Sync Thread.
+   * This will lock the mutex in mVSyncThreadWaitCondition.
+   */
+  inline void PauseVSyncThread();
 
-  // Undefined copy constructor.
-  ThreadSynchronization( const ThreadSynchronization& );
+  /**
+   * Stops the V-Sync Thread.
+   * This will lock the mutex in mVSyncThreadWaitCondition.
+   */
+  inline void StopVSyncThread();
 
-  // Undefined assignment operator.
-  ThreadSynchronization& operator=( const ThreadSynchronization& );
+  /**
+   * Stops the Render Thread.
+   * This will lock the mutex in mRenderThreadWaitCondition.
+   */
+  inline void StopRenderThread();
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by V-Sync Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
   /**
-   * Helper to add a performance marker to the performance server (if its active)
-   * @param type performance marker type
+   * Checks if the V-Sync thread should be running.
+   * This will lock the mutex in mVSyncThreadWaitCondition.
+   *
+   * @return true if running, false otherwise.
    */
-  void AddPerformanceMarker( PerformanceInterface::MarkerType type );
+  inline bool IsVSyncThreadRunning();
 
-private:
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Called by Render Thread
+  /////////////////////////////////////////////////////////////////////////////////////////////////
 
-  const unsigned int mMaximumUpdateCount;             ///< How many frames may be prepared, ahead of the rendering.
+  /**
+   * Checks if the Render thread should be running.
+   * This will lock the mutex in mRenderThreadWaitCondition.
+   *
+   * @return true if running, false otherwise.
+   */
+  inline bool IsRenderThreadRunning();
 
-  unsigned int mNumberOfVSyncsPerRender;              ///< How many frames for each update/render cycle.
+  /**
+   * Checks if the render thread should be replacing the surface
+   * This will lock the mutex in mRenderThreadWaitCondition.
+   *
+   * @return true if the render thread should be replacing the surface, false otherwise.
+   */
+  inline bool IsRenderThreadReplacingSurface();
+
+private:
 
-  volatile unsigned int mUpdateReadyCount;            ///< Incremented after each update, decremented after each render (protected by mMutex)
-  // ARM CPUs perform aligned 32 bit read/writes atomically, so the following variables do not require mutex protection on modification
-  volatile int mRunning;                              ///< Used during UpdateThread::Stop() to exit the update & render loops
-  volatile int mUpdateRequired;                       ///< Used to inform the update thread, that render requires another update
-  volatile int mPaused;                               ///< The paused flag
-  volatile int mUpdateRequested;                      ///< An update has been requested
-  volatile int mAllowUpdateWhilePaused;               ///< whether to allow (one) update while paused
-  volatile int mVSyncSleep;                           ///< Set true when the VSync thread should sleep
-  volatile unsigned int mSyncFrameNumber;            ///< Frame number of latest Sync
-  volatile unsigned int mSyncSeconds;                ///< Timestamp (seconds) of latest Sync
-  volatile unsigned int mSyncMicroseconds;           ///< Timestamp (microseconds) of latest Sync
-
-  boost::mutex mMutex;                                ///< This mutex must be locked before reading/writing mUpdateReadyCount
-  boost::condition_variable mUpdateFinishedCondition; ///< The render thread waits for this condition
-  boost::condition_variable mUpdateSleepCondition;    ///< The update thread waits for this condition when sleeping
-  boost::condition_variable mRenderFinishedCondition; ///< The update thread waits for this condition
-  boost::condition_variable mVSyncReceivedCondition;  ///< The render thread waits on this condition
-  boost::condition_variable mVSyncSleepCondition;     ///< The vsync thread waits for this condition
-  boost::condition_variable mPausedCondition;         ///< The controller waits for this condition while paused
-  boost::condition_variable mRenderRequestSleepCondition;   ///< The render thread waits for this condition
-  boost::condition_variable mRenderRequestFinishedCondition;///< The controller waits for this condition
+  struct State
+  {
+    enum Type
+    {
+      STOPPED,
+      INITIALISING,
+      RUNNING,
+      PAUSED,
+      SLEEPING,
+      REPLACING_SURFACE
+    };
+  };
 
   FrameTime mFrameTime;                               ///< Frame timer predicts next vsync time
   TriggerEventInterface& mNotificationTrigger;        ///< Reference to notification event trigger
   PerformanceInterface* mPerformanceInterface;        ///< The performance logging interface
+  ReplaceSurfaceRequest mReplaceSurfaceRequest;       ///< Holder for a replace surface request
+
+  ConditionalWait mUpdateThreadWaitCondition;         ///< The wait condition for the update-thread.
+  ConditionalWait mRenderThreadWaitCondition;         ///< The wait condition for the render-thread.
+  ConditionalWait mVSyncThreadWaitCondition;          ///< The wait condition for the v-sync-thread.
+  ConditionalWait mEventThreadWaitCondition;          ///< The wait condition for the event-thread.
+
+  const int mMaximumUpdateCount;                      ///< How many frames may be prepared, ahead of the rendering.
+  unsigned int mNumberOfVSyncsPerRender;              ///< How many frames for each update/render cycle.
+
+  unsigned int mTryToSleepCount;                      ///< Count to ensure we don't go to sleep too early
+
+  volatile State::Type mState;                        ///< The current state of synchronisation (set & read by both the event & update threads).
+
+  volatile int mVSyncAheadOfUpdate;                   ///< The number of frames vsync is ahead of update (set & read by both the v-sync & update threads).
+  volatile int mUpdateAheadOfRender;                  ///< The number of frames update is ahead of render (set & read by both the update & render threads).
+  volatile int mNumberOfThreadsStarted;               ///< The number of threads that are initialised and running (set by update, v-sync & render threads, read by event-thread).
+
+  //
+  // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write
+  //
+
+  volatile unsigned int mUpdateThreadResuming;        ///< Whether the update-thread is resuming.
+
+  volatile unsigned int mVSyncThreadRunning;          ///< Whether the V-Sync thread is running (set by the update-thread, read by v-sync-thread).
+  volatile unsigned int mVSyncThreadStop;             ///< Whether the V-Sync thread should be stopped (set by the update-thread, read by the v-sync-thread).
+
+  volatile unsigned int mRenderThreadStop;            ///< Whether the render-thread should be stopped (set by the update-thread, read by the render-thread).
+  volatile unsigned int mRenderThreadReplacingSurface;///< Whether the render-thread should replace the surface (set by the event & render threads, read by the render-thread).
 
-  ReplaceSurfaceRequest mReplaceSurfaceRequest; ///< Holder for a replace surface request
-  bool mReplaceSurfaceRequested; ///< True if there is a new replace surface request
+  volatile unsigned int mEventThreadSurfaceReplaced;  ///< Checked by the event-thread & set by the render-thread when the surface has been replaced (set by the event & render threads, read by the event-thread).
 
+  unsigned int mVSyncThreadInitialised;               ///< Whether the V-Sync thread has been initialised (only used by v-sync-thread).
+  unsigned int mRenderThreadInitialised;              ///< Whether the render-thread has been initialised (only used by the render-thread).
+  unsigned int mRenderThreadSurfaceReplaced;          ///< Whether the render-thread has replaced the surface (only used by render-thread).
 }; // class ThreadSynchronization
 
 } // namespace Adaptor
@@ -292,4 +396,4 @@ private:
 
 } // namespace Dali
 
-#endif // __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
+#endif // __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
index a1b6a00..451d301 100644 (file)
@@ -48,7 +48,7 @@ Integration::Log::Filter* gUpdateLogFilter = Integration::Log::Filter::New(Debug
 UpdateThread::UpdateThread( ThreadSynchronization& sync,
                             AdaptorInternalServices& adaptorInterfaces,
                             const EnvironmentOptions& environmentOptions )
-: mThreadSync( sync ),
+: mThreadSynchronization( sync ),
   mCore( adaptorInterfaces.GetCore()),
   mFpsTrackingSeconds( fabsf( environmentOptions.GetFrameRateLoggingFrequency() ) ),
   mFrameCount( 0.0f ),
@@ -97,69 +97,55 @@ void UpdateThread::Stop()
 bool UpdateThread::Run()
 {
   DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run()\n");
-  Integration::UpdateStatus status;
 
-  // install a function for logging
+  // Install a function for logging
   mEnvironmentOptions.InstallLogFunction();
 
-  bool running( true );
+  Integration::UpdateStatus status;
+  bool runUpdate = true;
+  float lastFrameDelta( 0.0f );
+  unsigned int lastSyncTime( 0 );
+  unsigned int nextSyncTime( 0 );
 
   // Update loop, we stay inside here while the update-thread is running
-  while ( running )
+  // We also get the last delta and the predict when this update will be rendered
+  while ( mThreadSynchronization.UpdateReady( status.NeedsNotification(), runUpdate, lastFrameDelta, lastSyncTime, nextSyncTime ) )
   {
-    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 1 - Sync()\n");
-
-    // Inform synchronization object update is ready to run, this will pause update thread if required.
-    mThreadSync.UpdateReadyToRun();
-    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 2 - Ready()\n");
+    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 1 - UpdateReady(delta:%f, lastSync:%u, nextSync:%u)\n", lastFrameDelta, lastSyncTime, nextSyncTime);
 
-    // get the last delta and the predict when this update will be rendered
-    float lastFrameDelta( 0.0f );
-    unsigned int lastSyncTime( 0 );
-    unsigned int nextSyncTime( 0 );
-    mThreadSync.PredictNextSyncTime( lastFrameDelta, lastSyncTime, nextSyncTime );
-
-    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 3 - Update(delta:%f, lastSync:%u, nextSync:%u)\n", lastFrameDelta, lastSyncTime, nextSyncTime);
+    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 2 - Core.Update()\n");
 
+    mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::UPDATE_START );
     mCore.Update( lastFrameDelta, lastSyncTime, nextSyncTime, status );
+    mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::UPDATE_END );
 
     if( mFpsTrackingSeconds > 0.f )
     {
       FPSTracking(status.SecondsFromLastFrame());
     }
 
-    bool renderNeedsUpdate;
-
-    // tell the synchronisation class that a buffer has been written to,
-    // and to wait until there is a free buffer to write to
-    running = mThreadSync.UpdateSyncWithRender( status.NeedsNotification(), renderNeedsUpdate );
-    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 4 - UpdateSyncWithRender complete\n");
+    unsigned int keepUpdatingStatus = status.KeepUpdating();
 
-    if( running )
+    // Optional logging of update/render status
+    if ( mStatusLogInterval )
     {
-      unsigned int keepUpdatingStatus = status.KeepUpdating();
-
-      // Optional logging of update/render status
-      if ( mStatusLogInterval )
-      {
-        UpdateStatusLogging( keepUpdatingStatus, renderNeedsUpdate );
-      }
+      UpdateStatusLogging( keepUpdatingStatus );
+    }
 
-      //  2 things can keep update running.
-      // - The status of the last update
-      // - The status of the last render
-      bool runUpdate = (Integration::KeepUpdating::NOT_REQUESTED != keepUpdatingStatus) || renderNeedsUpdate;
+    //  2 things can keep update running.
+    // - The status of the last update
+    // - The status of the last render
+    runUpdate = (Integration::KeepUpdating::NOT_REQUESTED != keepUpdatingStatus);
 
-      if( !runUpdate )
-      {
-        DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 5 - Nothing to update, trying to sleep\n");
+    DALI_LOG_INFO( gUpdateLogFilter, Debug::Verbose, "UpdateThread::Run. 3 - runUpdate(%d)\n", runUpdate );
 
-        running = mThreadSync.UpdateTryToSleep();
-      }
-    }
+    // Reset time variables
+    lastFrameDelta = 0.0f;
+    lastSyncTime = 0;
+    nextSyncTime = 0;
   }
 
-  // uninstall a function for logging
+  // Uninstall the logging function
   mEnvironmentOptions.UnInstallLogFunction();
 
   return true;
@@ -196,7 +182,7 @@ void UpdateThread::OutputFPSRecord()
   }
 }
 
-void UpdateThread::UpdateStatusLogging( unsigned int keepUpdatingStatus, bool renderNeedsUpdate )
+void UpdateThread::UpdateStatusLogging( unsigned int keepUpdatingStatus )
 {
   DALI_ASSERT_ALWAYS( mStatusLogInterval );
 
@@ -236,11 +222,6 @@ void UpdateThread::UpdateStatusLogging( unsigned int keepUpdatingStatus, bool re
       oss += "<Render task waiting for completion> ";
     }
 
-    if ( renderNeedsUpdate )
-    {
-      oss  +=  "<Render needs Update> ";
-    }
-
     DALI_LOG_UPDATE_STATUS( "%s\n", oss.c_str());
   }
 }
index faa512e..2043277 100644 (file)
@@ -95,9 +95,8 @@ private:
   /**
    * Optionally output the update thread status.
    * @param[in] keepUpdatingStatus Whether the update-thread requested further updates.
-   * @param[in] renderNeedsUpdate Whether the render-thread requested another update.
    */
-  void UpdateStatusLogging( unsigned int keepUpdatingStatus, bool renderNeedsUpdate );
+  void UpdateStatusLogging( unsigned int keepUpdatingStatus );
 
   /**
    * Helper for the thread calling the entry function
@@ -111,7 +110,7 @@ private:
 
 private: // Data
 
-  ThreadSynchronization&              mThreadSync;          ///< Used to synchronize all the threads
+  ThreadSynchronization&              mThreadSynchronization; ///< Used to synchronize all the threads
 
   Dali::Integration::Core&            mCore;                ///< Dali core reference
 
index 109a9df..ed6d8a3 100644 (file)
@@ -18,6 +18,8 @@
 // CLASS HEADER
 #include "vsync-notifier.h"
 
+// EXTERNAL INCLUDES
+#include <unistd.h>
 #include <dali/integration-api/core.h>
 #include <dali/integration-api/platform-abstraction.h>
 
@@ -50,7 +52,7 @@ Integration::Log::Filter* gSyncLogFilter = Integration::Log::Filter::New(Debug::
 VSyncNotifier::VSyncNotifier( ThreadSynchronization& sync,
                               AdaptorInternalServices& adaptorInterfaces,
                               const EnvironmentOptions& environmentOptions )
-: mThreadSync( sync ),
+: mThreadSynchronization( sync ),
   mCore( adaptorInterfaces.GetCore() ),
   mPlatformAbstraction( adaptorInterfaces.GetPlatformAbstractionInterface() ),
   mVSyncMonitor( adaptorInterfaces.GetVSyncMonitorInterface() ),
@@ -115,12 +117,10 @@ void VSyncNotifier::Run()
   unsigned int seconds( 0u );
   unsigned int microseconds( 0u );
 
-  bool running( true );
-  while( running )
+  bool validSync( true );
+  while( mThreadSynchronization.VSyncReady( validSync, frameNumber++, currentSeconds, currentMicroseconds, mNumberOfVSyncsPerRender ) )
   {
-    DALI_LOG_INFO( gSyncLogFilter, Debug::General, "VSyncNotifier::Run. 1 Start loop \n");
-
-    bool validSync( true );
+    DALI_LOG_INFO( gSyncLogFilter, Debug::General, "VSyncNotifier::Run. 1 SyncWithUpdateAndRender(frame#:%d, current Sec:%u current uSec:%u)\n", frameNumber-1, currentSeconds, currentMicroseconds);
 
     // Hardware VSyncs available?
     if( mVSyncMonitor->UseHardware() )
@@ -162,11 +162,7 @@ void VSyncNotifier::Run()
       DALI_LOG_INFO( gSyncLogFilter, Debug::General, "VSyncNotifier::Run. 2 Start software sync (%d frames, %u microseconds) \n", mNumberOfVSyncsPerRender, sleepTimeInMicroseconds);
       usleep( sleepTimeInMicroseconds );
     }
-
-    DALI_LOG_INFO( gSyncLogFilter, Debug::General, "VSyncNotifier::Run. 3 SyncWithUpdateAndRender(frame#:%d, current Sec:%u current uSec:%u)\n", frameNumber+1, currentSeconds, currentMicroseconds);
-
-    running = mThreadSync.VSyncNotifierSyncWithUpdateAndRender( validSync, ++frameNumber, currentSeconds, currentMicroseconds, mNumberOfVSyncsPerRender );
-    // The number of vsyncs per render may have been modified by this call.
+    mThreadSynchronization.AddPerformanceMarker( PerformanceInterface::VSYNC );
   }
 
   // uninstall a function for logging
index 725ce6c..fd6bdc3 100644 (file)
@@ -97,7 +97,7 @@ private:
 
 private:
 
-  ThreadSynchronization&              mThreadSync;              ///< Used to synchronize all the threads
+  ThreadSynchronization&              mThreadSynchronization;   ///< Used to synchronize all the threads
   Dali::Integration::Core&            mCore;                    ///< Dali core reference
   Integration::PlatformAbstraction&   mPlatformAbstraction;     ///< The platform abstraction for retrieving the current time etc.
   VSyncMonitorInterface*              mVSyncMonitor;            ///< VSyncMonitor interface
index db6189b..57d01a0 100644 (file)
@@ -257,8 +257,8 @@ void Adaptor::Start()
   PositionSize size = mSurface->GetPositionSize();
   mCore->SurfaceResized( size.width, size.height );
 
-  // Start all the threads
-  mThreadController->Start();
+  // Initialize the thread controller
+  mThreadController->Initialize();
 
   mState = RUNNING;
 
@@ -300,17 +300,8 @@ void Adaptor::Resume()
   // Only resume the adaptor if we are in the suspended state.
   if( PAUSED == mState )
   {
-    // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
-    // If there were events pending, mCore->Resume() will call
-    //   RenderController->RequestUpdate()
-    //     ThreadController->RequestUpdate()
-    //       ThreadSynchronization->RequestUpdate()
-    // and we should have reset the frame timers before allowing Core->Update() to be called.
-    //@todo Should we call ThreadController->Resume before mCore->Resume()?
-
-    mThreadController->ResumeFrameTime();
+    // Resume core first
     mCore->Resume();
-    mThreadController->Resume();
 
     mState = RUNNING;
 
@@ -327,6 +318,9 @@ void Adaptor::Resume()
     }
 
     ProcessCoreEvents(); // Ensure any outstanding messages are processed
+
+    // Ensure our first update includes the processed messages
+    mThreadController->Resume();
   }
 }
 
@@ -734,6 +728,9 @@ void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
 void Adaptor::NotifySceneCreated()
 {
   GetCore().SceneCreated();
+
+  // Start thread controller after the scene has been created
+  mThreadController->Start();
 }
 
 void Adaptor::NotifyLanguageChanged()
index 61704c1..3bccd22 100644 (file)
@@ -60,7 +60,7 @@ public:
     /* Do nothing in main implementation */
   }
 
-  void PostRender( unsigned int timeDelta )
+  void PostRender()
   {
     /* Do nothing in main implementation */
   }
index 61c4677..b23728d 100644 (file)
@@ -135,10 +135,9 @@ public:
    * @param[in] egl The Egl interface
    * @param[in] glAbstraction OpenGLES abstraction interface
    * @param[in] displayConnection display connection
-   * @param[in] deltaTime Time (in microseconds) since PostRender was last called.
    * @param[in] replacingSurface True if the surface is being replaced.
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface ) = 0;
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface ) = 0;
 
   /**
    * @brief Invoked by render thread when the thread should be stop
index cb595fe..99ceb45 100644 (file)
@@ -139,7 +139,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface ) = 0;
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface ) = 0;
 
   /**
    * @copydoc Dali::RenderSurface::ReleaseLock()
index bb7a0e4..ebe2532 100644 (file)
@@ -100,7 +100,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface );
 
   /**
    * @copydoc Dali::RenderSurface::StopRender()
index 1280125..7aed8b5 100644 (file)
@@ -147,7 +147,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface ) = 0;
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface ) = 0;
 
   /**
    * @copydoc Dali::RenderSurface::ReleaseLock()
index cd9b5ce..b90e324 100644 (file)
@@ -100,7 +100,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface );
 
   /**
    * @copydoc Dali::RenderSurface::StopRender()
index 6d7a716..f104850 100644 (file)
@@ -114,7 +114,7 @@ bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
+void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
 {
   // flush gl instruction queue
   glAbstraction.Flush();
index f2d83ba..cd565c9 100644 (file)
@@ -175,7 +175,7 @@ bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
+void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
 {
   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
   eglImpl.SwapBuffers();
index 4102522..9a27b8b 100644 (file)
@@ -126,7 +126,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface );
 
   /**
    * @copydoc Dali::RenderSurface::StopRender()
index 6f7b09b..fa26edb 100644 (file)
@@ -147,7 +147,7 @@ bool PixmapRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
+void PixmapRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
 {
   // flush gl instruction queue
   glAbstraction.Flush();
index 1f43521..18b8d14 100644 (file)
@@ -188,7 +188,7 @@ bool WindowRenderSurface::PreRender( EglInterface&, Integration::GlAbstraction&
   return true;
 }
 
-void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface )
+void WindowRenderSurface::PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface )
 {
   Internal::Adaptor::EglImplementation& eglImpl = static_cast<Internal::Adaptor::EglImplementation&>( egl );
   eglImpl.SwapBuffers();
index 45c58ff..77b5e0a 100644 (file)
@@ -127,7 +127,7 @@ public: // from Dali::RenderSurface
   /**
    * @copydoc Dali::RenderSurface::PostRender()
    */
-  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, unsigned int deltaTime, bool replacingSurface );
+  virtual void PostRender( EglInterface& egl, Integration::GlAbstraction& glAbstraction, DisplayConnection* displayConnection, bool replacingSurface );
 
   /**
    * @copydoc Dali::RenderSurface::StopRender()
index 7ca22a5..fa51412 100644 (file)
@@ -54,7 +54,7 @@ public:
   void Initialize();
 
   void PreRender();
-  void PostRender(unsigned int timeDelta);
+  void PostRender();
 
   /* OpenGL ES 2.0 */