Make dirtyrect use map container instead of vector
[platform/core/uifw/dali-core.git] / dali / internal / update / common / scene-graph-scene.h
index cca0106..d004f16 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_SCENE_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
  * limitations under the License.
  */
 
+// EXTERNAL INCLUDE
+#include <cstddef>
+#include <unordered_map>
+
 // INTERNAL INCLUDES
 #include <dali/graphics-api/graphics-controller.h>
 #include <dali/integration-api/core.h>
 #include <dali/internal/common/message.h>
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/internal/render/renderers/render-renderer.h> // RendererKey
 #include <dali/internal/update/nodes/scene-graph-layer.h>
 #include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/compile-time-math.h>
 
 namespace Dali
 {
 namespace Internal
 {
-namespace Render
-{
-class Renderer;
-}
-
 namespace SceneGraph
 {
 class RenderInstructionContainer;
 class Node;
 
-struct DirtyRect
+struct DirtyRectKey
 {
-  DirtyRect(Node* node, Render::Renderer* renderer, Rect<int>& rect)
+  DirtyRectKey(Node* node, Render::RendererKey renderer)
   : node(node),
-    renderer(renderer),
-    rect(rect),
-    visited(true)
+    renderer(renderer)
   {
   }
 
-  DirtyRect() = default;
+  DirtyRectKey() = default;
 
-  bool operator<(const DirtyRect& rhs) const
+  bool operator==(const DirtyRectKey& rhs) const
   {
-    if(node == rhs.node)
-    {
-      return renderer < rhs.renderer;
-    }
-    else
+    return node == rhs.node && renderer == rhs.renderer;
+  }
+
+  struct DirtyRectKeyHash
+  {
+    // Reference by : https://stackoverflow.com/a/21062236
+    std::size_t operator()(DirtyRectKey const& key) const noexcept
     {
-      return node < rhs.node;
+      constexpr std::size_t nodeShift     = Dali::Log<1 + sizeof(Node)>::value;
+      constexpr std::size_t rendererShift = Dali::Log<1 + sizeof(Render::Renderer)>::value;
+
+      constexpr std::size_t zitterShift = sizeof(std::size_t) * 4; // zitter shift to avoid hash collision
+
+      return ((reinterpret_cast<std::size_t>(key.node) >> nodeShift) << zitterShift) ^
+             (key.renderer.Value() >> rendererShift);
     }
+  };
+
+  Node*               node{nullptr};
+  Render::RendererKey renderer{};
+};
+
+struct DirtyRectValue
+{
+  DirtyRectValue(Rect<int>& rect)
+  : rect(rect),
+    visited(true)
+  {
   }
 
-  Node*             node{nullptr};
-  Render::Renderer* renderer{nullptr};
-  Rect<int32_t>     rect{};
-  bool              visited{true};
+  DirtyRectValue() = default;
+
+  Rect<int32_t> rect{};
+  bool          visited{true};
 };
 
 class Scene
 {
 public:
+  using ItemsDirtyRectsContainer = std::unordered_map<DirtyRectKey, DirtyRectValue, DirtyRectKey::DirtyRectKeyHash>;
+
   /**
    * Constructor
    * @param[in] surface The render surface
@@ -173,11 +194,12 @@ public:
   const Rect<int32_t>& GetSurfaceRect() const;
 
   /**
-   * Set the surface orientation when surface is rotated.
+   * Set the surface orientations when surface or screen is rotated.
    *
-   * @param[in] orientation The orientation value representing the surface.
+   * @param[in] windowOrientation The orientations value representing surface.
+   * @param[in] screenOrienation The orientations value representing screen.
    */
-  void SetSurfaceOrientation(int32_t orientation);
+  void SetSurfaceOrientations(int32_t windowOrientation, int32_t screenOrienation);
 
   /**
    * Get the surface orientation.
@@ -187,6 +209,13 @@ public:
   int32_t GetSurfaceOrientation() const;
 
   /**
+   * Get the screen orientation.
+   *
+   * @return the current screen orientation
+   */
+  int32_t GetScreenOrientation() const;
+
+  /**
    * Query wheter the surface rect is changed or not.
    * @return true if the surface rect is changed.
    */
@@ -272,7 +301,7 @@ public:
    *
    * @return the ItemsDirtyRects
    */
-  std::vector<DirtyRect>& GetItemsDirtyRects();
+  ItemsDirtyRectsContainer& GetItemsDirtyRects();
 
 private:
   // Render instructions describe what should be rendered during RenderManager::RenderScene()
@@ -289,7 +318,8 @@ private:
 
   Rect<int32_t> mSurfaceRect;                      ///< The rectangle of surface which is related ot this scene.
   int32_t       mSurfaceOrientation;               ///< The orientation of surface which is related of this scene
-  bool          mSurfaceRectChanged;               ///< The flag of surface's rectangle is changed when is resized, moved or rotated.
+  int32_t       mScreenOrientation;                ///< The orientation of screen
+  bool          mSurfaceRectChanged;               ///< The flag of surface's rectangle is changed when is resized or moved.
   bool          mRotationCompletedAcknowledgement; ///< The flag of sending the acknowledgement to complete window rotation.
 
   // Render pass and render target
@@ -307,8 +337,8 @@ private:
 
   SceneGraph::Layer* mRoot{nullptr}; ///< Root node
 
-  std::vector<Graphics::ClearValue>                  mClearValues{};     ///< Clear colors
-  std::vector<Dali::Internal::SceneGraph::DirtyRect> mItemsDirtyRects{}; ///< Dirty rect list
+  std::vector<Graphics::ClearValue> mClearValues{};     ///< Clear colors
+  ItemsDirtyRectsContainer          mItemsDirtyRects{}; ///< Dirty rect list
 };
 
 /// Messages
@@ -345,15 +375,15 @@ inline void SetSurfaceRectMessage(EventThreadServices& eventThreadServices, cons
   new(slot) LocalType(&scene, &Scene::SetSurfaceRect, rect);
 }
 
-inline void SetSurfaceOrientationMessage(EventThreadServices& eventThreadServices, const Scene& scene, int32_t orientation)
+inline void SetSurfaceOrientationsMessage(EventThreadServices& eventThreadServices, const Scene& scene, const int32_t windowOrientation, const int32_t screenOrientation)
 {
-  using LocalType = MessageValue1<Scene, int32_t>;
+  using LocalType = MessageValue2<Scene, int32_t, int32_t>;
 
   // 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(&scene, &Scene::SetSurfaceOrientation, orientation);
+  new(slot) LocalType(&scene, &Scene::SetSurfaceOrientations, windowOrientation, screenOrientation);
 }
 
 inline void SetRotationCompletedAcknowledgementMessage(EventThreadServices& eventThreadServices, const Scene& scene)