[NUI] Add property NotifyAfterRasterization + Fix EnableFrameCache works well
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 9 Apr 2024 00:55:29 +0000 (09:55 +0900)
committerbshsqa <32317749+bshsqa@users.noreply.github.com>
Mon, 13 May 2024 07:08:49 +0000 (16:08 +0900)
Let we add some flag that notify to event/main thread every frames when
given lottie image rasterize finished.

Until before, there was no way to notify render thread that lottie surface
updated. So we make render thread always make rendered if lottie image used.

But sometimes, if some application want to render 30fps or less frame rate
lottie image, 60fps rendering is not a neccessary behavior.

To give them a choice, we give the property, `NotifyAfterRasterization`.

If we set this flag, some 30fps lottie file will awake render thread every 30fps.

Instead, the awake message might give overhead. So if lottie file is 60fps, we'd better set this flag as false.

Below dali patch required:

* https://review.tizen.org/gerrit/c/platform/core/uifw/dali-adaptor/+/309120
* https://review.tizen.org/gerrit/c/platform/core/uifw/dali-toolkit/+/309127
* https://review.tizen.org/gerrit/c/platform/core/uifw/dali-extension/+/309128

Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
src/Tizen.NUI/src/public/BaseComponents/LottieAnimationView.cs
src/Tizen.NUI/src/public/BaseComponents/LottieAnimationViewBindableProperty.cs
src/Tizen.NUI/src/public/Visuals/VisualConstants.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/LottieAnimationTest.cs

index 88a5ddcf325a37da1b4b68297a45f67fcc9d38a7..2c8a788ab49ad124157a78fce4ec3f04684f632f 100755 (executable)
@@ -44,10 +44,12 @@ namespace Tizen.NUI.BaseComponents
                 LoopCountProperty = BindableProperty.Create(nameof(LoopCount), typeof(int), typeof(Tizen.NUI.BaseComponents.LottieAnimationView), 0, propertyChanged: SetInternalLoopCountProperty, defaultValueCreator: GetInternalLoopCountProperty);
 
                 StopBehaviorProperty = BindableProperty.Create(nameof(StopBehavior), typeof(StopBehaviorType), typeof(LottieAnimationView), default(StopBehaviorType), propertyChanged: SetInternalStopBehaviorProperty, defaultValueCreator: GetInternalStopBehaviorProperty);
-                        
+
                 RedrawInScalingDownProperty = BindableProperty.Create(nameof(RedrawInScalingDown), typeof(bool), typeof(Tizen.NUI.BaseComponents.LottieAnimationView), false, propertyChanged: SetInternalRedrawInScalingDownProperty, defaultValueCreator: GetInternalRedrawInScalingDownProperty);
 
                 EnableFrameCacheProperty = BindableProperty.Create(nameof(EnableFrameCache), typeof(bool), typeof(Tizen.NUI.BaseComponents.LottieAnimationView), false, propertyChanged: SetInternalEnableFrameCacheProperty, defaultValueCreator: GetInternalEnableFrameCacheProperty);
+
+                NotifyAfterRasterizationProperty = BindableProperty.Create(nameof(NotifyAfterRasterization), typeof(bool), typeof(Tizen.NUI.BaseComponents.LottieAnimationView), false, propertyChanged: SetInternalNotifyAfterRasterizationProperty, defaultValueCreator: GetInternalNotifyAfterRasterizationProperty);
             }
         }
 
@@ -83,6 +85,8 @@ namespace Tizen.NUI.BaseComponents
             currentStates.desiredWidth = 0;
             currentStates.desiredHeight = 0;
             currentStates.synchronousLoading = true;
+            currentStates.enableFrameCache = false;
+            currentStates.notifyAfterRasterization = false;
 
             // Notify to base ImageView cache that default synchronousLoading for lottie file is true.
             base.SynchronousLoading = currentStates.synchronousLoading;
@@ -195,7 +199,6 @@ namespace Tizen.NUI.BaseComponents
                 currentStates.framePlayRangeMin = -1;
                 currentStates.framePlayRangeMax = -1;
                 currentStates.totalFrame = -1;
-                currentStates.enableFrameCache = false;
 
                 string ret = (value == null ? "" : value);
                 currentStates.url = ret;
@@ -211,6 +214,8 @@ namespace Tizen.NUI.BaseComponents
                 using PropertyValue loopMode = new PropertyValue((int)currentStates.loopMode);
                 using PropertyValue redrawInScalingDown = new PropertyValue(currentStates.redrawInScalingDown);
                 using PropertyValue synchronousLoading = new PropertyValue(currentStates.synchronousLoading);
+                using PropertyValue enableFrameCache = new PropertyValue(currentStates.enableFrameCache);
+                using PropertyValue notifyAfterRasterization = new PropertyValue(currentStates.notifyAfterRasterization);
 
                 map.Add(Visual.Property.Type, type)
                     .Add(ImageVisualProperty.URL, url)
