/*
- * Copyright (c) 2017 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/gl-context-helper-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>
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::GlContextHelperAbstraction;
using Integration::Event;
using Integration::UpdateStatus;
using Integration::RenderStatus;
PlatformAbstraction& platform,
GlAbstraction& glAbstraction,
GlSyncAbstraction& glSyncAbstraction,
- GestureManager& gestureManager,
+ GlContextHelperAbstraction& glContextHelperAbstraction,
ResourcePolicy::DataRetention dataRetentionPolicy,
Integration::RenderToFrameBuffer renderToFboEnabled,
Integration::DepthBufferAvailable depthBufferAvailable,
- Integration::StencilBufferAvailable stencilBufferAvailable )
+ Integration::StencilBufferAvailable stencilBufferAvailable,
+ Integration::PartialUpdateAvailable partialUpdateAvailable )
: mRenderController( renderController ),
mPlatform(platform),
- mProcessingEvent(false)
+ mProcessingEvent(false),
+ mForceNextUpdate( false )
{
// Create the thread local storage
CreateThreadLocalStorage();
mRenderTaskProcessor = new SceneGraph::RenderTaskProcessor();
- mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, depthBufferAvailable, stencilBufferAvailable );
+ mRenderManager = RenderManager::New( glAbstraction, glSyncAbstraction, glContextHelperAbstraction, depthBufferAvailable, stencilBufferAvailable, partialUpdateAvailable );
RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
renderController,
*mRenderManager,
renderQueue,
- *mRenderTaskProcessor );
+ *mRenderTaskProcessor,
+ partialUpdateAvailable == Integration::PartialUpdateAvailable::TRUE );
mRenderManager->SetShaderSaver( *mUpdateManager );
- mStage = IntrusivePtr<Stage>( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager, mRenderController ) );
+ 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( renderToFboEnabled == Integration::RenderToFrameBuffer::TRUE );
-
- mGestureEventProcessor = new GestureEventProcessor( *mStage, *mUpdateManager, gestureManager, mRenderController );
- mEventProcessor = new EventProcessor( *mStage, *mNotificationManager, *mGestureEventProcessor );
+ mGestureEventProcessor = new GestureEventProcessor( *mUpdateManager, mRenderController );
mShaderFactory = new ShaderFactory();
mUpdateManager->SetShaderSaver( *mShaderFactory );
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();
}
+void Core::Initialize()
+{
+ mStage->Initialize( *mScenes[0] );
+}
+
Integration::ContextNotifierInterface* Core::GetContextNotifier()
{
return mStage.Get();
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::SurfaceDeleted( 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 scene : mScenes )
+ {
+ if( scene->GetSurface() == surface )
+ {
+ scene->SurfaceDeleted();
+ break;
+ }
+ }
}
-void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status, bool renderToFboEnabled, bool isRenderingToFbo )
+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
// 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
}
-void Core::Render( RenderStatus& status )
+void Core::Render( RenderStatus& status, bool forceClear, bool uploadOnly )
{
- mRenderManager->Render( status );
+ mRenderManager->Render( status, forceClear, uploadOnly );
}
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()
// Signal that any messages received will be flushed soon
mUpdateManager->EventProcessingStarted();
- mEventProcessor->ProcessEvents();
+ // Scene could be added or removed while processing the events
+ // Copy the Scene container locally to avoid possibly invalid iterator
+ SceneContainer scenes = mScenes;
+
+ // process events in all scenes
+ for( auto scene : scenes )
+ {
+ scene->ProcessEvents();
+ }
mNotificationManager->ProcessMessages();
// Emit signal here to inform listeners that event processing has finished.
- mStage->EmitEventProcessingFinishedSignal();
+ for( auto scene : scenes )
+ {
+ scene->EmitEventProcessingFinishedSignal();
+ }
+
+ // Run any registered processors
+ RunProcessors();
// Run the size negotiation after event processing finished signal
mRelayoutController->Relayout();
// Rebuild depth tree after event processing has finished
- mStage->RebuildDepthTree();
+ for( auto scene : scenes )
+ {
+ scene->RebuildDepthTree();
+ }
// Flush any queued messages for the update-thread
const bool messagesToProcess = mUpdateManager->FlushQueue();
// Check if the touch or gestures require updates.
const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
// Check if the next update is forced.
- const bool forceUpdate = mStage->IsNextUpdateForced();
+ const bool forceUpdate = IsNextUpdateForced();
if( messagesToProcess || gestureNeedsUpdate || forceUpdate )
{
mProcessingEvent = false;
}
-unsigned int Core::GetMaximumUpdateCount() const
+uint32_t Core::GetMaximumUpdateCount() const
{
return MAXIMUM_UPDATE_COUNT;
}
-Integration::SystemOverlay& Core::GetSystemOverlay()
+void Core::RegisterProcessor( Integration::Processor& processor )
{
- return mStage->GetSystemOverlay();
+ mProcessors.PushBack(&processor);
}
-void Core::SetViewMode( ViewMode viewMode )
+void Core::UnregisterProcessor( Integration::Processor& processor )
{
- mStage->SetViewMode( viewMode );
-}
-
-ViewMode Core::GetViewMode() const
-{
- 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 *(mRelayoutController.Get());
}
+ObjectRegistry& Core::GetObjectRegistry() const
+{
+ return *(mObjectRegistry.Get());
+}
+
+EventThreadServices& Core::GetEventThreadServices()
+{
+ return *this;
+}
+
+PropertyNotificationManager& Core::GetPropertyNotificationManager() const
+{
+ return *(mPropertyNotificationManager);
+}
+
+AnimationPlaylist& Core::GetAnimationPlaylist() const
+{
+ 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
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