Changed handling of uniforms of arrays of structs
[platform/core/uifw/dali-core.git] / dali / internal / update / common / uniform-map.h
index 1fb6e43..0a505de 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_H
 
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
  * limitations under the License.
  */
 
+// EXTERNAL INCLUDES
+#include <cstdint> // uint32_t
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/hash.h>
+#include <dali/devel-api/common/owner-container.h>
+#include <dali/internal/common/const-string.h>
+
 namespace Dali
 {
 namespace Internal
 {
+class PropertyInputImpl;
+
 namespace SceneGraph
 {
+/**
+ * The uniform map is used to map a uniform name to a property value.
+ */
+class UniformPropertyMapping
+{
+public:
+  using Hash = unsigned long;
+
+  /**
+   * Constructor
+   */
+  UniformPropertyMapping(ConstString theUniformName, const PropertyInputImpl* thePropertyPtr)
+  : propertyPtr(thePropertyPtr),
+    uniformName(theUniformName),
+    uniformNameHash(0u),
+    uniformNameHashNoArray(0u),
+    arrayIndex(0u)
+  {
+    // Look for array index closing bracket
+    auto nameStringView = theUniformName.GetStringView();
+    auto pos            = nameStringView.rfind("]");
+
+    // If found, extract the array index and store it, if it's an element in an array of basic types.
+    if(pos != std::string::npos)
+    {
+      auto pos0 = theUniformName.GetStringView().rfind("[", pos);
+      if(pos == nameStringView.length() - 1) // if element is in struct, don't set array index.
+      {
+        arrayIndex = atoi(theUniformName.GetCString() + pos0 + 1);
+      }
+      // Calculate hash from name without array index
+      uniformNameHashNoArray = Dali::CalculateHash(theUniformName.GetStringView().substr(0, pos0).data(), '[');
+    }
+    uniformName     = theUniformName;
+    uniformNameHash = Dali::CalculateHash(theUniformName.GetCString());
+  }
+
+  UniformPropertyMapping() = default;
+
+  const PropertyInputImpl* propertyPtr{nullptr};
+  ConstString              uniformName{};
+  Hash                     uniformNameHash{0u};
+  Hash                     uniformNameHashNoArray{0u};
+  int32_t                  arrayIndex{0u};
+};
 
 /**
- * The uniform map is generated on stage change, e.g when renderers, materials, geometry,
- * actors etc are added/removed from the stage.
+ * The UniformMap class is used to map uniform names to property values. It is available
+ * in all of the classes responsible for rendering:
+ * Actor, Renderer, Geometry, TextureSet, Shader.
  *
- * It computes a list of uniform strings to property value addresses that is needed
- * for the Renderer to match once against Program uniforms; subsequent render calls do
- * not need to re-generate the match, instead using the uniform index.
+ * It can be observed for changes to the mapping table.
  */
 class UniformMap
 {
 public:
+  using SizeType = uint32_t;
+
+  class Observer
+  {
+  public:
+    /**
+     * Inform observer that uniform mappings have been changed
+     * @param mappings
+     */
+    virtual void UniformMappingsChanged(const UniformMap& mappings) = 0;
+
+  protected:
+    /**
+     * Virtual destructor, no deletion through this interface
+     */
+    virtual ~Observer() = default;
+  };
+
   /**
-   * Constructor
+   * Add an observer that watches for changes in the mappings
+   */
+  void AddObserver(Observer& observer);
+
+  /**
+   * Remove an observer
+   */
+  void RemoveObserver(Observer& observer);
+
+  /**
+   * Add a map to the mappings table.
+   */
+  void Add(UniformPropertyMapping map);
+
+  /**
+   * Remove a map from the mappings table
+   */
+  void Remove(ConstString uniformName);
+
+  /**
+   * Find a property given the uniform name.
+   * @return The address of the property if it's in the map, or NULL otherwise.
+   */
+  const PropertyInputImpl* Find(ConstString uniformName);
+
+  /**
+   * Get the count of uniforms in the map
+   * @return The number of uniform mappings
+   */
+  SizeType Count() const;
+
+  /**
+   * @pre index must be in the range 0 :: Count()-1
+   * @param[in] index The index of the element to fetch
+   * @return reference to the element in the map
    */
-  UniformMap();
+  const UniformPropertyMapping& operator[](SizeType index) const;
 
+private:
   /**
-   * Destructor
+   * Helper to call the observers when the mappings have changed
    */
-  ~UniformMap();
+  void MappingChanged();
 
 private:
-  // data
+  using UniformMapContainer = Dali::Vector<UniformPropertyMapping>;
+  using UniformMapIter      = UniformMapContainer::Iterator;
+  using Observers           = Dali::Vector<Observer*>;
+  using ObserversIter       = Observers::Iterator;
+
+  UniformMapContainer mUniformMaps; // Owner container of uniform maps
+
+  Observers mObservers;
 };
 
 } // namespace SceneGraph