Add environment variables for Pinch and Rotation gesture
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / adaptor-impl.cpp
1 /*
2  * Copyright (c) 2019 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 <dali/internal/adaptor/common/adaptor-impl.h>
20 #include <dali/internal/adaptor/common/adaptor-builder-impl.h>
21
22 // EXTERNAL INCLUDES
23 #include <dali/public-api/common/stage.h>
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/public-api/object/any.h>
26 #include <dali/devel-api/actors/actor-devel.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/integration-api/core.h>
29 #include <dali/integration-api/context-notifier.h>
30 #include <dali/integration-api/profiling.h>
31 #include <dali/integration-api/input-options.h>
32 #include <dali/integration-api/events/key-event-integ.h>
33 #include <dali/integration-api/events/touch-event-integ.h>
34 #include <dali/integration-api/events/wheel-event-integ.h>
35 #include <dali/integration-api/processor-interface.h>
36
37 #include <fstream>
38
39 // INTERNAL INCLUDES
40 #include <dali/public-api/dali-adaptor-common.h>
41 #include <dali/internal/system/common/thread-controller.h>
42 #include <dali/internal/system/common/performance-interface-factory.h>
43 #include <dali/internal/adaptor/common/lifecycle-observer.h>
44 #include <dali/internal/adaptor/common/thread-controller-interface.h>
45
46 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
47 #include <dali/internal/graphics/gles/egl-graphics.h> // Temporary until Core is abstracted
48
49 #include <dali/devel-api/text-abstraction/font-client.h>
50
51 #include <dali/internal/system/common/callback-manager.h>
52 #include <dali/internal/accessibility/common/tts-player-impl.h>
53 #include <dali/internal/accessibility/common/accessibility-adaptor-impl.h>
54 #include <dali/internal/window-system/common/event-handler.h>
55 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
56 #include <dali/internal/graphics/gles/gl-implementation.h>
57 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
58 #include <dali/internal/graphics/common/egl-image-extensions.h>
59 #include <dali/internal/clipboard/common/clipboard-impl.h>
60 #include <dali/internal/system/common/object-profiler.h>
61 #include <dali/internal/window-system/common/display-connection.h>
62 #include <dali/internal/window-system/common/window-impl.h>
63 #include <dali/internal/window-system/common/window-render-surface.h>
64
65 #include <dali/internal/system/common/logging.h>
66
67 #include <dali/internal/system/common/locale-utils.h>
68 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
69 #include <dali/internal/imaging/common/image-loader.h>
70
71 #include <dali/devel-api/adaptor-framework/file-stream.h>
72
73 using Dali::TextAbstraction::FontClient;
74
75 extern std::string GetSystemCachePath();
76
77 namespace Dali
78 {
79
80 namespace Internal
81 {
82
83 namespace Adaptor
84 {
85
86 namespace
87 {
88 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
89 } // unnamed namespace
90
91 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
92 {
93   Dali::Adaptor* adaptor = new Dali::Adaptor;
94   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions );
95   adaptor->mImpl = impl;
96
97   Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder();
98   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
99
100   impl->Initialize( graphicsFactory, configuration );
101   delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
102
103   return adaptor;
104 }
105
106 Dali::Adaptor* Adaptor::New( Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
107 {
108   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
109   Dali::Adaptor* adaptor = New( window, windowImpl.GetSurface(), configuration, environmentOptions );
110   windowImpl.SetAdaptor( *adaptor );
111   return adaptor;
112 }
113
114 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
115 {
116   Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
117   Adaptor* impl = new Adaptor( window, *adaptor, surface, environmentOptions ); // Impl adaptor
118   adaptor->mImpl = impl;
119
120   impl->Initialize( graphicsFactory, configuration );
121
122   return adaptor;
123 } // Called second
124
125 Dali::Adaptor* Adaptor::New( GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
126 {
127   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( window );
128   Dali::Adaptor* adaptor = New( graphicsFactory, window, windowImpl.GetSurface(), configuration, environmentOptions );
129   windowImpl.SetAdaptor( *adaptor );
130   return adaptor;
131 } // Called first
132
133 void Adaptor::Initialize( GraphicsFactory& graphicsFactory, Dali::Configuration::ContextLoss configuration )
134 {
135   // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
136   Dali::Integration::Log::LogFunction logFunction( Dali::TizenPlatform::LogMessage );
137   mEnvironmentOptions->SetLogFunction( logFunction );
138   mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
139
140   mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
141
142   std::string path;
143   GetDataStoragePath( path );
144   mPlatformAbstraction->SetDataStoragePath( path );
145
146   ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
147   if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
148   {
149     dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
150   }
151
152   // Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from files automatically.
153
154   if( mEnvironmentOptions->PerformanceServerRequired() )
155   {
156     mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface( *this, *mEnvironmentOptions );
157   }
158
159   mEnvironmentOptions->CreateTraceManager( mPerformanceInterface );
160   mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
161
162   mCallbackManager = CallbackManager::New();
163
164   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
165
166   DALI_ASSERT_DEBUG( defaultWindow->GetSurface() && "Surface not initialized" );
167
168   mGraphics = &( graphicsFactory.Create() );
169   mGraphics->Initialize( mEnvironmentOptions );
170
171   auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
172
173   // This will only be created once
174   eglGraphics->Create();
175
176   GlImplementation& mGLES = eglGraphics->GetGlesInterface();
177   EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
178   EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
179
180   mCore = Integration::Core::New( *this,
181                                   *mPlatformAbstraction,
182                                   mGLES,
183                                   eglSyncImpl,
184                                   eglContextHelperImpl,
185                                   dataRetentionPolicy ,
186                                   ( 0u != mEnvironmentOptions->GetRenderToFboInterval() ) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
187                                   mGraphics->GetDepthBufferRequired(),
188                                   mGraphics->GetStencilBufferRequired() );
189
190   defaultWindow->SetAdaptor( Get() );
191
192   Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
193
194   mWindowCreatedSignal.Emit( defaultSceneHolder );
195
196   const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
197   if( 0u < timeInterval )
198   {
199     mObjectProfiler = new ObjectProfiler( timeInterval );
200   }
201
202   mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
203
204   mDisplayConnection = Dali::DisplayConnection::New( *mGraphics, defaultWindow->GetSurface()->GetSurfaceType() );
205
206   mThreadController = new ThreadController( *this, *mEnvironmentOptions );
207
208   // Should be called after Core creation
209   if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
210   {
211     Integration::EnableProfiling( Dali::Integration::PROFILING_TYPE_PAN_GESTURE );
212   }
213   if( mEnvironmentOptions->GetPanGesturePredictionMode() >= 0 )
214   {
215     Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
216   }
217   if( mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0 )
218   {
219     Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
220   }
221   if( mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0 )
222   {
223     Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
224   }
225   if( mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0 )
226   {
227     Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
228   }
229   if( mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0 )
230   {
231     Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
232   }
233   if( mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0 )
234   {
235     Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
236   }
237   if( mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f )
238   {
239     Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
240   }
241   if( mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0 )
242   {
243     Integration::SetPanGestureUseActualTimes( mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false );
244   }
245   if( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0 )
246   {
247     Integration::SetPanGestureInterpolationTimeRange( mEnvironmentOptions->GetPanGestureInterpolationTimeRange() );
248   }
249   if( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0 )
250   {
251     Integration::SetPanGestureScalarOnlyPredictionEnabled( mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false  );
252   }
253   if( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0 )
254   {
255     Integration::SetPanGestureTwoPointPredictionEnabled( mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false  );
256   }
257   if( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0 )
258   {
259     Integration::SetPanGestureTwoPointInterpolatePastTime( mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() );
260   }
261   if( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f )
262   {
263     Integration::SetPanGestureTwoPointVelocityBias( mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() );
264   }
265   if( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f )
266   {
267     Integration::SetPanGestureTwoPointAccelerationBias( mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() );
268   }
269   if( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0 )
270   {
271     Integration::SetPanGestureMultitapSmoothingRange( mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() );
272   }
273   if( mEnvironmentOptions->GetMinimumPanDistance() >= 0 )
274   {
275     Integration::SetPanGestureMinimumDistance( mEnvironmentOptions->GetMinimumPanDistance() );
276   }
277   if( mEnvironmentOptions->GetMinimumPanEvents() >= 0 )
278   {
279     Integration::SetPanGestureMinimumPanEvents( mEnvironmentOptions->GetMinimumPanEvents() );
280   }
281   if( mEnvironmentOptions->GetMinimumPinchDistance() >= 0 )
282   {
283     Integration::SetPinchGestureMinimumDistance( mEnvironmentOptions->GetMinimumPinchDistance() );
284   }
285   if( mEnvironmentOptions->GetMinimumPinchTouchEvents() >= 0 )
286   {
287     Integration::SetPinchGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumPinchTouchEvents() );
288   }
289   if( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() >= 0 )
290   {
291     Integration::SetPinchGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() );
292   }
293   if( mEnvironmentOptions->GetMinimumRotationTouchEvents() >= 0 )
294   {
295     Integration::SetRotationGestureMinimumTouchEvents( mEnvironmentOptions->GetMinimumRotationTouchEvents() );
296   }
297   if( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() >= 0 )
298   {
299     Integration::SetRotationGestureMinimumTouchEventsAfterStart( mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() );
300   }
301   if( mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0 )
302   {
303     Integration::SetLongPressMinimumHoldingTime( mEnvironmentOptions->GetLongPressMinimumHoldingTime() );
304   }
305
306   // Set max texture size
307   if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
308   {
309     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
310   }
311
312   std::string systemCachePath = GetSystemCachePath();
313   if ( ! systemCachePath.empty() )
314   {
315     Dali::FileStream fileStream( systemCachePath + "gpu-environment.conf", Dali::FileStream::READ | Dali::FileStream::TEXT );
316     std::fstream& stream = dynamic_cast<std::fstream&>( fileStream.GetStream() );
317     if( stream.is_open() )
318     {
319       std::string line;
320       while( std::getline( stream, line ) )
321       {
322         line.erase( line.find_last_not_of( " \t\r\n" ) + 1 );
323         line.erase( 0, line.find_first_not_of( " \t\r\n" ) );
324         if( '#' == *( line.cbegin() ) || line == "" )
325         {
326           continue;
327         }
328
329         std::istringstream stream( line );
330         std::string environmentVariableName, environmentVariableValue;
331         std::getline(stream, environmentVariableName, ' ');
332         if( environmentVariableName == "DALI_ENV_MAX_TEXTURE_SIZE" && mEnvironmentOptions->GetMaxTextureSize() == 0 )
333         {
334           std::getline(stream, environmentVariableValue);
335           setenv( environmentVariableName.c_str() , environmentVariableValue.c_str(), 1 );
336           Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( std::atoi( environmentVariableValue.c_str() ) );
337         }
338       }
339     }
340     else
341     {
342       DALI_LOG_ERROR( "Fail to open file : %s\n", ( systemCachePath + "gpu-environment.conf" ).c_str() );
343     }
344   }
345 }
346
347 Adaptor::~Adaptor()
348 {
349   // Ensure stop status
350   Stop();
351
352   // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
353   gThreadLocalAdaptor = NULL;
354
355   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
356   {
357     (*iter)->OnDestroy();
358   }
359
360   // Clear out all the handles to Windows
361   mWindows.clear();
362
363   delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
364   delete mObjectProfiler;
365
366   delete mCore;
367
368   delete mDisplayConnection;
369   delete mPlatformAbstraction;
370   delete mCallbackManager;
371   delete mPerformanceInterface;
372
373   mGraphics->Destroy();
374
375   // uninstall it on this thread (main actor thread)
376   Dali::Integration::Log::UninstallLogFunction();
377
378   // Delete environment options if we own it
379   if( mEnvironmentOptionsOwned )
380   {
381     delete mEnvironmentOptions;
382   }
383 }
384
385 void Adaptor::Start()
386 {
387   // It doesn't support restart after stop at this moment to support restarting, need more testing
388   if( READY != mState )
389   {
390     return;
391   }
392
393   mCore->Initialize();
394
395   SetupSystemInformation();
396
397   // Start the callback manager
398   mCallbackManager->Start();
399
400   Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
401
402   unsigned int dpiHor, dpiVer;
403   dpiHor = dpiVer = 0;
404
405   defaultWindow->GetSurface()->GetDpi( dpiHor, dpiVer );
406
407   // set the DPI value for font rendering
408   FontClient fontClient = FontClient::Get();
409   fontClient.SetDpi( dpiHor, dpiVer );
410
411   // Initialize the thread controller
412   mThreadController->Initialize();
413
414   if( !Dali::TizenPlatform::ImageLoader::MaxTextureSizeUpdated() )
415   {
416     auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
417     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
418     Dali::TizenPlatform::ImageLoader::SetMaxTextureSize( mGLES.GetMaxTextureSize() );
419
420     std::string systemCachePath = GetSystemCachePath();
421     if( ! systemCachePath.empty() )
422     {
423       const int dir_err = system( std::string( "mkdir " + systemCachePath ).c_str() );
424       if (-1 == dir_err)
425       {
426           printf("Error creating directory!n");
427           exit(1);
428       }
429
430       Dali::FileStream fileStream( systemCachePath + "gpu-environment.conf", Dali::FileStream::WRITE | Dali::FileStream::TEXT );
431       std::fstream& configFile = dynamic_cast<std::fstream&>( fileStream.GetStream() );
432       if( configFile.is_open() )
433       {
434         configFile << "DALI_ENV_MAX_TEXTURE_SIZE " << mGLES.GetMaxTextureSize() << std::endl;
435       }
436     }
437   }
438
439   ProcessCoreEvents(); // Ensure any startup messages are processed.
440
441   // Initialize the image loader plugin
442   Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
443
444   for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
445   {
446     (*iter)->OnStart();
447   }
448 }
449
450 // Dali::Internal::Adaptor::Adaptor::Pause
451 void Adaptor::Pause()
452 {
453   // Only pause the adaptor if we're actually running.
454   if( RUNNING == mState )
455   {
456     // Inform observers that we are about to be paused.
457     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
458     {
459       (*iter)->OnPause();
460     }
461
462     // Pause all windows event handlers when adaptor paused
463     for( auto window : mWindows )
464     {
465       window->Pause();
466     }
467
468     mThreadController->Pause();
469     mState = PAUSED;
470
471     // Ensure any messages queued during pause callbacks are processed by doing another update.
472     RequestUpdateOnce();
473
474     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Paused\n" );
475   }
476   else
477   {
478     DALI_LOG_RELEASE_INFO( "Adaptor::Pause: Not paused [%d]\n", mState );
479   }
480 }
481
482 // Dali::Internal::Adaptor::Adaptor::Resume
483 void Adaptor::Resume()
484 {
485   // Only resume the adaptor if we are in the suspended state.
486   if( PAUSED == mState )
487   {
488     mState = RUNNING;
489
490     // Reset the event handlers when adaptor resumed
491     for( auto window : mWindows )
492     {
493       window->Resume();
494     }
495
496     // Inform observers that we have resumed.
497     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
498     {
499       (*iter)->OnResume();
500     }
501
502     // Trigger processing of events queued up while paused
503     mCore->ProcessEvents();
504
505     // Do at end to ensure our first update/render after resumption includes the processed messages as well
506     mThreadController->Resume();
507
508     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Resumed\n");
509   }
510   else
511   {
512     DALI_LOG_RELEASE_INFO( "Adaptor::Resume: Not resumed [%d]\n", mState );
513   }
514 }
515
516 void Adaptor::Stop()
517 {
518   if( RUNNING == mState ||
519       PAUSED  == mState ||
520       PAUSED_WHILE_HIDDEN == mState )
521   {
522     for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
523     {
524       (*iter)->OnStop();
525     }
526
527     mThreadController->Stop();
528
529     // Delete the TTS player
530     for( int i =0; i < Dali::TtsPlayer::MODE_NUM; i++ )
531     {
532       if( mTtsPlayers[i] )
533       {
534         mTtsPlayers[i].Reset();
535       }
536     }
537
538     // Destroy the image loader plugin
539     Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
540
541     delete mNotificationTrigger;
542     mNotificationTrigger = NULL;
543
544     mCallbackManager->Stop();
545
546     mState = STOPPED;
547
548     DALI_LOG_RELEASE_INFO( "Adaptor::Stop\n" );
549   }
550 }
551
552 void Adaptor::ContextLost()
553 {
554   mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
555 }
556
557 void Adaptor::ContextRegained()
558 {
559   // Inform core, so that texture resources can be reloaded
560   mCore->RecoverFromContextLoss();
561
562   mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
563 }
564
565 void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
566 {
567   Integration::Point convertedPoint( point );
568   mWindows.front()->FeedTouchPoint( convertedPoint, timeStamp );
569 }
570
571 void Adaptor::FeedWheelEvent( WheelEvent& wheelEvent )
572 {
573   Integration::WheelEvent event( static_cast< Integration::WheelEvent::Type >(wheelEvent.type), wheelEvent.direction, wheelEvent.modifiers, wheelEvent.point, wheelEvent.z, wheelEvent.timeStamp );
574   mWindows.front()->FeedWheelEvent( event );
575 }
576
577 void Adaptor::FeedKeyEvent( KeyEvent& keyEvent )
578 {
579   Integration::KeyEvent convertedEvent( keyEvent );
580   mWindows.front()->FeedKeyEvent( convertedEvent );
581 }
582
583 void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface )
584 {
585   Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation( window );
586   for( auto windowPtr : mWindows )
587   {
588     if( windowPtr == windowImpl ) // the window is not deleted
589     {
590       mResizedSignal.Emit( mAdaptor );
591
592       windowImpl->SetSurface( &newSurface );
593
594       // Flush the event queue to give the update-render thread chance
595       // to start processing messages for new camera setup etc as soon as possible
596       ProcessCoreEvents();
597
598       // This method blocks until the render thread has completed the replace.
599       mThreadController->ReplaceSurface( &newSurface );
600       break;
601     }
602   }
603 }
604
605 void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
606 {
607   // Flush the event queue to give the update-render thread chance
608   // to start processing messages for new camera setup etc as soon as possible
609   ProcessCoreEvents();
610
611   // This method blocks until the render thread has finished rendering the current surface.
612   mThreadController->DeleteSurface( &surface );
613 }
614
615 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
616 {
617   return *mWindows.front()->GetSurface();
618 }
619
620 void Adaptor::ReleaseSurfaceLock()
621 {
622   mWindows.front()->GetSurface()->ReleaseLock();
623 }
624
625 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
626 {
627   if( !mTtsPlayers[mode] )
628   {
629     // Create the TTS player when it needed, because it can reduce launching time.
630     mTtsPlayers[mode] = TtsPlayer::New(mode);
631   }
632
633   return mTtsPlayers[mode];
634 }
635
636 bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue, bool forceAdd )
637 {
638   bool idleAdded(false);
639
640   // Only add an idle if the Adaptor is actually running
641   if( RUNNING == mState || READY == mState || forceAdd )
642   {
643     idleAdded = mCallbackManager->AddIdleCallback( callback, hasReturnValue );
644   }
645
646   return idleAdded;
647 }
648
649 void Adaptor::RemoveIdle( CallbackBase* callback )
650 {
651   mCallbackManager->RemoveIdleCallback( callback );
652 }
653
654 void Adaptor::SetPreRenderCallback( CallbackBase* callback )
655 {
656   mThreadController->SetPreRenderCallback( callback );
657 }
658
659 bool Adaptor::AddWindow( Dali::Integration::SceneHolder childWindow, const std::string& childWindowName, const std::string& childWindowClassName, bool childWindowMode )
660 {
661   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( childWindow );
662   windowImpl.SetAdaptor( Get() );
663
664   // Add the new Window to the container - the order is not important
665   mWindows.push_back( &windowImpl );
666
667   mWindowCreatedSignal.Emit( childWindow );
668
669   return true;
670 }
671
672 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
673 {
674   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
675   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
676   {
677     if( *iter == &windowImpl )
678     {
679       mWindows.erase( iter );
680       return true;
681     }
682   }
683
684   return false;
685 }
686
687 bool Adaptor::RemoveWindow( std::string childWindowName )
688 {
689   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
690   {
691     if( ( *iter )->GetName() == childWindowName )
692     {
693       mWindows.erase( iter );
694       return true;
695     }
696   }
697
698   return false;
699 }
700
701 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
702 {
703   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
704   {
705     if( ( *iter )->GetId() == childWindow->GetId() )
706     {
707       mWindows.erase( iter );
708       return true;
709     }
710   }
711
712   return false;
713 }
714
715 Dali::Adaptor& Adaptor::Get()
716 {
717   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
718   return gThreadLocalAdaptor->mAdaptor;
719 }
720
721 bool Adaptor::IsAvailable()
722 {
723   return gThreadLocalAdaptor != NULL;
724 }
725
726 void Adaptor::SceneCreated()
727 {
728   mCore->SceneCreated();
729 }
730
731 Dali::Integration::Core& Adaptor::GetCore()
732 {
733   return *mCore;
734 }
735
736 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
737 {
738   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
739 }
740
741 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
742 {
743   DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
744   return *mDisplayConnection;
745 }
746
747 GraphicsInterface& Adaptor::GetGraphicsInterface()
748 {
749   DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
750   return *mGraphics;
751 }
752
753 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
754 {
755   return *mPlatformAbstraction;
756 }
757
758 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
759 {
760   return *mNotificationTrigger;
761 }
762
763 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
764 {
765   return mTriggerEventFactory;
766 }
767
768 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
769 {
770   return mSocketFactory;
771 }
772
773 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
774 {
775   if( !mWindows.empty() )
776   {
777     return mWindows.front()->GetSurface();
778   }
779
780   return nullptr;
781 }
782
783 TraceInterface& Adaptor::GetKernelTraceInterface()
784 {
785   return mKernelTracer;
786 }
787
788 TraceInterface& Adaptor::GetSystemTraceInterface()
789 {
790   return mSystemTracer;
791 }
792
793 PerformanceInterface* Adaptor::GetPerformanceInterface()
794 {
795   return mPerformanceInterface;
796 }
797
798 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
799 {
800   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
801   return *mPlatformAbstraction;
802 }
803
804 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
805 {
806   if( mTtsPlayers[mode] )
807   {
808     mTtsPlayers[mode].Reset();
809   }
810 }
811
812 Any Adaptor::GetNativeWindowHandle()
813 {
814   return mWindows.front()->GetNativeHandle();
815 }
816
817 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
818 {
819   Any nativeWindowHandle;
820
821   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
822
823   for( auto sceneHolder : mWindows )
824   {
825     if ( scene == sceneHolder->GetScene() )
826     {
827       nativeWindowHandle = sceneHolder->GetNativeHandle();
828       break;
829     }
830   }
831
832   return nativeWindowHandle;
833 }
834
835 Any Adaptor::GetGraphicsDisplay()
836 {
837   Any display;
838
839   if (mGraphics)
840   {
841     auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
842
843     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
844     display = eglImpl.GetDisplay();
845   }
846
847   return display;
848 }
849
850 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
851 {
852   mUseRemoteSurface = useRemoteSurface;
853 }
854
855 void Adaptor::AddObserver( LifeCycleObserver& observer )
856 {
857   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
858
859   if ( match == mObservers.end() )
860   {
861     mObservers.push_back( &observer );
862   }
863 }
864
865 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
866 {
867   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
868
869   if ( match != mObservers.end() )
870   {
871     mObservers.erase( match );
872   }
873 }
874
875 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
876 {
877   if( mCore )
878   {
879     mCore->QueueEvent(event);
880   }
881 }
882
883 void Adaptor::ProcessCoreEvents()
884 {
885   if( mCore )
886   {
887     if( mPerformanceInterface )
888     {
889       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
890     }
891
892     mCore->ProcessEvents();
893
894     if( mPerformanceInterface )
895     {
896       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
897     }
898   }
899 }
900
901 void Adaptor::RequestUpdate( bool forceUpdate )
902 {
903   switch( mState )
904   {
905     case RUNNING:
906     {
907       mThreadController->RequestUpdate();
908       break;
909     }
910     case PAUSED:
911     case PAUSED_WHILE_HIDDEN:
912     {
913       if( forceUpdate )
914       {
915         // Update (and resource upload) without rendering
916         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
917       }
918       break;
919     }
920     default:
921     {
922       // Do nothing
923       break;
924     }
925   }
926 }
927
928 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
929 {
930   // Only request a notification if the Adaptor is actually running
931   // and we haven't installed the idle notification
932   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
933   {
934     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
935   }
936 }
937
938 void Adaptor::OnWindowShown()
939 {
940   if( PAUSED_WHILE_HIDDEN == mState )
941   {
942     // Adaptor can now be resumed
943     mState = PAUSED;
944
945     Resume();
946
947     // Force a render task
948     RequestUpdateOnce();
949   }
950   else if( RUNNING == mState )
951   {
952     // Force a render task
953     RequestUpdateOnce();
954
955     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
956   }
957   else
958   {
959     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
960   }
961 }
962
963 void Adaptor::OnWindowHidden()
964 {
965   if( RUNNING == mState || READY == mState )
966   {
967     bool allWindowsHidden = true;
968
969     for( auto window : mWindows )
970     {
971       if ( window->IsVisible() )
972       {
973         allWindowsHidden = false;
974         break;
975       }
976     }
977
978     // Only pause the adaptor when all the windows are hidden
979     if( allWindowsHidden )
980     {
981       if( mState == RUNNING )
982       {
983         Pause();
984
985         // Adaptor cannot be resumed until any window is shown
986         mState = PAUSED_WHILE_HIDDEN;
987       }
988       else  // mState is READY
989       {
990         // Pause the adaptor after the state gets RUNNING
991         mState = PAUSED_WHILE_INITIALIZING;
992       }
993     }
994     else
995     {
996       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
997     }
998   }
999   else
1000   {
1001     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
1002   }
1003 }
1004
1005 // Dali::Internal::Adaptor::Adaptor::OnDamaged
1006 void Adaptor::OnDamaged( const DamageArea& area )
1007 {
1008   // This is needed for the case where Dali window is partially obscured
1009   RequestUpdate( false );
1010 }
1011
1012 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1013 {
1014   mResizedSignal.Emit( mAdaptor );
1015 }
1016
1017 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1018 {
1019   // Flush the event queue to give the update-render thread chance
1020   // to start processing messages for new camera setup etc as soon as possible
1021   ProcessCoreEvents();
1022
1023   mThreadController->ResizeSurface();
1024 }
1025
1026 void Adaptor::NotifySceneCreated()
1027 {
1028   GetCore().SceneCreated();
1029
1030   // Flush the event queue to give the update-render thread chance
1031   // to start processing messages for new camera setup etc as soon as possible
1032   ProcessCoreEvents();
1033
1034   // Start thread controller after the scene has been created
1035   mThreadController->Start();
1036
1037   // Process after surface is created (registering to remote surface provider if required)
1038   SurfaceInitialized();
1039
1040   if( mState != PAUSED_WHILE_INITIALIZING )
1041   {
1042     mState = RUNNING;
1043
1044     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1045   }
1046   else
1047   {
1048     mState = RUNNING;
1049
1050     Pause();
1051
1052     mState = PAUSED_WHILE_HIDDEN;
1053
1054     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1055   }
1056 }
1057
1058 void Adaptor::NotifyLanguageChanged()
1059 {
1060   mLanguageChangedSignal.Emit( mAdaptor );
1061 }
1062
1063 void Adaptor::RenderOnce()
1064 {
1065   RequestUpdateOnce();
1066 }
1067
1068 const LogFactoryInterface& Adaptor::GetLogFactory()
1069 {
1070   return *mEnvironmentOptions;
1071 }
1072
1073 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1074 {
1075   GetCore().RegisterProcessor(processor);
1076 }
1077
1078 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1079 {
1080   GetCore().UnregisterProcessor(processor);
1081 }
1082
1083 bool Adaptor::IsMultipleWindowSupported() const
1084 {
1085   auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
1086   EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
1087   bool ret = eglImpl.IsSurfacelessContextSupported();
1088   return ret;
1089 }
1090
1091 void Adaptor::RequestUpdateOnce()
1092 {
1093   if( mThreadController )
1094   {
1095     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1096   }
1097 }
1098
1099 bool Adaptor::ProcessCoreEventsFromIdle()
1100 {
1101   ProcessCoreEvents();
1102
1103   // the idle handle automatically un-installs itself
1104   mNotificationOnIdleInstalled = false;
1105
1106   return false;
1107 }
1108
1109 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1110 {
1111   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1112
1113   for( auto window : mWindows )
1114   {
1115     if ( scene == window->GetScene() )
1116     {
1117       return window;
1118     }
1119   }
1120
1121   return nullptr;
1122 }
1123
1124 Dali::WindowContainer Adaptor::GetWindows() const
1125 {
1126   Dali::WindowContainer windows;
1127
1128   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1129   {
1130     // Downcast to Dali::Window
1131     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1132     if ( window )
1133     {
1134       windows.push_back( window );
1135     }
1136   }
1137
1138   return windows;
1139 }
1140
1141 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1142 {
1143   Dali::SceneHolderList sceneHolderList;
1144
1145   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1146   {
1147     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1148   }
1149
1150   return sceneHolderList;
1151 }
1152
1153 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1154 : mResizedSignal(),
1155   mLanguageChangedSignal(),
1156   mWindowCreatedSignal(),
1157   mAdaptor( adaptor ),
1158   mState( READY ),
1159   mCore( nullptr ),
1160   mThreadController( nullptr ),
1161   mGraphics( nullptr ),
1162   mDisplayConnection( nullptr ),
1163   mWindows(),
1164   mPlatformAbstraction( nullptr ),
1165   mCallbackManager( nullptr ),
1166   mNotificationOnIdleInstalled( false ),
1167   mNotificationTrigger( nullptr ),
1168   mDaliFeedbackPlugin(),
1169   mFeedbackController( nullptr ),
1170   mTtsPlayers(),
1171   mObservers(),
1172   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1173   mPerformanceInterface( nullptr ),
1174   mKernelTracer(),
1175   mSystemTracer(),
1176   mTriggerEventFactory(),
1177   mObjectProfiler( nullptr ),
1178   mSocketFactory(),
1179   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1180   mUseRemoteSurface( false )
1181 {
1182   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1183   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1184
1185   gThreadLocalAdaptor = this;
1186 }
1187
1188 void Adaptor::SetRootLayoutDirection( std::string locale )
1189 {
1190   Dali::Stage stage = Dali::Stage::GetCurrent();
1191
1192   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1193                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1194 }
1195
1196 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1197 {
1198   bool idleAdded( false );
1199
1200   // Only add an idle if the Adaptor is actually running
1201   if( RUNNING == mState || READY == mState || forceAdd )
1202   {
1203     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1204   }
1205
1206   return idleAdded;
1207 }
1208
1209 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1210 {
1211   mCallbackManager->RemoveIdleEntererCallback( callback );
1212 }
1213
1214 } // namespace Adaptor
1215
1216 } // namespace Internal
1217
1218 } // namespace Dali