{
namespace Internal
{
+const uint32_t POOL_KEY_BLOCK_ID_MASK = 0xF8000000;
+const uint32_t POOL_KEY_BLOCK_ID_SHIFT = 27;
+const uint32_t POOL_KEY_INDEX_MASK = 0x07FFFFFF;
+
/**
* @brief Private implementation class
*/
}
}
+void* FixedSizeMemoryPool::GetPtrToObject(uint32_t key)
+{
+ uint32_t blockId = (key & POOL_KEY_BLOCK_ID_MASK) >> POOL_KEY_BLOCK_ID_SHIFT;
+ uint32_t index = key & POOL_KEY_INDEX_MASK;
+ auto* block = &mImpl->mMemoryBlocks;
+ while(block && blockId > 0)
+ {
+ block = block->nextBlock;
+ --blockId;
+ }
+ if(block != nullptr)
+ {
+ return static_cast<uint8_t*>(block->blockMemory) + mImpl->mFixedSize * index;
+ }
+ return nullptr;
+}
+
+uint32_t FixedSizeMemoryPool::GetIndexOfObject(void* ptr)
+{
+ uint32_t blockId = 0;
+ uint32_t index = 0;
+ auto* block = &mImpl->mMemoryBlocks;
+ bool found = false;
+
+ while(block)
+ {
+ const void* const endOfBlock = reinterpret_cast<char*>(block->blockMemory) + block->mBlockSize;
+ if(block->blockMemory <= ptr && ptr <= endOfBlock)
+ {
+ index = (static_cast<uint8_t*>(ptr) - static_cast<uint8_t*>(block->blockMemory)) / mImpl->mFixedSize;
+ found = true;
+ break;
+ }
+
+ block = block->nextBlock;
+ ++blockId;
+ }
+ if(found)
+ {
+ return blockId << POOL_KEY_BLOCK_ID_SHIFT | (index & POOL_KEY_INDEX_MASK);
+ }
+ return 0u;
+}
+
uint32_t FixedSizeMemoryPool::GetCapacity() const
{
// Ignores deleted objects list, just returns currently allocated size
return totalAllocation;
}
+/*
+ *
+ * Or, don't use index, create a key, which combines block id & offset in block...
+ * e.g. use top 5 bits for block id, lower 27 bits for offset. (can address 150m entries)
+ *
+ * FixedMemoryPool is a linked list, so still have to loop to find base block address.
+ * (Or cache in struct - Only need to cache 23 ptrs...)
+ *
+ *
+ * Algorithm to find index from address...
+ * Currently, we return a ptr from the allocation alg so that it can run a placement new...
+ * could store off the index in the allocated memory, so it can be retrieved before doing
+ * placement new...
+ */
+
} // namespace Internal
} // namespace Dali
*/
void FreeThreadSafe(void* memory);
+ void* GetPtrToObject(uint32_t key);
+
+ uint32_t GetIndexOfObject(void* ptr);
+
/**
* Get the current capacity of the memory pool
*
}
/**
+ * Get a pointer to the indexed item
+ * index must be valid.
+ */
+ T* GetPtrToObject(uint32_t index)
+ {
+ return static_cast<T*>(mPool->GetPtrToObject(index));
+ }
+
+ uint32_t GetIndexOfObject(T* object)
+ {
+ return mPool->GetIndexOfObject(object);
+ }
+
+ /**
* @brief Get the capacity of the memory pool
*/
uint32_t GetCapacity() const
DecoratedVisualRendererPtr DecoratedVisualRenderer::New()
{
// create scene object first so it's guaranteed to exist for the event side
- auto sceneObject = SceneGraph::Renderer::New();
+ auto sceneObjectIndex = SceneGraph::Renderer::NewKey();
auto animatableVisualProperties = new SceneGraph::VisualRenderer::AnimatableVisualProperties();
auto animatableDecoratedVisualProperties = new SceneGraph::VisualRenderer::AnimatableDecoratedVisualProperties();
animatableVisualProperties->mExtendedProperties = animatableDecoratedVisualProperties;
animatableVisualProperties->mExtendedPropertiesDeleteFunction = SceneGraph::VisualRenderer::AnimatableDecoratedVisualProperties::DeleteFunction;
+ auto sceneObject = SceneGraph::Renderer::Get(sceneObjectIndex);
sceneObject->SetVisualProperties(animatableVisualProperties);
- OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
// pass the pointer to base for message passing
DecoratedVisualRendererPtr rendererPtr(new DecoratedVisualRenderer(sceneObject));
rendererPtr->AddUniformMappings(); // Ensure properties are mapped to uniforms
- // transfer scene object ownership to update manager
EventThreadServices& eventThreadServices = rendererPtr->GetEventThreadServices();
SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
- AddRendererMessage(updateManager, transferOwnership);
+ AddRendererMessage(updateManager, sceneObjectIndex);
eventThreadServices.RegisterObject(rendererPtr.Get());
return rendererPtr;
RendererPtr Renderer::New()
{
// create scene object first so it's guaranteed to exist for the event side
- auto sceneObject = SceneGraph::Renderer::New();
- OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
+ auto sceneObjectKey = SceneGraph::Renderer::NewKey();
+
// pass the pointer to base for message passing
- RendererPtr rendererPtr(new Renderer(sceneObject));
- // transfer scene object ownership to update manager
+ RendererPtr rendererPtr(new Renderer(SceneGraph::Renderer::Get(sceneObjectKey)));
+
EventThreadServices& eventThreadServices = rendererPtr->GetEventThreadServices();
SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
- AddRendererMessage(updateManager, transferOwnership);
+ AddRendererMessage(updateManager, sceneObjectKey);
eventThreadServices.RegisterObject(rendererPtr.Get());
return rendererPtr;
{
EventThreadServices& eventThreadServices = GetEventThreadServices();
SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
- RemoveRendererMessage(updateManager, GetRendererSceneObject());
+ RemoveRendererMessage(updateManager, SceneGraph::Renderer::GetIndex(GetRendererSceneObject()));
eventThreadServices.UnregisterObject(this);
}
VisualRendererPtr VisualRenderer::New()
{
// create scene object first so it's guaranteed to exist for the event side
- auto sceneObject = SceneGraph::Renderer::New();
+ auto sceneObjectIndex = SceneGraph::Renderer::NewKey();
+ auto sceneObject = SceneGraph::Renderer::Get(sceneObjectIndex);
- sceneObject->SetVisualProperties(new SceneGraph::VisualRenderer::AnimatableVisualProperties());
+ sceneObjectKey->SetVisualProperties(new SceneGraph::VisualRenderer::AnimatableVisualProperties());
- OwnerPointer<SceneGraph::Renderer> transferOwnership(sceneObject);
// pass the pointer to base for message passing
VisualRendererPtr rendererPtr(new VisualRenderer(sceneObject));
// transfer scene object ownership to update manager
EventThreadServices& eventThreadServices = rendererPtr->GetEventThreadServices();
SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
- AddRendererMessage(updateManager, transferOwnership);
+ AddRendererMessage(updateManager, sceneObjectIndex);
eventThreadServices.RegisterObject(rendererPtr.Get());
return rendererPtr;
{
mDiscardQueue[updateBufferIndex].PushBack(object);
}
- void add(BufferIndex updateBufferIndex, Type object)
- {
- mDiscardQueue[updateBufferIndex].push_back(object);
- }
void Clear(BufferIndex updateBufferIndex)
{
mDiscardQueue[updateBufferIndex].Clear();
}
- void clear(BufferIndex updateBufferIndex)
- {
- mDiscardQueue[updateBufferIndex].clear();
- }
private:
TypeContainer mDiscardQueue[2];
--- /dev/null
+#ifndef DALI_INTERNAL_OWNER_KEY_CONTAINER_H
+#define DALI_INTERNAL_OWNER_KEY_CONTAINER_H
+
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali::Internal
+{
+/**
+ * OwnerKeyContainer is a vector which "owns" memory-pool allocated objects.
+ * Unlike vector this will call delete on the stored objects during destruction.
+ *
+ * @endcode
+ */
+template<class ObjectType>
+class OwnerKeyContainer : public Dali::Vector<uint32_t>
+{
+public:
+ using KeyType = uint32_t;
+ using SizeType = typename Dali::Vector<KeyType>::SizeType;
+ using Iterator = typename Vector<KeyType>::Iterator;
+ using ConstIterator = typename Vector<KeyType>::ConstIterator;
+
+ /**
+ * Create a pointer-container.
+ */
+ OwnerKeyContainer() = default;
+
+ /**
+ * Non-virtual destructor; OwnerKeyContainer<T> is not suitable as base class.
+ */
+ ~OwnerKeyContainer()
+ {
+ Clear();
+ VectorBase::Release();
+ }
+
+ // Not copyable or movable
+ OwnerKeyContainer(const OwnerKeyContainer&) = delete; ///< Deleted copy constructor
+ OwnerKeyContainer(OwnerKeyContainer&&) = delete; ///< Deleted move constructor
+ OwnerKeyContainer& operator=(const OwnerKeyContainer&) = delete; ///< Deleted copy assignment operator
+ OwnerKeyContainer& operator=(OwnerKeyContainer&&) = delete; ///< Deleted move assignment operator
+
+ /**
+ * Test whether the container is empty.
+ * @return True if the container is empty
+ */
+ bool IsEmpty() const
+ {
+ return VectorBase::Count() == 0u;
+ }
+
+ /**
+ * Erase an object from the container (delete from heap).
+ * @param[in] position A dereferencable iterator to an element in mContainer.
+ * @return iterator pointing to next element
+ */
+ Iterator Erase(Iterator position)
+ {
+ Delete(*position);
+ return Vector<KeyType>::Erase(position);
+ }
+
+ /**
+ * @brief Erases all elements that satisfy the predicate from the OwnerKeyContainer.
+ *
+ * @param[in] predicate The predicate
+ */
+ template<class Predicate>
+ void EraseIf(Predicate predicate)
+ {
+ auto begin = Vector<KeyType>::Begin();
+ auto end = Vector<KeyType>::End();
+
+ auto function = [predicate](auto& key) {
+ if(predicate(ObjectType::Get(key)))
+ {
+ delete ObjectType::Get(key);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ };
+
+ Vector<KeyType>::Erase(std::remove_if(begin, end, function), end);
+ }
+
+ /**
+ * Erases a range of elements.(delete from heap).
+ */
+ Iterator Erase(Iterator first, Iterator last)
+ {
+ auto itr = first;
+ while(itr < last)
+ {
+ Delete(*itr);
+ ++itr;
+ }
+
+ return Vector<KeyType>::Erase(first, last);
+ }
+
+ /**
+ * Erase an object from OwnerKeyContainer
+ * @param object to remove
+ */
+ inline void EraseObject(ObjectType* object)
+ {
+ DALI_ASSERT_DEBUG(object && "NULL object not allowed");
+
+ KeyType key = ObjectType::GetIndex(object);
+
+ Iterator iter = Vector<KeyType>::Begin();
+ const ConstIterator endIter = Vector<KeyType>::End();
+ for(; iter != endIter; ++iter)
+ {
+ if(*iter == key)
+ {
+ Erase(iter);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Release the ownership of an object, without deleting it.
+ * @param[in] position A dereferencable iterator to an element in mContainer.
+ * @post iterators are invalidated by this method.
+ * @return pointer to the released item
+ */
+ KeyType Release(Iterator position)
+ {
+ KeyType key = *position;
+ Vector<KeyType>::Erase(position);
+ return key;
+ }
+
+ /**
+ * Destroy all of the elements in the container.
+ */
+ void Clear()
+ {
+ ConstIterator end = Vector<KeyType>::End();
+ for(Iterator iter = Vector<KeyType>::Begin(); iter != end; ++iter)
+ {
+ Delete(*iter);
+ }
+ Vector<KeyType>::Clear();
+ }
+
+ /**
+ * Resizes the container to hold specific amount of elements
+ * @param size to resize to
+ */
+ void Resize(SizeType size)
+ {
+ if(size < VectorBase::Count())
+ {
+ // OwnerKeyContainer owns these heap-allocated objects
+ ConstIterator end = Vector<KeyType>::End();
+ for(Iterator iter = Vector<KeyType>::Begin() + size; iter != end; ++iter)
+ {
+ Delete(*iter);
+ }
+ }
+ Vector<KeyType>::Resize(size);
+ }
+
+ /**
+ * Move the ownership of objects from another OwnerKeyContainer to this one
+ * without deleting them. It will keep the original items here as well.
+ * @param[in] source where to move elements from to this OwnerKeyContainer
+ */
+ void MoveFrom(OwnerKeyContainer& source)
+ {
+ typename Vector<KeyType>::SizeType sourceCount = source.Count();
+ // if source is empty, nothing to move
+ if(sourceCount > 0u)
+ {
+ // Optimisation for the case that this is empty
+ if(IsEmpty())
+ {
+ VectorBase::Swap(source);
+ }
+ else
+ {
+ // make space for new items
+ Vector<KeyType>::Reserve(VectorBase::Count() + sourceCount);
+ Iterator iter = source.Begin();
+ ConstIterator end = source.End();
+ for(; iter != end; ++iter)
+ {
+ KeyType key = *iter;
+ Vector<KeyType>::PushBack(key);
+ }
+ // cannot call Clear on OwnerKeyContainer as that deletes the elements
+ source.Vector<KeyType>::Clear();
+ }
+ }
+ }
+
+private:
+ /**
+ * @brief delete the contents of the pointer
+ * Function provided to allow classes to provide a custom destructor through template specialisation
+ * @param pointer to the object
+ */
+ void Delete(KeyType key)
+ {
+ delete ObjectType::Get(key);
+ }
+};
+
+} // namespace Dali::Internal
+
+#endif //DALI_INTERNAL_OWNER_KEY_CONTAINER_H
RenderableContainer& target = DALI_LIKELY(inheritedDrawMode == DrawMode::NORMAL) ? layer->colorRenderables : layer->overlayRenderables;
for(uint32_t i = 0; i < count; ++i)
{
- SceneGraph::Renderer* renderer = node.GetRendererAt(i);
- target.PushBack(Renderable(&node, renderer));
+ SceneGraph::RendererIndex rendererIndex = node.GetRendererAt(i);
+ SceneGraph::Renderer* renderer = Renderer::Get(rendererIndex);
+ target.PushBack(Renderable(&node, renderer));
keepRendering = keepRendering || (renderer->GetRenderingBehavior() == DevelRenderer::Rendering::CONTINUOUSLY);
}
const uint32_t count = node.GetRendererCount();
for(uint32_t i = 0; i < count; ++i)
{
- SceneGraph::Renderer* renderer = node.GetRendererAt(i);
+ auto rendererIndex = node.GetRendererAt(i);
+ Renderer* renderer = Renderer::Get(rendererIndex);
if(renderer->IsDirty())
{
layer->SetReuseRenderers(updateBufferIndex, false);
#include <dali/internal/update/controllers/render-message-dispatcher.h>
#include <dali/internal/update/controllers/scene-controller-impl.h>
#include <dali/internal/update/manager/frame-callback-processor.h>
+#include <dali/internal/update/manager/owner-key-container.h>
#include <dali/internal/update/manager/render-task-processor.h>
#include <dali/internal/update/manager/transform-manager.h>
#include <dali/internal/update/manager/update-algorithms.h>
}
/**
+ * 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
+ */
+template<class Type>
+inline void EraseUsingDiscardQueue(OwnerKeyContainer<Type>& container, Type* object, DiscardQueue<uint32_t, OwnerKeyContainer<Type>>& discardQueue, BufferIndex updateBufferIndex)
+{
+ DALI_ASSERT_DEBUG(object && "NULL object not allowed");
+
+ auto key = Type::GetIndex(object);
+
+ for(auto iter = container.begin(), end = container.end(); iter != end; ++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
+ }
+ }
+}
+
+/**
* 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
*/
OwnerContainer<NodeResetter*> nodeResetters; ///< A container of node 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
+ 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
- DiscardQueue<Node*, OwnerContainer<Node*>> nodeDiscardQueue; ///< Nodes are added here when disconnected from the scene-graph.
- DiscardQueue<Shader*, OwnerContainer<Shader*>> shaderDiscardQueue;
- DiscardQueue<Renderer*, OwnerContainer<Renderer*>> rendererDiscardQueue;
- DiscardQueue<Scene*, OwnerContainer<Scene*>> sceneDiscardQueue;
+ DiscardQueue<Node*, OwnerContainer<Node*>> nodeDiscardQueue; ///< Nodes are added here when disconnected from the scene-graph.
+ DiscardQueue<Shader*, OwnerContainer<Shader*>> shaderDiscardQueue;
+ DiscardQueue<uint32_t, OwnerKeyContainer<Renderer>> rendererDiscardQueue;
+ DiscardQueue<Scene*, OwnerContainer<Scene*>> sceneDiscardQueue;
OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
mImpl->shaderSaver = &upstream;
}
-void UpdateManager::AddRenderer(OwnerPointer<Renderer>& renderer)
+void UpdateManager::AddRenderer(RendererIndex rendererKey)
{
- DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get());
+ SceneGraph::Renderer* renderer = SceneGraph::Renderer::Get(rendererKey);
+
+ DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer);
renderer->ConnectToSceneGraph(*mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex());
- mImpl->renderers.PushBack(renderer.Release());
+ mImpl->renderers.PushBack(rendererKey);
}
-void UpdateManager::RemoveRenderer(Renderer* renderer)
+void UpdateManager::RemoveRenderer(RendererIndex rendererKey)
{
+ SceneGraph::Renderer* renderer = SceneGraph::Renderer::Get(rendererKey);
DALI_LOG_INFO(gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer);
// Find the renderer and destroy it
void UpdateManager::AttachRenderer(Node* node, Renderer* renderer)
{
- node->AddRenderer(renderer);
+ node->AddRenderer(Renderer::GetIndex(renderer));
mImpl->renderersAdded = true;
}
void UpdateManager::UpdateRenderers(BufferIndex bufferIndex)
{
- for(auto&& renderer : mImpl->renderers)
+ for(auto rendererKey : mImpl->renderers)
{
// Apply constraints
+ auto renderer = Renderer::Get(rendererKey);
ConstrainPropertyOwner(*renderer, bufferIndex);
mImpl->renderingRequired = renderer->PrepareRender(bufferIndex) || mImpl->renderingRequired;
void UpdateManager::PostRender()
{
// Reset dirty flag
- for(auto&& renderer : mImpl->renderers)
+ for(auto&& rendererIndex : mImpl->renderers)
{
+ Renderer* renderer = Renderer::Get(rendererIndex);
renderer->ResetDirtyFlag();
}
* Add a new renderer to scene
* @param renderer to add
*/
- void AddRenderer(OwnerPointer<Renderer>& renderer);
+ void AddRenderer(RendererIndex renderer);
/**
* Add a renderer from scene
* @param renderer to remove
*/
- void RemoveRenderer(Renderer* renderer);
+ void RemoveRenderer(RendererIndex renderer);
/**
* Attach a renderer to node
new(slot) LocalType(&manager, &UpdateManager::SetLayerDepths, layers, rootLayer);
}
-inline void AddRendererMessage(UpdateManager& manager, OwnerPointer<Renderer>& object)
+inline void AddRendererMessage(UpdateManager& manager, RendererIndex rendererIndex)
{
- using LocalType = MessageValue1<UpdateManager, OwnerPointer<Renderer>>;
+ using LocalType = MessageValue1<UpdateManager, RendererIndex>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
// Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&manager, &UpdateManager::AddRenderer, object);
+ new(slot) LocalType(&manager, &UpdateManager::AddRenderer, rendererIndex);
}
-inline void RemoveRendererMessage(UpdateManager& manager, const Renderer& object)
+inline void RemoveRendererMessage(UpdateManager& manager, RendererIndex rendererIndex)
{
- using LocalType = MessageValue1<UpdateManager, Renderer*>;
+ using LocalType = MessageValue1<UpdateManager, RendererIndex>;
// Reserve some memory inside the message queue
uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
// Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&manager, &UpdateManager::RemoveRenderer, const_cast<Renderer*>(&object));
+ new(slot) LocalType(&manager, &UpdateManager::RemoveRenderer, rendererIndex);
}
inline void AttachRendererMessage(UpdateManager& manager, const Node& node, const Renderer& renderer)
found->RecursiveDisconnectFromSceneGraph(updateBufferIndex);
}
-void Node::AddRenderer(Renderer* renderer)
+void Node::AddRenderer(RendererIndex renderer)
{
// If it is the first renderer added, make sure the world transform will be calculated
// in the next update as world transform is not computed if node has no renderers.
- if(mRenderer.Empty())
+ if(mRenderers.Empty())
{
mDirtyFlags |= NodePropertyFlags::TRANSFORM;
}
else
{
// Check that it has not been already added.
- for(auto&& existingRenderer : mRenderer)
+ for(auto&& existingRenderer : mRenderers)
{
if(existingRenderer == renderer)
{
SetUpdated(true);
- mRenderer.PushBack(renderer);
+ mRenderers.PushBack(renderer);
}
-void Node::RemoveRenderer(const Renderer* renderer)
+void Node::RemoveRenderer(const RendererIndex renderer)
{
- RendererContainer::SizeType rendererCount(mRenderer.Size());
+ RendererContainer::SizeType rendererCount(mRenderers.Size());
for(RendererContainer::SizeType i = 0; i < rendererCount; ++i)
{
- if(mRenderer[i] == renderer)
+ if(mRenderers[i] == renderer)
{
SetUpdated(true);
- mRenderer.Erase(mRenderer.Begin() + i);
+ mRenderers.Erase(mRenderers.Begin() + i);
return;
}
}
* Add a renderer to the node
* @param[in] renderer The renderer added to the node
*/
- void AddRenderer(Renderer* renderer);
+ void AddRenderer(RendererIndex renderer);
/**
* Remove a renderer from the node
* @param[in] renderer The renderer to be removed
*/
- void RemoveRenderer(const Renderer* renderer);
+ void RemoveRenderer(const RendererIndex renderer);
/*
* Get the renderer at the given index
* @param[in] index
*/
- Renderer* GetRendererAt(uint32_t index) const
+ RendererIndex GetRendererAt(uint32_t index) const
{
- return mRenderer[index];
+ return mRenderers[index];
}
/**
*/
uint32_t GetRendererCount() const
{
- return static_cast<uint32_t>(mRenderer.Size());
+ return static_cast<uint32_t>(mRenderers.Size());
}
// Containment methods
Node* mParent; ///< Pointer to parent node (a child is owned by its parent)
RenderTask* mExclusiveRenderTask; ///< Nodes can be marked as exclusive to a single RenderTask
- RendererContainer mRenderer; ///< Container of renderers; not owned
+ RendererContainer mRenderers; ///< Container of renderers; not owned
NodeContainer mChildren; ///< Container of children; not owned
inline void DetachRendererMessage(EventThreadServices& eventThreadServices, const Node& node, const Renderer& renderer)
{
- using LocalType = MessageValue1<Node, const Renderer*>;
+ using LocalType = MessageValue1<Node, RendererIndex>;
// Reserve some memory inside the message queue
uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
// Construct message in the message queue memory; note that delete should not be called on the return value
- new(slot) LocalType(&node, &Node::RemoveRenderer, &renderer);
+ new(slot) LocalType(&node, &Node::RemoveRenderer, Renderer::GetIndex(renderer));
}
inline void SetDepthIndexMessage(EventThreadServices& eventThreadServices, const Node& node, uint32_t depthIndex)
return new(gRendererMemoryPool.AllocateRawThreadSafe()) Renderer();
}
+// Becomes
+
+RendererIndex Renderer::NewKey()
+{
+ void* ptr = gRendererMemoryPool.AllocateRawThreadSafe();
+ auto key = gRendererMemoryPool.GetIndexOfObject(static_cast<Renderer*>(ptr));
+ new(ptr) Renderer();
+ return key;
+}
+
Renderer::Renderer()
: mSceneController(nullptr),
mRenderer(nullptr),
gRendererMemoryPool.FreeThreadSafe(static_cast<Renderer*>(ptr));
}
+Renderer* Renderer::Get(RendererIndex rendererIndex)
+{
+ return gRendererMemoryPool.GetPtrToObject(rendererIndex);
+}
+
+RendererIndex Renderer::GetIndex(const Renderer& renderer)
+{
+ return gRendererMemoryPool.GetIndexOfObject(const_cast<Renderer*>(&renderer));
+}
+
+RendererIndex Renderer::GetIndex(Renderer* renderer)
+{
+ return gRendererMemoryPool.GetIndexOfObject(renderer);
+}
+
bool Renderer::PrepareRender(BufferIndex updateBufferIndex)
{
bool rendererUpdated = mResendFlag || mRenderingBehavior == DevelRenderer::Rendering::CONTINUOUSLY || mUpdateDecay > 0;
class SceneController;
class Renderer;
-using RendererContainer = Dali::Vector<Renderer*>;
+using RendererIndex = uint32_t;
+using RendererContainer = Dali::Vector<RendererIndex>;
using RendererIter = RendererContainer::Iterator;
using RendererConstIter = RendererContainer::ConstIterator;
*/
static Renderer* New();
+ static RendererIndex NewKey();
+
/**
* Destructor
*/
void operator delete(void* ptr);
/**
+ * Get pointer to a renderer at the given index.
+ * @param[in] rendererIndex Index of renderer to retrieve object
+ * @return The object's address, or nullptr if not found
+ */
+ static Renderer* Get(RendererIndex rendererIndex);
+
+ static RendererIndex GetIndex(const Renderer& renderer);
+ static RendererIndex GetIndex(Renderer* renderer);
+
+ /**
* Set the texture set for the renderer
* @param[in] textureSet The texture set this renderer will use
*/