b1106e9f2fded98c28292f57b7e38d55193c89bf
[platform/core/uifw/dali-adaptor.git] / adaptors / base / thread-synchronization.h
1 #ifndef __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
2 #define __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
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
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/threading/conditional-wait.h>
23
24 // INTERNAL INCLUDES
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>
30
31 namespace Dali
32 {
33
34 class RenderSurface;
35
36 namespace Internal
37 {
38
39 namespace Adaptor
40 {
41
42 class AdaptorInternalServices;
43
44 /**
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.
49  *
50  */
51 class ThreadSynchronization : public Dali::ThreadSynchronizationInterface
52 {
53 public:
54
55   /**
56    * Create an update/render synchronization object.
57    * @param[in] adaptorInterfaces base adaptor interface
58    * @param[in] numberOfVSyncsPerRender The number of frames per render
59   */
60   ThreadSynchronization( AdaptorInternalServices& adaptorInterfaces, unsigned int numberOfVSyncsPerRender );
61
62   /**
63    * Non virtual destructor. Not intended as base class.
64    */
65   ~ThreadSynchronization();
66
67   /////////////////////////////////////////////////////////////////////////////////////////////////
68   // Called by the Event Thread
69   /////////////////////////////////////////////////////////////////////////////////////////////////
70
71   /**
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.
76    *
77    * @note Should only be called by the Event Thread.
78    */
79   void Initialise();
80
81   /**
82    * Starts running all threads. This waits until all threads are up and running.
83    *
84    * @pre A call to Initialise has been made.
85    *
86    * @note Should only be called by the Event Thread.
87    */
88   void Start();
89
90   /**
91    * Stop the threads.
92    *
93    * @note Should only be called by the Event Thread.
94    */
95   void Stop();
96
97   /**
98    * Pause the controller (and threads).
99    *
100    * @note Should only be called by the Event Thread.
101    */
102   void Pause();
103
104   /**
105    * Resume the controller (and threads).
106    *
107    * @note Should only be called by the Event Thread.
108    */
109   void Resume();
110
111   /**
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.
116    *
117    * @note Should only be called by the Event Thread.
118    */
119   void UpdateRequest();
120
121   /**
122    * Update once (even if paused)
123    *
124    * @note Should only be called by the Event Thread.
125    */
126   void UpdateOnce();
127
128   /**
129    * Inform the render thread that there is a new surface, and that
130    * it should replace the current surface.
131    *
132    * @param[in] newSurface The new surface for rendering.
133    *
134    * @note Should only be called by the Event Thread.
135    */
136   void ReplaceSurface( RenderSurface* newSurface );
137
138   /**
139    * Set the refresh rate for rendering
140    *
141    * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
142    *
143    * @note Should only be called by the Event Thread.
144    */
145   void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
146
147   /////////////////////////////////////////////////////////////////////////////////////////////////
148   // Called by the Update Thread
149   /////////////////////////////////////////////////////////////////////////////////////////////////
150
151   /**
152    * Called by Update thread when it is ready to run the update.
153    *
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.
160    *
161    * @note Should only be called by the Update thread.
162    */
163   bool UpdateReady( bool notifyEvent, bool runUpdate, float& lastFrameDeltaSeconds, unsigned int& lastSyncTimeMilliseconds, unsigned int& nextSyncTimeMilliseconds );
164
165   /////////////////////////////////////////////////////////////////////////////////////////////////
166   // Called by the Render Thread
167   /////////////////////////////////////////////////////////////////////////////////////////////////
168
169   /**
170    * Called by the Render thread when it is ready to render.
171    *
172    * @param[in] request Pointer to set if there are any requests. This does not need to be freed by the caller.
173    *
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
176    */
177   bool RenderReady( RenderRequest*& request );
178
179   /**
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.
183    */
184   void RenderFinished();
185
186   /**
187    * Called by the Render thread to inform the synchronization class that the surface has been replaced.
188    *
189    * @note Should only be called by the Render thread.
190    */
191   void RenderInformSurfaceReplaced();
192
193   /////////////////////////////////////////////////////////////////////////////////////////////////
194   // Called by the V-Sync Thread
195   /////////////////////////////////////////////////////////////////////////////////////////////////
196
197   /**
198    * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
199    *
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.
206    *
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).
209    */
210   bool VSyncReady( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
211
212   /////////////////////////////////////////////////////////////////////////////////////////////////
213   // POST RENDERING
214   /////////////////////////////////////////////////////////////////////////////////////////////////
215
216   /////////////////////////////////////////////////////////////////////////////////////////////////
217   //// Called by the Event Thread if post-rendering is required
218   /////////////////////////////////////////////////////////////////////////////////////////////////
219
220   /**
221    * @copydoc ThreadSynchronizationInterface::PostRenderComplete()
222    */
223   void PostRenderComplete();
224
225   /////////////////////////////////////////////////////////////////////////////////////////////////
226   //// Called by the Render Thread if post-rendering is required
227   /////////////////////////////////////////////////////////////////////////////////////////////////
228
229   /**
230    * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
231    */
232   void PostRenderStarted();
233
234   /**
235    * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
236    */
237   void PostRenderWaitForCompletion();
238
239   /////////////////////////////////////////////////////////////////////////////////////////////////
240   // Called by ALL Threads
241   /////////////////////////////////////////////////////////////////////////////////////////////////
242
243   /**
244    * Helper to add a performance marker to the performance server (if it's active)
245    * @param type performance marker type
246    */
247   void AddPerformanceMarker( PerformanceInterface::MarkerType type );
248
249 private:
250
251   // Undefined copy constructor.
252   ThreadSynchronization( const ThreadSynchronization& );
253
254   // Undefined assignment operator.
255   ThreadSynchronization& operator=( const ThreadSynchronization& );
256
257   /////////////////////////////////////////////////////////////////////////////////////////////////
258   // Called by ALL Threads
259   /////////////////////////////////////////////////////////////////////////////////////////////////
260
261   /**
262    * Called by the update, render & v-sync thread when they up and running.
263    * This will lock the mutex in mEventThreadWaitCondition.
264    */
265   inline void NotifyThreadInitialised();
266
267   /////////////////////////////////////////////////////////////////////////////////////////////////
268   // Called by Update Thread
269   /////////////////////////////////////////////////////////////////////////////////////////////////
270
271   /**
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.
274    */
275   void UpdateInitialising();
276
277   /**
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.
280    */
281   void UpdateTryToSleep( bool runUpdate );
282
283   /**
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.
286    */
287   void UpdateWaitIfReplacingSurface();
288
289   /**
290    * Called by the update thread to check if we're just resuming.
291    * This will lock the mutex in mUpdateThreadWaitCondition.
292    */
293   inline bool IsUpdateThreadResuming();
294
295   /**
296    * Called by the update thread to check if the update thread should be running.
297    * This will lock the mutex in mUpdateThreadWaitCondition.
298    *
299    * @return True if we're stopping, false otherwise.
300    */
301   inline bool IsUpdateThreadStopping();
302
303   /**
304    * Called by the update thread to check if we've filled all update buffers.
305    * This will lock the mutex in mRenderThreadWaitCondition.
306    *
307    * @return True if all update buffers are full.
308    */
309   inline bool MaximumUpdateAheadOfRenderReached();
310
311   /**
312    * Called by the update thread when we are about to stop.
313    * This will call other functions which lock various conditional wait mutexes.
314    */
315   inline void StopAllThreads();
316
317   /**
318    * Runs the V-Sync Thread.
319    * This will lock the mutex in mVSyncThreadWaitCondition.
320    */
321   inline void RunVSyncThread();
322
323   /**
324    * Pauses the V-Sync Thread.
325    * This will lock the mutex in mVSyncThreadWaitCondition.
326    */
327   inline void PauseVSyncThread();
328
329   /**
330    * Stops the V-Sync Thread.
331    * This will lock the mutex in mVSyncThreadWaitCondition.
332    */
333   inline void StopVSyncThread();
334
335   /**
336    * Stops the Render Thread.
337    * This will lock the mutex in mRenderThreadWaitCondition.
338    */
339   inline void StopRenderThread();
340
341   /////////////////////////////////////////////////////////////////////////////////////////////////
342   // Called by V-Sync Thread
343   /////////////////////////////////////////////////////////////////////////////////////////////////
344
345   /**
346    * Checks if the V-Sync thread should be running.
347    * This will lock the mutex in mVSyncThreadWaitCondition.
348    *
349    * @return true if running, false otherwise.
350    */
351   inline bool IsVSyncThreadRunning();
352
353   /////////////////////////////////////////////////////////////////////////////////////////////////
354   // Called by Render Thread
355   /////////////////////////////////////////////////////////////////////////////////////////////////
356
357   /**
358    * Checks if the Render thread should be running.
359    * This will lock the mutex in mRenderThreadWaitCondition.
360    *
361    * @return true if running, false otherwise.
362    */
363   inline bool IsRenderThreadRunning();
364
365   /**
366    * Checks if the render thread should be replacing the surface
367    * This will lock the mutex in mRenderThreadWaitCondition.
368    *
369    * @return true if the render thread should be replacing the surface, false otherwise.
370    */
371   inline bool IsRenderThreadReplacingSurface();
372
373 private:
374
375   struct State
376   {
377     enum Type
378     {
379       STOPPED,
380       INITIALISING,
381       RUNNING,
382       PAUSED,
383       SLEEPING,
384       REPLACING_SURFACE
385     };
386   };
387
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
392
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.
397
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.
400
401   unsigned int mTryToSleepCount;                      ///< Count to ensure we don't go to sleep too early
402
403   volatile State::Type mState;                        ///< The current state of synchronisation (set & read by both the event & update threads).
404
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).
408
409   //
410   // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write
411   //
412
413   volatile unsigned int mUpdateThreadResuming;        ///< Whether the update-thread is resuming.
414
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).
417
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).
420
421   volatile unsigned int mRenderThreadPostRendering;   ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
422
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).
424
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
429
430 } // namespace Adaptor
431
432 } // namespace Internal
433
434 } // namespace Dali
435
436 #endif // __DALI_INTERNAL_THREAD_SYNCHRONIZATION_H__