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.
24 #include <base/interfaces/performance-interface.h>
25 #include <base/conditional-wait.h>
26 #include <trigger-event-interface.h>
27 #include <base/frame-time.h>
28 #include <base/render-thread.h>
41 class AdaptorInternalServices;
44 * This object is used to synchronize the update, render and vsync threads.
45 * The Core::GetMaximumUpdateCount() method determines how many frames may be prepared, ahead of the rendering.
46 * 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.
47 * However the Core::Update() for frame N+2 may not be called, until the Core::Render() method for frame N has returned.
50 class ThreadSynchronization
55 * Create an update/render synchronization object.
56 * @param[in] adaptorInterfaces base adaptor interface
57 * @param[in] numberOfVSyncsPerRender The number of frames per render
59 ThreadSynchronization( AdaptorInternalServices& adaptorInterfaces, unsigned int numberOfVSyncsPerRender );
62 * Non virtual destructor. Not intended as base class.
64 ~ThreadSynchronization();
66 /////////////////////////////////////////////////////////////////////////////////////////////////
67 // Called by the Event Thread
68 /////////////////////////////////////////////////////////////////////////////////////////////////
71 * Initialises the ThreadSynchronisation class. The expectation is that this function will be
72 * called when all threads are about to be set up and that Start will be called when
73 * the the scene is actually prepared and ready to be displayed. This way our first update
74 * will have the actual scene we require.
76 * @note Should only be called by the Event Thread.
81 * Starts running all threads. This waits until all threads are up and running.
83 * @pre A call to Initialise has been made.
85 * @note Should only be called by the Event Thread.
92 * @note Should only be called by the Event Thread.
97 * Pause the controller (and threads).
99 * @note Should only be called by the Event Thread.
104 * Resume the controller (and threads).
106 * @note Should only be called by the Event Thread.
111 * Wake update thread if sleeping. If the update thread is not sleeping
112 * this becomes a no-op.
113 * Called when an update is requested by Core.
114 * i.e. when a batch of messages have been queued for the next update.
116 * @note Should only be called by the Event Thread.
118 void UpdateRequest();
121 * Update once (even if paused)
123 * @note Should only be called by the Event Thread.
128 * Inform the render thread that there is a new surface, and that
129 * it should replace the current surface.
131 * @param[in] newSurface The new surface for rendering.
133 * @note Should only be called by the Event Thread.
135 void ReplaceSurface( RenderSurface* newSurface );
138 * Set the refresh rate for rendering
140 * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
142 * @note Should only be called by the Event Thread.
144 void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
146 /////////////////////////////////////////////////////////////////////////////////////////////////
147 // Called by the Update Thread
148 /////////////////////////////////////////////////////////////////////////////////////////////////
151 * Called by Update thread when it is ready to run the update.
153 * @param[in] notifyEvent Whether the event thread should be woken up.
154 * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
155 * @param[out] lastFrameDeltaSeconds The delta, in seconds (with float precision), between the last two renders.
156 * @param[out] lastSyncTimeMilliseconds The time, in milliseconds, of the last Sync.
157 * @param[out] nextSyncTimeMilliseconds The estimated time, in milliseconds, at the next Sync.
158 * @return true if updating should continue, false if the update-thread should quit.
160 * @note Should only be called by the Update thread.
162 bool UpdateReady( bool notifyEvent, bool runUpdate, float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds );
164 /////////////////////////////////////////////////////////////////////////////////////////////////
165 // Called by the Render Thread
166 /////////////////////////////////////////////////////////////////////////////////////////////////
169 * Called by the Render thread when it is ready to render.
171 * @param[in] request Pointer to set if there are any requests. This does not need to be freed by the caller.
173 * @note Should only be called by the Render thread.
174 * @note If there is a request, then the Render thread should NOT perform a Render and only process the request
176 bool RenderReady( RenderRequest*& request );
179 * Called by the Render thread to inform the synchronization class that the surface has been replaced.
181 * @note Should only be called by the Render thread.
183 void RenderInformSurfaceReplaced();
185 /////////////////////////////////////////////////////////////////////////////////////////////////
186 // Called by the V-Sync Thread
187 /////////////////////////////////////////////////////////////////////////////////////////////////
190 * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
192 * @param[in] validSync True if the sync was valid (@see VSyncMonitor::DoSync)
193 * @param[in] frameNumber The current frame number
194 * @param[in] seconds The current time
195 * @param[in] microseconds The current time
196 * @param[out] numberOfVSyncsPerRender The number of frames per render.
197 * @return true if VSync monitoring/notifications should continue.
199 * @note Should only be called by the VSync thread.
200 * @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).
202 bool VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
204 /////////////////////////////////////////////////////////////////////////////////////////////////
205 // Called by ALL Threads
206 /////////////////////////////////////////////////////////////////////////////////////////////////
209 * Helper to add a performance marker to the performance server (if it's active)
210 * @param type performance marker type
212 void AddPerformanceMarker( PerformanceInterface::MarkerType type );
216 // Undefined copy constructor.
217 ThreadSynchronization( const ThreadSynchronization& );
219 // Undefined assignment operator.
220 ThreadSynchronization& operator=( const ThreadSynchronization& );
222 /////////////////////////////////////////////////////////////////////////////////////////////////
223 // Called by ALL Threads
224 /////////////////////////////////////////////////////////////////////////////////////////////////
227 * Called by the update, render & v-sync thread when they up and running.
228 * This will lock the mutex in mEventThreadWaitCondition.
230 inline void NotifyThreadInitialised();
232 /////////////////////////////////////////////////////////////////////////////////////////////////
233 // Called by Update Thread
234 /////////////////////////////////////////////////////////////////////////////////////////////////
237 * Called by the update-thread when the state is State::INITIALISING.
238 * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
240 void UpdateInitialising();
243 * Called by the update thread to attempt to sleep.
244 * @param[in] runUpdate Whether to run another update. If false, then the update-thread will attempt to sleep.
246 void UpdateTryToSleep( bool runUpdate );
249 * Called by the update thread to wait while the render-surface is being replaced.
250 * Calls methods that lock and locks itself so should NOT be called while a scoped-lock is held.
252 void UpdateWaitIfReplacingSurface();
255 * Called by the update thread to check if we're just resuming.
256 * This will lock the mutex in mUpdateThreadWaitCondition.
258 inline bool IsUpdateThreadResuming();
261 * Called by the update thread to check if the update thread should be running.
262 * This will lock the mutex in mUpdateThreadWaitCondition.
264 * @return True if we're stopping, false otherwise.
266 inline bool IsUpdateThreadStopping();
269 * Called by the update thread to check if we've filled all update buffers.
270 * This will lock the mutex in mRenderThreadWaitCondition.
272 * @return True if all update buffers are full.
274 inline bool MaximumUpdateAheadOfRenderReached();
277 * Called by the update thread when we are about to stop.
278 * This will call other functions which lock various conditional wait mutexes.
280 inline void StopAllThreads();
283 * Runs the V-Sync Thread.
284 * This will lock the mutex in mVSyncThreadWaitCondition.
286 inline void RunVSyncThread();
289 * Pauses the V-Sync Thread.
290 * This will lock the mutex in mVSyncThreadWaitCondition.
292 inline void PauseVSyncThread();
295 * Stops the V-Sync Thread.
296 * This will lock the mutex in mVSyncThreadWaitCondition.
298 inline void StopVSyncThread();
301 * Stops the Render Thread.
302 * This will lock the mutex in mRenderThreadWaitCondition.
304 inline void StopRenderThread();
306 /////////////////////////////////////////////////////////////////////////////////////////////////
307 // Called by V-Sync Thread
308 /////////////////////////////////////////////////////////////////////////////////////////////////
311 * Checks if the V-Sync thread should be running.
312 * This will lock the mutex in mVSyncThreadWaitCondition.
314 * @return true if running, false otherwise.
316 inline bool IsVSyncThreadRunning();
318 /////////////////////////////////////////////////////////////////////////////////////////////////
319 // Called by Render Thread
320 /////////////////////////////////////////////////////////////////////////////////////////////////
323 * Checks if the Render thread should be running.
324 * This will lock the mutex in mRenderThreadWaitCondition.
326 * @return true if running, false otherwise.
328 inline bool IsRenderThreadRunning();
331 * Checks if the render thread should be replacing the surface
332 * This will lock the mutex in mRenderThreadWaitCondition.
334 * @return true if the render thread should be replacing the surface, false otherwise.
336 inline bool IsRenderThreadReplacingSurface();
353 FrameTime mFrameTime; ///< Frame timer predicts next vsync time
354 TriggerEventInterface& mNotificationTrigger; ///< Reference to notification event trigger
355 PerformanceInterface* mPerformanceInterface; ///< The performance logging interface
356 ReplaceSurfaceRequest mReplaceSurfaceRequest; ///< Holder for a replace surface request
358 ConditionalWait mUpdateThreadWaitCondition; ///< The wait condition for the update-thread.
359 ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the render-thread.
360 ConditionalWait mVSyncThreadWaitCondition; ///< The wait condition for the v-sync-thread.
361 ConditionalWait mEventThreadWaitCondition; ///< The wait condition for the event-thread.
363 const int mMaximumUpdateCount; ///< How many frames may be prepared, ahead of the rendering.
364 unsigned int mNumberOfVSyncsPerRender; ///< How many frames for each update/render cycle.
366 unsigned int mTryToSleepCount; ///< Count to ensure we don't go to sleep too early
368 volatile State::Type mState; ///< The current state of synchronisation (set & read by both the event & update threads).
370 volatile int mVSyncAheadOfUpdate; ///< The number of frames vsync is ahead of update (set & read by both the v-sync & update threads).
371 volatile int mUpdateAheadOfRender; ///< The number of frames update is ahead of render (set & read by both the update & render threads).
372 volatile int mNumberOfThreadsStarted; ///< The number of threads that are initialised and running (set by update, v-sync & render threads, read by event-thread).
375 // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write
378 volatile unsigned int mUpdateThreadResuming; ///< Whether the update-thread is resuming.
380 volatile unsigned int mVSyncThreadRunning; ///< Whether the V-Sync thread is running (set by the update-thread, read by v-sync-thread).
381 volatile unsigned int mVSyncThreadStop; ///< Whether the V-Sync thread should be stopped (set by the update-thread, read by the v-sync-thread).
383 volatile unsigned int mRenderThreadStop; ///< Whether the render-thread should be stopped (set by the update-thread, read by the render-thread).
384 volatile unsigned int mRenderThreadReplacingSurface;///< Whether the render-thread should replace the surface (set by the event & render threads, read by the render-thread).
386 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).
388 unsigned int mVSyncThreadInitialised; ///< Whether the V-Sync thread has been initialised (only used by v-sync-thread).
389 unsigned int mRenderThreadInitialised; ///< Whether the render-thread has been initialised (only used by the render-thread).
390 unsigned int mRenderThreadSurfaceReplaced; ///< Whether the render-thread has replaced the surface (only used by render-thread).
391 }; // class ThreadSynchronization
393 } // namespace Adaptor
395 } // namespace Internal
399 #endif // __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__