@@ -218,7 +223,9 @@ namespace Tizen.NUI.BaseComponents
                     .Add(ImageVisualProperty.StopBehavior, stopAction)
                     .Add(ImageVisualProperty.LoopingMode, loopMode)
                     .Add(ImageVisualProperty.RedrawInScalingDown, redrawInScalingDown)
-                    .Add(ImageVisualProperty.SynchronousLoading, synchronousLoading);
+                    .Add(ImageVisualProperty.SynchronousLoading, synchronousLoading)
+                    .Add(ImageVisualProperty.EnableFrameCache, enableFrameCache)
+                    .Add(ImageVisualProperty.NotifyAfterRasterization, notifyAfterRasterization);
 
                 if (currentStates.desiredWidth > 0)
                 {
@@ -390,7 +397,7 @@ namespace Tizen.NUI.BaseComponents
                 }
                 else
                 {
-                    return (int) GetInternalCurrentFrameProperty(this);
+                    return (int)GetInternalCurrentFrameProperty(this);
                 }
             }
             set
@@ -653,7 +660,17 @@ namespace Tizen.NUI.BaseComponents
             }
         }
 
-
+        /// <summary>
+        /// Whether to AnimatedVectorImageVisual fixed cache or not.
+        /// </summary>
+        /// <remarks>
+        /// If this property is true, AnimatedVectorImageVisual enable frame cache for loading and keeps loaded frame
+        /// until the visual is removed. It reduces CPU cost when the animated image will be looping.
+        /// But it can spend a lot of memory if the resource has high resolution image or many frame count.
+        ///
+        /// Inhouse API.
+        /// It is used in the AnimatedVectorImageVisual.The default is false.
+        /// </remarks>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public bool EnableFrameCache
         {
@@ -702,6 +719,66 @@ namespace Tizen.NUI.BaseComponents
                 return currentStates.enableFrameCache;
             }
         }
+
+        /// <summary>
+        /// Whether notify AnimatedVectorImageVisual to render thread after every rasterization or not.
+        /// </summary>
+        /// <remarks>
+        /// If this property is true, AnimatedVectorImageVisual send notify to render thread after every rasterization.
+        /// If false, AnimatedVectorImageVisual set Renderer's Behaviour as Continouly (mean, always update the render thread.)
+        /// This flag is useful if given resource has low fps, so we don't need to render every frame.
+        ///
+        /// Inhouse API.
+        /// It is used in the AnimatedVectorImageVisual.The default is false.
+        /// </remarks>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool NotifyAfterRasterization
+        {
+            get
+            {
+                if (NUIApplication.IsUsingXaml)
+                {
+                    return (bool)GetValue(NotifyAfterRasterizationProperty);
+                }
+                else
+                {
+                    return (bool)GetInternalNotifyAfterRasterizationProperty(this);
+                }
+            }
+            set
+            {
+                if (NUIApplication.IsUsingXaml)
+                {
+                    SetValue(NotifyAfterRasterizationProperty, value);
+                }
+                else
+                {
+                    SetInternalNotifyAfterRasterizationProperty(this, null, value);
+                }
+                NotifyPropertyChanged();
+            }
+        }
+
+        private bool InternalNotifyAfterRasterization
+        {
+            set
+            {
+                if (currentStates.notifyAfterRasterization != value)
+                {
+                    currentStates.changed = true;
+                    currentStates.notifyAfterRasterization = value;
+
+                    NUILog.Debug($"<[{GetId()}]SET currentStates.NotifyAfterRasterization={currentStates.notifyAfterRasterization}>");
+
+                    Interop.View.InternalUpdateVisualPropertyBool(this.SwigCPtr, ImageView.Property.IMAGE, ImageVisualProperty.NotifyAfterRasterization, currentStates.notifyAfterRasterization);
+                }
+            }
+            get
+            {
+                NUILog.Debug($"NotifyAfterRasterization get! {currentStates.notifyAfterRasterization}");
+                return currentStates.notifyAfterRasterization;
+            }
+        }
         #endregion Property
 
 
@@ -1017,13 +1094,15 @@ namespace Tizen.NUI.BaseComponents
             if (!imagePropertyUpdatedFlag) return;
 
             // Update currentStates properties to cachedImagePropertyMap
-            if(currentStates.changed)
+            if (currentStates.changed)
             {
                 UpdateImage(ImageVisualProperty.LoopCount, new PropertyValue(currentStates.loopCount), false);
                 UpdateImage(ImageVisualProperty.StopBehavior, new PropertyValue((int)currentStates.stopEndAction), false);
                 UpdateImage(ImageVisualProperty.LoopingMode, new PropertyValue((int)currentStates.loopMode), false);
                 UpdateImage(ImageVisualProperty.RedrawInScalingDown, new PropertyValue(currentStates.redrawInScalingDown), false);
                 UpdateImage(ImageVisualProperty.SynchronousLoading, new PropertyValue(currentStates.synchronousLoading), false);
+                UpdateImage(ImageVisualProperty.EnableFrameCache, new PropertyValue(currentStates.enableFrameCache), false);
+                UpdateImage(ImageVisualProperty.NotifyAfterRasterization, new PropertyValue(currentStates.notifyAfterRasterization), false);
 
                 // Do not cache PlayRange and TotalFrameNumber into cachedImagePropertyMap.
                 // (To keep legacy implements behaviour)
@@ -1404,6 +1483,8 @@ namespace Tizen.NUI.BaseComponents
             ImageVisualProperty.StopBehavior,
             ImageVisualProperty.LoopingMode,
             ImageVisualProperty.RedrawInScalingDown,
+            ImageVisualProperty.EnableFrameCache,
+            ImageVisualProperty.NotifyAfterRasterization,
         };
 
         private struct states
