/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// INTERNAL INCLUDES
#include <dali/integration-api/core.h>
+#include <dali/internal/common/owner-key-container.h>
+
#include <dali/internal/event/animation/animation-playlist.h>
#include <dali/internal/event/common/notification-manager.h>
#include <dali/internal/event/common/property-notifier.h>
#include <dali/internal/update/controllers/scene-controller-impl.h>
#include <dali/internal/update/manager/frame-callback-processor.h>
#include <dali/internal/update/manager/render-task-processor.h>
+#include <dali/internal/update/manager/resetter-container.h>
#include <dali/internal/update/manager/transform-manager.h>
#include <dali/internal/update/manager/update-algorithms.h>
#include <dali/internal/update/manager/update-manager-debug.h>
#include <dali/internal/render/common/render-manager.h>
#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/render-vertex-buffer.h>
// Un-comment to enable node tree debug logging
//#define NODE_TREE_LOGGING 1
* @param discardQueue to put the object to
* @param updateBufferIndex to use
*/
-template<class T>
-inline void EraseUsingDiscardQueue(OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex)
+template<class Type>
+inline void EraseUsingDiscardQueue(OwnerContainer<Type*>& container, Type* object, DiscardQueue<Type*, OwnerContainer<Type*>>& discardQueue, BufferIndex updateBufferIndex)
{
DALI_ASSERT_DEBUG(object && "NULL object not allowed");
}
/**
- * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
- * @param[in] node The node whose hierarchy to descend
+ * Helper to Erase an object from std::vector using discard queue
+ * @param container to remove from
+ * @param object to remove
+ * @param discardQueue to put the object to
+ * @param updateBufferIndex to use
*/
-void SortSiblingNodesRecursively(Node& node)
+template<class Type>
+inline void EraseUsingDiscardQueue(OwnerKeyContainer<Type>& container, const MemoryPoolKey<Type>& key, DiscardQueue<MemoryPoolKey<Type>, OwnerKeyContainer<Type>>& discardQueue, BufferIndex updateBufferIndex)
{
- NodeContainer& container = node.GetChildren();
- std::sort(container.Begin(), container.End(), [](Node* a, Node* b) { return a->GetDepthIndex() < b->GetDepthIndex(); });
+ DALI_ASSERT_DEBUG(key && "INVALID Key not allowed");
- // Descend tree and sort as well
- for(auto&& iter : container)
+ for(auto iter = container.begin(), end = container.end(); iter != end; ++iter)
{
- SortSiblingNodesRecursively(*iter);
+ if(*iter == key)
+ {
+ // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
+ discardQueue.Add(updateBufferIndex, container.Release(iter));
+ return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
+ }
}
}
Impl(NotificationManager& notificationManager,
CompleteNotificationInterface& animationPlaylist,
PropertyNotifier& propertyNotifier,
- DiscardQueue& discardQueue,
RenderController& renderController,
RenderManager& renderManager,
RenderQueue& renderQueue,
animationPlaylist(animationPlaylist),
propertyNotifier(propertyNotifier),
shaderSaver(nullptr),
- discardQueue(discardQueue),
renderController(renderController),
sceneController(nullptr),
renderManager(renderManager),
panGestureProcessor(nullptr),
messageQueue(renderController, sceneGraphBuffers),
frameCallbackProcessor(nullptr),
- keepRenderingSeconds(0.0f),
nodeDirtyFlags(NodePropertyFlags::TRANSFORM), // set to TransformFlag to ensure full update the first time through Update()
frameCounter(0),
renderingBehavior(DevelStage::Rendering::IF_REQUIRED),
renderersAdded(false),
renderingRequired(false)
{
- sceneController = new SceneControllerImpl(renderMessageDispatcher, renderQueue, discardQueue);
+ sceneController = new SceneControllerImpl(renderMessageDispatcher, renderQueue);
// create first 'dummy' node
nodes.PushBack(nullptr);
(*iter)->OnDestroy();
Node::Delete(*iter);
}
+ nodeIdMap.clear();
for(auto&& scene : scenes)
{
scenes.clear();
delete sceneController;
+
+ // Ensure to clear renderers
+ renderers.Clear();
+ shaders.Clear();
}
/**
CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
ShaderSaver* shaderSaver; ///< Saves shader binaries.
- DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
RenderController& renderController; ///< render controller
SceneControllerImpl* sceneController; ///< scene controller
RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
Vector<Node*> nodes; ///< A container of all instantiated nodes
- OwnerContainer<Camera*> cameras; ///< A container of cameras
+ std::unordered_map<uint32_t, Node*> nodeIdMap; ///< A container of nodes map by id.
+
+ Vector<Camera*> cameras; ///< A container of cameras. Note : these cameras are owned by Impl::nodes.
+
OwnerContainer<PropertyOwner*> customObjects; ///< A container of owned objects (with custom properties)
- OwnerContainer<PropertyResetterBase*> propertyResetters; ///< A container of property resetters
+ ResetterContainer<PropertyResetterBase> propertyResetters; ///< A container of property resetters
+ ResetterContainer<NodeResetter> nodeResetters; ///< A container of node resetters
+ ResetterContainer<RendererResetter> rendererResetters; ///< A container of renderer resetters
+
OwnerContainer<Animation*> animations; ///< A container of owned animations
- PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
- OwnerContainer<Renderer*> renderers; ///< A container of owned renderers
+ OwnerContainer<PropertyNotification*> propertyNotifications; ///< A container of owner property notifications.
+ OwnerKeyContainer<Renderer> renderers; ///< A container of owned renderers
OwnerContainer<TextureSet*> textureSets; ///< A container of owned texture sets
OwnerContainer<Shader*> shaders; ///< A container of owned shaders
- OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
+
+ DiscardQueue<Node*, OwnerContainer<Node*>> nodeDiscardQueue; ///< Nodes are added here when disconnected from the scene-graph.
+ DiscardQueue<Shader*, OwnerContainer<Shader*>> shaderDiscardQueue;
+ DiscardQueue<MemoryPoolKey<Renderer>, OwnerKeyContainer<Renderer>> rendererDiscardQueue;
+ DiscardQueue<Scene*, OwnerContainer<Scene*>> sceneDiscardQueue;
+
+ CompleteNotificationInterface::ParameterList notifyRequiredAnimations; ///< A temperal container of complete notify required animations, like animation finished, stopped, or loop completed.
+
+ OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
MessageQueue messageQueue; ///< The messages queued from the event-thread
std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
- float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
- NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
- uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
-
- DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
+ std::atomic<std::size_t> renderInstructionCapacity{0u};
+ NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
+ uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
+ DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
UpdateManager::UpdateManager(NotificationManager& notificationManager,
CompleteNotificationInterface& animationFinishedNotifier,
PropertyNotifier& propertyNotifier,
- DiscardQueue& discardQueue,
RenderController& controller,
RenderManager& renderManager,
RenderQueue& renderQueue,
mImpl = new Impl(notificationManager,
animationFinishedNotifier,
propertyNotifier,
- discardQueue,
controller,
renderManager,
renderQueue,
Layer* rootLayer = layer.Release();
- DALI_ASSERT_DEBUG(std::find_if(mImpl->scenes.begin(), mImpl->scenes.end(), [rootLayer](Impl::SceneInfoPtr& scene) {
- return scene && scene->root == rootLayer;
- }) == mImpl->scenes.end() &&
+ DALI_ASSERT_DEBUG(std::find_if(mImpl->scenes.begin(), mImpl->scenes.end(), [rootLayer](Impl::SceneInfoPtr& scene) { return scene && scene->root == rootLayer; }) == mImpl->scenes.end() &&
"Root Node already installed");
rootLayer->CreateTransform(&mImpl->transformManager);
rootLayer->SetRoot(true);
+ rootLayer->AddInitializeResetter(*this);
+
+ // Do not allow to insert duplicated nodes.
+ // It could be happened if node id is overflowed.
+ DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rootLayer->GetId(), rootLayer}).second);
+
mImpl->scenes.emplace_back(new Impl::SceneInfo(rootLayer));
}
}
}
- mImpl->discardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), layer);
+ mImpl->nodeIdMap.erase(layer->GetId());
+
+ mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), layer);
// Notify the layer about impending destruction
layer->OnDestroy();
Node* rawNode = node.Release();
DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddNode\n", rawNode);
+ // Add camera nodes occured rarely.
+ if(DALI_UNLIKELY(rawNode->IsCamera()))
+ {
+ AddCamera(static_cast<Camera*>(rawNode));
+ }
+
+ // Do not allow to insert duplicated nodes.
+ // It could be happened if node id is overflowed.
+ DALI_ASSERT_ALWAYS(mImpl->nodeIdMap.insert({rawNode->GetId(), rawNode}).second);
+
mImpl->nodes.PushBack(rawNode);
+
rawNode->CreateTransform(&mImpl->transformManager);
}
DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] ConnectNode\n", node);
+ parent->SetDirtyFlag(NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
parent->ConnectChild(node);
+ node->AddInitializeResetter(*this);
+
// Inform the frame-callback-processor, if set, about the node-hierarchy changing
if(mImpl->frameCallbackProcessor)
{
Node* parent = node->GetParent();
DALI_ASSERT_ALWAYS(nullptr != parent);
- parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED); // make parent dirty so that render items dont get reused
+ parent->SetDirtyFlag(NodePropertyFlags::CHILD_DELETED | NodePropertyFlags::DESCENDENT_HIERARCHY_CHANGED); // make parent dirty so that render items dont get reused
parent->DisconnectChild(mSceneGraphBuffers.GetUpdateBufferIndex(), *node);
}
}
- mImpl->discardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
+ // Remove camera nodes occured rarely.
+ if(DALI_UNLIKELY(node->IsCamera()))
+ {
+ RemoveCamera(static_cast<Camera*>(node));
+ }
+
+ mImpl->nodeIdMap.erase(node->GetId());
+
+ mImpl->nodeDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), node);
// Notify the Node about impending destruction
node->OnDestroy();
}
-void UpdateManager::AddCamera(OwnerPointer<Camera>& camera)
+void UpdateManager::AddCamera(Camera* camera)
{
- mImpl->cameras.PushBack(camera.Release()); // takes ownership
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddCamera\n", camera);
+
+ mImpl->cameras.PushBack(camera);
}
void UpdateManager::RemoveCamera(Camera* camera)
{
- // Find the camera and destroy it
- EraseUsingDiscardQueue(mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveCamera\n", camera);
+
+ // Find the camera and remove it from list of cameras
+ Vector<Camera*>::Iterator iter = mImpl->cameras.Begin();
+ Vector<Camera*>::Iterator endIter = mImpl->cameras.End();
+ for(; iter != endIter; ++iter)
+ {
+ if((*iter) == camera)
+ {
+ mImpl->cameras.Erase(iter);
+ break;
+ }
+ }
}
void UpdateManager::AddObject(OwnerPointer<PropertyOwner>& object)
void UpdateManager::AddRenderTaskList(OwnerPointer<RenderTaskList>& taskList)
{
RenderTaskList* taskListPointer = taskList.Release();
- taskListPointer->SetRenderMessageDispatcher(&mImpl->renderMessageDispatcher);
+ taskListPointer->Initialize(*this, mImpl->renderMessageDispatcher);
mImpl->scenes.back()->taskList = taskListPointer;
}
void UpdateManager::AddScene(OwnerPointer<Scene>& scene)
{
- mImpl->scenes.back()->scene = scene.Release();
+ auto& sceneInfo = mImpl->scenes.back();
+ sceneInfo->scene = scene.Release();
+
+ // Set root to the Scene
+ sceneInfo->scene->SetRoot(sceneInfo->root);
// Initialize the context from render manager
typedef MessageValue1<RenderManager, SceneGraph::Scene*> DerivedType;
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
// Construct message in the render queue memory; note that delete should not be called on the return value
- SceneGraph::Scene& sceneObject = *mImpl->scenes.back()->scene;
+ SceneGraph::Scene& sceneObject = *sceneInfo->scene;
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::InitializeScene, &sceneObject);
}
// Construct message in the render queue memory; note that delete should not be called on the return value
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::UninitializeScene, scene);
+ scene->RemoveSurfaceRenderTarget();
+
for(auto&& sceneInfo : mImpl->scenes)
{
if(sceneInfo && sceneInfo->scene && sceneInfo->scene.Get() == scene)
{
- mImpl->discardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), sceneInfo->scene.Release()); // take the address of the reference to a pointer
+ mImpl->sceneDiscardQueue.Add(mSceneGraphBuffers.GetUpdateBufferIndex(), sceneInfo->scene.Release()); // take the address of the reference to a pointer
break;
}
}
mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
}
+void UpdateManager::ClearAnimation(Animation* animation)
+{
+ DALI_ASSERT_DEBUG(animation && "NULL animation called to clear");
+
+ animation->ClearAnimator(mSceneGraphBuffers.GetUpdateBufferIndex());
+}
+
void UpdateManager::RemoveAnimation(Animation* animation)
{
DALI_ASSERT_DEBUG(animation && "NULL animation called to remove");
animation->OnDestroy(mSceneGraphBuffers.GetUpdateBufferIndex());
DALI_ASSERT_DEBUG(animation->GetState() == Animation::Destroyed);
+
+ // Do not remove from container now. Destroyed animation will be removed at Animate.
}
bool UpdateManager::IsAnimationRunning() const
mImpl->propertyResetters.PushBack(propertyResetter.Release());
}
+void UpdateManager::AddNodeResetter(const Node& node)
+{
+ OwnerPointer<SceneGraph::NodeResetter> nodeResetter = SceneGraph::NodeResetter::New(node);
+ nodeResetter->Initialize();
+ mImpl->nodeResetters.PushBack(nodeResetter.Release());
+}
+
+void UpdateManager::AddRendererResetter(const Renderer& renderer)
+{
+ OwnerPointer<SceneGraph::RendererResetter> rendererResetter = SceneGraph::RendererResetter::New(renderer);
+ rendererResetter->Initialize();
+ mImpl->rendererResetters.PushBack(rendererResetter.Release());
+}
+
void UpdateManager::AddPropertyNotification(OwnerPointer<PropertyNotification>& propertyNotification)
{
mImpl->propertyNotifications.PushBack(propertyNotification.Release());
void UpdateManager::RemovePropertyNotification(PropertyNotification* propertyNotification)
{
- mImpl->propertyNotifications.EraseObject(propertyNotification);
+ auto iter = std::find(mImpl->propertyNotifications.Begin(), mImpl->propertyNotifications.End(), propertyNotification);
+ if(iter != mImpl->propertyNotifications.End())
+ {
+ mImpl->propertyNotifications.Erase(iter);
+ }
}
void UpdateManager::PropertyNotificationSetNotify(PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode)
void UpdateManager::RemoveShader(Shader* shader)
{
// Find the shader and destroy it
- EraseUsingDiscardQueue(mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
+ EraseUsingDiscardQueue(mImpl->shaders, shader, mImpl->shaderDiscardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
}
void UpdateManager::SaveBinary(Internal::ShaderDataPtr shaderData)
mImpl->shaderSaver = &upstream;
}
-void UpdateManager::AddRenderer(OwnerPointer<Renderer>& renderer)
+void UpdateManager::AddRenderer(const RendererKey& rendererKey)
{
- DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get());
+ SceneGraph::Renderer* renderer = rendererKey.Get();
+
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer);
renderer->ConnectToSceneGraph(*mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex());
- mImpl->renderers.PushBack(renderer.Release());
+ renderer->AddInitializeResetter(*this);
+
+ mImpl->renderers.PushBack(rendererKey);
}
-void UpdateManager::RemoveRenderer(Renderer* renderer)
+void UpdateManager::RemoveRenderer(const RendererKey& rendererKey)
{
- DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer);
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveRenderer\n", rendererKey.Get());
// Find the renderer and destroy it
- EraseUsingDiscardQueue(mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
+ EraseUsingDiscardQueue(mImpl->renderers, rendererKey, mImpl->rendererDiscardQueue, mSceneGraphBuffers.GetUpdateBufferIndex());
// Need to remove the render object as well
- renderer->DisconnectFromSceneGraph(*mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex());
+ rendererKey->DisconnectFromSceneGraph(*mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex());
}
void UpdateManager::AttachRenderer(Node* node, Renderer* renderer)
{
- node->AddRenderer(renderer);
+ node->AddRenderer(Renderer::GetKey(renderer));
mImpl->renderersAdded = true;
}
void UpdateManager::AddTextureSet(OwnerPointer<TextureSet>& textureSet)
{
+ textureSet->SetRenderMessageDispatcher(&mImpl->renderMessageDispatcher);
mImpl->textureSets.PushBack(textureSet.Release());
}
return mImpl->messageQueue.ReserveMessageSlot(size, updateScene);
}
+std::size_t UpdateManager::GetUpdateMessageQueueCapacity() const
+{
+ return mImpl->messageQueue.GetCapacity();
+}
+
+std::size_t UpdateManager::GetRenderMessageQueueCapacity() const
+{
+ return mImpl->renderQueue.GetCapacity();
+}
+
+std::size_t UpdateManager::GetRenderInstructionCapacity() const
+{
+ return mImpl->renderInstructionCapacity;
+}
+
void UpdateManager::EventProcessingStarted()
{
mImpl->messageQueue.EventProcessingStarted();
}
+void UpdateManager::EventProcessingFinished()
+{
+ mImpl->messageQueue.EventProcessingFinished();
+}
+
bool UpdateManager::FlushQueue()
{
return mImpl->messageQueue.FlushQueue();
// Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
mImpl->animationFinishedDuringUpdate = false;
- // Reset all animating / constrained properties
- std::vector<PropertyResetterBase*> toDelete;
- for(auto&& element : mImpl->propertyResetters)
- {
- element->ResetToBaseValue(bufferIndex);
- if(element->IsFinished())
- {
- toDelete.push_back(element);
- }
- }
+ // Reset node properties
+ mImpl->nodeResetters.ResetToBaseValues(bufferIndex);
- // If a resetter is no longer required (the animator or constraint has been removed), delete it.
- for(auto&& elementPtr : toDelete)
- {
- mImpl->propertyResetters.EraseObject(elementPtr);
- }
+ // Reset renderer properties
+ mImpl->rendererResetters.ResetToBaseValues(bufferIndex);
+
+ // Reset all animating / constrained properties
+ mImpl->propertyResetters.ResetToBaseValues(bufferIndex);
// Clear all root nodes dirty flags
for(auto& scene : mImpl->scenes)
{
bool animationActive = false;
- auto&& iter = mImpl->animations.Begin();
- bool animationLooped = false;
+ auto&& iter = mImpl->animations.Begin();
while(iter != mImpl->animations.End())
{
Animation* animation = *iter;
bool finished = false;
- bool looped = false;
+ bool stopped = false;
bool progressMarkerReached = false;
- animation->Update(bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached);
+ animation->Update(bufferIndex, elapsedSeconds, stopped, finished, progressMarkerReached);
animationActive = animationActive || animation->IsActive();
if(progressMarkerReached)
{
- mImpl->notificationManager.QueueMessage(Internal::NotifyProgressReachedMessage(mImpl->animationPlaylist, animation));
+ mImpl->notificationManager.QueueMessage(Internal::NotifyProgressReachedMessage(mImpl->animationPlaylist, animation->GetNotifyId()));
}
mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
- animationLooped = animationLooped || looped;
+
+ // queue the notification on finished or stopped
+ if(finished || stopped)
+ {
+ mImpl->notifyRequiredAnimations.PushBack(animation->GetNotifyId());
+ }
// Remove animations that had been destroyed but were still waiting for an update
if(animation->GetState() == Animation::Destroyed)
}
}
- // queue the notification on finished or looped (to update loop count)
- if(mImpl->animationFinishedDuringUpdate || animationLooped)
+ // The application should be notified by NotificationManager, in another thread
+ if(!mImpl->notifyRequiredAnimations.Empty())
{
- // The application should be notified by NotificationManager, in another thread
- mImpl->notificationManager.QueueCompleteNotification(&mImpl->animationPlaylist);
+ mImpl->notificationManager.QueueNotification(&mImpl->animationPlaylist, std::move(mImpl->notifyRequiredAnimations));
}
return animationActive;
}
-void UpdateManager::ConstrainCustomObjects(BufferIndex bufferIndex)
+void UpdateManager::ConstrainCustomObjects(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
- //Constrain custom objects (in construction order)
+ // Constrain custom objects (in construction order)
for(auto&& object : mImpl->customObjects)
{
ConstrainPropertyOwner(*object, bufferIndex);
+ if(!object->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(object);
+ }
}
}
-void UpdateManager::ConstrainRenderTasks(BufferIndex bufferIndex)
+void UpdateManager::ConstrainRenderTasks(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
// Constrain render-tasks
for(auto&& scene : mImpl->scenes)
for(auto&& task : tasks)
{
ConstrainPropertyOwner(*task, bufferIndex);
+ if(!task->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(task);
+ }
}
}
}
}
-void UpdateManager::ConstrainShaders(BufferIndex bufferIndex)
+void UpdateManager::ConstrainShaders(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
// constrain shaders... (in construction order)
for(auto&& shader : mImpl->shaders)
{
ConstrainPropertyOwner(*shader, bufferIndex);
+ if(!shader->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(shader);
+ }
}
}
bool valid = notification->Check(bufferIndex);
if(valid)
{
- mImpl->notificationManager.QueueMessage(PropertyChangedMessage(mImpl->propertyNotifier, notification, notification->GetValidity()));
+ mImpl->notificationManager.QueueMessage(PropertyChangedMessage(mImpl->propertyNotifier, notification->GetNotifyId(), notification->GetValidity()));
}
}
}
}
}
-void UpdateManager::UpdateRenderers(BufferIndex bufferIndex)
+void UpdateManager::UpdateRenderers(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
- for(auto&& renderer : mImpl->renderers)
+ for(const auto& rendererKey : mImpl->renderers)
{
- //Apply constraints
+ // Apply constraints
+ auto renderer = rendererKey.Get();
ConstrainPropertyOwner(*renderer, bufferIndex);
+ if(!renderer->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(renderer);
+ }
mImpl->renderingRequired = renderer->PrepareRender(bufferIndex) || mImpl->renderingRequired;
}
}
-void UpdateManager::UpdateNodes(BufferIndex bufferIndex)
+void UpdateManager::UpdateNodes(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
// And add the renderers to the sorted layers. Start from root, which is also a layer
mImpl->nodeDirtyFlags |= UpdateNodeTree(*scene->root,
bufferIndex,
- mImpl->renderQueue);
+ mImpl->renderQueue,
+ postPropertyOwners);
+ }
+ }
+}
+
+void UpdateManager::UpdateLayers(BufferIndex bufferIndex)
+{
+ for(auto&& scene : mImpl->scenes)
+ {
+ if(scene && scene->root)
+ {
+ SceneGraph::UpdateLayerTree(*scene->root, bufferIndex);
}
}
}
uint32_t lastVSyncTimeMilliseconds,
uint32_t nextVSyncTimeMilliseconds,
bool renderToFboEnabled,
- bool isRenderingToFbo)
+ bool isRenderingToFbo,
+ bool uploadOnly)
{
const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
- //Clear nodes/resources which were previously discarded
- mImpl->discardQueue.Clear(bufferIndex);
+ // Clear nodes/resources which were previously discarded
+ mImpl->nodeDiscardQueue.Clear(bufferIndex);
+ mImpl->shaderDiscardQueue.Clear(bufferIndex);
+ mImpl->rendererDiscardQueue.Clear(bufferIndex);
+ mImpl->sceneDiscardQueue.Clear(bufferIndex);
bool isAnimationRunning = IsAnimationRunning();
- //Process Touches & Gestures
+ // Process Touches & Gestures
const bool gestureUpdated = ProcessGestures(bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds);
bool updateScene = // The scene-graph requires an update if..
mImpl->frameCallbackProcessor || // ..a frame callback processor is existed OR
gestureUpdated; // ..a gesture property was updated
- bool keepRendererRendering = false;
- mImpl->renderingRequired = false;
+ uint32_t keepUpdating = 0;
+ bool keepRendererRendering = false;
+ mImpl->renderingRequired = false;
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// values if the scene was updated in the previous frame.
if(updateScene || mImpl->previousUpdateScene)
{
- //Reset properties from the previous update
+ // Reset properties from the previous update
ResetProperties(bufferIndex);
mImpl->transformManager.ResetToBaseValue();
}
// be set again
updateScene |= mImpl->messageQueue.ProcessMessages(bufferIndex);
- //Forward compiled shader programs to event thread for saving
+ // Forward compiled shader programs to event thread for saving
ForwardCompiledShadersToEventThread();
// Although the scene-graph may not require an update, we still need to synchronize double-buffered
// We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
if(updateScene || mImpl->previousUpdateScene)
{
- //Animate
+ // Animate
bool animationActive = Animate(bufferIndex, elapsedSeconds);
- //Constraint custom objects
- ConstrainCustomObjects(bufferIndex);
+ PropertyOwnerContainer postPropertyOwners;
+ // Constraint custom objects
+ ConstrainCustomObjects(postPropertyOwners, bufferIndex);
- //Clear the lists of renderers from the previous update
+ // Clear the lists of renderers from the previous update
for(auto&& scene : mImpl->scenes)
{
if(scene)
// Call the frame-callback-processor if set
if(mImpl->frameCallbackProcessor)
{
- mImpl->frameCallbackProcessor->Update(bufferIndex, elapsedSeconds);
+ keepRendererRendering |= mImpl->frameCallbackProcessor->Update(bufferIndex, elapsedSeconds);
}
- //Update node hierarchy, apply constraints and perform sorting / culling.
- //This will populate each Layer with a list of renderers which are ready.
- UpdateNodes(bufferIndex);
+ // Update node hierarchy, apply constraints,
+ UpdateNodes(postPropertyOwners, bufferIndex);
- //Apply constraints to RenderTasks, shaders
- ConstrainRenderTasks(bufferIndex);
- ConstrainShaders(bufferIndex);
+ // Apply constraints to RenderTasks, shaders
+ ConstrainRenderTasks(postPropertyOwners, bufferIndex);
+ ConstrainShaders(postPropertyOwners, bufferIndex);
- //Update renderers and apply constraints
- UpdateRenderers(bufferIndex);
+ // Update renderers and apply constraints
+ UpdateRenderers(postPropertyOwners, bufferIndex);
- //Update the transformations of all the nodes
+ // Update the transformations of all the nodes
if(mImpl->transformManager.Update())
{
mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
}
- //Process Property Notifications
+ // Constraint applied after transform manager updated. Only required property owner processed.
+ for(auto&& propertyOwner : postPropertyOwners)
+ {
+ ConstrainPropertyOwner(*propertyOwner, bufferIndex, false);
+ }
+
+ // Initialise layer renderable reuse
+ UpdateLayers(bufferIndex);
+
+ // Process Property Notifications
ProcessPropertyNotifications(bufferIndex);
- //Update cameras
+ // Update cameras
for(auto&& cameraIterator : mImpl->cameras)
{
cameraIterator->Update(bufferIndex);
}
- //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
- //reset the update buffer index and make sure there is enough room in the instruction container
+ // Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
+ // reset the update buffer index and make sure there is enough room in the instruction container
if(mImpl->renderersAdded)
{
// Calculate how many render tasks we have in total
}
std::size_t numberOfRenderInstructions = 0;
+ mImpl->renderInstructionCapacity = 0u;
for(auto&& scene : mImpl->scenes)
{
if(scene && scene->root && scene->taskList && scene->scene)
scene->scene->GetRenderInstructions().ResetAndReserve(bufferIndex,
static_cast<uint32_t>(scene->taskList->GetTasks().Count()));
+ bool sceneKeepUpdating = scene->scene->KeepRenderingCheck(elapsedSeconds);
+ if(sceneKeepUpdating)
+ {
+ keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
+ }
+
// If there are animations running, only add render instruction if at least one animation is currently active (i.e. not delayed)
// or the nodes are dirty
- if(!isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags))
+ // or keep rendering is requested
+ if(!isAnimationRunning || animationActive || mImpl->renderingRequired || (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || sceneKeepUpdating)
{
keepRendererRendering |= mImpl->renderTaskProcessor.Process(bufferIndex,
*scene->taskList,
renderToFboEnabled,
isRenderingToFbo);
+ mImpl->renderInstructionCapacity += scene->scene->GetRenderInstructions().GetCapacity();
scene->scene->SetSkipRendering(false);
}
else
}
}
- for(auto&& scene : mImpl->scenes)
+ if(!uploadOnly)
{
- if(scene && scene->root && scene->taskList)
- {
- RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
+ // check the countdown and notify
+ mImpl->renderTaskWaiting = false;
- // check the countdown and notify
- bool doRenderOnceNotify = false;
- mImpl->renderTaskWaiting = false;
- for(auto&& renderTask : tasks)
+ for(auto&& scene : mImpl->scenes)
+ {
+ if(scene && scene->root && scene->taskList)
{
- renderTask->UpdateState();
+ RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
+
+ CompleteNotificationInterface::ParameterList notifyRequiredRenderTasks;
- if(renderTask->IsWaitingToRender() &&
- renderTask->ReadyToRender(bufferIndex) /*avoid updating forever when source actor is off-stage*/)
+ for(auto&& renderTask : tasks)
{
- mImpl->renderTaskWaiting = true; // keep update/render threads alive
+ renderTask->UpdateState();
+
+ if(renderTask->IsWaitingToRender() &&
+ renderTask->ReadyToRender(bufferIndex) /*avoid updating forever when source actor is off-stage*/)
+ {
+ mImpl->renderTaskWaiting = true; // keep update/render threads alive
+ }
+
+ if(renderTask->HasRendered())
+ {
+ notifyRequiredRenderTasks.PushBack(renderTask->GetNotifyId());
+ }
}
- if(renderTask->HasRendered())
+ if(!notifyRequiredRenderTasks.Empty())
{
- doRenderOnceNotify = true;
+ DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
+ mImpl->notificationManager.QueueNotification(scene->taskList->GetCompleteNotificationInterface(), std::move(notifyRequiredRenderTasks));
}
}
-
- if(doRenderOnceNotify)
- {
- DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
- mImpl->notificationManager.QueueCompleteNotification(scene->taskList->GetCompleteNotificationInterface());
- }
}
}
mImpl->previousUpdateScene = updateScene;
// Check whether further updates are required
- uint32_t keepUpdating = KeepUpdatingCheck(elapsedSeconds);
+ keepUpdating |= KeepUpdatingCheck(elapsedSeconds);
if(keepRendererRendering)
{
keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
+ }
+ if(keepUpdating & KeepUpdating::STAGE_KEEP_RENDERING)
+ {
// Set dirty flags for next frame to continue rendering
mImpl->nodeDirtyFlags |= RenderableUpdateFlags;
}
return keepUpdating;
}
-uint32_t UpdateManager::KeepUpdatingCheck(float elapsedSeconds) const
+void UpdateManager::PostRender()
{
- // Update the duration set via Stage::KeepRendering()
- if(mImpl->keepRenderingSeconds > 0.0f)
+ // Reset dirty flag
+ for(auto&& renderer : mImpl->renderers)
+ {
+ renderer->SetUpdated(false);
+ }
+
+ for(auto&& shader : mImpl->shaders)
+ {
+ shader->SetUpdated(false);
+ }
+
+ for(auto&& scene : mImpl->scenes)
{
- mImpl->keepRenderingSeconds -= elapsedSeconds;
+ scene->root->SetUpdatedTree(false);
}
+}
+uint32_t UpdateManager::KeepUpdatingCheck(float elapsedSeconds) const
+{
uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
// If the rendering behavior is set to continuously render, then continue to render.
- // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
// Keep updating until no messages are received and no animations are running.
// If an animation has just finished, update at least once more for Discard end-actions.
// No need to check for renderQueue as there is always a render after update and if that
// render needs another update it will tell the adaptor to call update again
- if((mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY) ||
- (mImpl->keepRenderingSeconds > 0.0f))
+ if(mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY)
{
keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
}
void UpdateManager::KeepRendering(float durationSeconds)
{
- mImpl->keepRenderingSeconds = std::max(mImpl->keepRenderingSeconds, durationSeconds);
+ for(auto&& scene : mImpl->scenes)
+ {
+ if(scene->scene)
+ {
+ scene->scene->KeepRendering(durationSeconds);
+ }
+ }
}
void UpdateManager::SetRenderingBehavior(DevelStage::Rendering renderingBehavior)
mImpl->renderingRequired = true;
}
+Node* UpdateManager::GetNodePointerById(uint32_t nodeId) const
+{
+ Node* foundNodePointer = nullptr;
+ auto iter = mImpl->nodeIdMap.find(nodeId);
+ if(iter != mImpl->nodeIdMap.end())
+ {
+ foundNodePointer = iter->second;
+ }
+ return foundNodePointer;
+}
+
void UpdateManager::SetLayerDepths(const SortedLayerPointers& layers, const Layer* rootLayer)
{
for(auto&& scene : mImpl->scenes)
void UpdateManager::SetDepthIndices(OwnerPointer<NodeDepths>& nodeDepths)
{
- // note,this vector is already in depth order. It could be used as-is to
- // remove sorting in update algorithm. However, it lacks layer boundary markers.
- for(auto&& iter : nodeDepths->nodeDepths)
- {
- iter.node->SetDepthIndex(iter.sortedDepth);
- }
+ // note, this vector is already in depth order.
+ // So if we reverse iterate, we can assume that
+ // my descendant node's depth index are updated.
- for(auto&& scene : mImpl->scenes)
+ // And also, This API is the last flushed message.
+ // We can now setup the DESCENDENT_HIERARCHY_CHANGED flag here.
+ for(auto rIter = nodeDepths->nodeDepths.rbegin(), rEndIter = nodeDepths->nodeDepths.rend(); rIter != rEndIter; rIter++)
{
- if(scene)
+ auto* node = rIter->node;
+ node->PropagateDescendentFlags();
+ node->SetDepthIndex(rIter->sortedDepth);
+ if(node->IsChildrenReorderRequired())
{
- // Go through node hierarchy and rearrange siblings according to depth-index
- SortSiblingNodesRecursively(*scene->root);
+ // Reorder children container only if sibiling order changed.
+ NodeContainer& container = node->GetChildren();
+ std::sort(container.Begin(), container.End(), [](Node* a, Node* b) { return a->GetDepthIndex() < b->GetDepthIndex(); });
}
}
}
mImpl->GetFrameCallbackProcessor(*this).RemoveFrameCallback(frameCallback);
}
+void UpdateManager::NotifyFrameCallback(FrameCallbackInterface* frameCallback, Dali::UpdateProxy::NotifySyncPoint syncPoint)
+{
+ mImpl->GetFrameCallbackProcessor(*this).NotifyFrameCallback(frameCallback, syncPoint);
+}
+
void UpdateManager::AddSampler(OwnerPointer<Render::Sampler>& sampler)
{
// Message has ownership of Sampler while in transit from update to render
- using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::Sampler> >;
+ using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::Sampler>>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
void UpdateManager::AddVertexBuffer(OwnerPointer<Render::VertexBuffer>& vertexBuffer)
{
// Message has ownership of format while in transit from update -> render
- using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::VertexBuffer> >;
+ using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::VertexBuffer>>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
void UpdateManager::SetVertexBufferFormat(Render::VertexBuffer* vertexBuffer, OwnerPointer<Render::VertexBuffer::Format>& format)
{
// Message has ownership of format while in transit from update -> render
- using DerivedType = MessageValue2<RenderManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format> >;
+ using DerivedType = MessageValue2<RenderManager, Render::VertexBuffer*, OwnerPointer<Render::VertexBuffer::Format>>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetVertexBufferFormat, vertexBuffer, format);
}
-void UpdateManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t> >& data, uint32_t size)
+void UpdateManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size)
{
// Message has ownership of format while in transit from update -> render
- using DerivedType = MessageValue3<RenderManager, Render::VertexBuffer*, OwnerPointer<Dali::Vector<uint8_t> >, uint32_t>;
+ using DerivedType = MessageValue3<RenderManager, Render::VertexBuffer*, OwnerPointer<Dali::Vector<uint8_t>>, uint32_t>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetVertexBufferData, vertexBuffer, data, size);
}
+void UpdateManager::SetVertexBufferDivisor(Render::VertexBuffer* vertexBuffer, uint32_t divisor)
+{
+ using LocalType = MessageValue1<Render::VertexBuffer, uint32_t>;
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(LocalType));
+ new(slot) LocalType(vertexBuffer, &Render::VertexBuffer::SetDivisor, divisor);
+}
+
+void UpdateManager::SetVertexBufferUpdateCallback(Render::VertexBuffer* vertexBuffer, Dali::VertexBufferUpdateCallback* callback)
+{
+ // Message has ownership of format while in transit from update -> render
+ using DerivedType = MessageValue2<RenderManager, Render::VertexBuffer*, Dali::VertexBufferUpdateCallback*>;
+
+ // Reserve some memory inside the render queue
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetVertexBufferUpdateCallback, vertexBuffer, callback);
+}
+
void UpdateManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
{
// Message has ownership of format while in transit from update -> render
- using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::Geometry> >;
+ using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::Geometry>>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType);
}
-void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector<uint16_t>& indices)
+void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint16ContainerType& indices)
+{
+ using DerivedType = IndexBufferMessage<RenderManager, Render::Geometry::Uint16ContainerType>;
+
+ // Reserve some memory inside the render queue
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new(slot) DerivedType(&mImpl->renderManager, geometry, indices);
+}
+
+void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint32ContainerType& indices)
{
- using DerivedType = IndexBufferMessage<RenderManager>;
+ using DerivedType = IndexBufferMessage<RenderManager, Render::Geometry::Uint32ContainerType>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, vertexBuffer);
}
-void UpdateManager::AddTexture(OwnerPointer<Render::Texture>& texture)
+void UpdateManager::AddTexture(const Render::TextureKey& texture)
{
- // Message has ownership of Texture while in transit from update -> render
- using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::Texture> >;
+ using DerivedType = MessageValue1<RenderManager, Render::TextureKey>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::AddTexture, texture);
}
-void UpdateManager::RemoveTexture(Render::Texture* texture)
+void UpdateManager::RemoveTexture(const Render::TextureKey& texture)
{
- using DerivedType = MessageValue1<RenderManager, Render::Texture*>;
+ using DerivedType = MessageValue1<RenderManager, Render::TextureKey>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::RemoveTexture, texture);
}
-void UpdateManager::UploadTexture(Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params)
+void UpdateManager::UploadTexture(const Render::TextureKey& texture, PixelDataPtr pixelData, const Graphics::UploadParams& params)
{
- using DerivedType = MessageValue3<RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams>;
+ using DerivedType = MessageValue3<RenderManager, Render::TextureKey, PixelDataPtr, Graphics::UploadParams>;
// Reserve some memory inside the message queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params);
}
-void UpdateManager::GenerateMipmaps(Render::Texture* texture)
+void UpdateManager::GenerateMipmaps(const Render::TextureKey& texture)
{
- using DerivedType = MessageValue1<RenderManager, Render::Texture*>;
+ using DerivedType = MessageValue1<RenderManager, Render::TextureKey>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::GenerateMipmaps, texture);
}
+void UpdateManager::SetTextureSize(const Render::TextureKey& texture, const Dali::ImageDimensions& size)
+{
+ using DerivedType = MessageValue2<RenderManager, Render::TextureKey, Dali::ImageDimensions>;
+
+ // Reserve some memory inside the render queue
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetTextureSize, texture, size);
+}
+
+void UpdateManager::SetTextureFormat(const Render::TextureKey& texture, Dali::Pixel::Format pixelFormat)
+{
+ using DerivedType = MessageValue2<RenderManager, Render::TextureKey, Dali::Pixel::Format>;
+
+ // Reserve some memory inside the render queue
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetTextureFormat, texture, pixelFormat);
+}
+
void UpdateManager::AddFrameBuffer(OwnerPointer<Render::FrameBuffer>& frameBuffer)
{
- using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::FrameBuffer> >;
+ using DerivedType = MessageValue1<RenderManager, OwnerPointer<Render::FrameBuffer>>;
// Reserve some memory inside the render queue
uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::AttachDepthStencilTextureToFrameBuffer, frameBuffer, texture, mipmapLevel);
}
+void UpdateManager::SetMultiSamplingLevelToFrameBuffer(Render::FrameBuffer* frameBuffer, uint8_t multiSamplingLevel)
+{
+ using DerivedType = MessageValue2<RenderManager, Render::FrameBuffer*, uint8_t>;
+
+ // Reserve some memory inside the render queue
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType));
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetMultiSamplingLevelToFrameBuffer, frameBuffer, multiSamplingLevel);
+}
+
} // namespace SceneGraph
} // namespace Internal