2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/adaptor/common/adaptor-builder-impl.h>
20 #include <dali/internal/adaptor/common/adaptor-impl.h>
21 #include <dali/internal/addons/common/addon-manager-factory.h>
22 #include <dali/internal/addons/common/addon-manager-impl.h>
25 #include <dali/devel-api/actors/actor-devel.h>
26 #include <dali/devel-api/common/stage.h>
27 #include <dali/integration-api/addon-manager.h>
28 #include <dali/integration-api/context-notifier.h>
29 #include <dali/integration-api/core.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/integration-api/events/key-event-integ.h>
32 #include <dali/integration-api/events/touch-event-integ.h>
33 #include <dali/integration-api/events/wheel-event-integ.h>
34 #include <dali/integration-api/input-options.h>
35 #include <dali/integration-api/processor-interface.h>
36 #include <dali/integration-api/profiling.h>
37 #include <dali/integration-api/trace.h>
38 #include <dali/public-api/actors/layer.h>
39 #include <dali/public-api/events/wheel-event.h>
40 #include <dali/public-api/object/any.h>
41 #include <dali/public-api/object/object-registry.h>
46 #include <dali/internal/adaptor/common/lifecycle-observer.h>
47 #include <dali/internal/adaptor/common/thread-controller-interface.h>
48 #include <dali/internal/system/common/performance-interface-factory.h>
49 #include <dali/internal/system/common/thread-controller.h>
50 #include <dali/public-api/dali-adaptor-common.h>
52 #include <dali/internal/graphics/gles/egl-graphics-factory.h>
53 #include <dali/internal/graphics/gles/egl-graphics.h>
55 #include <dali/devel-api/text-abstraction/font-client.h>
57 #include <dali/internal/accessibility/common/tts-player-impl.h>
58 #include <dali/internal/graphics/common/egl-image-extensions.h>
59 #include <dali/internal/graphics/gles/egl-sync-implementation.h>
60 #include <dali/internal/graphics/gles/gl-implementation.h>
61 #include <dali/internal/graphics/gles/gl-proxy-implementation.h>
62 #include <dali/internal/system/common/callback-manager.h>
63 #include <dali/internal/system/common/object-profiler.h>
64 #include <dali/internal/system/common/system-factory.h>
65 #include <dali/internal/window-system/common/display-connection.h>
66 #include <dali/internal/window-system/common/display-utils.h> // For Utils::MakeUnique
67 #include <dali/internal/window-system/common/event-handler.h>
68 #include <dali/internal/window-system/common/window-impl.h>
69 #include <dali/internal/window-system/common/window-render-surface.h>
70 #include <dali/internal/window-system/common/window-system.h>
72 #include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
73 #include <dali/internal/system/common/logging.h>
75 #include <dali/internal/imaging/common/image-loader-plugin-proxy.h>
76 #include <dali/internal/imaging/common/image-loader.h>
77 #include <dali/internal/system/common/locale-utils.h>
79 #include <dali/devel-api/adaptor-framework/environment-variable.h>
80 #include <dali/internal/system/common/configuration-manager.h>
81 #include <dali/internal/system/common/environment-variables.h>
83 using Dali::TextAbstraction::FontClient;
85 extern std::string GetSystemCachePath();
95 thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
97 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
99 const char* ENABLE_IMAGE_LOADER_PLUGIN_ENV = "DALI_ENABLE_IMAGE_LOADER_PLUGIN";
100 } // unnamed namespace
102 Dali::Adaptor* Adaptor::New(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
104 Dali::Adaptor* adaptor = new Dali::Adaptor;
105 Adaptor* impl = new Adaptor(window, *adaptor, surface, environmentOptions, threadMode);
106 adaptor->mImpl = impl;
108 Dali::Internal::Adaptor::AdaptorBuilder* mAdaptorBuilder = new AdaptorBuilder(*(impl->mEnvironmentOptions));
109 auto graphicsFactory = mAdaptorBuilder->GetGraphicsFactory();
111 impl->Initialize(graphicsFactory);
112 delete mAdaptorBuilder; // Not needed anymore as the graphics interface has now been created
117 Dali::Adaptor* Adaptor::New(Dali::Integration::SceneHolder window, EnvironmentOptions* environmentOptions)
119 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(window);
120 Dali::Adaptor* adaptor = New(window, windowImpl.GetSurface(), environmentOptions, ThreadMode::NORMAL);
121 windowImpl.SetAdaptor(*adaptor);
125 Dali::Adaptor* Adaptor::New(GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
127 Dali::Adaptor* adaptor = new Dali::Adaptor; // Public adaptor
128 Adaptor* impl = new Adaptor(window, *adaptor, surface, environmentOptions, threadMode); // Impl adaptor
129 adaptor->mImpl = impl;
131 impl->Initialize(graphicsFactory);
136 Dali::Adaptor* Adaptor::New(GraphicsFactory& graphicsFactory, Dali::Integration::SceneHolder window, EnvironmentOptions* environmentOptions)
138 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(window);
139 Dali::Adaptor* adaptor = New(graphicsFactory, window, windowImpl.GetSurface(), environmentOptions, ThreadMode::NORMAL);
140 windowImpl.SetAdaptor(*adaptor);
144 void Adaptor::Initialize(GraphicsFactory& graphicsFactory)
146 // all threads here (event, update, and render) will send their logs to TIZEN Platform's LogMessage handler.
147 Dali::Integration::Log::LogFunction logFunction(Dali::TizenPlatform::LogMessage);
148 mEnvironmentOptions->SetLogFunction(logFunction);
149 mEnvironmentOptions->InstallLogFunction(); // install logging for main thread
151 mPlatformAbstraction = new TizenPlatform::TizenPlatformAbstraction;
154 GetDataStoragePath(path);
155 mPlatformAbstraction->SetDataStoragePath(path);
157 if(mEnvironmentOptions->PerformanceServerRequired())
159 mPerformanceInterface = PerformanceInterfaceFactory::CreateInterface(*this, *mEnvironmentOptions);
162 mEnvironmentOptions->CreateTraceManager(mPerformanceInterface);
163 mEnvironmentOptions->InstallTraceFunction(); // install tracing for main thread
165 mCallbackManager = Dali::Internal::Adaptor::GetSystemFactory()->CreateCallbackManager();
167 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
169 DALI_ASSERT_DEBUG(defaultWindow->GetSurface() && "Surface not initialized");
171 mGraphics = std::unique_ptr<GraphicsInterface>(&graphicsFactory.Create());
173 // Create the AddOnManager
174 mAddOnManager.reset(Dali::Internal::AddOnManagerFactory::CreateAddOnManager());
176 mCore = Integration::Core::New(*this,
177 *mPlatformAbstraction,
178 mGraphics->GetController(),
179 (0u != mEnvironmentOptions->GetRenderToFboInterval()) ? Integration::RenderToFrameBuffer::TRUE : Integration::RenderToFrameBuffer::FALSE,
180 mGraphics->GetDepthBufferRequired(),
181 mGraphics->GetStencilBufferRequired(),
182 mGraphics->GetPartialUpdateRequired());
184 // Create TextureUploadManager after mCore created
185 mTextureUploadManager = Dali::Devel::TextureUploadManager::Get();
187 defaultWindow->SetAdaptor(Get());
189 Dali::Integration::SceneHolder defaultSceneHolder(defaultWindow);
191 mWindowCreatedSignal.Emit(defaultSceneHolder);
193 const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
194 if(0u < timeInterval)
196 mObjectProfiler = new ObjectProfiler(mCore->GetObjectRegistry(), timeInterval);
199 const uint32_t poolTimeInterval = mEnvironmentOptions->GetMemoryPoolInterval();
200 if(0u < poolTimeInterval)
202 mMemoryPoolTimer = Dali::Timer::New(poolTimeInterval * 1000);
203 mMemoryPoolTimer.TickSignal().Connect(mMemoryPoolTimerSlotDelegate, &Adaptor::MemoryPoolTimeout);
204 mMemoryPoolTimer.Start();
207 mNotificationTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &Adaptor::ProcessCoreEvents), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
209 mDisplayConnection = Dali::DisplayConnection::New(*mGraphics, defaultWindow->GetSurface()->GetSurfaceType());
211 mThreadController = new ThreadController(*this, *mEnvironmentOptions, mThreadMode);
213 // Should be called after Core creation
214 if(mEnvironmentOptions->GetPanGestureLoggingLevel())
216 Integration::EnableProfiling(Dali::Integration::PROFILING_TYPE_PAN_GESTURE);
218 if(mEnvironmentOptions->GetPanGesturePredictionMode() >= 0)
220 Integration::SetPanGesturePredictionMode(mEnvironmentOptions->GetPanGesturePredictionMode());
222 if(mEnvironmentOptions->GetPanGesturePredictionAmount() >= 0)
224 Integration::SetPanGesturePredictionAmount(mEnvironmentOptions->GetPanGesturePredictionAmount());
226 if(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount() >= 0)
228 Integration::SetPanGestureMaximumPredictionAmount(mEnvironmentOptions->GetPanGestureMaximumPredictionAmount());
230 if(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount() >= 0)
232 Integration::SetPanGestureMinimumPredictionAmount(mEnvironmentOptions->GetPanGestureMinimumPredictionAmount());
234 if(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment() >= 0)
236 Integration::SetPanGesturePredictionAmountAdjustment(mEnvironmentOptions->GetPanGesturePredictionAmountAdjustment());
238 if(mEnvironmentOptions->GetPanGestureSmoothingMode() >= 0)
240 Integration::SetPanGestureSmoothingMode(mEnvironmentOptions->GetPanGestureSmoothingMode());
242 if(mEnvironmentOptions->GetPanGestureSmoothingAmount() >= 0.0f)
244 Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
246 if(mEnvironmentOptions->GetPanGestureUseActualTimes() >= 0)
248 Integration::SetPanGestureUseActualTimes(mEnvironmentOptions->GetPanGestureUseActualTimes() == 0 ? true : false);
250 if(mEnvironmentOptions->GetPanGestureInterpolationTimeRange() >= 0)
252 Integration::SetPanGestureInterpolationTimeRange(mEnvironmentOptions->GetPanGestureInterpolationTimeRange());
254 if(mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() >= 0)
256 Integration::SetPanGestureScalarOnlyPredictionEnabled(mEnvironmentOptions->GetPanGestureScalarOnlyPredictionEnabled() == 0 ? true : false);
258 if(mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() >= 0)
260 Integration::SetPanGestureTwoPointPredictionEnabled(mEnvironmentOptions->GetPanGestureTwoPointPredictionEnabled() == 0 ? true : false);
262 if(mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime() >= 0)
264 Integration::SetPanGestureTwoPointInterpolatePastTime(mEnvironmentOptions->GetPanGestureTwoPointInterpolatePastTime());
266 if(mEnvironmentOptions->GetPanGestureTwoPointVelocityBias() >= 0.0f)
268 Integration::SetPanGestureTwoPointVelocityBias(mEnvironmentOptions->GetPanGestureTwoPointVelocityBias());
270 if(mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias() >= 0.0f)
272 Integration::SetPanGestureTwoPointAccelerationBias(mEnvironmentOptions->GetPanGestureTwoPointAccelerationBias());
274 if(mEnvironmentOptions->GetPanGestureMultitapSmoothingRange() >= 0)
276 Integration::SetPanGestureMultitapSmoothingRange(mEnvironmentOptions->GetPanGestureMultitapSmoothingRange());
278 if(mEnvironmentOptions->GetMinimumPanDistance() >= 0)
280 Integration::SetPanGestureMinimumDistance(mEnvironmentOptions->GetMinimumPanDistance());
282 if(mEnvironmentOptions->GetMinimumPanEvents() >= 0)
284 Integration::SetPanGestureMinimumPanEvents(mEnvironmentOptions->GetMinimumPanEvents());
286 if(mEnvironmentOptions->GetMinimumPinchDistance() >= 0)
288 Integration::SetPinchGestureMinimumDistance(mEnvironmentOptions->GetMinimumPinchDistance());
290 if(mEnvironmentOptions->GetMinimumPinchTouchEvents() >= 0)
292 Integration::SetPinchGestureMinimumTouchEvents(mEnvironmentOptions->GetMinimumPinchTouchEvents());
294 if(mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart() >= 0)
296 Integration::SetPinchGestureMinimumTouchEventsAfterStart(mEnvironmentOptions->GetMinimumPinchTouchEventsAfterStart());
298 if(mEnvironmentOptions->GetMinimumRotationTouchEvents() >= 0)
300 Integration::SetRotationGestureMinimumTouchEvents(mEnvironmentOptions->GetMinimumRotationTouchEvents());
302 if(mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart() >= 0)
304 Integration::SetRotationGestureMinimumTouchEventsAfterStart(mEnvironmentOptions->GetMinimumRotationTouchEventsAfterStart());
306 if(mEnvironmentOptions->GetLongPressMinimumHoldingTime() >= 0)
308 Integration::SetLongPressMinimumHoldingTime(mEnvironmentOptions->GetLongPressMinimumHoldingTime());
310 if(mEnvironmentOptions->GetTapMaximumAllowedTime() > 0)
312 Integration::SetTapMaximumAllowedTime(mEnvironmentOptions->GetTapMaximumAllowedTime());
315 std::string systemCachePath = GetSystemCachePath();
316 if(!systemCachePath.empty())
318 const int dir_err = mkdir(systemCachePath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
319 if(0 != dir_err && errno != EEXIST)
321 DALI_LOG_ERROR("Error creating system cache directory: %s!\n", systemCachePath.c_str());
325 mConfigurationManager = Utils::MakeUnique<ConfigurationManager>(systemCachePath, mGraphics.get(), mThreadController);
328 void Adaptor::AccessibilityObserver::OnAccessibleKeyEvent(const Dali::KeyEvent& event)
330 Accessibility::KeyEventType type;
331 if(event.GetState() == Dali::KeyEvent::DOWN)
333 type = Accessibility::KeyEventType::KEY_PRESSED;
335 else if(event.GetState() == Dali::KeyEvent::UP)
337 type = Accessibility::KeyEventType::KEY_RELEASED;
343 Dali::Accessibility::Bridge::GetCurrentBridge()->Emit(type, event.GetKeyCode(), event.GetKeyName(), event.GetTime(), !event.GetKeyString().empty());
348 Accessibility::Bridge::GetCurrentBridge()->Terminate();
350 // Ensure stop status
353 // set to NULL first as we do not want any access to Adaptor as it is being destroyed.
354 gThreadLocalAdaptor = NULL;
356 for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
358 (*iter)->OnDestroy();
361 // Clear out all the handles to Windows
364 delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
365 delete mObjectProfiler;
369 delete mDisplayConnection;
370 delete mPlatformAbstraction;
372 mCallbackManager.reset();
374 delete mPerformanceInterface;
376 mGraphics->Destroy();
378 // uninstall it on this thread (main actor thread)
379 Dali::Integration::Log::UninstallLogFunction();
381 // Delete environment options if we own it
382 if(mEnvironmentOptionsOwned)
384 delete mEnvironmentOptions;
388 void Adaptor::Start()
390 // It doesn't support restart after stop at this moment to support restarting, need more testing
398 SetupSystemInformation();
400 // Start the callback manager
401 mCallbackManager->Start();
403 // Initialize accessibility bridge after callback manager is started to use Idler callback
404 auto appName = GetApplicationPackageName();
405 auto bridge = Accessibility::Bridge::GetCurrentBridge();
406 bridge->SetApplicationName(appName);
407 bridge->Initialize();
408 Dali::Stage::GetCurrent().KeyEventSignal().Connect(&mAccessibilityObserver, &AccessibilityObserver::OnAccessibleKeyEvent);
410 Dali::Internal::Adaptor::SceneHolder* defaultWindow = mWindows.front();
412 unsigned int dpiHor, dpiVer;
415 defaultWindow->GetSurface()->GetDpi(dpiHor, dpiVer);
416 Dali::Internal::Adaptor::WindowSystem::SetDpi(dpiHor, dpiVer);
418 // Initialize the thread controller
419 mThreadController->Initialize();
421 // Set max texture size
422 if(mEnvironmentOptions->GetMaxTextureSize() > 0)
424 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(mEnvironmentOptions->GetMaxTextureSize());
428 unsigned int maxTextureSize = mConfigurationManager->GetMaxTextureSize();
429 Dali::TizenPlatform::ImageLoader::SetMaxTextureSize(maxTextureSize);
432 // cache advanced blending and shader language version
433 mGraphics->CacheConfigurations(*mConfigurationManager.get());
435 ProcessCoreEvents(); // Ensure any startup messages are processed.
437 // Initialize the image loader plugin
438 auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(ENABLE_IMAGE_LOADER_PLUGIN_ENV);
439 bool enablePlugin = enablePluginString ? std::atoi(enablePluginString) : false;
442 Internal::Adaptor::ImageLoaderPluginProxy::Initialize();
445 for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
452 mAddOnManager->Start();
456 // Dali::Internal::Adaptor::Adaptor::Pause
457 void Adaptor::Pause()
459 // Only pause the adaptor if we're actually running.
460 if(RUNNING == mState)
462 // Inform observers that we are about to be paused.
463 for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
471 mAddOnManager->Pause();
474 // Pause all windows event handlers when adaptor paused
475 for(auto window : mWindows)
480 mThreadController->Pause();
483 // Ensure any messages queued during pause callbacks are processed by doing another update.
486 DALI_LOG_RELEASE_INFO("Adaptor::Pause: Paused\n");
490 DALI_LOG_RELEASE_INFO("Adaptor::Pause: Not paused [%d]\n", mState);
494 // Dali::Internal::Adaptor::Adaptor::Resume
495 void Adaptor::Resume()
497 // Only resume the adaptor if we are in the suspended state.
502 // Reset the event handlers when adaptor resumed
503 for(auto window : mWindows)
508 // Resume AddOnManager
511 mAddOnManager->Resume();
514 // Inform observers that we have resumed.
515 for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
520 // Trigger processing of events queued up while paused
521 mCore->ProcessEvents();
523 // Do at end to ensure our first update/render after resumption includes the processed messages as well
524 mThreadController->Resume();
526 DALI_LOG_RELEASE_INFO("Adaptor::Resume: Resumed\n");
530 DALI_LOG_RELEASE_INFO("Adaptor::Resume: Not resumed [%d]\n", mState);
536 if(RUNNING == mState ||
538 PAUSED_WHILE_HIDDEN == mState)
540 for(ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter)
547 mAddOnManager->Stop();
550 mThreadController->Stop();
552 // Delete the TTS player
553 for(int i = 0; i < Dali::TtsPlayer::MODE_NUM; i++)
557 mTtsPlayers[i].Reset();
561 // Destroy the image loader plugin
562 auto enablePluginString = Dali::EnvironmentVariable::GetEnvironmentVariable(ENABLE_IMAGE_LOADER_PLUGIN_ENV);
563 bool enablePlugin = enablePluginString ? std::atoi(enablePluginString) : false;
566 Internal::Adaptor::ImageLoaderPluginProxy::Destroy();
569 delete mNotificationTrigger;
570 mNotificationTrigger = NULL;
572 mCallbackManager->Stop();
576 RemoveSystemInformation();
578 DALI_LOG_RELEASE_INFO("Adaptor::Stop\n");
582 void Adaptor::ContextLost()
584 mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
587 void Adaptor::ContextRegained()
589 // Inform core, so that texture resources can be reloaded
590 mCore->RecoverFromContextLoss();
592 mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
595 void Adaptor::FeedTouchPoint(TouchPoint& point, int timeStamp)
597 Integration::Point convertedPoint(point);
598 mWindows.front()->FeedTouchPoint(convertedPoint, timeStamp);
601 void Adaptor::FeedWheelEvent(Dali::WheelEvent& wheelEvent)
603 Integration::WheelEvent event(static_cast<Integration::WheelEvent::Type>(wheelEvent.GetType()), wheelEvent.GetDirection(), wheelEvent.GetModifiers(), wheelEvent.GetPoint(), wheelEvent.GetDelta(), wheelEvent.GetTime());
604 mWindows.front()->FeedWheelEvent(event);
607 void Adaptor::FeedKeyEvent(Dali::KeyEvent& keyEvent)
609 Integration::KeyEvent convertedEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
610 mWindows.front()->FeedKeyEvent(convertedEvent);
613 void Adaptor::ReplaceSurface(Dali::Integration::SceneHolder window, Dali::RenderSurfaceInterface& newSurface)
615 Internal::Adaptor::SceneHolder* windowImpl = &Dali::GetImplementation(window);
616 for(auto windowPtr : mWindows)
618 if(windowPtr == windowImpl) // the window is not deleted
620 mResizedSignal.Emit(mAdaptor);
622 windowImpl->SetSurface(&newSurface);
624 // Flush the event queue to give the update-render thread chance
625 // to start processing messages for new camera setup etc as soon as possible
628 // This method blocks until the render thread has completed the replace.
629 mThreadController->ReplaceSurface(&newSurface);
635 void Adaptor::DeleteSurface(Dali::RenderSurfaceInterface& surface)
637 // Flush the event queue to give the update-render thread chance
638 // to start processing messages for new camera setup etc as soon as possible
641 // This method blocks until the render thread has finished rendering the current surface.
642 mThreadController->DeleteSurface(&surface);
645 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
647 return *mWindows.front()->GetSurface();
650 void Adaptor::ReleaseSurfaceLock()
652 mWindows.front()->GetSurface()->ReleaseLock();
655 Dali::TtsPlayer Adaptor::GetTtsPlayer(Dali::TtsPlayer::Mode mode)
657 if(!mTtsPlayers[mode])
659 // Create the TTS player when it needed, because it can reduce launching time.
660 mTtsPlayers[mode] = TtsPlayer::New(mode);
663 return mTtsPlayers[mode];
666 bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
668 bool idleAdded(false);
670 // We want to run the processes even when paused
671 if(STOPPED != mState)
673 idleAdded = mCallbackManager->AddIdleCallback(callback, hasReturnValue);
685 void Adaptor::RemoveIdle(CallbackBase* callback)
687 mCallbackManager->RemoveIdleCallback(callback);
690 void Adaptor::ProcessIdle()
692 bool idleProcessed = mCallbackManager->ProcessIdle();
693 mNotificationOnIdleInstalled = mNotificationOnIdleInstalled && !idleProcessed;
696 void Adaptor::SetPreRenderCallback(CallbackBase* callback)
698 mThreadController->SetPreRenderCallback(callback);
701 bool Adaptor::AddWindow(Dali::Integration::SceneHolder childWindow)
703 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(childWindow);
704 windowImpl.SetAdaptor(Get());
706 // ChildWindow is set to the layout direction of the default window.
707 windowImpl.GetRootLayer().SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
709 // Add the new Window to the container - the order is not important
711 Dali::Mutex::ScopedLock lock(mMutex);
712 mWindows.push_back(&windowImpl);
715 Dali::RenderSurfaceInterface* surface = windowImpl.GetSurface();
717 mThreadController->AddSurface(surface);
719 mWindowCreatedSignal.Emit(childWindow);
724 bool Adaptor::RemoveWindow(Dali::Integration::SceneHolder* childWindow)
726 Internal::Adaptor::SceneHolder& windowImpl = Dali::GetImplementation(*childWindow);
727 for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
729 if(*iter == &windowImpl)
731 Dali::Mutex::ScopedLock lock(mMutex);
732 mWindows.erase(iter);
740 bool Adaptor::RemoveWindow(std::string childWindowName)
742 for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
744 if((*iter)->GetName() == childWindowName)
746 Dali::Mutex::ScopedLock lock(mMutex);
747 mWindows.erase(iter);
755 bool Adaptor::RemoveWindow(Internal::Adaptor::SceneHolder* childWindow)
757 for(WindowContainer::iterator iter = mWindows.begin(); iter != mWindows.end(); ++iter)
759 if((*iter)->GetId() == childWindow->GetId())
761 Dali::Mutex::ScopedLock lock(mMutex);
762 mWindows.erase(iter);
770 Dali::Adaptor& Adaptor::Get()
772 DALI_ASSERT_ALWAYS(IsAvailable() && "Adaptor not instantiated");
773 return gThreadLocalAdaptor->mAdaptor;
776 bool Adaptor::IsAvailable()
778 return gThreadLocalAdaptor != NULL;
781 void Adaptor::SceneCreated()
783 mCore->SceneCreated();
786 Dali::Integration::Core& Adaptor::GetCore()
791 void Adaptor::SetRenderRefreshRate(unsigned int numberOfVSyncsPerRender)
793 mThreadController->SetRenderRefreshRate(numberOfVSyncsPerRender);
796 Dali::DisplayConnection& Adaptor::GetDisplayConnectionInterface()
798 DALI_ASSERT_DEBUG(mDisplayConnection && "Display connection not created");
799 return *mDisplayConnection;
802 GraphicsInterface& Adaptor::GetGraphicsInterface()
804 DALI_ASSERT_DEBUG(mGraphics && "Graphics interface not created");
805 return *(mGraphics.get());
808 Dali::Integration::PlatformAbstraction& Adaptor::GetPlatformAbstractionInterface()
810 return *mPlatformAbstraction;
813 TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
815 return *mNotificationTrigger;
818 SocketFactoryInterface& Adaptor::GetSocketFactoryInterface()
820 return mSocketFactory;
823 Dali::RenderSurfaceInterface* Adaptor::GetRenderSurfaceInterface()
825 if(!mWindows.empty())
827 return mWindows.front()->GetSurface();
833 TraceInterface& Adaptor::GetKernelTraceInterface()
835 return mKernelTracer;
838 TraceInterface& Adaptor::GetSystemTraceInterface()
840 return mSystemTracer;
843 PerformanceInterface* Adaptor::GetPerformanceInterface()
845 return mPerformanceInterface;
848 Integration::PlatformAbstraction& Adaptor::GetPlatformAbstraction() const
850 DALI_ASSERT_DEBUG(mPlatformAbstraction && "PlatformAbstraction not created");
851 return *mPlatformAbstraction;
854 void Adaptor::GetWindowContainerInterface(WindowContainer& windows)
856 Dali::Mutex::ScopedLock lock(mMutex);
860 Devel::TextureUploadManager& Adaptor::GetTextureUploadManager()
862 return mTextureUploadManager;
865 void Adaptor::DestroyTtsPlayer(Dali::TtsPlayer::Mode mode)
867 if(mTtsPlayers[mode])
869 mTtsPlayers[mode].Reset();
873 Any Adaptor::GetNativeWindowHandle()
875 return mWindows.front()->GetNativeHandle();
878 Any Adaptor::GetNativeWindowHandle(Dali::Actor actor)
880 Any nativeWindowHandle;
882 Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
884 for(auto sceneHolder : mWindows)
886 if(scene == sceneHolder->GetScene())
888 nativeWindowHandle = sceneHolder->GetNativeHandle();
893 return nativeWindowHandle;
896 Any Adaptor::GetGraphicsDisplay()
902 GraphicsInterface* graphics = mGraphics.get(); // This interface is temporary until Core has been updated to match
903 auto eglGraphics = static_cast<EglGraphics*>(graphics);
905 EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
906 display = eglImpl.GetDisplay();
912 void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
914 mUseRemoteSurface = useRemoteSurface;
917 void Adaptor::AddObserver(LifeCycleObserver& observer)
919 ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
921 if(match == mObservers.end())
923 mObservers.push_back(&observer);
927 void Adaptor::RemoveObserver(LifeCycleObserver& observer)
929 ObserverContainer::iterator match(find(mObservers.begin(), mObservers.end(), &observer));
931 if(match != mObservers.end())
933 mObservers.erase(match);
937 void Adaptor::QueueCoreEvent(const Dali::Integration::Event& event)
941 mCore->QueueEvent(event);
945 void Adaptor::FlushUpdateMessages()
949 DALI_TRACE_SCOPE(gTraceFilter, "DALI_FLUSH_UPDATE_MESSAGES");
951 mCore->ForceRelayout();
955 void Adaptor::ProcessCoreEvents()
959 DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_CORE_EVENTS");
961 if(mPerformanceInterface)
963 mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_START);
966 mCore->ProcessEvents();
968 if(mPerformanceInterface)
970 mPerformanceInterface->AddMarker(PerformanceInterface::PROCESS_EVENTS_END);
975 void Adaptor::RequestUpdate()
981 mThreadController->RequestUpdate();
985 case PAUSED_WHILE_HIDDEN:
987 // Update (and resource upload) without rendering
988 mThreadController->RequestUpdateOnce(UpdateMode::SKIP_RENDER);
999 void Adaptor::RequestProcessEventsOnIdle()
1001 // We want to run the processes even when paused
1002 if(STOPPED != mState)
1004 if(!mNotificationOnIdleInstalled)
1006 // If we haven't installed the idle notification, install it idle enterer.
1007 mNotificationOnIdleInstalled = AddIdleEnterer(MakeCallback(this, &Adaptor::ProcessCoreEventsFromIdle));
1011 // Request comes during ProcessCoreEventsFromIdle running.
1012 // Mark as we need to call ProcessEvents in next idle events.
1013 mRequiredIdleRepeat = true;
1018 void Adaptor::OnWindowShown()
1020 if(PAUSED_WHILE_HIDDEN == mState)
1022 // Adaptor can now be resumed
1027 // Force a render task
1028 RequestUpdateOnce();
1030 else if(RUNNING == mState)
1032 // Force a render task
1033 RequestUpdateOnce();
1035 DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Update requested.\n");
1037 else if(PAUSED_WHILE_INITIALIZING == mState)
1039 // Change the state to READY again. It will be changed to RUNNING after the adaptor is started.
1044 DALI_LOG_RELEASE_INFO("Adaptor::OnWindowShown: Adaptor is not paused state.[%d]\n", mState);
1048 void Adaptor::OnWindowHidden()
1050 if(RUNNING == mState || READY == mState)
1052 bool allWindowsHidden = true;
1054 for(auto window : mWindows)
1056 if(window->IsVisible())
1058 allWindowsHidden = false;
1063 // Only pause the adaptor when all the windows are hidden
1064 if(allWindowsHidden)
1066 if(mState == RUNNING)
1070 // Adaptor cannot be resumed until any window is shown
1071 mState = PAUSED_WHILE_HIDDEN;
1073 else // mState is READY
1075 // Pause the adaptor after the state gets RUNNING
1076 mState = PAUSED_WHILE_INITIALIZING;
1081 DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Some windows are shown. Don't pause adaptor.\n");
1086 DALI_LOG_RELEASE_INFO("Adaptor::OnWindowHidden: Adaptor is not running state.[%d]\n", mState);
1090 // Dali::Internal::Adaptor::Adaptor::OnDamaged
1091 void Adaptor::OnDamaged(const DamageArea& area)
1093 // This is needed for the case where Dali window is partially obscured
1097 void Adaptor::SurfaceResizePrepare(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1099 mResizedSignal.Emit(mAdaptor);
1102 void Adaptor::SurfaceResizeComplete(Dali::RenderSurfaceInterface* surface, SurfaceSize surfaceSize)
1104 // Nofify surface resizing before flushing event queue
1105 mThreadController->ResizeSurface();
1107 // Flush the event queue to give the update-render thread chance
1108 // to start processing messages for new camera setup etc as soon as possible
1109 ProcessCoreEvents();
1112 void Adaptor::IncreaseSurfaceResizeCounter()
1114 // Nofify surface resizing before flushing event queue
1115 if(mThreadController)
1117 mThreadController->ResizeSurface();
1121 void Adaptor::NotifySceneCreated()
1123 GetCore().SceneCreated();
1125 // Flush the event queue to give the update-render thread chance
1126 // to start processing messages for new camera setup etc as soon as possible
1127 ProcessCoreEvents();
1129 // Start thread controller after the scene has been created
1130 mThreadController->Start();
1132 // Process after surface is created (registering to remote surface provider if required)
1133 SurfaceInitialized();
1135 if(mState != PAUSED_WHILE_INITIALIZING)
1139 DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is running\n");
1147 mState = PAUSED_WHILE_HIDDEN;
1149 DALI_LOG_RELEASE_INFO("Adaptor::NotifySceneCreated: Adaptor is paused\n");
1153 void Adaptor::NotifyLanguageChanged()
1155 mLanguageChangedSignal.Emit(mAdaptor);
1158 void Adaptor::RenderOnce()
1160 if(mThreadController)
1162 UpdateMode updateMode;
1163 if(mThreadMode == ThreadMode::NORMAL)
1165 updateMode = UpdateMode::NORMAL;
1169 updateMode = UpdateMode::FORCE_RENDER;
1171 ProcessCoreEvents();
1175 for(auto&& iter : mWindows)
1177 iter->GetSurface()->SetFullSwapNextFrame();
1180 mThreadController->RequestUpdateOnce(updateMode);
1184 const LogFactoryInterface& Adaptor::GetLogFactory()
1186 return *mEnvironmentOptions;
1189 const TraceFactoryInterface& Adaptor::GetTraceFactory()
1191 return *mEnvironmentOptions;
1194 void Adaptor::RegisterProcessor(Integration::Processor& processor, bool postProcessor)
1196 GetCore().RegisterProcessor(processor, postProcessor);
1199 void Adaptor::UnregisterProcessor(Integration::Processor& processor, bool postProcessor)
1201 GetCore().UnregisterProcessor(processor, postProcessor);
1204 bool Adaptor::IsMultipleWindowSupported() const
1206 return mConfigurationManager->IsMultipleWindowSupported();
1209 int32_t Adaptor::GetRenderThreadId() const
1211 if(mThreadController)
1213 return mThreadController->GetThreadId();
1218 void Adaptor::RequestUpdateOnce()
1220 if(mThreadController)
1222 mThreadController->RequestUpdateOnce(UpdateMode::NORMAL);
1226 bool Adaptor::ProcessCoreEventsFromIdle()
1228 // Reset repeat idler flag.
1229 mRequiredIdleRepeat = false;
1230 ProcessCoreEvents();
1232 // If someone request ProcessCoreEvents during above ProcessCoreEvents call, we might need to run idle one more times.
1233 // Else, the idle handle automatically un-installs itself
1234 mNotificationOnIdleInstalled = mRequiredIdleRepeat;
1236 if(mRequiredIdleRepeat)
1238 DALI_LOG_DEBUG_INFO("Required ProcessCoreEvents one more times\n");
1241 return mRequiredIdleRepeat;
1244 Dali::Internal::Adaptor::SceneHolder* Adaptor::GetWindow(Dali::Actor& actor)
1246 Dali::Integration::Scene scene = Dali::Integration::Scene::Get(actor);
1248 for(auto window : mWindows)
1250 if(scene == window->GetScene())
1259 Dali::WindowContainer Adaptor::GetWindows() const
1261 Dali::WindowContainer windows;
1263 for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1265 // Downcast to Dali::Window
1266 Dali::Window window(dynamic_cast<Dali::Internal::Adaptor::Window*>(*iter));
1269 windows.push_back(window);
1276 Dali::SceneHolderList Adaptor::GetSceneHolders() const
1278 Dali::SceneHolderList sceneHolderList;
1280 for(auto iter = mWindows.begin(); iter != mWindows.end(); ++iter)
1282 sceneHolderList.push_back(Dali::Integration::SceneHolder(*iter));
1285 return sceneHolderList;
1288 Dali::ObjectRegistry Adaptor::GetObjectRegistry() const
1290 Dali::ObjectRegistry registry;
1293 registry = mCore->GetObjectRegistry();
1298 Adaptor::Adaptor(Dali::Integration::SceneHolder window, Dali::Adaptor& adaptor, Dali::RenderSurfaceInterface* surface, EnvironmentOptions* environmentOptions, ThreadMode threadMode)
1300 mLanguageChangedSignal(),
1301 mWindowCreatedSignal(),
1305 mThreadController(nullptr),
1307 mDisplayConnection(nullptr),
1309 mConfigurationManager(nullptr),
1310 mPlatformAbstraction(nullptr),
1311 mCallbackManager(nullptr),
1312 mNotificationOnIdleInstalled(false),
1313 mRequiredIdleRepeat(false),
1314 mNotificationTrigger(nullptr),
1315 mDaliFeedbackPlugin(),
1316 mFeedbackController(nullptr),
1319 mEnvironmentOptions(environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
1320 mPerformanceInterface(nullptr),
1323 mTextureUploadManager(),
1324 mObjectProfiler(nullptr),
1325 mMemoryPoolTimerSlotDelegate(this),
1328 mThreadMode(threadMode),
1329 mEnvironmentOptionsOwned(environmentOptions ? false : true /* If not provided then we own the object */),
1330 mUseRemoteSurface(false),
1331 mRootLayoutDirection(Dali::LayoutDirection::LEFT_TO_RIGHT)
1333 DALI_ASSERT_ALWAYS(!IsAvailable() && "Cannot create more than one Adaptor per thread");
1334 mWindows.insert(mWindows.begin(), &Dali::GetImplementation(window));
1336 gThreadLocalAdaptor = this;
1339 void Adaptor::SetRootLayoutDirection(std::string locale)
1341 mRootLayoutDirection = static_cast<LayoutDirection::Type>(Internal::Adaptor::Locale::GetDirection(std::string(locale)));
1342 for(auto& window : mWindows)
1344 Dali::Actor root = window->GetRootLayer();
1345 root.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, mRootLayoutDirection);
1349 bool Adaptor::AddIdleEnterer(CallbackBase* callback)
1351 bool idleAdded(false);
1353 // We want to run the processes even when paused
1354 if(STOPPED != mState)
1356 idleAdded = mCallbackManager->AddIdleEntererCallback(callback);
1368 void Adaptor::RemoveIdleEnterer(CallbackBase* callback)
1370 mCallbackManager->RemoveIdleEntererCallback(callback);
1373 bool Adaptor::MemoryPoolTimeout()
1375 mCore->LogMemoryPools();
1376 return true; // Keep logging forever
1379 } // namespace Adaptor
1381 } // namespace Internal