Uses TextArray new type definition.
[platform/core/uifw/dali-adaptor.git] / adaptors / base / vsync-notifier.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 // EXTERNAL INCLUDES
19 #include <xf86drm.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <boost/thread.hpp>
24
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/platform-abstraction.h>
27
28 // INTERNAL INCLUDES
29 #include "vsync-notifier.h"
30 #include <base/interfaces/adaptor-internal-services.h>
31 #include <base/update-render-synchronization.h>
32 #include <base/environment-options.h>
33
34 namespace Dali
35 {
36
37 namespace Internal
38 {
39
40 namespace Adaptor
41 {
42
43 namespace
44 {
45
46 const unsigned int MICROSECONDS_PER_SECOND( 100000u );
47 const unsigned int TIME_PER_FRAME_IN_MICROSECONDS( 16667u );
48
49 #if defined(DEBUG_ENABLED)
50 Integration::Log::Filter* gLogFilter = Integration::Log::Filter::New(Debug::Concise, false, "LOG_VSYNC_NOTIFIER");
51 #endif
52
53 } // unnamed namespace
54
55 VSyncNotifier::VSyncNotifier( UpdateRenderSynchronization& sync,
56                               AdaptorInternalServices& adaptorInterfaces,
57                               const EnvironmentOptions& environmentOptions )
58 : mUpdateRenderSync( sync ),
59   mCore( adaptorInterfaces.GetCore() ),
60   mPlatformAbstraction( adaptorInterfaces.GetPlatformAbstractionInterface() ),
61   mVSyncMonitor( adaptorInterfaces.GetVSyncMonitorInterface() ),
62   mThread( NULL ),
63   mEnvironmentOptions( environmentOptions )
64 {
65 }
66
67 VSyncNotifier::~VSyncNotifier()
68 {
69   DALI_LOG_INFO( gLogFilter, Debug::General, "%s\n", __func__ );
70
71   Stop();
72 }
73
74 void VSyncNotifier::Start()
75 {
76   DALI_LOG_INFO( gLogFilter, Debug::General, "%s\n", __func__ );
77
78   if ( !mThread )
79   {
80     mVSyncMonitor->Initialize();
81
82     mThread = new boost::thread( boost::bind( &VSyncNotifier::Run, this ) );
83   }
84 }
85
86 void VSyncNotifier::Stop()
87 {
88   DALI_LOG_INFO( gLogFilter, Debug::General, "%s\n", __func__ );
89
90   if( mThread )
91   {
92     // wait for the thread to finish
93     mThread->join();
94
95     delete mThread;
96     mThread = NULL;
97   }
98
99   mVSyncMonitor->Terminate();
100 }
101
102 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
103 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 // The following is executed inside the notifier thread !!!
105 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107
108 void VSyncNotifier::Run()
109 {
110   // install a function for logging
111   mEnvironmentOptions.InstallLogFunction();
112
113   unsigned int frameNumber( 0u );             // frameCount, updated when the thread is paused
114   unsigned int currentSequenceNumber( 0u );   // platform specific vsync sequence number (increments with each vsync)
115   unsigned int currentSeconds( 0u );          // timestamp at latest vsync
116   unsigned int currentMicroseconds( 0u );     // timestamp at latest vsync
117   unsigned int seconds( 0u );
118   unsigned int microseconds( 0u );
119
120   bool running( true );
121   while( running )
122   {
123     bool validSync( true );
124
125     // Hardware VSyncs available?
126     if( mVSyncMonitor->UseHardware() )
127     {
128       // Yes..wait for hardware VSync
129       validSync = mVSyncMonitor->DoSync( currentSequenceNumber, currentSeconds, currentMicroseconds );
130     }
131     else
132     {
133       // No..use software timer
134       mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
135
136       unsigned int timeDelta( MICROSECONDS_PER_SECOND * (seconds - currentSeconds) );
137       if( microseconds < currentMicroseconds)
138       {
139         timeDelta += (microseconds + MICROSECONDS_PER_SECOND) - currentMicroseconds;
140       }
141       else
142       {
143         timeDelta += microseconds - currentMicroseconds;
144       }
145
146       if( timeDelta < TIME_PER_FRAME_IN_MICROSECONDS )
147       {
148           usleep( TIME_PER_FRAME_IN_MICROSECONDS - timeDelta );
149       }
150       else
151       {
152         usleep( TIME_PER_FRAME_IN_MICROSECONDS );
153       }
154     }
155
156     if( validSync )
157     {
158       // call Core::VSync with frame number and time stamp
159       mCore.VSync( ++frameNumber, currentSeconds, currentMicroseconds );
160     }
161
162     running = mUpdateRenderSync.VSyncNotifierSyncWithUpdateAndRender( frameNumber, currentSeconds, currentMicroseconds );
163   }
164
165   // uninstall a function for logging
166   mEnvironmentOptions.UnInstallLogFunction();
167
168 }
169
170 } // namespace Adaptor
171
172 } // namespace Internal
173
174 } // namespace Dali