Convert Renderer ptrs to 32 bit keys 69/284269/10
authorDavid Steele <david.steele@samsung.com>
Fri, 21 Oct 2022 11:10:35 +0000 (12:10 +0100)
committerDavid Steele <david.steele@samsung.com>
Tue, 17 Jan 2023 16:30:00 +0000 (16:30 +0000)
Change-Id: I9ac5971cd768da552c188909771a12b437e11435

16 files changed:
dali/internal/common/fixed-size-memory-pool.cpp
dali/internal/common/fixed-size-memory-pool.h
dali/internal/common/memory-pool-object-allocator.h
dali/internal/event/rendering/decorated-visual-renderer-impl.cpp
dali/internal/event/rendering/renderer-impl.cpp
dali/internal/event/rendering/visual-renderer-impl.cpp
dali/internal/update/common/discard-queue.h
dali/internal/update/manager/owner-key-container.h [new file with mode: 0644]
dali/internal/update/manager/render-task-processor.cpp
dali/internal/update/manager/update-algorithms.cpp
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/nodes/node.cpp
dali/internal/update/nodes/node.h
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h

index f225a8d..6c7a7b1 100644 (file)
@@ -26,6 +26,10 @@ namespace Dali
 {
 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
  */
@@ -231,6 +235,50 @@ void FixedSizeMemoryPool::FreeThreadSafe(void* memory)
   }
 }
 
+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
@@ -247,6 +295,21 @@ uint32_t FixedSizeMemoryPool::GetCapacity() const
   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
index 6e05ffe..01620ea 100644 (file)
@@ -97,6 +97,10 @@ public:
    */
   void FreeThreadSafe(void* memory);
 
+  void* GetPtrToObject(uint32_t key);
+
+  uint32_t GetIndexOfObject(void* ptr);
+  
   /**
    * Get the current capacity of the memory pool
    *
index 554ce9a..ebc14fc 100644 (file)
@@ -155,6 +155,20 @@ public:
   }
 
   /**
+   * 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
index b6fc151..85f6a55 100644 (file)
@@ -74,7 +74,7 @@ void SetValue(EventThreadServices& eventThreadServices, const Property::Value& p
 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();
@@ -83,18 +83,17 @@ DecoratedVisualRendererPtr DecoratedVisualRenderer::New()
   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;
index ca336e1..3040904 100644 (file)
@@ -194,14 +194,14 @@ TypeRegistration mType(typeid(Dali::Renderer), typeid(Dali::Handle), Create, Ren
 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;
@@ -805,7 +805,7 @@ Renderer::~Renderer()
   {
     EventThreadServices&       eventThreadServices = GetEventThreadServices();
     SceneGraph::UpdateManager& updateManager       = eventThreadServices.GetUpdateManager();
-    RemoveRendererMessage(updateManager, GetRendererSceneObject());
+    RemoveRendererMessage(updateManager, SceneGraph::Renderer::GetIndex(GetRendererSceneObject()));
 
     eventThreadServices.UnregisterObject(this);
   }
index a359d81..989d949 100644 (file)
@@ -66,11 +66,11 @@ TypeRegistration mType(typeid(Dali::VisualRenderer), typeid(Dali::Renderer), Cre
 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));
 
@@ -79,7 +79,7 @@ VisualRendererPtr VisualRenderer::New()
   // 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;
index e02a843..fcdee43 100644 (file)
@@ -37,18 +37,10 @@ public:
   {
     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];
diff --git a/dali/internal/update/manager/owner-key-container.h b/dali/internal/update/manager/owner-key-container.h
new file mode 100644 (file)
index 0000000..fddeb64
--- /dev/null
@@ -0,0 +1,236 @@
+#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
index 0da46fc..6b6d25b 100644 (file)
@@ -174,9 +174,10 @@ bool AddRenderablesForTask(BufferIndex updateBufferIndex,
   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);
   }
 
index 7cd6ac6..8aa5cd6 100644 (file)
@@ -217,7 +217,8 @@ inline void UpdateLayers(Node&             node,
     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);
index d181771..2031536 100644 (file)
@@ -30,6 +30,7 @@
 #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>
@@ -106,6 +107,31 @@ inline void EraseUsingDiscardQueue(OwnerContainer<Type*>& container, Type* objec
 }
 
 /**
+ * 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
  */
@@ -274,14 +300,14 @@ struct UpdateManager::Impl
   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
 
@@ -645,16 +671,19 @@ void UpdateManager::SetShaderSaver(ShaderSaver& upstream)
   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
@@ -665,7 +694,7 @@ void UpdateManager::RemoveRenderer(Renderer* renderer)
 
 void UpdateManager::AttachRenderer(Node* node, Renderer* renderer)
 {
-  node->AddRenderer(renderer);
+  node->AddRenderer(Renderer::GetIndex(renderer));
   mImpl->renderersAdded = true;
 }
 
@@ -904,9 +933,10 @@ void UpdateManager::ForwardCompiledShadersToEventThread()
 
 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;
@@ -1164,8 +1194,9 @@ uint32_t UpdateManager::Update(float    elapsedSeconds,
 void UpdateManager::PostRender()
 {
   // Reset dirty flag
-  for(auto&& renderer : mImpl->renderers)
+  for(auto&& rendererIndex : mImpl->renderers)
   {
+    Renderer* renderer = Renderer::Get(rendererIndex);
     renderer->ResetDirtyFlag();
   }
 
index a0714bc..677ea55 100644 (file)
@@ -320,13 +320,13 @@ public:
    * 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
@@ -1104,24 +1104,24 @@ inline void SetLayerDepthsMessage(UpdateManager& manager, const std::vector<Laye
   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)
index 87b4603..3936269 100644 (file)
@@ -199,18 +199,18 @@ void Node::DisconnectChild(BufferIndex updateBufferIndex, Node& childNode)
   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)
       {
@@ -222,18 +222,18 @@ void Node::AddRenderer(Renderer* 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;
     }
   }
index c11c430..d0fb785 100644 (file)
@@ -228,21 +228,21 @@ public:
    * 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];
   }
 
   /**
@@ -250,7 +250,7 @@ public:
    */
   uint32_t GetRendererCount() const
   {
-    return static_cast<uint32_t>(mRenderer.Size());
+    return static_cast<uint32_t>(mRenderers.Size());
   }
 
   // Containment methods
@@ -988,7 +988,7 @@ protected:
   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
 
@@ -1103,13 +1103,13 @@ inline void SetTransparentMessage(EventThreadServices& eventThreadServices, cons
 
 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)
index 8c0d502..0c33062 100644 (file)
@@ -83,6 +83,16 @@ Renderer* Renderer::New()
   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),
@@ -119,6 +129,21 @@ void Renderer::operator delete(void* ptr)
   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;
index 49cd12b..93bfeb0 100644 (file)
@@ -44,7 +44,8 @@ namespace SceneGraph
 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;
 
@@ -155,6 +156,8 @@ public:
    */
   static Renderer* New();
 
+  static RendererIndex NewKey();
+
   /**
    * Destructor
    */
@@ -167,6 +170,16 @@ public:
   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
    */