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