1 #ifndef __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
2 #define __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__
5 * Copyright (c) 2014 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.
23 #include <boost/thread.hpp>
24 #include <boost/thread/condition_variable.hpp>
27 #include <base/interfaces/performance-interface.h>
28 #include <trigger-event-interface.h>
29 #include <base/frame-time.h>
30 #include <base/render-thread.h>
41 class PlatformAbstraction;
43 } // namespace Integration
51 class AdaptorInternalServices;
54 * This object is used to synchronize the update, render and vsync threads.
55 * The Core::GetMaximumUpdateCount() method determines how many frames may be prepared, ahead of the rendering.
56 * 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.
57 * However the Core::Update() for frame N+2 may not be called, until the Core::Render() method for frame N has returned.
60 class UpdateRenderSynchronization
65 * Create an update/render synchronization object.
66 * @param[in] adaptorInterfaces base adaptor interface
67 * @param[in] numberOfVSyncsPerRender The number of frames per render
69 UpdateRenderSynchronization( AdaptorInternalServices& adaptorInterfaces, unsigned int numberOfVSyncsPerRender );
72 * Non virtual destructor. Not intended as base class.
74 ~UpdateRenderSynchronization();
87 * Pause the controller (and threads)
92 * Resume the controller (and threads)
97 * Resume the frame time predictor
99 void ResumeFrameTime();
102 * Wake update thread if sleeping. If the update thread is not sleeping
103 * this becomes a noop.
104 * Called when an update is requested by Core.
105 * i.e. when a batch of messages have been queued for the next update.
107 void UpdateRequested();
110 * Update once (even if paused)
112 void UpdateWhilePaused();
115 * Inform the render thread that there is a new surface, and that
116 * it should replace the current surface.
117 * @param[in] newSurface The new surface for rendering.
119 bool ReplaceSurface( RenderSurface* newSurface );
122 * Inform the render thread that there is a new surface. Should be used
123 * after SurfaceLost() has been used to inform RenderThread that the surface
126 * @param[in] newSurface The new surface for rendering.
128 bool NewSurface( RenderSurface* newSurface );
131 * Called by Update thread before it runs the update. This is the point where we can pause
133 void UpdateReadyToRun();
136 * Called after an update has completed, to inform render-thread a buffer is ready to render.
137 * The function also waits for a free buffer to become available before returning.
138 * @pre Called by update thread only.
139 * @param[in] notifyEvent Whether the event thread should be woken up.
140 * @param[out] renderNeedsUpdate Whether the render task requires another update.
141 * @return True if updating should continue, false if the update-thread should quit.
143 bool UpdateSyncWithRender( bool notifyEvent, bool& renderNeedsUpdate );
146 * Called by update thread to wait for all rendering to finish.
147 * Used by update to check the status of the final render before pausing.
148 * @pre Called by update thread only.
150 void UpdateWaitForAllRenderingToFinish();
153 * Try block the update-thread when there's nothing to update.
154 * @return True if updating should continue, false if the update-thread should quit.
156 bool UpdateTryToSleep();
159 * Block the render thread whilst waiting for requests e.g. providing a new
161 * @param[in] request Pointer to set if there are any requests
163 bool RenderSyncWithRequest(RenderRequest*& request );
166 * Called by the render-thread to wait for a buffer to read from and then render.
167 * @pre Called by render thread only.
168 * @param[in] request Pointer to set if there are any requests
169 * @return True if rendering should continue, false if the render-thread should quit.
171 bool RenderSyncWithUpdate( RenderRequest*& request);
174 * Called by the render thread after it renders a frame.
175 * Used to notify the update-thread that a frame has been rendered.
176 * @pre Called by render thread only.
177 * @param[in] updateRequired Whether a further update is required.
178 * @param[in] requestProcessed True if a render request was processed this frame
180 void RenderFinished( bool updateRequired, bool requestProcessed );
183 * Called by the render/update threads to wait for a Synchronization
188 * Called by the VSync notifier thread so it can sleep if Update/Render threads are sleeping/paused
189 * @param[in] validSync True if the sync was valid (@see VSyncMonitor::DoSync)
190 * @param[in] frameNumber The current frame number
191 * @param[in] seconds The current time
192 * @param[in] microseconds The current time
193 * @param[out] numberOfVSyncsPerRender The number of frames per render.
194 * @return true if VSync monitoring/notifications should continue.
196 bool VSyncNotifierSyncWithUpdateAndRender( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender );
199 * Sets the expected minimum frame time interval.
200 * @param[in] interval The interval in microseconds.
202 void SetMinimumFrameTimeInterval( unsigned int timeInterval );
205 * Predicts when the next render time will occur.
207 * @param[out] lastFrameDeltaSeconds The delta, in seconds (with float precision), between the last two renders.
208 * @param[out] lastSyncTimeMilliseconds The time, in milliseconds, of the last Sync.
209 * @param[out] nextSyncTimeMilliseconds The estimated time, in milliseconds, at the next Sync.
211 * @note Should only be called once per tick, from the update thread.
213 void PredictNextSyncTime( float& lastFrameDeltaSeconds,
214 unsigned int& lastSyncTimeMilliseconds,
215 unsigned int& nextSyncTimeMilliseconds );
218 * Retrieves the last sync frame number.
219 * This is a count of the number of synchronised update/render
220 * frames, not a count of hardware VSync frames.
222 * @return The sync frame number.
224 unsigned int GetFrameNumber() const;
227 * Retrieves the time (in microseconds) at the last VSync
228 * @return The VSync timestamp in microseconds.
230 uint64_t GetTimeMicroseconds();
233 * Set the refresh rate for rendering
234 * @param[in] numberOfVSyncsPerRender The number of vsync frames per render
236 void SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender );
240 // Undefined copy constructor.
241 UpdateRenderSynchronization( const UpdateRenderSynchronization& );
243 // Undefined assignment operator.
244 UpdateRenderSynchronization& operator=( const UpdateRenderSynchronization& );
247 * Helper to add a performance marker to the performance server (if its active)
248 * @param type performance marker type
250 void AddPerformanceMarker( PerformanceInterface::MarkerType type );
254 const unsigned int mMaximumUpdateCount; ///< How many frames may be prepared, ahead of the rendering.
256 unsigned int mNumberOfVSyncsPerRender; ///< How many frames for each update/render cycle.
258 volatile unsigned int mUpdateReadyCount; ///< Incremented after each update, decremented after each render (protected by mMutex)
259 // ARM CPUs perform aligned 32 bit read/writes atomically, so the following variables do not require mutex protection on modification
260 volatile int mRunning; ///< Used during UpdateThread::Stop() to exit the update & render loops
261 volatile int mUpdateRequired; ///< Used to inform the update thread, that render requires another update
262 volatile int mPaused; ///< The paused flag
263 volatile int mUpdateRequested; ///< An update has been requested
264 volatile int mAllowUpdateWhilePaused; ///< whether to allow (one) update while paused
265 volatile int mVSyncSleep; ///< Set true when the VSync thread should sleep
266 volatile unsigned int mSyncFrameNumber; ///< Frame number of latest Sync
267 volatile unsigned int mSyncSeconds; ///< Timestamp (seconds) of latest Sync
268 volatile unsigned int mSyncMicroseconds; ///< Timestamp (microseconds) of latest Sync
270 boost::mutex mMutex; ///< This mutex must be locked before reading/writing mUpdateReadyCount
271 boost::condition_variable mUpdateFinishedCondition; ///< The render thread waits for this condition
272 boost::condition_variable mUpdateSleepCondition; ///< The update thread waits for this condition when sleeping
273 boost::condition_variable mRenderFinishedCondition; ///< The update thread waits for this condition
274 boost::condition_variable mVSyncReceivedCondition; ///< The render thread waits on this condition
275 boost::condition_variable mVSyncSleepCondition; ///< The vsync thread waits for this condition
276 boost::condition_variable mPausedCondition; ///< The controller waits for this condition while paused
277 boost::condition_variable mRenderRequestSleepCondition; ///< The render thread waits for this condition
278 boost::condition_variable mRenderRequestFinishedCondition;///< The controller waits for this condition
280 FrameTime mFrameTime; ///< Frame timer predicts next vsync time
281 TriggerEventInterface& mNotificationTrigger; ///< Reference to notification event trigger
282 PerformanceInterface* mPerformanceInterface; ///< The performance logging interface
284 ReplaceSurfaceRequest mReplaceSurfaceRequest; ///< Holder for a replace surface request
285 bool mReplaceSurfaceRequested; ///< True if there is a new replace surface request
287 }; // class UpdateRenderSynchronization
289 } // namespace Adaptor
291 } // namespace Internal
295 #endif // __DALI_INTERNAL_UPDATE_RENDER_SYNCHRONIZATION_H__