/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// EXTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/core.h>
#include <dali/integration-api/context-notifier.h>
#include <dali/integration-api/events/touch-event-integ.h>
// INTERNAL INCLUDES
-#include <base/update-render-controller.h>
+#include <base/thread-controller.h>
#include <base/performance-logging/performance-interface-factory.h>
#include <base/lifecycle-observer.h>
#include <dali/devel-api/text-abstraction/font-client.h>
#include <callback-manager.h>
-#include <trigger-event.h>
#include <render-surface.h>
#include <tts-player-impl.h>
-#include <accessibility-manager-impl.h>
+#include <accessibility-adaptor-impl.h>
#include <events/gesture-manager.h>
#include <events/event-handler.h>
-#include <feedback/feedback-controller.h>
-#include <feedback/feedback-plugin-proxy.h>
#include <gl/gl-proxy-implementation.h>
#include <gl/gl-implementation.h>
#include <gl/egl-sync-implementation.h>
#include <window-impl.h>
#include <tizen-logging.h>
+#include <image-loading.h>
+
+#include <locale-utils.h>
using Dali::TextAbstraction::FontClient;
namespace
{
-__thread Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
+thread_local Adaptor* gThreadLocalAdaptor = NULL; // raw thread specific pointer to allow Adaptor::Get
} // unnamed namespace
Dali::Adaptor* Adaptor::New( Any nativeWindow, RenderSurface *surface, Dali::Configuration::ContextLoss configuration, EnvironmentOptions* environmentOptions )
ResourcePolicy::DataRetention dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
if( configuration == Dali::Configuration::APPLICATION_DOES_NOT_HANDLE_CONTEXT_LOSS )
{
- dataRetentionPolicy = ResourcePolicy::DALI_RETAINS_MESH_DATA;
+ dataRetentionPolicy = ResourcePolicy::DALI_DISCARDS_ALL_DATA;
}
// Note, Tizen does not use DALI_RETAINS_ALL_DATA, as it can reload images from
// files automatically.
mGLES = new GlImplementation();
}
- mEglFactory = new EglFactory();
+ mEglFactory = new EglFactory( mEnvironmentOptions->GetMultiSamplingLevel() );
EglSyncImplementation* eglSyncImpl = mEglFactory->GetSyncImplementation();
mCore = Integration::Core::New( *this, *mPlatformAbstraction, *mGLES, *eglSyncImpl, *mGestureManager, dataRetentionPolicy );
- mObjectProfiler = new ObjectProfiler();
+ const unsigned int timeInterval = mEnvironmentOptions->GetObjectProfilerInterval();
+ if( 0u < timeInterval )
+ {
+ mObjectProfiler = new ObjectProfiler( timeInterval );
+ }
- mNotificationTrigger = new TriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ) );
+ mNotificationTrigger = mTriggerEventFactory.CreateTriggerEvent( MakeCallback( this, &Adaptor::ProcessCoreEvents ), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
mVSyncMonitor = new VSyncMonitor;
- mUpdateRenderController = new UpdateRenderController( *this, *mEnvironmentOptions );
-
- mDaliFeedbackPlugin = new FeedbackPluginProxy( FeedbackPluginProxy::DEFAULT_OBJECT_NAME );
+ mThreadController = new ThreadController( *this, *mEnvironmentOptions );
// Should be called after Core creation
if( mEnvironmentOptions->GetPanGestureLoggingLevel() )
{
Integration::SetPanGestureSmoothingAmount(mEnvironmentOptions->GetPanGestureSmoothingAmount());
}
+
+ // Set max texture size
+ if( mEnvironmentOptions->GetMaxTextureSize() > 0 )
+ {
+ Dali::SetMaxTextureSize( mEnvironmentOptions->GetMaxTextureSize() );
+ }
+
+ SetupSystemInformation();
}
Adaptor::~Adaptor()
(*iter)->OnDestroy();
}
- delete mUpdateRenderController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
+ delete mThreadController; // this will shutdown render thread, which will call Core::ContextDestroyed before exit
delete mVSyncMonitor;
delete mEventHandler;
delete mObjectProfiler;
delete mCore;
delete mEglFactory;
- // Delete feedback controller before feedback plugin & style monitor dependencies
- delete mFeedbackController;
- delete mDaliFeedbackPlugin;
delete mGLES;
delete mGestureManager;
delete mPlatformAbstraction;
PositionSize size = mSurface->GetPositionSize();
mCore->SurfaceResized( size.width, size.height );
- // Start the update & render threads
- mUpdateRenderController->Start();
+ // Initialize the thread controller
+ mThreadController->Initialize();
mState = RUNNING;
ProcessCoreEvents(); // Ensure any startup messages are processed.
- if ( !mFeedbackController )
- {
- // Start sound & haptic feedback
- mFeedbackController = new FeedbackController( *mDaliFeedbackPlugin );
- }
-
for ( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
{
(*iter)->OnStart();
// Reset the event handler when adaptor paused
if( mEventHandler )
{
- mEventHandler->Reset();
+ mEventHandler->Pause();
}
- mUpdateRenderController->Pause();
+ mThreadController->Pause();
mCore->Suspend();
mState = PAUSED;
}
// Only resume the adaptor if we are in the suspended state.
if( PAUSED == mState )
{
- // We put ResumeFrameTime first, as this was originally called at the start of mCore->Resume()
- // If there were events pending, mCore->Resume() will call
- // RenderController->RequestUpdate()
- // UpdateRenderController->RequestUpdate()
- // UpdateRenderSynchronization->RequestUpdate()
- // and we should have reset the frame timers before allowing Core->Update() to be called.
- //@todo Should we call UpdateRenderController->Resume before mCore->Resume()?
-
- mUpdateRenderController->ResumeFrameTime();
- mCore->Resume();
- mUpdateRenderController->Resume();
-
mState = RUNNING;
// Reset the event handler when adaptor resumed
if( mEventHandler )
{
- mEventHandler->Reset();
+ mEventHandler->Resume();
}
// Inform observers that we have resumed.
(*iter)->OnResume();
}
- ProcessCoreEvents(); // Ensure any outstanding messages are processed
+ // Resume core so it processes any requests as well
+ mCore->Resume();
+
+ // Do at end to ensure our first update/render after resumption includes the processed messages as well
+ mThreadController->Resume();
}
}
(*iter)->OnStop();
}
- mUpdateRenderController->Stop();
+ mThreadController->Stop();
mCore->Suspend();
// Delete the TTS player
}
}
+void Adaptor::ContextLost()
+{
+ mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
+}
+
+void Adaptor::ContextRegained()
+{
+ // Inform core, so that texture resources can be reloaded
+ mCore->RecoverFromContextLoss();
+
+ mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
+}
+
void Adaptor::FeedTouchPoint( TouchPoint& point, int timeStamp )
{
mEventHandler->FeedTouchPoint( point, timeStamp );
mEventHandler->FeedKeyEvent( keyEvent );
}
-bool Adaptor::MoveResize( const PositionSize& positionSize )
-{
- PositionSize old = mSurface->GetPositionSize();
-
- // just resize the surface. The driver should automatically resize the egl Surface (untested)
- // EGL Spec says : EGL window surfaces need to be resized when their corresponding native window
- // is resized. Implementations typically use hooks into the OS and native window
- // system to perform this resizing on demand, transparently to the client.
- mSurface->MoveResize( positionSize );
-
- if(old.width != positionSize.width || old.height != positionSize.height)
- {
- SurfaceSizeChanged(positionSize);
- }
-
- return true;
-}
-
-void Adaptor::SurfaceResized( const PositionSize& positionSize )
+void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
{
- PositionSize old = mSurface->GetPositionSize();
+ PositionSize positionSize = surface.GetPositionSize();
- // Called by an application, when it has resized a window outside of Dali.
- // The EGL driver automatically detects X Window resize calls, and resizes
- // the EGL surface for us.
- mSurface->MoveResize( positionSize );
+ // let the core know the surface size has changed
+ mCore->SurfaceResized( positionSize.width, positionSize.height );
- if(old.width != positionSize.width || old.height != positionSize.height)
- {
- SurfaceSizeChanged(positionSize);
- }
-}
+ mResizedSignal.Emit( mAdaptor );
-void Adaptor::ReplaceSurface( Any nativeWindow, RenderSurface& surface )
-{
mNativeWindow = nativeWindow;
mSurface = &surface;
- SurfaceSizeChanged(mSurface->GetPositionSize());
-
- // flush the event queue to give update and render threads chance
+ // flush the event queue to give the update-render thread chance
// to start processing messages for new camera setup etc as soon as possible
ProcessCoreEvents();
- mCore->GetContextNotifier()->NotifyContextLost(); // Inform stage
-
// this method blocks until the render thread has completed the replace.
- mUpdateRenderController->ReplaceSurface(mSurface);
-
- // Inform core, so that texture resources can be reloaded
- mCore->RecoverFromContextLoss();
-
- mCore->GetContextNotifier()->NotifyContextRegained(); // Inform stage
+ mThreadController->ReplaceSurface(mSurface);
}
RenderSurface& Adaptor::GetSurface() const
// Only add an idle if the Adaptor is actually running
if( RUNNING == mState )
{
- idleAdded = mCallbackManager->AddCallback( callback, CallbackManager::IDLE_PRIORITY );
+ idleAdded = mCallbackManager->AddIdleCallback( callback );
}
return idleAdded;
}
-bool Adaptor::CallFromMainLoop( CallbackBase* callback )
+void Adaptor::RemoveIdle( CallbackBase* callback )
{
- bool callAdded(false);
-
- // Only allow the callback if the Adaptor is actually running
- if ( RUNNING == mState )
- {
- callAdded = mCallbackManager->AddCallback( callback, CallbackManager::DEFAULT_PRIORITY );
- }
-
- return callAdded;
+ mCallbackManager->RemoveIdleCallback( callback );
}
Dali::Adaptor& Adaptor::Get()
return gThreadLocalAdaptor != NULL;
}
+void Adaptor::SceneCreated()
+{
+ mCore->SceneCreated();
+}
+
Dali::Integration::Core& Adaptor::GetCore()
{
return *mCore;
void Adaptor::SetRenderRefreshRate( unsigned int numberOfVSyncsPerRender )
{
- mUpdateRenderController->SetRenderRefreshRate( numberOfVSyncsPerRender );
+ mThreadController->SetRenderRefreshRate( numberOfVSyncsPerRender );
}
void Adaptor::SetUseHardwareVSync( bool useHardware )
return *mGLES;
}
-TriggerEventInterface& Adaptor::GetTriggerEventInterface()
+TriggerEventInterface& Adaptor::GetProcessCoreEventsTrigger()
{
return *mNotificationTrigger;
}
return mNativeWindow;
}
+void Adaptor::SetUseRemoteSurface(bool useRemoteSurface)
+{
+ mUseRemoteSurface = useRemoteSurface;
+}
+
void Adaptor::AddObserver( LifeCycleObserver& observer )
{
ObserverContainer::iterator match ( find(mObservers.begin(), mObservers.end(), &observer) );
if ( PAUSED == mState ||
RUNNING == mState )
{
- mUpdateRenderController->RequestUpdate();
+ mThreadController->RequestUpdate();
}
}
RequestUpdate();
}
-void Adaptor::SurfaceSizeChanged(const PositionSize& positionSize)
+void Adaptor::SurfaceResizePrepare( Dali::Adaptor::SurfaceSize surfaceSize )
{
// let the core know the surface size has changed
- mCore->SurfaceResized(positionSize.width, positionSize.height);
+ mCore->SurfaceResized( surfaceSize.GetWidth(), surfaceSize.GetHeight() );
mResizedSignal.Emit( mAdaptor );
}
+void Adaptor::SurfaceResizeComplete( Dali::Adaptor::SurfaceSize surfaceSize )
+{
+ // flush the event queue to give the update-render thread chance
+ // to start processing messages for new camera setup etc as soon as possible
+ ProcessCoreEvents();
+
+ // this method blocks until the render thread has completed the resizing.
+ mThreadController->ResizeSurface();
+}
+
void Adaptor::NotifySceneCreated()
{
GetCore().SceneCreated();
+
+ // Start thread controller after the scene has been created
+ mThreadController->Start();
+
+ // process after surface is created (registering to remote surface provider if required)
+ SurfaceInitialized();
}
void Adaptor::NotifyLanguageChanged()
mLanguageChangedSignal.Emit( mAdaptor );
}
+void Adaptor::RenderOnce()
+{
+ RequestUpdateOnce();
+}
+
void Adaptor::RequestUpdateOnce()
{
if( PAUSED_WHILE_HIDDEN != mState )
{
- if( mUpdateRenderController )
+ if( mThreadController )
{
- mUpdateRenderController->RequestUpdateOnce();
+ mThreadController->RequestUpdateOnce();
}
}
}
+void Adaptor::IndicatorSizeChanged(int height)
+{
+ // let the core know the indicator height is changed
+ mCore->SetTopMargin(height);
+}
+
void Adaptor::ProcessCoreEventsFromIdle()
{
ProcessCoreEvents();
Adaptor::Adaptor(Any nativeWindow, Dali::Adaptor& adaptor, RenderSurface* surface, EnvironmentOptions* environmentOptions)
: mResizedSignal(),
mLanguageChangedSignal(),
- mAdaptor(adaptor),
- mState(READY),
- mCore(NULL),
- mUpdateRenderController(NULL),
- mVSyncMonitor(NULL),
+ mAdaptor( adaptor ),
+ mState( READY ),
+ mCore( NULL ),
+ mThreadController( NULL ),
+ mVSyncMonitor( NULL ),
mGLES( NULL ),
+ mGlSync( NULL ),
mEglFactory( NULL ),
mNativeWindow( nativeWindow ),
mSurface( surface ),
mEventHandler( NULL ),
mCallbackManager( NULL ),
mNotificationOnIdleInstalled( false ),
- mNotificationTrigger(NULL),
- mGestureManager(NULL),
- mDaliFeedbackPlugin(NULL),
- mFeedbackController(NULL),
+ mNotificationTrigger( NULL ),
+ mGestureManager( NULL ),
+ mDaliFeedbackPlugin(),
+ mFeedbackController( NULL ),
+ mTtsPlayers(),
mObservers(),
mDragAndDropDetector(),
- mDeferredRotationObserver(NULL),
+ mDeferredRotationObserver( NULL ),
mEnvironmentOptions( environmentOptions ? environmentOptions : new EnvironmentOptions /* Create the options if not provided */),
- mPerformanceInterface(NULL),
- mObjectProfiler(NULL),
- mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ )
+ mPerformanceInterface( NULL ),
+ mKernelTracer(),
+ mSystemTracer(),
+ mTriggerEventFactory(),
+ mObjectProfiler( NULL ),
+ mSocketFactory(),
+ mEnvironmentOptionsOwned( environmentOptions ? false : true /* If not provided then we own the object */ ),
+ mUseRemoteSurface( false )
{
DALI_ASSERT_ALWAYS( !IsAvailable() && "Cannot create more than one Adaptor per thread" );
gThreadLocalAdaptor = this;
return mCore->GetStereoBase();
}
+void Adaptor::SetRootLayoutDirection( std::string locale )
+{
+ Dali::Stage stage = Dali::Stage::GetCurrent();
+
+ stage.GetRootLayer().SetProperty( DevelActor::Property::LAYOUT_DIRECTION,
+ static_cast< DevelActor::LayoutDirection::Type >( Internal::Adaptor::Locale::GetDirection( std::string( locale ) ) ) );
+}
+
} // namespace Adaptor
} // namespace Internal