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   // Quit the application when the window is closed
164   GetImplementation( mMainWindow ).DeleteRequestSignal().Connect( mSlotDelegate, &Application::Quit );
165 }
166
167 void Application::CreateAdaptor()
168 {
169   DALI_ASSERT_ALWAYS( mMainWindow && "Window required to create adaptor" );
170
171   auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
172
173   mAdaptor = Dali::Internal::Adaptor::Adaptor::New( graphicsFactory, mMainWindow, mContextLossConfiguration, &mEnvironmentOptions );
174
175   mAdaptor->ResizedSignal().Connect( mSlotDelegate, &Application::OnResize );
176
177   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).SetUseRemoteSurface( mUseRemoteSurface );
178 }
179
180 void Application::CreateAdaptorBuilder()
181 {
182   mAdaptorBuilder = new AdaptorBuilder();
183 }
184
185 void Application::MainLoop(Dali::Configuration::ContextLoss configuration)
186 {
187   mContextLossConfiguration = configuration;
188
189   // Run the application
190   mFramework->Run();
191 }
192
193 void Application::Lower()
194 {
195   // Lower the application without quitting it.
196   mMainWindow.Lower();
197 }
198
199 void Application::Quit()
200 {
201   // Actually quit the application.
202   // Force a call to Quit even if adaptor is not running.
203   Internal::Adaptor::Adaptor::GetImplementation(*mAdaptor).AddIdle( MakeCallback( this, &Application::QuitFromMainLoop ), false, true );
204 }
205
206 void Application::QuitFromMainLoop()
207 {
208   mAdaptor->Stop();
209
210   mFramework->Quit();
211   // This will trigger OnTerminate(), below, after the main loop has completed.
212 }
213
214 void Application::OnInit()
215 {
216   mFramework->AddAbortCallback( MakeCallback( this, &Application::QuitFromMainLoop ) );
217
218   CreateAdaptorBuilder();
219
220   // If an application was pre-initialized, a window was made in advance
221   if( mLaunchpadState == Launchpad::NONE )
222   {
223     CreateWindow();
224   }
225
226   CreateAdaptor();
227
228   // Run the adaptor
229   mAdaptor->Start();
230
231   // Check if user requires no vsyncing and set Adaptor
232   if (mCommandLineOptions->noVSyncOnRender)
233   {
234     mAdaptor->SetUseHardwareVSync(false);
235   }
236
237   if( ! mStylesheet.empty() )
238   {
239     Dali::StyleMonitor::Get().SetTheme( mStylesheet );
240   }
241
242   // Wire up the LifecycleController
243   Dali::LifecycleController lifecycleController = Dali::LifecycleController::Get();
244
245   InitSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnInit );
246   TerminateSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnTerminate );
247   PauseSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnPause );
248   ResumeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResume );
249   ResetSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnReset );
250   ResizeSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnResize );
251   LanguageChangedSignal().Connect( &GetImplementation( lifecycleController ), &LifecycleController::OnLanguageChanged );
252
253   Dali::Application application(this);
254   mInitSignal.Emit( application );
255
256   mAdaptor->NotifySceneCreated();
257 }
258
259 void Application::OnTerminate()
260 {
261   // We've been told to quit by AppCore, ecore_x_destroy has been called, need to quit synchronously
262   // delete the window as ecore_x has been destroyed by AppCore
263
264   Dali::Application application(this);
265   mTerminateSignal.Emit( application );
266
267   if( mAdaptor )
268   {
269     // Ensure that the render-thread is not using the surface(window) after we delete it
270     mAdaptor->Stop();
271   }
272
273   mMainWindow.Reset(); // This only resets (clears) the default Window
274 }
275
276 void Application::OnPause()
277 {
278   // A DALi app should handle Pause/Resume events.
279   // DALi just delivers the framework Pause event to the application, but not actually pause DALi core.
280   // Pausing DALi core only occurs on the Window Hidden framework event
281   Dali::Application application(this);
282   mPauseSignal.Emit( application );
283 }
284
285 void Application::OnResume()
286 {
287   // Emit the signal first so the application can queue any messages before we do an update/render
288   // This ensures we do not just redraw the last frame before pausing if that's not required
289   Dali::Application application(this);
290   mResumeSignal.Emit( application );
291
292   // DALi just delivers the framework Resume event to the application.
293   // Resuming DALi core only occurs on the Window Show framework event
294
295   // Trigger processing of events queued up while paused
296   CoreEventInterface& coreEventInterface = Internal::Adaptor::Adaptor::GetImplementation( GetAdaptor() );
297   coreEventInterface.ProcessCoreEvents();
298 }
299
300 void Application::OnReset()
301 {
302   /*
303    * usually, reset callback was called when a caller request to launch this application via aul.
304    * because Application class already handled initialization in OnInit(), OnReset do nothing.
305    */
306   Dali::Application application(this);
307   mResetSignal.Emit( application );
308 }
309
310 void Application::OnAppControl(void *data)
311 {
312   Dali::Application application(this);
313   mAppControlSignal.Emit( application , data );
314 }
315
316 void Application::OnLanguageChanged()
317 {
318   mAdaptor->NotifyLanguageChanged();
319   Dali::Application application(this);
320   mLanguageChangedSignal.Emit( application );
321 }
322
323 void Application::OnRegionChanged()
324 {
325   Dali::Application application(this);
326   mRegionChangedSignal.Emit( application );
327 }
328
329 void Application::OnBatteryLow( Dali::DeviceStatus::Battery::Status status )
330 {
331   Dali::Application application(this);
332   mBatteryLowSignal.Emit( application );
333
334   mLowBatterySignal.Emit( status );
335 }
336
337 void Application::OnMemoryLow( Dali::DeviceStatus::Memory::Status status )
338 {
339   Dali::Application application(this);
340   mMemoryLowSignal.Emit( application );
341
342   mLowMemorySignal.Emit( status );
343 }
344 void Application::OnResize(Dali::Adaptor& adaptor)
345 {
346   Dali::Application application(this);
347   mResizeSignal.Emit( application );
348 }
349
350 bool Application::AddIdle( CallbackBase* callback, bool hasReturnValue )
351 {
352   return mAdaptor->AddIdle( callback, hasReturnValue );
353 }
354
355 std::string Application::GetRegion() const
356 {
357   return mFramework->GetRegion();
358 }
359
360 std::string Application::GetLanguage() const
361 {
362   return mFramework->GetLanguage();
363 }
364
365 Dali::Adaptor& Application::GetAdaptor()
366 {
367   return *mAdaptor;
368 }
369
370 Dali::Window Application::GetWindow()
371 {
372   return mMainWindow;
373 }
374
375 // Stereoscopy
376
377 void Application::SetViewMode( ViewMode viewMode )
378 {
379   mViewMode = viewMode;
380 }
381
382 ViewMode Application::GetViewMode() const
383 {
384   return mViewMode;
385 }
386
387 void Application::SetStereoBase( float stereoBase )
388 {
389   mStereoBase = stereoBase;
390 }
391
392 float Application::GetStereoBase() const
393 {
394   return mStereoBase;
395 }
396
397 void Application::ReplaceWindow( const PositionSize& positionSize, const std::string& name )
398 {
399   Dali::Window newWindow = Dali::Window::New( positionSize, name, mMainWindowMode == Dali::Application::TRANSPARENT );
400   Window& windowImpl = GetImplementation(newWindow);
401   windowImpl.SetAdaptor(*mAdaptor);
402
403   Internal::Adaptor::WindowRenderSurface* renderSurface = windowImpl.GetSurface();
404
405   Any nativeWindow = newWindow.GetNativeHandle();
406   Internal::Adaptor::Adaptor::GetImplementation( *mAdaptor ).ReplaceSurface(nativeWindow, *renderSurface);
407   mMainWindow = newWindow;
408   mWindowPositionSize = positionSize;
409 }
410
411 std::string Application::GetResourcePath()
412 {
413   return Internal::Adaptor::Framework::GetResourcePath();
414 }
415
416 std::string Application::GetDataPath()
417 {
418   return Internal::Adaptor::Framework::GetDataPath();
419 }
420
421 void Application::SetStyleSheet( const std::string& stylesheet )
422 {
423   mStylesheet = stylesheet;
424 }
425
426 ApplicationPtr Application::GetPreInitializedApplication()
427 {
428   return gPreInitializedApplication;
429 }
430
431 } // namespace Adaptor
432
433 } // namespace Internal
434
435 } // namespace Dali