[Tizen] Implement partial update
[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   mWindowCreatedSignal.Emit( childWindow );
653
654   return true;
655 }
656
657 bool Adaptor::RemoveWindow( Dali::Integration::SceneHolder* childWindow )
658 {
659   Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation( *childWindow );
660   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
661   {
662     if( *iter == &windowImpl )
663     {
664       mWindows.erase( iter );
665       return true;
666     }
667   }
668
669   return false;
670 }
671
672 bool Adaptor::RemoveWindow( std::string childWindowName )
673 {
674   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
675   {
676     if( ( *iter )->GetName() == childWindowName )
677     {
678       mWindows.erase( iter );
679       return true;
680     }
681   }
682
683   return false;
684 }
685
686 bool Adaptor::RemoveWindow( Internal::Adaptor::SceneHolder* childWindow )
687 {
688   for ( WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter )
689   {
690     if( ( *iter )->GetId() == childWindow->GetId() )
691     {
692       mWindows.erase( iter );
693       return true;
694     }
695   }
696
697   return false;
698 }
699
700 Dali::Adaptor& Adaptor::Get()
701 {
702   DALI_ASSERT_ALWAYS( IsAvailable() && "Adaptor not instantiated" );
703   return gThreadLocalAdaptor->mAdaptor;
704 }
705
706 bool Adaptor::IsAvailable()
707 {
708   return gThreadLocalAdaptor != NULL;
709 }
710
711 void Adaptor::SceneCreated()
712 {
713   mCore->SceneCreated();
714 }
715
716 Dali::Integration::Core& Adaptor::GetCore()
717 {
718   return *mCore;
719 }
720
721 void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
722 {
723   mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
724 }
725
726 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
727 {
728   DALI_ASSERT_DEBUG( mDisplayConnection && "Display connection not created" );
729   return *mDisplayConnection;
730 }
731
732 GraphicsInterface& Adaptor::GetGraphicsInterface()
733 {
734   DALI_ASSERT_DEBUG( mGraphics && "Graphics interface not created" );
735   return *mGraphics;
736 }
737
738 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
739 {
740   return *mPlatformAbstraction;
741 }
742
743 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
744 {
745   return *mNotificationTrigger;
746 }
747
748 TriggerEventFactoryInterface& Adaptor::GetTriggerEventFactoryInterface()
749 {
750   return mTriggerEventFactory;
751 }
752
753 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
754 {
755   return mSocketFactory;
756 }
757
758 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
759 {
760   if( !mWindows.empty() )
761   {
762     return mWindows.front()->GetSurface();
763   }
764
765   return nullptr;
766 }
767
768 TraceInterface& Adaptor::GetKernelTraceInterface()
769 {
770   return mKernelTracer;
771 }
772
773 TraceInterface& Adaptor::GetSystemTraceInterface()
774 {
775   return mSystemTracer;
776 }
777
778 PerformanceInterface* Adaptor::GetPerformanceInterface()
779 {
780   return mPerformanceInterface;
781 }
782
783 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
784 {
785   DALI_ASSERT_DEBUG( mPlatformAbstraction && "PlatformAbstraction not created" );
786   return *mPlatformAbstraction;
787 }
788
789 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
790 {
791   if( mTtsPlayers[mode] )
792   {
793     mTtsPlayers[mode].Reset();
794   }
795 }
796
797 Any Adaptor::GetNativeWindowHandle()
798 {
799   return mWindows.front()->GetNativeHandle();
800 }
801
802 Any Adaptor::GetNativeWindowHandle( Dali::Actor actor )
803 {
804   Any nativeWindowHandle;
805
806   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
807
808   for( auto sceneHolder : mWindows )
809   {
810     if ( scene == sceneHolder->GetScene() )
811     {
812       nativeWindowHandle = sceneHolder->GetNativeHandle();
813       break;
814     }
815   }
816
817   return nativeWindowHandle;
818 }
819
820 Any Adaptor::GetGraphicsDisplay()
821 {
822   Any display;
823
824   if (mGraphics)
825   {
826     auto eglGraphics = static_cast<EglGraphics *>( mGraphics ); // This interface is temporary until Core has been updated to match
827
828     EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
829     display = eglImpl.GetDisplay();
830   }
831
832   return display;
833 }
834
835 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
836 {
837   mUseRemoteSurface = useRemoteSurface;
838 }
839
840 void Adaptor::AddObserver( LifeCycleObserver& observer )
841 {
842   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
843
844   if ( match == mObservers.end() )
845   {
846     mObservers.push_back( &observer );
847   }
848 }
849
850 void Adaptor::RemoveObserver( LifeCycleObserver& observer )
851 {
852   ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
853
854   if ( match != mObservers.end() )
855   {
856     mObservers.erase( match );
857   }
858 }
859
860 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
861 {
862   if( mCore )
863   {
864     mCore->QueueEvent(event);
865   }
866 }
867
868 void Adaptor::ProcessCoreEvents()
869 {
870   if( mCore )
871   {
872     if( mPerformanceInterface )
873     {
874       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_START );
875     }
876
877     mCore->ProcessEvents();
878
879     if( mPerformanceInterface )
880     {
881       mPerformanceInterface->AddMarker( PerformanceInterface::PROCESS_EVENTS_END );
882     }
883   }
884 }
885
886 void Adaptor::RequestUpdate( bool forceUpdate )
887 {
888   switch( mState )
889   {
890     case RUNNING:
891     {
892       mThreadController->RequestUpdate();
893       break;
894     }
895     case PAUSED:
896     case PAUSED_WHILE_HIDDEN:
897     {
898       if( forceUpdate )
899       {
900         // Update (and resource upload) without rendering
901         mThreadController->RequestUpdateOnce( UpdateMode::SKIP_RENDER );
902       }
903       break;
904     }
905     default:
906     {
907       // Do nothing
908       break;
909     }
910   }
911 }
912
913 void Adaptor::RequestProcessEventsOnIdle( bool forceProcess )
914 {
915   // Only request a notification if the Adaptor is actually running
916   // and we haven't installed the idle notification
917   if( ( ! mNotificationOnIdleInstalled ) && ( RUNNING == mState || READY == mState || forceProcess ) )
918   {
919     mNotificationOnIdleInstalled = AddIdleEnterer( MakeCallback( this, &Adaptor::ProcessCoreEventsFromIdle ), forceProcess );
920   }
921 }
922
923 void Adaptor::OnWindowShown()
924 {
925   if( PAUSED_WHILE_HIDDEN == mState )
926   {
927     // Adaptor can now be resumed
928     mState = PAUSED;
929
930     Resume();
931
932     // Force a render task
933     RequestUpdateOnce();
934   }
935   else if( RUNNING == mState )
936   {
937     // Force a render task
938     RequestUpdateOnce();
939
940     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Update requested.\n" );
941   }
942   else
943   {
944     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState );
945   }
946 }
947
948 void Adaptor::OnWindowHidden()
949 {
950   if( RUNNING == mState || READY == mState )
951   {
952     bool allWindowsHidden = true;
953
954     for( auto window : mWindows )
955     {
956       if ( window->IsVisible() )
957       {
958         allWindowsHidden = false;
959         break;
960       }
961     }
962
963     // Only pause the adaptor when all the windows are hidden
964     if( allWindowsHidden )
965     {
966       if( mState == RUNNING )
967       {
968         Pause();
969
970         // Adaptor cannot be resumed until any window is shown
971         mState = PAUSED_WHILE_HIDDEN;
972       }
973       else  // mState is READY
974       {
975         // Pause the adaptor after the state gets RUNNING
976         mState = PAUSED_WHILE_INITIALIZING;
977       }
978     }
979     else
980     {
981       DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n" );
982     }
983   }
984   else
985   {
986     DALI_LOG_RELEASE_INFO( "Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState );
987   }
988 }
989
990 // Dali::Internal::Adaptor::Adaptor::OnDamaged
991 void Adaptor::OnDamaged( const DamageArea& area )
992 {
993   // This is needed for the case where Dali window is partially obscured
994   RequestUpdate( false );
995 }
996
997 void Adaptor::SurfaceResizePrepare( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
998 {
999   mResizedSignal.Emit( mAdaptor );
1000 }
1001
1002 void Adaptor::SurfaceResizeComplete( Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize )
1003 {
1004   // Flush the event queue to give the update-render thread chance
1005   // to start processing messages for new camera setup etc as soon as possible
1006   ProcessCoreEvents();
1007
1008   mThreadController->ResizeSurface();
1009 }
1010
1011 void Adaptor::NotifySceneCreated()
1012 {
1013   GetCore().SceneCreated();
1014
1015   // Flush the event queue to give the update-render thread chance
1016   // to start processing messages for new camera setup etc as soon as possible
1017   ProcessCoreEvents();
1018
1019   // Start thread controller after the scene has been created
1020   mThreadController->Start();
1021
1022   // Process after surface is created (registering to remote surface provider if required)
1023   SurfaceInitialized();
1024
1025   if( mState != PAUSED_WHILE_INITIALIZING )
1026   {
1027     mState = RUNNING;
1028
1029     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is running\n" );
1030   }
1031   else
1032   {
1033     mState = RUNNING;
1034
1035     Pause();
1036
1037     mState = PAUSED_WHILE_HIDDEN;
1038
1039     DALI_LOG_RELEASE_INFO( "Adaptor::NotifySceneCreated: Adaptor is paused\n" );
1040   }
1041 }
1042
1043 void Adaptor::NotifyLanguageChanged()
1044 {
1045   mLanguageChangedSignal.Emit( mAdaptor );
1046 }
1047
1048 void Adaptor::RenderOnce()
1049 {
1050   RequestUpdateOnce();
1051 }
1052
1053 const LogFactoryInterface& Adaptor::GetLogFactory()
1054 {
1055   return *mEnvironmentOptions;
1056 }
1057
1058 void Adaptor::RegisterProcessor( Integration::Processor& processor )
1059 {
1060   GetCore().RegisterProcessor(processor);
1061 }
1062
1063 void Adaptor::UnregisterProcessor( Integration::Processor& processor )
1064 {
1065   GetCore().UnregisterProcessor(processor);
1066 }
1067
1068 bool Adaptor::IsMultipleWindowSupported() const
1069 {
1070   auto eglGraphics = static_cast<EglGraphics *>( mGraphics );
1071   EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
1072   bool ret = eglImpl.IsSurfacelessContextSupported();
1073   return ret;
1074 }
1075
1076 void Adaptor::RequestUpdateOnce()
1077 {
1078   if( mThreadController )
1079   {
1080     mThreadController->RequestUpdateOnce( UpdateMode::NORMAL );
1081   }
1082 }
1083
1084 bool Adaptor::ProcessCoreEventsFromIdle()
1085 {
1086   ProcessCoreEvents();
1087
1088   // the idle handle automatically un-installs itself
1089   mNotificationOnIdleInstalled = false;
1090
1091   return false;
1092 }
1093
1094 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow( Dali::Actor& actor )
1095 {
1096   Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor );
1097
1098   for( auto window : mWindows )
1099   {
1100     if ( scene == window->GetScene() )
1101     {
1102       return window;
1103     }
1104   }
1105
1106   return nullptr;
1107 }
1108
1109 Dali::WindowContainer Adaptor::GetWindows() const
1110 {
1111   Dali::WindowContainer windows;
1112
1113   for ( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1114   {
1115     // Downcast to Dali::Window
1116     Dali::Window window( dynamic_cast<Dali::Internal::Adaptor::Window*>( *iter ) );
1117     if ( window )
1118     {
1119       windows.push_back( window );
1120     }
1121   }
1122
1123   return windows;
1124 }
1125
1126 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1127 {
1128   Dali::SceneHolderList sceneHolderList;
1129
1130   for( auto iter = mWindows.begin(); iter != mWindows.end(); ++iter )
1131   {
1132     sceneHolderList.push_back( Dali::Integration::SceneHolder( *iter ) );
1133   }
1134
1135   return sceneHolderList;
1136 }
1137
1138 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions)
1139 : mResizedSignal(),
1140   mLanguageChangedSignal(),
1141   mWindowCreatedSignal(),
1142   mAdaptor( adaptor ),
1143   mState( READY ),
1144   mCore( nullptr ),
1145   mThreadController( nullptr ),
1146   mGraphics( nullptr ),
1147   mDisplayConnection( nullptr ),
1148   mWindows(),
1149   mPlatformAbstraction( nullptr ),
1150   mCallbackManager( nullptr ),
1151   mNotificationOnIdleInstalled( false ),
1152   mNotificationTrigger( nullptr ),
1153   mDaliFeedbackPlugin(),
1154   mFeedbackController( nullptr ),
1155   mTtsPlayers(),
1156   mObservers(),
1157   mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1158   mPerformanceInterface( nullptr ),
1159   mKernelTracer(),
1160   mSystemTracer(),
1161   mTriggerEventFactory(),
1162   mObjectProfiler( nullptr ),
1163   mSocketFactory(),
1164   mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
1165   mUseRemoteSurface( false )
1166 {
1167   DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
1168   mWindows.insert( mWindows.begin(), &Dali::GetImplementation( window ) );
1169
1170   gThreadLocalAdaptor = this;
1171 }
1172
1173 void Adaptor::SetRootLayoutDirection( std::string locale )
1174 {
1175   Dali::Stage stage = Dali::Stage::GetCurrent();
1176
1177   stage.GetRootLayer().SetProperty( Dali::Actor::Property::LAYOUT_DIRECTION,
1178                                     static_cast< LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
1179 }
1180
1181 bool Adaptor::AddIdleEnterer( CallbackBase* callback, bool forceAdd )
1182 {
1183   bool idleAdded( false );
1184
1185   // Only add an idle if the Adaptor is actually running
1186   if( RUNNING == mState || READY == mState || forceAdd )
1187   {
1188     idleAdded = mCallbackManager->AddIdleEntererCallback( callback );
1189   }
1190
1191   return idleAdded;
1192 }
1193
1194 void Adaptor::RemoveIdleEnterer( CallbackBase* callback )
1195 {
1196   mCallbackManager->RemoveIdleEntererCallback( callback );
1197 }
1198
1199 } // namespace Adaptor
1200
1201 } // namespace Internal
1202
1203 } // namespace Dali