Revert "[Tizen] Revert "Support multiple window rendering""
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / common / application-impl.cpp
1 /*
2  * Copyright (c) 2018 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/application-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/devel-api/adaptor-framework/style-monitor.h>
26 #include <dali/internal/system/common/command-line-options.h>
27 #include <dali/internal/adaptor/common/framework.h>
28 #include <dali/internal/system/common/singleton-service-impl.h>
29 #include <dali/internal/adaptor/common/lifecycle-controller-impl.h>
30 #include <dali/internal/window-system/common/window-impl.h>
31 #include <dali/internal/window-system/common/window-render-surface.h>
32
33 #undef Status
34
35 namespace Dali
36 {
37
38 namespace TizenPlatform
39 {
40 class TizenPlatformAbstraction;
41 }
42
43 namespace Integration
44 {
45 class Core;
46 }
47
48 namespace Internal
49 {
50
51 namespace Adaptor
52 {
53
54 namespace
55 {
56
57 const float DEFAULT_STEREO_BASE( 65.0f );
58
59 } // unnamed namespace
60
61 ApplicationPtr Application::gPreInitializedApplication( NULL );
62
63 ApplicationPtr Application::New(
64   int* argc,
65   char **argv[],
66   const std::string& stylesheet,
67   Dali::Application::WINDOW_MODE windowMode,
68   const PositionSize& positionSize,
69   Framework::Type applicationType)
70 {
71   ApplicationPtr application ( new Application (argc, argv, stylesheet, windowMode, positionSize, applicationType ) );
72   return application;
73 }
74
75 void Application::PreInitialize( int* argc, char** argv[] )
76 {
77   if( !gPreInitializedApplication )
78   {
79     gPreInitializedApplication = new Application ( argc, argv, "", Dali::Application::OPAQUE, PositionSize(), Framework::NORMAL );
80
81     gPreInitializedApplication->CreateWindow();    // Only create window
82
83     gPreInitializedApplication->mLaunchpadState = Launchpad::PRE_INITIALIZED;
84   }
85 }
86
87 Application::Application( int* argc, char** argv[], const std::string& stylesheet,
88   Dali::Application::WINDOW_MODE windowMode, const PositionSize& positionSize, Framework::Type applicationType )
89 : mInitSignal(),
90   mTerminateSignal(),
91   mPauseSignal(),
92   mResumeSignal(),
93   mResetSignal(),
94   mResizeSignal(),
95   mAppControlSignal(),
96   mLanguageChangedSignal(),
97   mRegionChangedSignal(),
98   mBatteryLowSignal(),
99   mMemoryLowSignal(),
100   mEventLoop( nullptr ),
101   mFramework( nullptr ),
102   mContextLossConfiguration( Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS ),
103   mCommandLineOptions( nullptr ),
104   mSingletonService( SingletonService::New() ),
105   mAdaptorBuilder( nullptr ),
106   mAdaptor( nullptr ),
107   mMainWindow(),
108   mMainWindowMode( windowMode ),
109   mMainWindowName(),
110   mStylesheet( stylesheet ),
111   mEnvironmentOptions(),
112   mWindowPositionSize( positionSize ),
113   mLaunchpadState( Launchpad::NONE ),
114   mSlotDelegate( this ),
115   mViewMode( MONO ),
116   mStereoBase( DEFAULT_STEREO_BASE )
117 {
118   // Get mName from environment options
119   mMainWindowName = mEnvironmentOptions.GetWindowName();
120   if( mMainWindowName.empty() && argc && ( *argc > 0 ) )
121   {
122     // Set mName from command-line args if environment option not set
123     mMainWindowName = (*argv)[0];
124   }
125
126   mCommandLineOptions = new CommandLineOptions(argc, argv);
127   mFramework = new Framework( *this, argc, argv, applicationType );
128   mUseRemoteSurface = (applicationType == Framework::WATCH);
129 }
130
131 Application::~Application()
132 {
133   mSingletonService.UnregisterAll();
134
135   mMainWindow.Reset();
136   delete mAdaptor;
137   delete mAdaptorBuilder;
138   delete mCommandLineOptions;
139   delete mFramework;
140 }
141
142 void Application::CreateWindow()
143 {
144   if( mWindowPositionSize.width == 0 && mWindowPositionSize.height == 0 )
145   {
146     if( mCommandLineOptions->stageWidth > 0 && mCommandLineOptions->stageHeight > 0 )
147     {
148       // Command line options override environment options and full screen
149       mWindowPositionSize.width = mCommandLineOptions->stageWidth;
150       mWindowPositionSize.height = mCommandLineOptions->stageHeight;
151     }
152     else if( mEnvironmentOptions.GetWindowWidth() && mEnvironmentOptions.GetWindowHeight() )
153     {
154       // Environment options override full screen functionality if command line arguments not provided
155       mWindowPositionSize.width = mEnvironmentOptions.GetWindowWidth();
156       mWindowPositionSize.height = mEnvironmentOptions.GetWindowHeight();
157     }
158   }
159
160   const std::string& windowClassName = mEnvironmentOptions.GetWindowClassName();
161   mMainWindow = Dali::Window::New( mWindowPositionSize, mMainWindowName, windowClassName, mMainWindowMode == Dali::Application::TRANSPARENT );
162
163   int indicatorVisibleMode = mEnvironmentOptions.GetIndicatorVisibleMode();
164   if( indicatorVisibleMode >= Dali::Window::INVISIBLE && indicatorVisibleMode <= Dali::Window::AUTO )
165   {
166     GetImplementation( mMainWindow ).SetIndicatorVisibleMode( static_cast< Dali::Window::IndicatorVisibleMode >( indicatorVisibleMode ) );
167   }
168
169   // Quit the application when the window is closed
170   GetImplementation( mMainWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
171 }
172
173 void Application::CreateAdaptor()
174 {
175   DALI_ASSERT_ALWAYS( mMainWindow && "Window required to create adaptor" );
176
177   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
178
179   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( graphicsFactory, mMainWindow, mContextLossConfiguration, &mEnvironmentOptions );
180
181   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
182
183   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
184 }
185
186 void Application::CreateAdaptorBuilder()
187 {
188   mAdaptorBuilder = new AdaptorBuilder();
189 }
190
191 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
192 {
193   mContextLossConfiguration = configuration;
194
195   // Run the application
196   mFramework->Run();
197 }
198
199 void Application::Lower()
200 {
201   // Lower the application without quitting it.
202   mMainWindow.Lower();
203 }
204
205 void Application::Quit()
206 {
207   // Actually quit the application.
208   // Force a call to Quit even if adaptor is not running.
209   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
210 }
211
212 void Application::QuitFromMainLoop()
213 {
214   mAdaptor->Stop();
215
216   mFramework->Quit();
217   // This will trigger OnTerminate(), below, after the main loop has completed.
218 }
219
220 void Application::DoInit()
221 {
222   CreateAdaptorBuilder();
223
224   // If an application was pre-initialized, a window was made in advance
225   if( mLaunchpadState == Launchpad::NONE )
226   {
227     CreateWindow();
228   }
229
230   CreateAdaptor();
231
232   // Run the adaptor
233   mAdaptor->Start();
234
235   // Check if user requires no vsyncing and set Adaptor
236   if (mCommandLineOptions->noVSyncOnRender)
237   {
238     mAdaptor->SetUseHardwareVSync(false);
239   }
240
241   if( ! mStylesheet.empty() )
242   {
243     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
244   }
245 }
246
247 void Application::DoStart()
248 {
249   mAdaptor->NotifySceneCreated();
250 }
251
252 void Application::DoTerminate()
253 {
254   if( mAdaptor )
255   {
256     // Ensure that the render-thread is not using the surface(window) after we delete it
257     mAdaptor->Stop();
258   }
259
260   mMainWindow.Reset(); // This only resets (clears) the default Window
261 }
262
263 void Application::DoPause()
264 {
265   mAdaptor->Pause();
266 }
267
268 void Application::DoResume()
269 {
270   mAdaptor->Resume();
271 }
272
273 void Application::DoLanguageChange()
274 {
275   mAdaptor->NotifyLanguageChanged();
276 }
277
278 void Application::OnInit()
279 {
280   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
281
282   DoInit();
283
284   // Wire up the LifecycleController
285   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
286
287   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
288   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
289   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
290   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
291   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
292   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
293   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
294
295   Dali::Application application(this);
296   mInitSignal.Emit( application );
297
298   DoStart();
299 }
300
301 void Application::OnTerminate()
302 {
303   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
304   // delete the window as ecore_x has been destroyed by AppCore
305
306   Dali::Application application(this);
307   mTerminateSignal.Emit( application );
308
309   DoTerminate();
310 }
311
312 void Application::OnPause()
313 {
314   // A DALi app should handle Pause/Resume events.
315   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
316   // Pausing DALi core only occurs on the Window Hidden framework event
317   Dali::Application application(this);
318   mPauseSignal.Emit( application );
319 }
320
321 void Application::OnResume()
322 {
323   // Emit the signal first so the application can queue any messages before we do an update/render
324   // This ensures we do not just redraw the last frame before pausing if that's not required
325   Dali::Application application(this);
326   mResumeSignal.Emit( application );
327
328   // DALi just delivers the framework Resume event to the application.
329   // Resuming DALi core only occurs on the Window Show framework event
330
331   // Trigger processing of events queued up while paused
332   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
333   coreEventInterface.ProcessCoreEvents();
334 }
335
336 void Application::OnReset()
337 {
338   /*
339    * usually, reset callback was called when a caller request to launch this application via aul.
340    * because Application class already handled initialization in OnInit(), OnReset do nothing.
341    */
342   Dali::Application application(this);
343   mResetSignal.Emit( application );
344 }
345
346 void Application::OnAppControl(void *data)
347 {
348   Dali::Application application(this);
349   mAppControlSignal.Emit( application , data );
350 }
351
352 void Application::OnLanguageChanged()
353 {
354   DoLanguageChange();
355   Dali::Application application(this);
356   mLanguageChangedSignal.Emit( application );
357 }
358
359 void Application::OnRegionChanged()
360 {
361   Dali::Application application(this);
362   mRegionChangedSignal.Emit( application );
363 }
364
365 void Application::OnBatteryLow( Dali::DeviceStatus::Battery::Status status )
366 {
367   Dali::Application application(this);
368   mBatteryLowSignal.Emit( application );
369
370   mLowBatterySignal.Emit( status );
371 }
372
373 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
374 {
375   Dali::Application application(this);
376   mMemoryLowSignal.Emit( application );
377
378   mLowMemorySignal.Emit( status );
379 }
380 void Application::OnResize(Dali::Adaptor& adaptor)
381 {
382   Dali::Application application(this);
383   mResizeSignal.Emit( application );
384 }
385
386 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
387 {
388   return mAdaptor->AddIdle( callback, hasReturnValue );
389 }
390
391 std::string Application::GetRegion() const
392 {
393   return mFramework->GetRegion();
394 }
395
396 std::string Application::GetLanguage() const
397 {
398   return mFramework->GetLanguage();
399 }
400
401 Dali::Adaptor& Application::GetAdaptor()
402 {
403   return *mAdaptor;
404 }
405
406 Dali::Window Application::GetWindow()
407 {
408   return mMainWindow;
409 }
410
411 // Stereoscopy
412
413 void Application::SetViewMode( ViewMode viewMode )
414 {
415   mViewMode = viewMode;
416 }
417
418 ViewMode Application::GetViewMode() const
419 {
420   return mViewMode;
421 }
422
423 void Application::SetStereoBase( float stereoBase )
424 {
425   mStereoBase = stereoBase;
426 }
427
428 float Application::GetStereoBase() const
429 {
430   return mStereoBase;
431 }
432
433 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
434 {
435   Dali::Window newWindow = Dali::Window::New( positionSize, name, mMainWindowMode == Dali::Application::TRANSPARENT );
436   Window& windowImpl = GetImplementation(newWindow);
437   windowImpl.SetAdaptor(*mAdaptor);
438
439   int indicatorVisibleMode = mEnvironmentOptions.GetIndicatorVisibleMode();
440   if( indicatorVisibleMode >= Dali::Window::INVISIBLE && indicatorVisibleMode <= Dali::Window::AUTO )
441   {
442     GetImplementation( newWindow ).SetIndicatorVisibleMode( static_cast< Dali::Window::IndicatorVisibleMode >( indicatorVisibleMode ) );
443   }
444
445   Internal::Adaptor::WindowRenderSurface* renderSurface = windowImpl.GetSurface();
446
447   Any nativeWindow = newWindow.GetNativeHandle();
448   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface(nativeWindow, *renderSurface);
449   mMainWindow = newWindow;
450   mWindowPositionSize = positionSize;
451 }
452
453 std::string Application::GetResourcePath()
454 {
455   return Internal::Adaptor::Framework::GetResourcePath();
456 }
457
458 std::string Application::GetDataPath()
459 {
460   return Internal::Adaptor::Framework::GetDataPath();
461 }
462
463 void Application::SetStyleSheet( const std::string& stylesheet )
464 {
465   mStylesheet = stylesheet;
466 }
467
468 ApplicationPtr Application::GetPreInitializedApplication()
469 {
470   return gPreInitializedApplication;
471 }
472
473 } // namespace Adaptor
474
475 } // namespace Internal
476
477 } // namespace Dali