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