Synchronize first update after wake-up with VSync
[platform/core/uifw/dali-adaptor.git] / adaptors / base / update-render-synchronization.h
1 #ifndef __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
2 #define __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
3
4 /*
5  * Copyright (c) 2014 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 // INTERNAL INCLUDES
22 #include <base/interfaces/performance-interface.h>
23
24 // EXTERNAL INCLUDES
25 #include <boost/thread.hpp>
26 #include <boost/thread/condition_variable.hpp>
27
28 namespace Dali
29 {
30
31 namespace Integration
32 {
33
34 class Core;
35 class PlatformAbstraction;
36
37 } // namespace Integration
38
39 namespace Internal
40 {
41
42 namespace Adaptor
43 {
44
45 class AdaptorInternalServices;
46
47 /**
48  * This object is used to synchronize the update, render and vsync threads.
49  * The Core::GetMaximumUpdateCount() method determines how many frames may be prepared, ahead of the rendering.
50  * 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.
51  * However the Core::Update() for frame N+2 may not be called, until the Core::Render() method for frame N has returned.
52  */
53 class UpdateRenderSynchronization
54 {
55 public:
56
57   /**
58    * Create an update/render synchronization object.
59    * @param[in] adaptorInterfaces base adaptor interface
60   */
61   UpdateRenderSynchronization( AdaptorInternalServices& adaptorInterfaces );
62
63   /**
64    * Non virtual destructor. Not inteded as base class.
65    */
66   ~UpdateRenderSynchronization();
67
68   /**
69    * Start the threads
70    */
71   void Start();
72
73   /**
74    * Stop the threads
75    */
76   void Stop();
77
78   /**
79    * Pause the controller (and threads)
80    */
81   void Pause();
82
83   /**
84    * Resume the controller (and threads)
85    */
86   void Resume();
87
88   /**
89    * Wake update thread if sleeping. If the update thread is not sleeping
90    * this becomes a noop.
91    * Called when an update is requested by Core.
92    * i.e. when a batch of messages have been queued for the next update.
93    */
94   void UpdateRequested();
95
96   /**
97    * Update once (even if paused)
98    */
99   void UpdateWhilePaused();
100
101   /**
102    * Called by Update thread before it runs the update. This is the point where we can pause
103    */
104   void UpdateReadyToRun();
105
106   /**
107    * Called after an update has completed, to inform render-thread a buffer is ready to render.
108    * The function also waits for a free buffer to become available before returning.
109    * @pre Called by update thread only.
110    * @param[out] renderNeedsUpdate Whether the render task requires another update.
111    * @return True if updating should continue, false if the update-thread should quit.
112    */
113   bool UpdateSyncWithRender( bool& renderNeedsUpdate );
114
115   /**
116    * Called by update thread to wait for all rendering to finish.
117    * Used by update to check the status of the final render before pausing.
118    * @pre Called by update thread only.
119    */
120   void UpdateWaitForAllRenderingToFinish();
121
122   /**
123    * Try block the update-thread when there's nothing to update.
124    * @return True if updating should continue, false if the update-thread should quit.
125    */
126   bool UpdateTryToSleep();
127
128   /**
129    * Called by the render thread after it renders a frame.
130    * Used to notify the update-thread that a frame has been rendered.
131    * @pre Called by render thread only.
132    * @param updateRequired Whether a further update is required.
133    */
134   void RenderFinished( bool updateRequired );
135
136   /**
137    * Called by the render-thread to wait for a buffer to read from and then render.
138    * @pre Called by render thread only.
139    * @return True if rendering should continue, false if the render-thread should quit.
140    */
141   bool RenderSyncWithUpdate();
142
143   /**
144    * Called by the render/update threads to wait for a VSync.
145    */
146   void WaitVSync();
147
148   /**
149    * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
150    * @return true if VSync monitoring/notifications should continue.
151    */
152   bool VSyncNotifierSyncWithUpdateAndRender( unsigned int frameNumber, unsigned int seconds, unsigned int microseconds );
153
154   /**
155    * Retrieves the last VSync frame number
156    * @return The VSync frame number.
157    */
158   unsigned int GetFrameNumber() const;
159
160   /**
161    * Retrieves the time (in microseconds) at the last VSync
162    * @return The VSync timestamp in microseconds.
163    */
164   uint64_t GetTimeMicroseconds();
165
166 private:
167
168   // Undefined copy constructor.
169   UpdateRenderSynchronization( const UpdateRenderSynchronization& );
170
171   // Undefined assignment operator.
172   UpdateRenderSynchronization& operator=( const UpdateRenderSynchronization& );
173
174   /**
175    * Helper to add a performance marker to the performance server (if its active)
176    * @param type performance marker type
177    */
178   void AddPerformanceMarker( PerformanceMarker::MarkerType type );
179
180 private:
181
182   const unsigned int mMaximumUpdateCount;             ///< How many frames may be prepared, ahead of the rendering.
183   volatile unsigned int mUpdateReadyCount;            ///< Incremented after each update, decremented after each render (protected by mMutex)
184   // ARM CPUs perform aligned 32 bit read/writes atomically, so the following variables do not require mutex protection on modification
185   volatile int mRunning;                              ///< Used during UpdateThread::Stop() to exit the update & render loops
186   volatile int mUpdateRequired;                       ///< Used to inform the update thread, that render requires another update
187   volatile int mPaused;                               ///< The paused flag
188   volatile int mUpdateRequested;                      ///< An update has been requested
189   volatile int mAllowUpdateWhilePaused;               ///< whether to allow (one) update while paused
190   volatile int mVSyncSleep;                           ///< Set true when the VSync thread should sleep
191   volatile unsigned int mVSyncFrameNumber;            ///< Frame number of latest VSync
192   volatile unsigned int mVSyncSeconds;                ///< Timestamp (seconds) of latest VSync
193   volatile unsigned int mVSyncMicroseconds;           ///< Timestamp (microseconds) of latest VSync
194
195   boost::mutex mMutex;                                ///< This mutex must be locked before reading/writing mUpdateReadyCount
196   boost::condition_variable mUpdateFinishedCondition; ///< The render thread waits for this condition
197   boost::condition_variable mUpdateSleepCondition;    ///< The update thread waits for this condition when sleeping
198   boost::condition_variable mRenderFinishedCondition; ///< The update thread waits for this condition
199   boost::condition_variable mVSyncReceivedCondition;  ///< The render thread waits on this condition
200   boost::condition_variable mVSyncSleepCondition;     ///< The vsync thread waits for this condition
201   boost::condition_variable mPausedCondition;         ///< The controller waits for this condition while paused
202
203   Dali::Integration::Core&            mCore;                ///< Dali core reference
204   PerformanceInterface*               mPerformanceInterface;///< The performance logging interface
205
206 }; // class UpdateRenderSynchronization
207
208 } // namespace Adaptor
209
210 } // namespace Internal
211
212 } // namespace Dali
213
214 #endif // __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__