@@ -1424,6 +1505,7 @@ namespace Tizen.NUI.BaseComponents
             internal int desiredWidth, desiredHeight;
             internal bool synchronousLoading;
             internal bool enableFrameCache;
+            internal bool notifyAfterRasterization;
             internal bool changed;
         };
         private states currentStates;
index b82a95a5a3fbf77d1d5d89efe0d52d0b6e8c3a25..3a91a5a5c728091baef0542566f6dc79c0f4e8a1 100755 (executable)
@@ -36,7 +36,7 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalURL = (string)newValue;
             }
         }
-        
+
         internal static object GetInternalURLProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
@@ -57,8 +57,7 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalCurrentFrame = (int)newValue;
             }
         }
-        
-        
+
         internal static object GetInternalCurrentFrameProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
@@ -100,7 +99,7 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalLoopCount = (int)newValue;
             }
         }
-               internal static object GetInternalLoopCountProperty(BindableObject bindable)
+        internal static object GetInternalLoopCountProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
             return instance.InternalLoopCount;
@@ -120,7 +119,7 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalStopBehavior = (Tizen.NUI.BaseComponents.LottieAnimationView.StopBehaviorType)newValue;
             }
         }
-        
+
         internal static object GetInternalStopBehaviorProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
@@ -141,7 +140,7 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalRedrawInScalingDown = (bool)newValue;
             }
         }
-        
+
         internal static object GetInternalRedrawInScalingDownProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
@@ -162,11 +161,32 @@ namespace Tizen.NUI.BaseComponents
                 instance.InternalEnableFrameCache = (bool)newValue;
             }
         }
-        
+
         internal static object GetInternalEnableFrameCacheProperty(BindableObject bindable)
         {
             var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
             return instance.InternalEnableFrameCache;
         }
+
+        /// <summary>
+        /// NotifyAfterRasterizationProperty
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty NotifyAfterRasterizationProperty = null;
+
+        internal static void SetInternalNotifyAfterRasterizationProperty(BindableObject bindable, object oldValue, object newValue)
+        {
+            var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
+            if (newValue != null)
+            {
+                instance.InternalNotifyAfterRasterization = (bool)newValue;
+            }
+        }
+
+        internal static object GetInternalNotifyAfterRasterizationProperty(BindableObject bindable)
+        {
+            var instance = (Tizen.NUI.BaseComponents.LottieAnimationView)bindable;
+            return instance.InternalNotifyAfterRasterization;
+        }
     }
 }
index bfbdbd526721a74de3f49e8e67657fa5249a4621..c73700f474490e93ba09b0bf9d0cc1996140e1b1 100755 (executable)
@@ -994,10 +994,22 @@ namespace Tizen.NUI
         /// If this property is true, animated image visual uses fixed cache for loading and keeps loaded frame
         /// until the visual is removed. It reduces CPU cost when the animated image will be looping.
         /// But it can spend a lot of memory if the resource has high resolution image or many frame count.
-        /// @note It is used in the AnimatedImageVisual. The default is false
+        /// @note It is used in the AnimatedVectorImageVisual. The default is false
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static readonly int EnableFrameCache = NDalic.ImageVisualOrientationCorrection + 16;
+
+        /// <summary>
+        /// @brief Whether notify AnimatedVectorImageVisual to render thread after every rasterization or not.
+        /// @details type Property::BOOLEAN.
+        /// If this property is true, AnimatedVectorImageVisual send notify to render thread after every rasterization.
+        /// If false, AnimatedVectorImageVisual set Renderer's Behaviour as Continouly (mean, always update the render thread.)
+        ///
+        /// This flag is useful if given resource has low fps, so we don't need to render every frame.
+        /// @note It is used in the AnimatedVectorImageVisual. The default is false.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly int NotifyAfterRasterization = NDalic.ImageVisualOrientationCorrection + 17;
     }
 
     /// <summary>
index d9f6c523f5434470b530b251ce2cde3f28b4cafe..3372215f9b731b17277470959d0c90d32d717b34 100755 (executable)
@@ -9,6 +9,7 @@ namespace Tizen.NUI.Samples
         {
             lav = new LottieAnimationView();
             lav.SynchronousLoading = false;
+            lav.NotifyAfterRasterization = true;
             lav.URL = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "a.json";
             lav.LoopCount = -1;
             lav.BackgroundColor = Color.White;