54cc67d6af86a60d43f9309facee11d3dec4fcfc
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / combined-update-render-controller.h
1 #ifndef DALI_INTERNAL_COMBINED_UPDATE_RENDER_CONTROLLER_H
2 #define DALI_INTERNAL_COMBINED_UPDATE_RENDER_CONTROLLER_H
3
4 /*
5  * Copyright (c) 2020 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 <pthread.h>
23 #include <semaphore.h>
24 #include <atomic>
25 #include <stdint.h>
26 #include <dali/devel-api/threading/conditional-wait.h>
27 #include <dali/integration-api/core.h>
28
29 // INTERNAL INCLUDES
30 #include <dali/integration-api/adaptor-framework/thread-synchronization-interface.h>
31 #include <dali/internal/adaptor/common/thread-controller-interface.h>
32 #include <dali/internal/system/common/fps-tracker.h>
33 #include <dali/internal/system/common/performance-interface.h>
34 #include <dali/internal/system/common/update-status-logger.h>
35 #include <dali/internal/window-system/common/display-connection.h>
36
37 namespace Dali
38 {
39
40 class RenderSurfaceInterface;
41 class TriggerEventInterface;
42
43 namespace Internal
44 {
45
46 namespace Adaptor
47 {
48
49 class AdaptorInternalServices;
50 class EnvironmentOptions;
51
52 /**
53  * @brief Two threads where events/application interaction is handled on the main/event thread and the Update & Render
54  * happen on the other thread.
55  *
56  * Key Points:
57  *  1. Two Threads:
58  *    a. Main/Event Thread.
59  *    b. Update/Render Thread.
60  *  2. There is NO VSync thread:
61  *    a. We retrieve the time before Update.
62  *    b. Then retrieve the time after Render.
63  *    c. We calculate the difference between these two times and if:
64  *      i.  The difference is less than the default frame time, we sleep.
65  *      ii. If it’s more or the same, we continue.
66  *  3. On the update/render thread, if we discover that we do not need to do any more updates, we use a trigger-event
67  *     to inform the main/event thread. This is then processed as soon as the event thread is able to do so where it
68  *     is easier to make a decision about whether we should stop the update/render thread or not (depending on any
69  *     update requests etc.).
70  *  4. The main thread is blocked while the surface is being replaced.
71  *  5. When we resume from paused, elapsed time is used for the animations, i.e. the could have finished while we were paused.
72  *     However, FinishedSignal emission will only happen upon resumption.
73  *  6. Elapsed time is NOT used while if we are waking up from a sleep state or doing an UpdateOnce.
74  */
75 class CombinedUpdateRenderController : public ThreadControllerInterface,
76                                        public ThreadSynchronizationInterface
77 {
78 public:
79
80   /**
81    * Constructor
82    */
83   CombinedUpdateRenderController( AdaptorInternalServices& adaptorInterfaces, const EnvironmentOptions& environmentOptions );
84
85   /**
86    * Non virtual destructor. Not intended as base class.
87    */
88   ~CombinedUpdateRenderController();
89
90   /**
91    * @copydoc ThreadControllerInterface::Initialize()
92    */
93   virtual void Initialize();
94
95   /**
96    * @copydoc ThreadControllerInterface::Start()
97    */
98   virtual void Start();
99
100   /**
101    * @copydoc ThreadControllerInterface::Pause()
102    */
103   virtual void Pause();
104
105   /**
106    * @copydoc ThreadControllerInterface::Resume()
107    */
108   virtual void Resume();
109
110   /**
111    * @copydoc ThreadControllerInterface::Stop()
112    */
113   virtual void Stop();
114
115   /**
116    * @copydoc ThreadControllerInterface::RequestUpdate()
117    */
118   virtual void RequestUpdate();
119
120   /**
121    * @copydoc ThreadControllerInterface::RequestUpdateOnce()
122    */
123   virtual void RequestUpdateOnce( UpdateMode updateMode );
124
125   /**
126    * @copydoc ThreadControllerInterface::ReplaceSurface()
127    */
128   virtual void ReplaceSurface( Dali::RenderSurfaceInterface* surface );
129
130   /**
131    * @copydoc ThreadControllerInterface::DeleteSurface()
132    */
133   virtual void DeleteSurface( Dali::RenderSurfaceInterface* surface );
134
135   /**
136    * @copydoc ThreadControllerInterface::ResizeSurface()
137    */
138   virtual void ResizeSurface();
139
140   /**
141    * @copydoc ThreadControllerInterface::WaitForGraphicsInitialization()
142    */
143   virtual void WaitForGraphicsInitialization();
144
145   /**
146    * @copydoc ThreadControllerInterface::SetRenderRefreshRate()
147    */
148   virtual void SetRenderRefreshRate( unsigned int numberOfFramesPerRender );
149
150   /**
151    * @copydoc ThreadControllerInterface::SetPreRenderCallback
152    */
153   void SetPreRenderCallback( CallbackBase* callback ) override;
154
155   /**
156    * @copydoc ThreadControllerInterface::AddSurface()
157    */
158   virtual void AddSurface( Dali::RenderSurfaceInterface* surface );
159
160 private:
161
162   // Undefined copy constructor.
163   CombinedUpdateRenderController( const CombinedUpdateRenderController& );
164
165   // Undefined assignment operator.
166   CombinedUpdateRenderController& operator=( const CombinedUpdateRenderController& );
167
168   /////////////////////////////////////////////////////////////////////////////////////////////////
169   // EventThread
170   /////////////////////////////////////////////////////////////////////////////////////////////////
171
172   enum AnimationProgression
173   {
174     USE_ELAPSED_TIME,          ///< Animation progression using elapsed time
175     NONE                       ///< No animation progression
176   };
177
178   /**
179    * Runs the Update/Render Thread.
180    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
181    *
182    * @param[in]  numberOfCycles           The number of times the update/render cycle should run. If -1, then it will run continuously.
183    * @param[in]  animationProgression     Whether to progress animation using time elapsed since the last frame.
184    * @param[in]  updateMode               The update mode (i.e. either update & render or skip rendering)
185    */
186   inline void RunUpdateRenderThread( int numberOfCycles, AnimationProgression animationProgression, UpdateMode updateMode );
187
188   /**
189    * Pauses the Update/Render Thread.
190    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
191    */
192   inline void PauseUpdateRenderThread();
193
194   /**
195    * Stops the Update/Render Thread.
196    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
197    *
198    * @note Should only be called in Stop as calling this will kill the update-thread.
199    */
200   inline void StopUpdateRenderThread();
201
202   /**
203    * Checks if the the Update/Render Thread is paused.
204    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
205    *
206    * @return true if paused, false otherwise
207    */
208   inline bool IsUpdateRenderThreadPaused();
209
210   /**
211    * Used as the callback for the sleep-trigger.
212    *
213    * Will sleep when enough requests are made without any requests.
214    */
215   void ProcessSleepRequest();
216
217   /////////////////////////////////////////////////////////////////////////////////////////////////
218   // UpdateRenderThread
219   /////////////////////////////////////////////////////////////////////////////////////////////////
220
221   /**
222    * The Update/Render thread loop. This thread will be destroyed on exit from this function.
223    */
224   void UpdateRenderThread();
225
226   /**
227    * Called by the Update/Render Thread which ensures a wait if required.
228    *
229    * @param[out] useElapsedTime    If true when returned, then the actual elapsed time will be used for animation.
230    *                               If false when returned, then there should NOT be any animation progression in the next Update.
231    * @param[in]  updateRequired    Whether another update is required.
232    * @param[out] timeToSleepUntil  The time remaining in nanoseconds to keep the thread sleeping before resuming.
233    * @return false, if the thread should stop.
234    */
235   bool UpdateRenderReady( bool& useElapsedTime, bool updateRequired, uint64_t& timeToSleepUntil );
236
237   /**
238    * Checks to see if the surface needs to be replaced.
239    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
240    *
241    * @return Pointer to the new surface, NULL otherwise
242    */
243   Dali::RenderSurfaceInterface* ShouldSurfaceBeReplaced();
244
245   /**
246    * Called by the Update/Render thread after a surface has been replaced.
247    *
248    * This will lock the mutex in mEventThreadWaitCondition
249    */
250   void SurfaceReplaced();
251
252   /**
253    * Checks to see if the surface needs to be deleted.
254    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
255    *
256    * @return Pointer to the deleted surface, nullptr otherwise
257    */
258   Dali::RenderSurfaceInterface* ShouldSurfaceBeDeleted();
259
260   /**
261    * Called by the Update/Render thread after a surface has been deleted.
262    *
263    * This will lock the mutex in mEventThreadWaitCondition
264    */
265   void SurfaceDeleted();
266
267   /**
268    * Checks to see if the surface needs to be resized.
269    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
270    *
271    * @return true if the surface should be resized, false otherwise
272    */
273   bool ShouldSurfaceBeResized();
274
275   /**
276    * Called by the Update/Render thread after a surface has been resized.
277    *
278    * This will lock the mutex in mEventThreadWaitCondition
279    */
280   void SurfaceResized();
281
282   /**
283    * Helper for the thread calling the entry function
284    * @param[in] This A pointer to the current object
285    */
286   static void* InternalUpdateRenderThreadEntryFunc( void* This )
287   {
288     ( static_cast<CombinedUpdateRenderController*>( This ) )->UpdateRenderThread();
289     return NULL;
290   }
291
292   /////////////////////////////////////////////////////////////////////////////////////////////////
293   // ALL Threads
294   /////////////////////////////////////////////////////////////////////////////////////////////////
295
296   /**
297    * Called by the update-render & v-sync threads when they up and running.
298    *
299    * This will lock the mutex in mEventThreadWaitCondition.
300    */
301   void NotifyThreadInitialised();
302
303   /**
304    * Called by the update-render thread when graphics has been initialised.
305    */
306   void NotifyGraphicsInitialised();
307
308   /**
309    * Helper to add a performance marker to the performance server (if it's active)
310    * @param[in]  type  performance marker type
311    */
312   void AddPerformanceMarker( PerformanceInterface::MarkerType type );
313
314   /////////////////////////////////////////////////////////////////////////////////////////////////
315   // POST RENDERING - ThreadSynchronizationInterface overrides
316   /////////////////////////////////////////////////////////////////////////////////////////////////
317
318   /////////////////////////////////////////////////////////////////////////////////////////////////
319   //// Called by the Event Thread if post-rendering is required
320   /////////////////////////////////////////////////////////////////////////////////////////////////
321
322   /**
323    * @copydoc ThreadSynchronizationInterface::PostRenderComplete()
324    */
325   virtual void PostRenderComplete();
326
327   /////////////////////////////////////////////////////////////////////////////////////////////////
328   //// Called by the Render Thread if post-rendering is required
329   /////////////////////////////////////////////////////////////////////////////////////////////////
330
331   /**
332    * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
333    */
334   virtual void PostRenderStarted();
335
336   /**
337    * @copydoc ThreadSynchronizationInterface::PostRenderStarted()
338    */
339   virtual void PostRenderWaitForCompletion();
340
341 private:
342
343   FpsTracker                        mFpsTracker;                       ///< Object that tracks the FPS
344   UpdateStatusLogger                mUpdateStatusLogger;               ///< Object that logs the update-status as required.
345
346   sem_t                             mEventThreadSemaphore;             ///< Used by the event thread to ensure all threads have been initialised, and when replacing the surface.
347   sem_t                             mGraphicsInitializeSemaphore;      ///< Used by the render thread to ensure the graphics has been initialised.
348
349   ConditionalWait                   mUpdateRenderThreadWaitCondition;  ///< The wait condition for the update-render-thread.
350
351   AdaptorInternalServices&          mAdaptorInterfaces;                ///< The adaptor internal interface
352   PerformanceInterface*             mPerformanceInterface;             ///< The performance logging interface
353   Integration::Core&                mCore;                             ///< Dali core reference
354   const EnvironmentOptions&         mEnvironmentOptions;               ///< Environment options
355   TriggerEventInterface&            mNotificationTrigger;              ///< Reference to notification event trigger
356   TriggerEventInterface*            mSleepTrigger;                     ///< Used by the update-render thread to trigger the event thread when it no longer needs to do any updates
357   CallbackBase*                     mPreRenderCallback;                ///< Used by Update/Render thread when PreRender is about to be called on graphics.
358
359   pthread_t*                        mUpdateRenderThread;               ///< The Update/Render thread.
360
361   float                             mDefaultFrameDelta;                ///< Default time delta between each frame (used for animations). Not protected by lock, but written to rarely so not worth adding a lock when reading.
362   // TODO: mDefaultFrameDurationMilliseconds is defined as uint64_t, the only place where it is used, it is converted to an unsigned int!!!
363   uint64_t                          mDefaultFrameDurationMilliseconds; ///< Default duration of a frame (used for predicting the time of the next frame). Not protected by lock, but written to rarely so not worth adding a lock when reading.
364   uint64_t                          mDefaultFrameDurationNanoseconds;  ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading.
365   uint64_t                          mDefaultHalfFrameNanoseconds;      ///< Is half of mDefaultFrameDurationNanoseconds. Using a member variable avoids having to do the calculation every frame. Not protected by lock, but written to rarely so not worth adding a lock when reading.
366
367   unsigned int                      mUpdateRequestCount;               ///< Count of update-requests we have received to ensure we do not go to sleep too early.
368   unsigned int                      mRunning;                          ///< Read and set on the event-thread only to state whether we are running.
369
370   //
371   // NOTE: cannot use booleans as these are used from multiple threads, must use variable with machine word size for atomic read/write
372   //
373
374   volatile int                      mUpdateRenderRunCount;             ///< The number of times Update/Render cycle should run. If -1, then will run continuously (set by the event-thread, read by v-sync-thread).
375   volatile unsigned int             mDestroyUpdateRenderThread;        ///< Whether the Update/Render thread be destroyed (set by the event-thread, read by the update-render-thread).
376   volatile unsigned int             mUpdateRenderThreadCanSleep;       ///< Whether the Update/Render thread can sleep (set by the event-thread, read by the update-render-thread).
377   volatile unsigned int             mPendingRequestUpdate;             ///< Is set as soon as an RequestUpdate is made and unset when the next update happens (set by the event-thread and update-render thread, read by the update-render-thread).
378                                                                        ///< Ensures we do not go to sleep if we have not processed the most recent update-request.
379
380   volatile unsigned int             mUseElapsedTimeAfterWait;          ///< Whether we should use the elapsed time after waiting (set by the event-thread, read by the update-render-thread).
381
382   Dali::RenderSurfaceInterface* volatile mNewSurface;                  ///< Will be set to the new-surface if requested (set by the event-thread, read & cleared by the update-render thread).
383   Dali::RenderSurfaceInterface* volatile mDeletedSurface;              ///< Will be set to the deleted surface if requested (set by the event-thread, read & cleared by the update-render thread).
384
385   volatile unsigned int             mPostRendering;                    ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
386   volatile unsigned int             mSurfaceResized;                   ///< Will be set to resize the surface (set by the event-thread, read & cleared by the update-render thread).
387   volatile unsigned int             mForceClear;                       ///< Will be set to clear forcibly
388
389   volatile unsigned int             mUploadWithoutRendering;           ///< Will be set to upload the resource only (with no rendering)
390
391   volatile unsigned int             mFirstFrameAfterResume;            ///< Will be set to check the first frame after resume (for log)
392 };
393
394 } // namespace Adaptor
395
396 } // namespace Internal
397
398 } // namespace Dali
399
400 #endif // DALI_INTERNAL_COMBINED_UPDATE_RENDER_CONTROLLER_H