[NUI] Add SetDefaultGrabTouchAfterLeave api.
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.PerformanceTest / PerformanceTest.cs
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // TODO : borderline, blur type need to solve partial update issue.
19 // Until that issue exist, just block it.
20 // #define ALLOW_BORDER_AND_BLUR
21
22 using System;
23 using Tizen.NUI;
24 using Tizen.NUI.BaseComponents;
25 using Tizen.NUI.Constants;
26
27
28 class PerformanceTestExample : NUIApplication
29 {
30     const uint ROWS_COUNT = 32;
31     const uint COLUMNS_COUNT = 32;
32     const uint TOTAL_COLUMNS_COUNT = 80;
33     const uint DURATION_PER_COLUMNS = 50; // miliseconds
34     const float VIEW_MARGIN_RATE = 0.1f;
35     enum ViewTestType{
36         TEST_TYPE_COLOR = 0,            ///< Test with simple color
37         TEST_TYPE_IMAGE,                ///< Test with simple image
38         TEST_TYPE_TEXT,                 ///< Test with simple text label
39         TEST_TYPE_ROUNDED_COLOR,        ///< Test with rounded color
40 #if ALLOW_BORDER_AND_BLUR
41         TEST_TYPE_BORDER_COLOR,         ///< Test with borderline color
42         TEST_TYPE_ROUNDED_BORDER_COLOR, ///< Test with rounded borderline color
43         TEST_TYPE_BLUR_COLOR,           ///< Test with blur color
44         TEST_TYPE_ROUNDED_BLUR_COLOR,   ///< Test with blur color
45 #endif
46         TEST_TYPE_MAX,
47     };
48
49     static string TestTypeString(ViewTestType type)
50     {
51         switch(type)
52         {
53             case ViewTestType.TEST_TYPE_COLOR:               return "COLOR";
54             case ViewTestType.TEST_TYPE_IMAGE:               return "IMAGE";
55             case ViewTestType.TEST_TYPE_TEXT:                return "TEXT";
56             case ViewTestType.TEST_TYPE_ROUNDED_COLOR:       return "ROUNDED COLOR";
57         #if ALLOW_BORDER_AND_BLUR
58             case ViewTestType.TEST_TYPE_BORDER_COLOR:        return "BORDER COLOR";
59             case ViewTestType.TEST_TYPE_ROUNDED_BORDER_COLOR:return "ROUNDED BORDER COLOR";
60             case ViewTestType.TEST_TYPE_BLUR_COLOR:          return "BLUR COLOR";
61             case ViewTestType.TEST_TYPE_ROUNDED_BLUR_COLOR:  return "ROUNDED BLUR COLOR";
62         #endif
63             default:                                         return "UNKNOWN";
64         }
65     }
66
67     static string IMAGE_DIR = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "image/";
68     readonly static string[] IMAGE_PATH = {
69     IMAGE_DIR + "gallery-medium-1.jpg",
70     IMAGE_DIR + "gallery-medium-2.jpg",
71     IMAGE_DIR + "gallery-medium-3.jpg",
72     IMAGE_DIR + "gallery-medium-4.jpg",
73     IMAGE_DIR + "gallery-medium-5.jpg",
74     IMAGE_DIR + "gallery-medium-6.jpg",
75     IMAGE_DIR + "gallery-medium-7.jpg",
76     IMAGE_DIR + "gallery-medium-8.jpg",
77     IMAGE_DIR + "gallery-medium-9.jpg",
78     IMAGE_DIR + "gallery-medium-10.jpg",
79     IMAGE_DIR + "gallery-medium-11.jpg",
80     IMAGE_DIR + "gallery-medium-12.jpg",
81     IMAGE_DIR + "gallery-medium-13.jpg",
82     IMAGE_DIR + "gallery-medium-14.jpg",
83     IMAGE_DIR + "gallery-medium-15.jpg",
84     IMAGE_DIR + "gallery-medium-16.jpg",
85     IMAGE_DIR + "gallery-medium-17.jpg",
86     IMAGE_DIR + "gallery-medium-18.jpg",
87     IMAGE_DIR + "gallery-medium-19.jpg",
88     IMAGE_DIR + "gallery-medium-20.jpg",
89     IMAGE_DIR + "gallery-medium-21.jpg",
90     IMAGE_DIR + "gallery-medium-22.jpg",
91     IMAGE_DIR + "gallery-medium-23.jpg",
92     IMAGE_DIR + "gallery-medium-24.jpg",
93     IMAGE_DIR + "gallery-medium-25.jpg",
94     IMAGE_DIR + "gallery-medium-26.jpg",
95     IMAGE_DIR + "gallery-medium-27.jpg",
96     IMAGE_DIR + "gallery-medium-28.jpg",
97     IMAGE_DIR + "gallery-medium-29.jpg",
98     IMAGE_DIR + "gallery-medium-30.jpg",
99     IMAGE_DIR + "gallery-medium-31.jpg",
100     IMAGE_DIR + "gallery-medium-32.jpg",
101     IMAGE_DIR + "gallery-medium-33.jpg",
102     IMAGE_DIR + "gallery-medium-34.jpg",
103     IMAGE_DIR + "gallery-medium-35.jpg",
104     IMAGE_DIR + "gallery-medium-36.jpg",
105     IMAGE_DIR + "gallery-medium-37.jpg",
106     IMAGE_DIR + "gallery-medium-38.jpg",
107     IMAGE_DIR + "gallery-medium-39.jpg",
108     IMAGE_DIR + "gallery-medium-40.jpg",
109     IMAGE_DIR + "gallery-medium-41.jpg",
110     IMAGE_DIR + "gallery-medium-42.jpg",
111     IMAGE_DIR + "gallery-medium-43.jpg",
112     IMAGE_DIR + "gallery-medium-44.jpg",
113     IMAGE_DIR + "gallery-medium-45.jpg",
114     IMAGE_DIR + "gallery-medium-46.jpg",
115     IMAGE_DIR + "gallery-medium-47.jpg",
116     IMAGE_DIR + "gallery-medium-48.jpg",
117     IMAGE_DIR + "gallery-medium-49.jpg",
118     IMAGE_DIR + "gallery-medium-50.jpg",
119     IMAGE_DIR + "gallery-medium-51.jpg",
120     IMAGE_DIR + "gallery-medium-52.jpg",
121     IMAGE_DIR + "gallery-medium-53.jpg",
122     };
123
124     class Statistic
125     {
126         const double trimRate = 0.34;
127         global::System.Collections.Generic.List<double> v;
128         int vcnt;
129         double vsum;
130         public Statistic()
131         {
132             clear();
133         }
134         public void clear()
135         {
136             v = new global::System.Collections.Generic.List<double>();
137             vcnt = 0;
138             vsum = 0.0;
139         }
140         public void add(double x)
141         {
142             v.Add(x);
143             vcnt++;
144             vsum += x;
145         }
146         public double getAverage()
147         {
148             if(vcnt == 0)return 0.0;
149             return vsum / vcnt;
150         }
151         public double getTrimedAverage()
152         {
153             if(vcnt == 0)return 0.0;
154             v.Sort();
155             double trimVsum = 0;
156             int removedCnt = (int)(vcnt * trimRate * 0.5);
157             int trimVcnt = vcnt - removedCnt * 2;
158             if(trimVcnt == 0)
159             {
160                 trimVcnt += 2;
161                 removedCnt--;
162             }
163             for(int i = removedCnt; i < vcnt - removedCnt; i++)
164             {
165                 trimVsum += v[i];
166             }
167
168             return trimVsum / trimVcnt;
169         }
170     };
171     Statistic mCreationStatistic;
172     Window mWindow;
173     Vector2 mWindowSize;
174     Vector2 mSize;
175     ViewTestType mTestType = ViewTestType.TEST_TYPE_COLOR;
176
177     // To keep reference count.
178     global::System.Collections.Generic.LinkedList<View> mViewList;
179     global::System.Collections.Generic.LinkedList<Timer> mTimerList;
180     global::System.Collections.Generic.LinkedList<Animation> mAnimationList;
181
182     uint mColumnsCount = ROWS_COUNT;
183     uint mRowsCount = COLUMNS_COUNT;
184     uint mTotalColumnsCount = TOTAL_COLUMNS_COUNT;
185     uint mDurationPerColumns = DURATION_PER_COLUMNS; // miliseconds
186
187     uint tickCount;
188     uint deleteCount;
189
190     DateTime appStartTime;
191     DateTime appEndTime;
192     protected void CreateScene()
193     {
194         appStartTime = DateTime.Now;
195
196         mViewList  = new global::System.Collections.Generic.LinkedList<View>();
197         mTimerList = new global::System.Collections.Generic.LinkedList<Timer>();
198         mAnimationList = new global::System.Collections.Generic.LinkedList<Animation>();
199
200         mWindow = Window.Instance;
201         mWindow.BackgroundColor = Color.White;
202         mWindowSize = mWindow.WindowSize;
203
204         mSize = new Vector2(mWindowSize.X / mColumnsCount, mWindowSize.Y / mRowsCount);
205
206         Timer timer = new Timer(mDurationPerColumns);
207         timer.Tick += OnTick;
208         mTimerList.AddLast(timer);
209
210         tickCount = 0;
211         deleteCount = 0;
212
213         mCreationStatistic = new Statistic();
214
215         timer.Start();
216
217         mWindow.KeyEvent += OnKeyEvent;
218     }
219     bool OnTick(object o, EventArgs e)
220     {
221         tickCount++;
222         if(tickCount < mTotalColumnsCount * (int)ViewTestType.TEST_TYPE_MAX)
223         {
224             // Start next phase.
225             Timer timer = new Timer(mDurationPerColumns);
226             timer.Tick += OnTick;
227             mTimerList.AddLast(timer);
228
229             timer.Start();
230         }
231         DateTime startTime;
232         DateTime endTime;
233
234         startTime = DateTime.Now;
235
236         View columnView = new View()
237         {
238             BackgroundColor = Color.Blue,
239             Size = new Size(mSize.X, mWindowSize.Y),
240             Position = new Position(mWindowSize.X, 0.0f),
241         };
242
243         for(int i = 0; i < mRowsCount; ++i)
244         {
245             View bgView;
246             switch(mTestType)
247             {
248                 case ViewTestType.TEST_TYPE_COLOR:
249                 default:
250                 {
251                     bgView = CreateColor();
252                     break;
253                 }
254                 case ViewTestType.TEST_TYPE_IMAGE:
255                 {
256                     bgView = CreateImage();
257                     break;
258                 }
259                 case ViewTestType.TEST_TYPE_TEXT:
260                 {
261                     bgView = CreateTextLabel();
262                     break;
263                 }
264                 case ViewTestType.TEST_TYPE_ROUNDED_COLOR:
265                 {
266                     bgView = CreateRoundedColor();
267                     break;
268                 }
269 #if ALLOW_BORDER_AND_BLUR
270                 case ViewTestType.TEST_TYPE_BORDER_COLOR:
271                 {
272                     bgView = CreateBorderColor(Math.Min(mSize.X, mSize.Y) * VIEW_MARGIN_RATE);
273                     break;
274                 }
275                 case ViewTestType.TEST_TYPE_ROUNDED_BORDER_COLOR:
276                 {
277                     bgView = CreateRoundedBorderColor(Math.Min(mSize.X, mSize.Y) * VIEW_MARGIN_RATE);
278                     break;
279                 }
280                 case ViewTestType.TEST_TYPE_BLUR_COLOR:
281                 {
282                     bgView = CreateBlurColor(Math.Min(mSize.X, mSize.Y) * VIEW_MARGIN_RATE * 0.5f);
283                     break;
284                 }
285                 case ViewTestType.TEST_TYPE_ROUNDED_BLUR_COLOR:
286                 {
287                     bgView = CreateRoundedBlurColor(Math.Min(mSize.X, mSize.Y) * VIEW_MARGIN_RATE * 0.5f);
288                     break;
289                 }
290 #endif
291             }
292             bgView.Size = new Size(mSize.X * (1.0f - VIEW_MARGIN_RATE), mSize.Y * (1.0f - VIEW_MARGIN_RATE));
293             bgView.Position = new Position(mSize.X * VIEW_MARGIN_RATE * 0.5f, (mSize.Y * VIEW_MARGIN_RATE * 0.5f) + (mSize.Y * (float)i));
294             columnView.Add(bgView);
295         }
296
297         mWindow.Add(columnView);
298         mViewList.AddLast(columnView);
299
300         // Add move animation
301         Animation animation = new Animation((int)(mDurationPerColumns * (mColumnsCount + 1)));
302         animation.AnimateTo(columnView, "PositionX", -mSize.X);
303         animation.Finished += OnAnimationFinished;
304         animation.Play();
305
306         mAnimationList.AddLast(animation);
307
308         endTime = DateTime.Now;
309
310         mCreationStatistic.add((endTime - startTime).TotalMilliseconds);
311
312         if(tickCount % mTotalColumnsCount == 0)
313         {
314             Tizen.Log.Error("NUI.PerfNew", $"Average of creation {mRowsCount} NUI({TestTypeString(mTestType)}) : {mCreationStatistic.getTrimedAverage()} ms\n");
315             mCreationStatistic.clear();
316             mTestType = (ViewTestType)(((int)(mTestType) + 1) % (int)(ViewTestType.TEST_TYPE_MAX));
317         }
318
319         return false;
320     }
321
322     void OnKeyEvent(object source, Window.KeyEventArgs e)
323     {
324         if (e.Key.State == Key.StateType.Down)
325         {
326             FullGC();
327             //Streamline.AnnotateChannelEnd(0);
328
329             switch( e.Key.KeyPressedName )
330             {
331                 case "Escape":
332                 case "Back":
333                 {
334                     Deactivate();
335                     Exit();
336                 }
337                 break;
338             }
339         }
340     }
341
342     void OnAnimationFinished(object o, EventArgs e)
343     {
344         // We can assume that front of mViewLIst must be deleted.
345         mViewList.First.Value.Unparent();
346         mViewList.First.Value.Dispose();
347         mViewList.RemoveFirst();
348
349         // Dereference timer safety
350         mTimerList.First.Value.Dispose();
351         mTimerList.RemoveFirst();
352
353         // Dereference animation safety
354         mAnimationList.RemoveFirst();
355
356         deleteCount++;
357
358         Animation me = o as Animation;
359         me.Dispose();
360
361         // If all views are deleted, quit this application. byebye~
362         if(deleteCount == mTotalColumnsCount * (int)ViewTestType.TEST_TYPE_MAX)
363         {
364             appEndTime = DateTime.Now;
365             Tizen.Log.Error("NUI.PerfNew", $"Duration of all app running time : {((appEndTime - appStartTime)).TotalMilliseconds} ms\n");
366             Deactivate();
367             FullGC();
368             Exit();
369         }
370     }
371
372     private View CreateColor()
373     {
374         View bgView = new View(){
375             BackgroundColor = Color.Yellow,
376         };
377         return bgView;
378     }
379     private int gImageCount = 0;
380     private View CreateImage()
381     {
382         ImageView bgView = new ImageView(){
383             BackgroundColor = Color.Yellow,
384             ResourceUrl = IMAGE_PATH[(gImageCount++) % (IMAGE_PATH.Length)],
385         };
386         return bgView;
387     }
388     private View CreateTextLabel()
389     {
390         TextLabel bgView = new TextLabel(){
391             Text = "Hello, World!",
392         };
393         return bgView;
394     }
395     private View CreateRoundedColor()
396     {
397         View bgView = new View(){
398             BackgroundColor = Color.Yellow,
399             CornerRadius = 0.5f,
400             CornerRadiusPolicy = VisualTransformPolicyType.Relative,
401         };
402         return bgView;
403     }
404
405 #if ALLOW_BORDER_AND_BLUR
406     private View CreateBorderColor(float requiredBorderlineWidth)
407     {
408         View bgView = new View(){
409             BackgroundColor = Color.Yellow,
410             BorderlineColor = Color.Red,
411             BorderlineWidth = requiredBorderlineWidth,
412         };
413         return bgView;
414     }
415     private View CreateRoundedBorderColor(float requiredBorderlineWidth)
416     {
417         View bgView = new View(){
418             BackgroundColor = Color.Yellow,
419             CornerRadius = 0.5f,
420             CornerRadiusPolicy = VisualTransformPolicyType.Relative,
421             BorderlineColor = Color.Red,
422             BorderlineWidth = requiredBorderlineWidth,
423         };
424         return bgView;
425     }
426     private View CreateBlurColor(float requiredBlurRadius)
427     {
428         View bgView = new View();
429
430         using(PropertyMap map = new PropertyMap())
431         {
432             map.Insert((int)Visual.Property.Type, new PropertyValue((int)Visual.Type.Color));
433             map.Insert((int)ColorVisualProperty.MixColor, new PropertyValue(Color.Yellow));
434             map.Insert((int)ColorVisualProperty.BlurRadius, new PropertyValue(requiredBlurRadius));
435
436             bgView.Background = map;
437         }
438
439         return bgView;
440     }
441     private View CreateRoundedBlurColor(float requiredBlurRadius)
442     {
443         View bgView = new View();
444
445         using(PropertyMap map = new PropertyMap())
446         {
447             map.Insert((int)Visual.Property.Type, new PropertyValue((int)Visual.Type.Color));
448             map.Insert((int)ColorVisualProperty.MixColor, new PropertyValue(Color.Yellow));
449             map.Insert((int)ColorVisualProperty.BlurRadius, new PropertyValue(requiredBlurRadius));
450             map.Insert((int)Visual.Property.CornerRadius, new PropertyValue(0.5f));
451             map.Insert((int)Visual.Property.CornerRadiusPolicy, new PropertyValue((int)VisualTransformPolicyType.Relative));
452
453             bgView.Background = map;
454         }
455
456         return bgView;
457     }
458 #endif
459
460     public void Activate()
461     {
462         CreateScene();
463     }
464     public void FullGC(){
465         global::System.GC.Collect();
466         global::System.GC.WaitForPendingFinalizers();
467         global::System.GC.Collect();
468     }
469
470     public void Deactivate()
471     {
472         DestroyScene();
473     }
474     private void DestroyScene()
475     {
476     }
477
478     protected override void OnCreate()
479     {
480         // Up call to the Base class first
481         base.OnCreate();
482         Activate();
483     }
484
485     /// <summary>
486     /// The main entry point for the application.
487     /// </summary>
488     [STAThread] // Forces app to use one thread to access NUI
489     static void Main(string[] args)
490     {
491         PerformanceTestExample example = new PerformanceTestExample();
492         example.Run(args);
493     }
494 }