/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 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.
#include <dali/internal/common/core-impl.h>
// INTERNAL INCLUDES
-#include <dali/integration-api/system-overlay.h>
#include <dali/integration-api/core.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/events/event.h>
#include <dali/integration-api/gl-sync-abstraction.h>
#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/processor-interface.h>
#include <dali/integration-api/render-controller.h>
+#include <dali/integration-api/render-surface.h>
#include <dali/internal/event/actors/actor-impl.h>
#include <dali/internal/event/animation/animation-playlist.h>
#include <dali/internal/event/common/property-notification-manager.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/event-thread-services.h>
#include <dali/internal/event/common/type-registry-impl.h>
#include <dali/internal/event/effects/shader-factory.h>
#include <dali/internal/event/events/event-processor.h>
#include <dali/internal/event/events/gesture-event-processor.h>
-#include <dali/internal/event/images/image-factory.h>
#include <dali/internal/event/render-tasks/render-task-list-impl.h>
#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
#include <dali/internal/update/common/discard-queue.h>
-#include <dali/internal/update/common/texture-cache-dispatcher.h>
#include <dali/internal/update/manager/update-manager.h>
-#include <dali/internal/update/manager/geometry-batcher.h>
#include <dali/internal/update/manager/render-task-processor.h>
-#include <dali/internal/update/resources/resource-manager.h>
#include <dali/internal/render/common/performance-monitor.h>
#include <dali/internal/render/common/render-manager.h>
-#include <dali/internal/render/gl-resources/texture-cache.h>
#include <dali/internal/render/gl-resources/context.h>
using Dali::Internal::SceneGraph::UpdateManager;
using Dali::Internal::SceneGraph::RenderManager;
using Dali::Internal::SceneGraph::DiscardQueue;
using Dali::Internal::SceneGraph::RenderQueue;
-using Dali::Internal::SceneGraph::TextureCache;
-using Dali::Internal::SceneGraph::TextureCacheDispatcher;
namespace
{
// The Update for frame N+1 may be processed whilst frame N is being rendered.
-const unsigned int MAXIMUM_UPDATE_COUNT = 2u;
+const uint32_t MAXIMUM_UPDATE_COUNT = 2u;
#if defined(DEBUG_ENABLED)
Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE");
using Integration::RenderController;
using Integration::PlatformAbstraction;
using Integration::GlSyncAbstraction;
-using Integration::GestureManager;
using Integration::GlAbstraction;
using Integration::Event;
using Integration::UpdateStatus;
using Integration::RenderStatus;
-Core::Core( RenderController& renderController, PlatformAbstraction& platform,
- GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction,
- GestureManager& gestureManager, ResourcePolicy::DataRetention dataRetentionPolicy)
+Core::Core( RenderController& renderController,
+ PlatformAbstraction& platform,
+ GlAbstraction& glAbstraction,
+ GlSyncAbstraction& glSyncAbstraction,
+ ResourcePolicy::DataRetention dataRetentionPolicy,
+ Integration::RenderToFrameBuffer renderToFboEnabled,
+ Integration::DepthBufferAvailable depthBufferAvailable,
+ Integration::StencilBufferAvailable stencilBufferAvailable )
: mRenderController( renderController ),
mPlatform(platform),
- mGestureEventProcessor(NULL),
- mEventProcessor(NULL),
- mUpdateManager(NULL),
- mRenderManager(NULL),
- mDiscardQueue(NULL),
- mTextureUploadedQueue(),
- mNotificationManager(NULL),
- mImageFactory(NULL),
- mShaderFactory(NULL),
- mGeometryBatcher( NULL ),
- mIsActive(true),
- mProcessingEvent(false)
+ mProcessingEvent(false),
+ mForceNextUpdate( false )
{
// Create the thread local storage
CreateThreadLocalStorage();
mPropertyNotificationManager = PropertyNotificationManager::New();
- mTextureUploadedQueue = new LockedResourceQueue;
-
- mGeometryBatcher = new SceneGraph::GeometryBatcher();
-
mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor();
- mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, *mGeometryBatcher, *mTextureUploadedQueue );
+ mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, depthBufferAvailable, stencilBufferAvailable );
RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
- TextureCache& textureCache = mRenderManager->GetTextureCache();
-
- ResourcePolicy::Discardable discardPolicy = ResourcePolicy::OWNED_DISCARD;
- if( dataRetentionPolicy == ResourcePolicy::DALI_RETAINS_ALL_DATA )
- {
- discardPolicy = ResourcePolicy::OWNED_RETAIN;
- }
- textureCache.SetDiscardBitmapsPolicy(discardPolicy);
-
- mTextureCacheDispatcher = new SceneGraph::TextureCacheDispatcher( renderQueue, textureCache );
mDiscardQueue = new DiscardQueue( renderQueue );
- mResourceManager = new ResourceManager( mPlatform,
- *mNotificationManager,
- *mTextureCacheDispatcher,
- *mTextureUploadedQueue,
- *mDiscardQueue,
- renderQueue );
-
mUpdateManager = new UpdateManager( *mNotificationManager,
*mAnimationPlaylist,
*mPropertyNotificationManager,
- *mResourceManager,
*mDiscardQueue,
renderController,
*mRenderManager,
renderQueue,
- *mTextureCacheDispatcher,
- *mGeometryBatcher,
*mRenderTaskProcessor );
mRenderManager->SetShaderSaver( *mUpdateManager );
- mStage = IntrusivePtr<Stage>( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager ) );
+ mObjectRegistry = ObjectRegistry::New();
+
+ mStage = IntrusivePtr<Stage>( Stage::New( *mUpdateManager ) );
// This must be called after stage is created but before stage initialization
mRelayoutController = IntrusivePtr< RelayoutController >( new RelayoutController( mRenderController ) );
- mStage->Initialize();
-
- mResourceClient = new ResourceClient( *mResourceManager, *mStage );
+ mGestureEventProcessor = new GestureEventProcessor( *mUpdateManager, mRenderController );
- mGestureEventProcessor = new GestureEventProcessor(*mStage, gestureManager, mRenderController);
- mEventProcessor = new EventProcessor(*mStage, *mNotificationManager, *mGestureEventProcessor);
-
- mImageFactory = new ImageFactory( *mResourceClient );
mShaderFactory = new ShaderFactory();
mUpdateManager->SetShaderSaver( *mShaderFactory );
Core::~Core()
{
- /**
- * TODO this should be done by Adaptor, Core does not know about threading
- * First stop the resource loading thread(s)
- */
- mPlatform.JoinLoaderThreads();
-
/*
* The order of destructing these singletons is important!!!
*/
if( tls )
{
tls->Remove();
+ delete tls;
}
+ mObjectRegistry.Reset();
+
// Stop relayout requests being raised on stage destruction
mRelayoutController.Reset();
- // Clean-up stage - remove default camera and root layer
- mStage->Uninitialize();
-
// remove (last?) reference to stage
mStage.Reset();
- delete mEventProcessor;
- delete mGestureEventProcessor;
- delete mNotificationManager;
- delete mImageFactory;
- delete mShaderFactory;
- delete mResourceClient;
- delete mResourceManager;
- delete mDiscardQueue;
- delete mTextureCacheDispatcher;
- delete mUpdateManager;
- delete mRenderManager;
- delete mRenderTaskProcessor;
- delete mGeometryBatcher;
- delete mTextureUploadedQueue;
+}
+
+void Core::Initialize()
+{
+ mStage->Initialize( *mScenes[0] );
}
Integration::ContextNotifierInterface* Core::GetContextNotifier()
{
DALI_LOG_INFO(gCoreFilter, Debug::Verbose, "Core::RecoverFromContextLoss()\n");
- mImageFactory->RecoverFromContextLoss(); // Reload images from files
mStage->GetRenderTaskList().RecoverFromContextLoss(); // Re-trigger render-tasks
}
mRenderManager->ContextDestroyed();
}
-void Core::SurfaceResized( unsigned int width, unsigned int height )
-{
- mStage->SurfaceResized( width, height );
-
- // The stage-size may be less than surface-size (reduced by top-margin)
- Vector2 size = mStage->GetSize();
- mRelayoutController->SetStageSize( size.width, size.height );
-}
-
-void Core::SetTopMargin( unsigned int margin )
+void Core::SurfaceResized( Integration::RenderSurface* surface )
{
- mStage->SetTopMargin( margin );
-
- // The stage-size may be less than surface-size (reduced by top-margin)
- Vector2 size = mStage->GetSize();
- mRelayoutController->SetStageSize( size.width, size.height );
-}
-
-void Core::SetDpi( unsigned int dpiHorizontal, unsigned int dpiVertical )
-{
- mStage->SetDpi( Vector2( dpiHorizontal , dpiVertical) );
+ for( auto iter = mScenes.begin(); iter != mScenes.end(); ++iter )
+ {
+ if( (*iter)->GetSurface() == surface )
+ {
+ (*iter)->SurfaceResized();
+ }
+ }
}
-void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status )
+void Core::Update( float elapsedSeconds, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo )
{
// set the time delta so adaptor can easily print FPS with a release build with 0 as
// it is cached by frametime
// Use the estimated time diff till we render as the elapsed time.
status.keepUpdating = mUpdateManager->Update( elapsedSeconds,
lastVSyncTimeMilliseconds,
- nextVSyncTimeMilliseconds );
+ nextVSyncTimeMilliseconds,
+ renderToFboEnabled,
+ isRenderingToFbo );
// Check the Notification Manager message queue to set needsNotification
status.needsNotification = mNotificationManager->MessagesToProcess();
+ // Check if the default surface is changed
+ status.surfaceRectChanged = mUpdateManager->IsDefaultSurfaceRectChanged();
+
// No need to keep update running if there are notifications to process.
// Any message to update will wake it up anyways
-
- if ( mResourceManager->ResourcesToProcess() )
- {
- // If we are still processing resources, then we have to continue the update
- status.keepUpdating |= Integration::KeepUpdating::LOADING_RESOURCES;
- }
-}
-
-void Core::Render( RenderStatus& status )
-{
- bool updateRequired = mRenderManager->Render( status );
-
- status.SetNeedsUpdate( updateRequired );
}
-void Core::Suspend()
+void Core::Render( RenderStatus& status, bool forceClear )
{
- mPlatform.Suspend();
-
- mIsActive = false;
-}
-
-void Core::Resume()
-{
- mPlatform.Resume();
-
- mIsActive = true;
-
- // trigger processing of events queued up while paused
- ProcessEvents();
+ mRenderManager->Render( status, forceClear );
}
void Core::SceneCreated()
mStage->EmitSceneCreatedSignal();
mRelayoutController->OnApplicationSceneCreated();
+
+ for( auto iter = mScenes.begin(); iter != mScenes.end(); ++iter )
+ {
+ Dali::Actor sceneRootLayer = (*iter)->GetRootLayer();
+ mRelayoutController->RequestRelayoutTree( sceneRootLayer );
+ }
}
void Core::QueueEvent( const Integration::Event& event )
{
- mEventProcessor->QueueEvent( event );
+ if (mScenes.size() != 0)
+ {
+ mScenes.front()->QueueEvent( event );
+ }
}
void Core::ProcessEvents()
if( mProcessingEvent )
{
DALI_LOG_ERROR( "ProcessEvents should not be called from within ProcessEvents!\n" );
- mRenderController.RequestProcessEventsOnIdle();
+ mRenderController.RequestProcessEventsOnIdle( false );
return;
}
// Signal that any messages received will be flushed soon
mUpdateManager->EventProcessingStarted();
- mEventProcessor->ProcessEvents();
+ // process events in all scenes
+ for( auto iter = mScenes.begin(); iter != mScenes.end(); ++iter )
+ {
+ (*iter)->ProcessEvents();
+ }
mNotificationManager->ProcessMessages();
- // Avoid allocating MessageBuffers, triggering size-negotiation or sending any other spam whilst paused
- if( mIsActive )
+ // Emit signal here to inform listeners that event processing has finished.
+ for( auto iter = mScenes.begin(); iter != mScenes.end(); ++iter )
{
- // Emit signal here to inform listeners that event processing has finished.
- mStage->EmitEventProcessingFinishedSignal();
+ (*iter)->EmitEventProcessingFinishedSignal();
+ }
- // Run the size negotiation after event processing finished signal
- mRelayoutController->Relayout();
+ // Run any registered processors
+ RunProcessors();
- // Flush discard queue for image factory
- mImageFactory->FlushReleaseQueue();
+ // Run the size negotiation after event processing finished signal
+ mRelayoutController->Relayout();
- // Flush any queued messages for the update-thread
- const bool messagesToProcess = mUpdateManager->FlushQueue();
+ // Rebuild depth tree after event processing has finished
+ for( auto iter = mScenes.begin(); iter != mScenes.end(); ++iter )
+ {
+ (*iter)->RebuildDepthTree();
+ }
- // Check if the touch or gestures require updates.
- const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
+ // Flush any queued messages for the update-thread
+ const bool messagesToProcess = mUpdateManager->FlushQueue();
- if( messagesToProcess || gestureNeedsUpdate )
- {
- // tell the render controller to keep update thread running
- mRenderController.RequestUpdate();
- }
+ // Check if the touch or gestures require updates.
+ const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
+ // Check if the next update is forced.
+ const bool forceUpdate = IsNextUpdateForced();
+
+ if( messagesToProcess || gestureNeedsUpdate || forceUpdate )
+ {
+ // tell the render controller to keep update thread running
+ mRenderController.RequestUpdate( forceUpdate );
}
mRelayoutController->SetProcessingCoreEvents( false );
mProcessingEvent = false;
}
-unsigned int Core::GetMaximumUpdateCount() const
+uint32_t Core::GetMaximumUpdateCount() const
{
return MAXIMUM_UPDATE_COUNT;
}
-Integration::SystemOverlay& Core::GetSystemOverlay()
-{
- return mStage->GetSystemOverlay();
-}
-
-void Core::SetViewMode( ViewMode viewMode )
+void Core::RegisterProcessor( Integration::Processor& processor )
{
- mStage->SetViewMode( viewMode );
+ mProcessors.PushBack(&processor);
}
-ViewMode Core::GetViewMode() const
+void Core::UnregisterProcessor( Integration::Processor& processor )
{
- return mStage->GetViewMode();
+ auto iter = std::find( mProcessors.Begin(), mProcessors.End(), &processor );
+ if( iter != mProcessors.End() )
+ {
+ mProcessors.Erase( iter );
+ }
}
-void Core::SetStereoBase( float stereoBase )
+void Core::RunProcessors()
{
- mStage->SetStereoBase( stereoBase );
-}
+ // Copy processor pointers to prevent changes to vector affecting loop iterator.
+ Dali::Vector<Integration::Processor*> processors( mProcessors );
-float Core::GetStereoBase() const
-{
- return mStage->GetStereoBase();
+ for( auto processor : processors )
+ {
+ if( processor )
+ {
+ processor->Process();
+ }
+ }
}
StagePtr Core::GetCurrentStage()
return *(mNotificationManager);
}
-ResourceManager& Core::GetResourceManager()
+ShaderFactory& Core::GetShaderFactory()
+{
+ return *(mShaderFactory);
+}
+
+GestureEventProcessor& Core::GetGestureEventProcessor()
{
- return *(mResourceManager);
+ return *(mGestureEventProcessor);
}
-ResourceClient& Core::GetResourceClient()
+RelayoutController& Core::GetRelayoutController()
{
- return *(mResourceClient);
+ return *(mRelayoutController.Get());
}
-ImageFactory& Core::GetImageFactory()
+ObjectRegistry& Core::GetObjectRegistry() const
{
- return *(mImageFactory);
+ return *(mObjectRegistry.Get());
}
-ShaderFactory& Core::GetShaderFactory()
+EventThreadServices& Core::GetEventThreadServices()
{
- return *(mShaderFactory);
+ return *this;
}
-GestureEventProcessor& Core::GetGestureEventProcessor()
+PropertyNotificationManager& Core::GetPropertyNotificationManager() const
{
- return *(mGestureEventProcessor);
+ return *(mPropertyNotificationManager);
}
-RelayoutController& Core::GetRelayoutController()
+AnimationPlaylist& Core::GetAnimationPlaylist() const
{
- return *(mRelayoutController.Get());
+ return *(mAnimationPlaylist);
+}
+
+void Core::AddScene( Scene* scene )
+{
+ mScenes.push_back( scene );
+}
+
+void Core::RemoveScene( Scene* scene )
+{
+ auto iter = std::find( mScenes.begin(), mScenes.end(), scene );
+ if( iter != mScenes.end() )
+ {
+ mScenes.erase( iter );
+ }
}
void Core::CreateThreadLocalStorage()
{
// a pointer to the ThreadLocalStorage object will be stored in TLS
- // and automatically deleted when the thread is killed
+ // The ThreadLocalStorage object should be deleted by the Core destructor
new ThreadLocalStorage(this);
}
+void Core::RegisterObject( Dali::BaseObject* object )
+{
+ mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
+ mObjectRegistry->RegisterObject( object );
+}
+
+void Core::UnregisterObject( Dali::BaseObject* object )
+{
+ mObjectRegistry = &ThreadLocalStorage::Get().GetObjectRegistry();
+ mObjectRegistry->UnregisterObject( object );
+}
+
+Integration::RenderController& Core::GetRenderController()
+{
+ return mRenderController;
+}
+
+uint32_t* Core::ReserveMessageSlot( uint32_t size, bool updateScene )
+{
+ return mUpdateManager->ReserveMessageSlot( size, updateScene );
+}
+
+BufferIndex Core::GetEventBufferIndex() const
+{
+ return mUpdateManager->GetEventBufferIndex();
+}
+
+void Core::ForceNextUpdate()
+{
+ mForceNextUpdate = true;
+}
+
+bool Core::IsNextUpdateForced()
+{
+ bool nextUpdateForced = mForceNextUpdate;
+ mForceNextUpdate = false;
+ return nextUpdateForced;
+}
+
} // namespace Internal
} // namespace Dali