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