Remove de-funct Bullet dynamics plugin
[platform/core/uifw/dali-adaptor.git] / adaptors / base / update-render-synchronization.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "update-render-synchronization.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <base/interfaces/adaptor-internal-services.h>
26
27 namespace Dali
28 {
29
30 namespace Internal
31 {
32
33 namespace Adaptor
34 {
35
36 namespace
37 {
38 const unsigned int TIME_PER_FRAME_IN_MICROSECONDS = 16667;
39 const unsigned int MICROSECONDS_PER_SECOND( 1000000 );
40 const unsigned int INPUT_EVENT_UPDATE_PERIOD( MICROSECONDS_PER_SECOND / 90 ); // period between ecore x event updates
41
42 } // unnamed namespace
43
44 UpdateRenderSynchronization::UpdateRenderSynchronization( AdaptorInternalServices& adaptorInterfaces,
45                                                           unsigned int numberOfVSyncsPerRender)
46 : mMaximumUpdateCount( adaptorInterfaces.GetCore().GetMaximumUpdateCount()),
47   mNumberOfVSyncsPerRender( numberOfVSyncsPerRender ),
48   mUpdateReadyCount( 0u ),
49   mRunning( false ),
50   mUpdateRequired( false ),
51   mPaused( false ),
52   mUpdateRequested( false ),
53   mAllowUpdateWhilePaused( false ),
54   mVSyncSleep( false ),
55   mSyncFrameNumber( 0u ),
56   mSyncSeconds( 0u ),
57   mSyncMicroseconds( 0u ),
58   mFrameTime( adaptorInterfaces.GetPlatformAbstractionInterface() ),
59   mNotificationTrigger( adaptorInterfaces.GetProcessCoreEventsTrigger() ),
60   mPerformanceInterface( adaptorInterfaces.GetPerformanceInterface() ),
61   mReplaceSurfaceRequest(),
62   mReplaceSurfaceRequested( false )
63 {
64 }
65
66 UpdateRenderSynchronization::~UpdateRenderSynchronization()
67 {
68 }
69
70 void UpdateRenderSynchronization::Start()
71 {
72   mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
73   mRunning = true;
74 }
75
76 void UpdateRenderSynchronization::Stop()
77 {
78   mRunning = false;
79
80   // Wake if sleeping
81   UpdateRequested();
82
83   // we may be paused so need to resume
84   Resume();
85
86   // Notify all condition variables, so if threads are waiting
87   // they can break out, and check the running status.
88   mUpdateFinishedCondition.notify_one();
89   mRenderFinishedCondition.notify_one();
90   mVSyncSleepCondition.notify_one();
91   mVSyncReceivedCondition.notify_one();
92   mRenderRequestSleepCondition.notify_one();
93
94   mFrameTime.Suspend();
95 }
96
97 void UpdateRenderSynchronization::Pause()
98 {
99   mPaused = true;
100
101   AddPerformanceMarker( PerformanceInterface::PAUSED );
102   mFrameTime.Suspend();
103 }
104
105 void UpdateRenderSynchronization::ResumeFrameTime()
106 {
107   mFrameTime.Resume();
108 }
109
110 void UpdateRenderSynchronization::Resume()
111 {
112   mPaused = false;
113   mVSyncSleep = false;
114
115   mPausedCondition.notify_one();
116   mVSyncSleepCondition.notify_one();
117
118   AddPerformanceMarker( PerformanceInterface::RESUME);
119 }
120
121 void UpdateRenderSynchronization::UpdateRequested()
122 {
123   mUpdateRequested = true;
124
125   // Wake update thread if sleeping
126   mUpdateSleepCondition.notify_one();
127 }
128
129 void UpdateRenderSynchronization::UpdateWhilePaused()
130 {
131   {
132     boost::unique_lock< boost::mutex > lock( mMutex );
133
134     mAllowUpdateWhilePaused = true;
135   }
136
137   // wake vsync if sleeping
138   mVSyncSleepCondition.notify_one();
139   // Wake update if sleeping
140   mUpdateSleepCondition.notify_one();
141   // stay paused but notify the pause condition
142   mPausedCondition.notify_one();
143 }
144
145 bool UpdateRenderSynchronization::ReplaceSurface( RenderSurface* newSurface )
146 {
147   bool result=false;
148
149   UpdateRequested();
150   UpdateWhilePaused();
151   {
152     boost::unique_lock< boost::mutex > lock( mMutex );
153
154     mReplaceSurfaceRequest.SetSurface(newSurface);
155     mReplaceSurfaceRequested = true;
156
157     mRenderRequestFinishedCondition.wait(lock); // wait unlocks the mutex on entry, and locks again on exit.
158
159     mReplaceSurfaceRequested = false;
160     result = mReplaceSurfaceRequest.GetReplaceCompleted();
161   }
162
163   return result;
164 }
165
166 bool UpdateRenderSynchronization::NewSurface( RenderSurface* newSurface )
167 {
168   bool result=false;
169
170   UpdateRequested();
171   UpdateWhilePaused();
172   {
173     boost::unique_lock< boost::mutex > lock( mMutex );
174
175     mReplaceSurfaceRequest.SetSurface(newSurface);
176     mReplaceSurfaceRequested = true;
177
178     // Unlock the render thread sleeping on requests
179     mRenderRequestSleepCondition.notify_one();
180
181     // Lock event thread until request has been processed
182     mRenderRequestFinishedCondition.wait(lock);// wait unlocks the mutex on entry, and locks again on exit.
183
184     mReplaceSurfaceRequested = false;
185     result = mReplaceSurfaceRequest.GetReplaceCompleted();
186   }
187
188   return result;
189 }
190
191
192 void UpdateRenderSynchronization::UpdateReadyToRun()
193 {
194   bool wokenFromPause( false );
195
196   // atomic check first to avoid mutex lock in 99.99% of cases
197   if( mPaused )
198   {
199     boost::unique_lock< boost::mutex > lock( mMutex );
200
201     // wait while paused
202     while( mPaused && !mAllowUpdateWhilePaused )
203     {
204       // this will automatically unlock mMutex
205       mPausedCondition.wait( lock );
206
207       wokenFromPause = true;
208     }
209   }
210
211   if ( !wokenFromPause )
212   {
213     // Wait for the next Sync
214     WaitSync();
215   }
216
217   AddPerformanceMarker( PerformanceInterface::UPDATE_START );
218 }
219
220 bool UpdateRenderSynchronization::UpdateSyncWithRender( bool notifyEvent, bool& renderNeedsUpdate )
221 {
222   AddPerformanceMarker( PerformanceInterface::UPDATE_END );
223
224   // Do the notifications first so the event thread can start processing them
225   if( notifyEvent && mRunning )
226   {
227     // Tell the event-thread to wake up (if asleep) and send a notification event to Core
228     mNotificationTrigger.Trigger();
229   }
230
231   boost::unique_lock< boost::mutex > lock( mMutex );
232
233   // Another frame was prepared for rendering; increment counter
234   ++mUpdateReadyCount;
235   DALI_ASSERT_DEBUG( mUpdateReadyCount <= mMaximumUpdateCount );
236
237   // Notify the render-thread that an update has completed
238   mUpdateFinishedCondition.notify_one();
239
240   // The update-thread must wait until a frame has been rendered, when mMaximumUpdateCount is reached
241   while( mRunning && ( mMaximumUpdateCount == mUpdateReadyCount ) )
242   {
243     // Wait will atomically add the thread to the set of threads waiting on
244     // the condition variable mRenderFinishedCondition and unlock the mutex.
245     mRenderFinishedCondition.wait( lock );
246   }
247
248   renderNeedsUpdate = mUpdateRequired;
249
250   // Flag is used to during UpdateThread::Stop() to exit the update/render loops
251   return mRunning;
252 }
253
254 void UpdateRenderSynchronization::UpdateWaitForAllRenderingToFinish()
255 {
256   boost::unique_lock< boost::mutex > lock( mMutex );
257
258   // Wait for all of the prepared frames to be rendered
259   while ( mRunning && ( 0u != mUpdateReadyCount ) && !mUpdateRequested )
260   {
261     // Wait will atomically add the thread to the set of threads waiting on
262     // the condition variable mRenderFinishedCondition and unlock the mutex.
263     mRenderFinishedCondition.wait( lock );
264   }
265 }
266
267 bool UpdateRenderSynchronization::UpdateTryToSleep()
268 {
269   if ( !mUpdateRequired && !mUpdateRequested )
270   {
271     // there's nothing to update in the scene, so wait for render to finish processing
272     UpdateWaitForAllRenderingToFinish();
273   }
274
275   boost::mutex sleepMutex;
276   boost::unique_lock< boost::mutex > lock( sleepMutex );
277
278   while( mRunning && !mUpdateRequired && !mUpdateRequested )
279   {
280     //
281     // Going to sleep
282     //
283
284     // 1. put VSync thread to sleep.
285     mVSyncSleep = true;
286
287     // 2. inform frame time
288     mFrameTime.Sleep();
289
290     // 3. block thread and wait for wakeup event
291     mUpdateSleepCondition.wait( lock );
292
293     //
294     // Woken up
295     //
296
297     // 1. inform frame timer
298     mFrameTime.WakeUp();
299
300     // 2. wake VSync thread.
301     mVSyncSleep = false;
302     mVSyncSleepCondition.notify_one();
303   }
304
305   mUpdateRequested = false;
306
307   return mRunning;
308 }
309
310 bool UpdateRenderSynchronization::RenderSyncWithRequest(RenderRequest*& requestPtr)
311 {
312   boost::unique_lock< boost::mutex > lock( mMutex );
313
314   // Wait for a replace surface request
315   mRenderRequestSleepCondition.wait(lock);
316
317   // write any new requests
318   if( mReplaceSurfaceRequested )
319   {
320     requestPtr = &mReplaceSurfaceRequest;
321   }
322   mReplaceSurfaceRequested = false;
323   return mRunning;
324 }
325
326 bool UpdateRenderSynchronization::RenderSyncWithUpdate(RenderRequest*& requestPtr)
327 {
328   boost::unique_lock< boost::mutex > lock( mMutex );
329
330   // Wait for update to produce a buffer, or for the mRunning state to change
331   while ( mRunning && ( 0u == mUpdateReadyCount ) )
332   {
333     // Wait will atomically add the thread to the set of threads waiting on
334     // the condition variable mUpdateFinishedCondition and unlock the mutex.
335     mUpdateFinishedCondition.wait( lock );
336   }
337
338   if( mRunning )
339   {
340     AddPerformanceMarker( PerformanceInterface::RENDER_START );
341   }
342
343   // write any new requests
344   if( mReplaceSurfaceRequested )
345   {
346     requestPtr = &mReplaceSurfaceRequest;
347   }
348   mReplaceSurfaceRequested = false;
349
350   // Flag is used to during UpdateThread::Stop() to exit the update/render loops
351   return mRunning;
352 }
353
354 void UpdateRenderSynchronization::RenderFinished( bool updateRequired, bool requestProcessed )
355 {
356   {
357     boost::unique_lock< boost::mutex > lock( mMutex );
358
359     // Set the flag to say if update needs to run again.
360     mUpdateRequired = updateRequired;
361
362     // A frame has been rendered; decrement counter
363     --mUpdateReadyCount;
364     DALI_ASSERT_DEBUG( mUpdateReadyCount < mMaximumUpdateCount );
365   }
366
367   // Notify the update-thread that a render has completed
368   mRenderFinishedCondition.notify_one();
369
370   if( requestProcessed )
371   {
372     // Notify the event thread that a request has completed
373     mRenderRequestFinishedCondition.notify_one();
374   }
375
376   AddPerformanceMarker( PerformanceInterface::RENDER_END );
377 }
378
379 void UpdateRenderSynchronization::WaitSync()
380 {
381   // Block until the start of a new sync.
382   // If we're experiencing slowdown and are behind by more than a frame
383   // then we should wait for the next frame
384
385   unsigned int updateFrameNumber = mSyncFrameNumber;
386
387   boost::unique_lock< boost::mutex > lock( mMutex );
388
389   while ( mRunning && ( updateFrameNumber == mSyncFrameNumber ) )
390   {
391     // Wait will atomically add the thread to the set of threads waiting on
392     // the condition variable mVSyncReceivedCondition and unlock the mutex.
393     mVSyncReceivedCondition.wait( lock );
394   }
395
396   // reset update while paused flag
397   mAllowUpdateWhilePaused = false;
398 }
399
400 bool UpdateRenderSynchronization::VSyncNotifierSyncWithUpdateAndRender( bool validSync, unsigned int frameNumber, unsigned int seconds, unsigned int microseconds, unsigned int& numberOfVSyncsPerRender )
401 {
402   // This may have changed since the last sync. Update VSyncNotifier's copy here if so.
403   if( numberOfVSyncsPerRender != mNumberOfVSyncsPerRender )
404   {
405     numberOfVSyncsPerRender = mNumberOfVSyncsPerRender; // save it back
406     mFrameTime.SetMinimumFrameTimeInterval( mNumberOfVSyncsPerRender * TIME_PER_FRAME_IN_MICROSECONDS );
407   }
408
409   if( validSync )
410   {
411     mFrameTime.SetSyncTime( frameNumber );
412   }
413
414   boost::unique_lock< boost::mutex > lock( mMutex );
415
416   mSyncFrameNumber = frameNumber;
417   mSyncSeconds = seconds;
418   mSyncMicroseconds = microseconds;
419
420   mVSyncReceivedCondition.notify_all();
421
422   AddPerformanceMarker( PerformanceInterface::VSYNC );
423
424   while( mRunning && // sleep on condition variable WHILE still running
425          !mAllowUpdateWhilePaused &&             // AND NOT allowing updates while paused
426          ( mVSyncSleep || mPaused ) )            // AND sleeping OR paused
427   {
428     // Wait will atomically add the thread to the set of threads waiting on
429     // the condition variable mVSyncSleepCondition and unlock the mutex.
430     mVSyncSleepCondition.wait( lock );
431   }
432
433   return mRunning;
434 }
435
436 unsigned int UpdateRenderSynchronization::GetFrameNumber() const
437 {
438   return mSyncFrameNumber;
439 }
440
441 uint64_t UpdateRenderSynchronization::GetTimeMicroseconds()
442 {
443   uint64_t currentTime(0);
444
445   {
446     boost::unique_lock< boost::mutex > lock( mMutex );
447
448     currentTime = mSyncSeconds;
449     currentTime *= MICROSECONDS_PER_SECOND;
450     currentTime += mSyncMicroseconds;
451   }
452
453   return currentTime;
454 }
455
456 void UpdateRenderSynchronization::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
457 {
458   mNumberOfVSyncsPerRender = numberOfVSyncsPerRender;
459 }
460
461 inline void UpdateRenderSynchronization::AddPerformanceMarker( PerformanceInterface::MarkerType type )
462 {
463   if( mPerformanceInterface )
464   {
465     mPerformanceInterface->AddMarker( type );
466   }
467 }
468
469 void UpdateRenderSynchronization::PredictNextSyncTime(
470   float& lastFrameDeltaSeconds,
471   unsigned int& lastSyncTimeMilliseconds,
472   unsigned int& nextSyncTimeMilliseconds )
473 {
474   mFrameTime.PredictNextSyncTime( lastFrameDeltaSeconds, lastSyncTimeMilliseconds, nextSyncTimeMilliseconds );
475 }
476
477 } // namespace Adaptor
478
479 } // namespace Internal
480
481 } // namespace Dali