Reducing message spam for baked properties
[platform/core/uifw/dali-core.git] / dali / internal / update / common / animatable-property-messages.h
index 57ce8d0..e18a3fd 100644 (file)
 
 namespace Dali::Internal
 {
-// Messages for AnimatableProperty<T>
 
-template<class T>
+/**
+ * Special message to first bake a property, then create a resetter for the
+ * property in the update thread to reduce load on event thread.
+ * @tparam T The type of the property
+ * @tparam P2 The type of the parameter to the second object method
+ */
+template<class T, typename P>
+class MessageBakeReset : public MessageBase
+{
+public:
+  using MemberFunction = void (T::*)(BufferIndex, typename ParameterType<P>::PassingType);
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] updateManager
+   * @param[in] propertyOwner The owner of the property
+   * @param[in] property The property to update
+   * @param[in] member The member function of the property object (bake/set)
+   * @param[in] p The value to update the property to
+   */
+  MessageBakeReset(SceneGraph::UpdateManager&             updateManager,
+                   const SceneGraph::PropertyOwner&       propertyOwner,
+                   const T*                               property,
+                   MemberFunction                         member,
+                   typename ParameterType<P>::PassingType p)
+  : MessageBase(),
+    mUpdateManager(updateManager),
+    mPropertyOwner(propertyOwner),
+    object(const_cast<T*>(property)),
+    memberFunction(member),
+    param(p)
+  {
+    DALI_ASSERT_DEBUG(property && "nullptr passed into message as property");
+  }
+
+  /**
+   * Virtual destructor
+   */
+  ~MessageBakeReset() override = default;
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  void Process(BufferIndex bufferIndex) override
+  {
+    // Bake/set the property
+    (object->*memberFunction)(bufferIndex, param);
+
+    // Create the resetter in the Update thread.
+    OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
+      new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&mPropertyOwner),
+                                    object,
+                                    SceneGraph::BakerResetter::Lifetime::BAKE));
+    mUpdateManager.AddPropertyResetter(resetter);
+  }
+
+private:
+  SceneGraph::UpdateManager&            mUpdateManager;
+  const SceneGraph::PropertyOwner&      mPropertyOwner;
+  T*                                    object;
+  MemberFunction                        memberFunction;
+  typename ParameterType<P>::HolderType param;
+};
+
+template<typename T>
 void BakeMessage(EventThreadServices&                     eventThreadServices,
                  const SceneGraph::PropertyOwner&         propertyOwner,
                  const SceneGraph::AnimatableProperty<T>& property,
                  typename ParameterType<T>::PassingType   newValue)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, T>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::Bake,
                       newValue);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 template<class T>
@@ -57,21 +118,17 @@ void BakeRelativeMessage(EventThreadServices&                     eventThreadSer
                          const SceneGraph::AnimatableProperty<T>& property,
                          const T&                                 delta)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, const T&>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::BakeRelative,
                       delta);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 template<class T>
@@ -80,21 +137,17 @@ void SetXComponentMessage(EventThreadServices&                       eventThread
                           const SceneGraph::AnimatableProperty<T>&   property,
                           typename ParameterType<float>::PassingType newValue)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, float>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, float>;
 
   // 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::BakeX,
                       newValue);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 template<class T>
@@ -103,21 +156,17 @@ void SetYComponentMessage(EventThreadServices&                       eventThread
                           const SceneGraph::AnimatableProperty<T>&   property,
                           typename ParameterType<float>::PassingType newValue)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, float>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, float>;
 
   // 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::BakeY,
                       newValue);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 template<class T>
@@ -126,21 +175,17 @@ void SetZComponentMessage(EventThreadServices&                       eventThread
                           const SceneGraph::AnimatableProperty<T>&   property,
                           typename ParameterType<float>::PassingType newValue)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, float>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, float>;
 
   // 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::BakeZ,
                       newValue);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 template<class T>
@@ -149,23 +194,19 @@ void SetWComponentMessage(EventThreadServices&                       eventThread
                           const SceneGraph::AnimatableProperty<T>&   property,
                           typename ParameterType<float>::PassingType newValue)
 {
-  using LocalType = MessageDoubleBuffered1<SceneGraph::AnimatableProperty<T>, float>;
+  using LocalType = MessageBakeReset<SceneGraph::AnimatableProperty<T>, float>;
 
   // 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(&property,
+  new(slot) LocalType(eventThreadServices.GetUpdateManager(),
+                      propertyOwner,
+                      &property,
                       &SceneGraph::AnimatableProperty<T>::BakeW,
                       newValue);
-
-  OwnerPointer<SceneGraph::PropertyResetterBase> resetter(
-    new SceneGraph::BakerResetter(const_cast<SceneGraph::PropertyOwner*>(&propertyOwner),
-                                  const_cast<SceneGraph::AnimatableProperty<T>*>(&property),
-                                  SceneGraph::BakerResetter::Lifetime::BAKE));
-  AddResetterMessage(eventThreadServices.GetUpdateManager(), resetter);
 }
 
 } // namespace Dali::Internal
 
-#endif //DALI_INTERNAL_COMMON_ANIMATABLE_PROPERTY_MESSAGES_H
+#endif // DALI_INTERNAL_COMMON_ANIMATABLE_PROPERTY_MESSAGES_H