1 #ifndef __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
2 #define __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
5 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 #include <dali/devel-api/threading/conditional-wait.h>
25 #include <integration-api/thread-synchronization-interface.h>
26 #include <base/interfaces/performance-interface.h>
27 #include <trigger-event-interface.h>
28 #include <base/frame-time.h>
29 #include <base/render-thread.h>
42 class AdaptorInternalServices;
45 * This object is used to synchronize the update, render and vsync threads.
46 * The Core::GetMaximumUpdateCount() method determines how many frames may be prepared, ahead of the rendering.
47 * For example if the maximum update count is 2, then Core::Update() for frame N+1 may be processed whilst frame N is being rendered.
48 * However the Core::Update() for frame N+2 may not be called, until the Core::Render() method for frame N has returned.
51 class ThreadSynchronization : public Dali::ThreadSynchronizationInterface
56 * Create an update/render synchronization object.
57 * @param[in] adaptorInterfaces base adaptor interface
58 * @param[in] numberOfVSyncsPerRender The number of frames per render
60 ThreadSynchronization( AdaptorInternalServices& adaptorInterfaces, unsigned int numberOfVSyncsPerRender );
63 * Non virtual destructor. Not intended as base class.
65 ~ThreadSynchronization();
67 /////////////////////////////////////////////////////////////////////////////////////////////////
68 // Called by the Event Thread
69 /////////////////////////////////////////////////////////////////////////////////////////////////
72 * Initialises the ThreadSynchronisation class. The expectation is that this function will be
73 * called when all threads are about to be set up and that Start will be called when
74 * the the scene is actually prepared and ready to be displayed. This way our first update
75 * will have the actual scene we require.
77 * @note Should only be called by the Event Thread.
82 * Starts running all threads. This waits until all threads are up and running.
84 * @pre A call to Initialise has been made.
86 * @note Should only be called by the Event Thread.
93 * @note Should only be called by the Event Thread.
98 * Pause the controller (and threads).
100 * @note Should only be called by the Event Thread.
105 * Resume the controller (and threads).
107 * @note Should only be called by the Event Thread.
112 * Wake update thread if sleeping. If the update thread is not sleeping
113 * this becomes a no-op.
114 * Called when an update is requested by Core.
115 * i.e. when a batch of messages have been queued for the next update.
117 * @note Should only be called by the Event Thread.
119 void UpdateRequest();
122 * Update once (even if paused)
124 * @note Should only be called by the Event Thread.
129 * Inform the render thread that there is a new surface, and that
130 * it should replace the current surface.
132 * @param[in] newSurface The new surface for rendering.
134 * @note Should only be called by the Event Thread.
136 void ReplaceSurface( RenderSurface* newSurface );
139 * Set the refresh rate for rendering
141 * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
143 * @note Should only be called by the Event Thread.
145 void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
147 /////////////////////////////////////////////////////////////////////////////////////////////////
148 // Called by the Update Thread
149 /////////////////////////////////////////////////////////////////////////////////////////////////
152 * Called by Update thread when it is ready to run the update.
154 * @param[in] notifyEvent Whether the event thread should be woken up.
155 * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
156 * @param[out] lastFrameDeltaSeconds The delta, in seconds (with float precision), between the last two renders.
157 * @param[out] lastSyncTimeMilliseconds The time, in milliseconds, of the last Sync.
158 * @param[out] nextSyncTimeMilliseconds The estimated time, in milliseconds, at the next Sync.
159 * @return true if updating should continue, false if the update-thread should quit.
161 * @note Should only be called by the Update thread.
163 bool UpdateReady( bool notifyEvent, bool runUpdate, float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds );
165 /////////////////////////////////////////////////////////////////////////////////////////////////
166 // Called by the Render Thread
167 /////////////////////////////////////////////////////////////////////////////////////////////////
170 * Called by the Render thread when it is ready to render.
172 * @param[in] request Pointer to set if there are any requests. This does not need to be freed by the caller.
174 * @note Should only be called by the Render thread.
175 * @note If there is a request, then the Render thread should NOT perform a Render and only process the request
177 bool RenderReady( RenderRequest*& request );
180 * Called by the render thread after it renders a frame.
181 * Used to notify the update-thread that a frame has been rendered.
182 * @pre Called by render thread only.
184 void RenderFinished();
187 * Called by the Render thread to inform the synchronization class that the surface has been replaced.
189 * @note Should only be called by the Render thread.
191 void RenderInformSurfaceReplaced();
193 /////////////////////////////////////////////////////////////////////////////////////////////////
194 // Called by the V-Sync Thread
195 /////////////////////////////////////////////////////////////////////////////////////////////////
198 * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
200 * @param[in] validSync True if the sync was valid (@see VSyncMonitor::DoSync)
201 * @param[in] frameNumber The current frame number
202 * @param[in] seconds The current time
203 * @param[in] microseconds The current time
204 * @param[out] numberOfVSyncsPerRender The number of frames per render.
205 * @return true if VSync monitoring/notifications should continue.
207 * @note Should only be called by the VSync thread.
208 * @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).
210 bool VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
212 /////////////////////////////////////////////////////////////////////////////////////////////////
214 /////////////////////////////////////////////////////////////////////////////////////////////////
216 /////////////////////////////////////////////////////////////////////////////////////////////////
217 //// Called by the Event Thread if post-rendering is required
218 /////////////////////////////////////////////////////////////////////////////////////////////////
221 * @copydoc ThreadSynchronizationInterface::PostRenderComplete()
223 void PostRenderComplete();
225 /////////////////////////////////////////////////////////////////////////////////////////////////
226 //// Called by the Render Thread if post-rendering is required
227 /////////////////////////////////////////////////////////////////////////////////////////////////
230 * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
232 void PostRenderStarted();
235 * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
237 void PostRenderWaitForCompletion();
239 /////////////////////////////////////////////////////////////////////////////////////////////////
240 // Called by ALL Threads
241 /////////////////////////////////////////////////////////////////////////////////////////////////
244 * Helper to add a performance marker to the performance server (if it's active)
245 * @param type performance marker type
247 void AddPerformanceMarker( PerformanceInterface::MarkerType type );
251 // Undefined copy constructor.
252 ThreadSynchronization( const ThreadSynchronization& );
254 // Undefined assignment operator.
255 ThreadSynchronization& operator=( const ThreadSynchronization& );
257 /////////////////////////////////////////////////////////////////////////////////////////////////
258 // Called by ALL Threads
259 /////////////////////////////////////////////////////////////////////////////////////////////////
262 * Called by the update, render & v-sync thread when they up and running.
263 * This will lock the mutex in mEventThreadWaitCondition.
265 inline void NotifyThreadInitialised();
267 /////////////////////////////////////////////////////////////////////////////////////////////////
268 // Called by Update Thread
269 /////////////////////////////////////////////////////////////////////////////////////////////////
272 * Called by the update-thread when the state is State::INITIALISING.
273 * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
275 void UpdateInitialising();
278 * Called by the update thread to attempt to sleep.
279 * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
281 void UpdateTryToSleep( bool runUpdate );
284 * Called by the update thread to wait while the render-surface is being replaced.
285 * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
287 void UpdateWaitIfReplacingSurface();
290 * Called by the update thread to check if we're just resuming.
291 * This will lock the mutex in mUpdateThreadWaitCondition.
293 inline bool IsUpdateThreadResuming();
296 * Called by the update thread to check if the update thread should be running.
297 * This will lock the mutex in mUpdateThreadWaitCondition.
299 * @return True if we're stopping, false otherwise.
301 inline bool IsUpdateThreadStopping();
304 * Called by the update thread to check if we've filled all update buffers.
305 * This will lock the mutex in mRenderThreadWaitCondition.
307 * @return True if all update buffers are full.
309 inline bool MaximumUpdateAheadOfRenderReached();
312 * Called by the update thread when we are about to stop.
313 * This will call other functions which lock various conditional wait mutexes.
315 inline void StopAllThreads();
318 * Runs the V-Sync Thread.
319 * This will lock the mutex in mVSyncThreadWaitCondition.
321 inline void RunVSyncThread();
324 * Pauses the V-Sync Thread.
325 * This will lock the mutex in mVSyncThreadWaitCondition.
327 inline void PauseVSyncThread();
330 * Stops the V-Sync Thread.
331 * This will lock the mutex in mVSyncThreadWaitCondition.
333 inline void StopVSyncThread();
336 * Stops the Render Thread.
337 * This will lock the mutex in mRenderThreadWaitCondition.
339 inline void StopRenderThread();
341 /////////////////////////////////////////////////////////////////////////////////////////////////
342 // Called by V-Sync Thread
343 /////////////////////////////////////////////////////////////////////////////////////////////////
346 * Checks if the V-Sync thread should be running.
347 * This will lock the mutex in mVSyncThreadWaitCondition.
349 * @return true if running, false otherwise.
351 inline bool IsVSyncThreadRunning();
353 /////////////////////////////////////////////////////////////////////////////////////////////////
354 // Called by Render Thread
355 /////////////////////////////////////////////////////////////////////////////////////////////////
358 * Checks if the Render thread should be running.
359 * This will lock the mutex in mRenderThreadWaitCondition.
361 * @return true if running, false otherwise.
363 inline bool IsRenderThreadRunning();
366 * Checks if the render thread should be replacing the surface
367 * This will lock the mutex in mRenderThreadWaitCondition.
369 * @return true if the render thread should be replacing the surface, false otherwise.
371 inline bool IsRenderThreadReplacingSurface();
388 FrameTime mFrameTime; ///< Frame timer predicts next vsync time
389 TriggerEventInterface& mNotificationTrigger; ///< Reference to notification event trigger
390 PerformanceInterface* mPerformanceInterface; ///< The performance logging interface
391 ReplaceSurfaceRequest mReplaceSurfaceRequest; ///< Holder for a replace surface request
393 ConditionalWait mUpdateThreadWaitCondition; ///< The wait condition for the update-thread.
394 ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the render-thread.
395 ConditionalWait mVSyncThreadWaitCondition; ///< The wait condition for the v-sync-thread.
396 ConditionalWait mEventThreadWaitCondition; ///< The wait condition for the event-thread.
398 const int mMaximumUpdateCount; ///< How many frames may be prepared, ahead of the rendering.
399 unsigned int mNumberOfVSyncsPerRender; ///< How many frames for each update/render cycle.
401 unsigned int mTryToSleepCount; ///< Count to ensure we don't go to sleep too early
403 volatile State::Type mState; ///< The current state of synchronisation (set & read by both the event & update threads).
405 volatile int mVSyncAheadOfUpdate; ///< The number of frames vsync is ahead of update (set & read by both the v-sync & update threads).
406 volatile int mUpdateAheadOfRender; ///< The number of frames update is ahead of render (set & read by both the update & render threads).
407 volatile int mNumberOfThreadsStarted; ///< The number of threads that are initialised and running (set by update, v-sync & render threads, read by event-thread).
410 // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write
413 volatile unsigned int mUpdateThreadResuming; ///< Whether the update-thread is resuming.
415 volatile unsigned int mVSyncThreadRunning; ///< Whether the V-Sync thread is running (set by the update-thread, read by v-sync-thread).
416 volatile unsigned int mVSyncThreadStop; ///< Whether the V-Sync thread should be stopped (set by the update-thread, read by the v-sync-thread).
418 volatile unsigned int mRenderThreadStop; ///< Whether the render-thread should be stopped (set by the update-thread, read by the render-thread).
419 volatile unsigned int mRenderThreadReplacingSurface;///< Whether the render-thread should replace the surface (set by the event & render threads, read by the render-thread).
421 volatile unsigned int mRenderThreadPostRendering; ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
423 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).
425 unsigned int mVSyncThreadInitialised; ///< Whether the V-Sync thread has been initialised (only used by v-sync-thread).
426 unsigned int mRenderThreadInitialised; ///< Whether the render-thread has been initialised (only used by the render-thread).
427 unsigned int mRenderThreadSurfaceReplaced; ///< Whether the render-thread has replaced the surface (only used by render-thread).
428 }; // class ThreadSynchronization
430 } // namespace Adaptor
432 } // namespace Internal
436 #endif // __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__