Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / perf-scroll / perf-scroll.cpp
1 /*
2  * Copyright (c) 2020 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 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
20 #include "shared/utility.h"
21
22 using namespace Dali;
23 using namespace Dali::Toolkit;
24
25 namespace
26 {
27 const char* IMAGE_PATH[] = {
28   DEMO_IMAGE_DIR "gallery-medium-1.jpg",
29   DEMO_IMAGE_DIR "gallery-medium-2.jpg",
30   DEMO_IMAGE_DIR "gallery-medium-3.jpg",
31   DEMO_IMAGE_DIR "gallery-medium-4.jpg",
32   DEMO_IMAGE_DIR "gallery-medium-5.jpg",
33   DEMO_IMAGE_DIR "gallery-medium-6.jpg",
34   DEMO_IMAGE_DIR "gallery-medium-7.jpg",
35   DEMO_IMAGE_DIR "gallery-medium-8.jpg",
36   DEMO_IMAGE_DIR "gallery-medium-9.jpg",
37   DEMO_IMAGE_DIR "gallery-medium-10.jpg",
38   DEMO_IMAGE_DIR "gallery-medium-11.jpg",
39   DEMO_IMAGE_DIR "gallery-medium-12.jpg",
40   DEMO_IMAGE_DIR "gallery-medium-13.jpg",
41   DEMO_IMAGE_DIR "gallery-medium-14.jpg",
42   DEMO_IMAGE_DIR "gallery-medium-15.jpg",
43   DEMO_IMAGE_DIR "gallery-medium-16.jpg",
44   DEMO_IMAGE_DIR "gallery-medium-17.jpg",
45   DEMO_IMAGE_DIR "gallery-medium-18.jpg",
46   DEMO_IMAGE_DIR "gallery-medium-19.jpg",
47   DEMO_IMAGE_DIR "gallery-medium-20.jpg",
48   DEMO_IMAGE_DIR "gallery-medium-21.jpg",
49   DEMO_IMAGE_DIR "gallery-medium-22.jpg",
50   DEMO_IMAGE_DIR "gallery-medium-23.jpg",
51   DEMO_IMAGE_DIR "gallery-medium-24.jpg",
52   DEMO_IMAGE_DIR "gallery-medium-25.jpg",
53   DEMO_IMAGE_DIR "gallery-medium-26.jpg",
54   DEMO_IMAGE_DIR "gallery-medium-27.jpg",
55   DEMO_IMAGE_DIR "gallery-medium-28.jpg",
56   DEMO_IMAGE_DIR "gallery-medium-29.jpg",
57   DEMO_IMAGE_DIR "gallery-medium-30.jpg",
58   DEMO_IMAGE_DIR "gallery-medium-31.jpg",
59   DEMO_IMAGE_DIR "gallery-medium-32.jpg",
60   DEMO_IMAGE_DIR "gallery-medium-33.jpg",
61   DEMO_IMAGE_DIR "gallery-medium-34.jpg",
62   DEMO_IMAGE_DIR "gallery-medium-35.jpg",
63   DEMO_IMAGE_DIR "gallery-medium-36.jpg",
64   DEMO_IMAGE_DIR "gallery-medium-37.jpg",
65   DEMO_IMAGE_DIR "gallery-medium-38.jpg",
66   DEMO_IMAGE_DIR "gallery-medium-39.jpg",
67   DEMO_IMAGE_DIR "gallery-medium-40.jpg",
68   DEMO_IMAGE_DIR "gallery-medium-41.jpg",
69   DEMO_IMAGE_DIR "gallery-medium-42.jpg",
70   DEMO_IMAGE_DIR "gallery-medium-43.jpg",
71   DEMO_IMAGE_DIR "gallery-medium-44.jpg",
72   DEMO_IMAGE_DIR "gallery-medium-45.jpg",
73   DEMO_IMAGE_DIR "gallery-medium-46.jpg",
74   DEMO_IMAGE_DIR "gallery-medium-47.jpg",
75   DEMO_IMAGE_DIR "gallery-medium-48.jpg",
76   DEMO_IMAGE_DIR "gallery-medium-49.jpg",
77   DEMO_IMAGE_DIR "gallery-medium-50.jpg",
78   DEMO_IMAGE_DIR "gallery-medium-51.jpg",
79   DEMO_IMAGE_DIR "gallery-medium-52.jpg",
80   DEMO_IMAGE_DIR "gallery-medium-53.jpg",
81 };
82
83 const char* NINEPATCH_IMAGE_PATH[] = {
84   DEMO_IMAGE_DIR "selection-popup-bg.1.9.png",
85   DEMO_IMAGE_DIR "selection-popup-bg.2.9.png",
86   DEMO_IMAGE_DIR "selection-popup-bg.3.9.png",
87   DEMO_IMAGE_DIR "selection-popup-bg.4.9.png",
88   DEMO_IMAGE_DIR "selection-popup-bg.5.9.png",
89   DEMO_IMAGE_DIR "selection-popup-bg.6.9.png",
90   DEMO_IMAGE_DIR "selection-popup-bg.7.9.png",
91   DEMO_IMAGE_DIR "selection-popup-bg.8.9.png",
92   DEMO_IMAGE_DIR "selection-popup-bg.9.9.png",
93   DEMO_IMAGE_DIR "selection-popup-bg.10.9.png",
94   DEMO_IMAGE_DIR "selection-popup-bg.11.9.png",
95   DEMO_IMAGE_DIR "selection-popup-bg.12.9.png",
96   DEMO_IMAGE_DIR "selection-popup-bg.13.9.png",
97   DEMO_IMAGE_DIR "selection-popup-bg.14.9.png",
98   DEMO_IMAGE_DIR "selection-popup-bg.15.9.png",
99   DEMO_IMAGE_DIR "selection-popup-bg.16.9.png",
100   DEMO_IMAGE_DIR "selection-popup-bg.17.9.png",
101   DEMO_IMAGE_DIR "selection-popup-bg.18.9.png",
102   DEMO_IMAGE_DIR "selection-popup-bg.19.9.png",
103   DEMO_IMAGE_DIR "selection-popup-bg.20.9.png",
104   DEMO_IMAGE_DIR "selection-popup-bg.21.9.png",
105   DEMO_IMAGE_DIR "selection-popup-bg.22.9.png",
106   DEMO_IMAGE_DIR "selection-popup-bg.23.9.png",
107   DEMO_IMAGE_DIR "selection-popup-bg.24.9.png",
108   DEMO_IMAGE_DIR "selection-popup-bg.25.9.png",
109   DEMO_IMAGE_DIR "selection-popup-bg.26.9.png",
110   DEMO_IMAGE_DIR "selection-popup-bg.27.9.png",
111   DEMO_IMAGE_DIR "selection-popup-bg.28.9.png",
112   DEMO_IMAGE_DIR "selection-popup-bg.29.9.png",
113   DEMO_IMAGE_DIR "selection-popup-bg.30.9.png",
114   DEMO_IMAGE_DIR "selection-popup-bg.31.9.png",
115   DEMO_IMAGE_DIR "selection-popup-bg.32.9.png",
116   DEMO_IMAGE_DIR "selection-popup-bg.33.9.png",
117   DEMO_IMAGE_DIR "button-disabled.9.png",
118   DEMO_IMAGE_DIR "button-down.9.png",
119   DEMO_IMAGE_DIR "button-down-disabled.9.png",
120   DEMO_IMAGE_DIR "button-up-1.9.png",
121   DEMO_IMAGE_DIR "button-up-2.9.png",
122   DEMO_IMAGE_DIR "button-up-3.9.png",
123   DEMO_IMAGE_DIR "button-up-4.9.png",
124   DEMO_IMAGE_DIR "button-up-5.9.png",
125   DEMO_IMAGE_DIR "button-up-6.9.png",
126   DEMO_IMAGE_DIR "button-up-7.9.png",
127   DEMO_IMAGE_DIR "button-up-8.9.png",
128   DEMO_IMAGE_DIR "button-up-9.9.png",
129   DEMO_IMAGE_DIR "button-up-10.9.png",
130   DEMO_IMAGE_DIR "button-up-11.9.png",
131   DEMO_IMAGE_DIR "button-up-12.9.png",
132   DEMO_IMAGE_DIR "button-up-13.9.png",
133   DEMO_IMAGE_DIR "button-up-14.9.png",
134   DEMO_IMAGE_DIR "button-up-15.9.png",
135   DEMO_IMAGE_DIR "button-up-16.9.png",
136   DEMO_IMAGE_DIR "button-up-17.9.png",
137 };
138
139 const unsigned int NUM_IMAGES           = sizeof(IMAGE_PATH) / sizeof(char*);
140 const unsigned int NUM_NINEPATCH_IMAGES = sizeof(NINEPATCH_IMAGE_PATH) / sizeof(char*);
141
142 const float ANIMATION_TIME(5.0f); // animation length in seconds
143
144 struct VertexWithTexture
145 {
146   Vector2 position;
147   Vector2 texCoord;
148 };
149
150 // clang-format off
151
152 const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
153     attribute mediump vec2 aPosition;\n
154     attribute mediump vec2 aTexCoord;\n
155     uniform mediump mat4 uMvpMatrix;\n
156     uniform mediump vec3 uSize;\n
157     varying mediump vec2 vTexCoord;\n
158     void main()\n
159     {\n
160       vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
161       gl_Position = uMvpMatrix * position;\n
162       vTexCoord = aTexCoord;\n
163     }\n
164 );
165
166 const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
167     uniform lowp vec4 uColor;\n
168     uniform sampler2D sTexture;\n
169     varying mediump vec2 vTexCoord;\n
170
171     void main()\n
172     {\n
173       gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
174     }\n
175 );
176
177 // clang-format on
178
179 bool         gUseMesh(false);
180 bool         gNinePatch(false);
181 unsigned int gRowsPerPage(15);
182 unsigned int gColumnsPerPage(15);
183 unsigned int gPageCount(10);
184 float        gDuration(10.0f);
185
186 Renderer CreateRenderer(unsigned int index, Geometry geometry, Shader shader)
187 {
188   Renderer    renderer   = Renderer::New(geometry, shader);
189   const char* imagePath  = !gNinePatch ? IMAGE_PATH[index] : NINEPATCH_IMAGE_PATH[index];
190   Texture     texture    = DemoHelper::LoadTexture(imagePath);
191   TextureSet  textureSet = TextureSet::New();
192   textureSet.SetTexture(0u, texture);
193   renderer.SetTextures(textureSet);
194   renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF);
195   return renderer;
196 }
197
198 } // namespace
199 // Test application to compare performance between ImageActor and ImageView
200 // By default, the application consist of 10 pages of 25x25 ImageActors, this can be modified using the following command line arguments:
201 // -t duration (sec )
202 // --use-imageview ( Use ImageView instead of ImageActor )
203 // --use-mesh ( Use new renderer API (as ImageView) but shares renderers between actors when possible )
204
205 //
206 class PerfScroll : public ConnectionTracker
207 {
208 public:
209   PerfScroll(Application& application)
210   : mApplication(application),
211     mRowsPerPage(gRowsPerPage),
212     mColumnsPerPage(gColumnsPerPage),
213     mPageCount(gPageCount)
214   {
215     // Connect to the Application's Init signal
216     mApplication.InitSignal().Connect(this, &PerfScroll::Create);
217   }
218
219   ~PerfScroll()
220   {
221     // Nothing to do here;
222   }
223
224   // The Init signal is received once (only) during the Application lifetime
225   void Create(Application& application)
226   {
227     // Get a handle to the window
228     Window window = application.GetWindow();
229     window.SetBackgroundColor(Color::WHITE);
230     Vector2 windowSize = window.GetSize();
231
232     window.GetRootLayer().SetProperty(Layer::Property::DEPTH_TEST, false);
233
234     mSize = Vector3(windowSize.x / mColumnsPerPage, windowSize.y / mRowsPerPage, 0.0f);
235
236     // Respond to a click anywhere on the window
237     window.GetRootLayer().TouchedSignal().Connect(this, &PerfScroll::OnTouch);
238
239     // Respond to key events
240     window.KeyEventSignal().Connect(this, &PerfScroll::OnKeyEvent);
241
242     mParent = Actor::New();
243     mParent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
244     window.Add(mParent);
245
246     if(gUseMesh)
247     {
248       CreateMeshActors();
249     }
250     else
251     {
252       CreateImageViews();
253     }
254
255     ShowAnimation();
256   }
257
258   bool OnTouch(Actor actor, const TouchEvent& touch)
259   {
260     // quit the application
261     mApplication.Quit();
262     return true;
263   }
264
265   const char* ImagePath(int i)
266   {
267     return !gNinePatch ? IMAGE_PATH[i % NUM_IMAGES] : NINEPATCH_IMAGE_PATH[i % NUM_NINEPATCH_IMAGES];
268   }
269
270   void CreateImageViews()
271   {
272     Window       window = mApplication.GetWindow();
273     unsigned int actorCount(mRowsPerPage * mColumnsPerPage * mPageCount);
274     mImageView.resize(actorCount);
275
276     for(size_t i(0); i < actorCount; ++i)
277     {
278       mImageView[i] = ImageView::New();
279       Property::Map propertyMap;
280       propertyMap.Insert(Toolkit::ImageVisual::Property::URL, ImagePath(i));
281       propertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
282       propertyMap.Insert(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE, Toolkit::DevelVisual::FILL);
283       mImageView[i].SetProperty(Toolkit::ImageView::Property::IMAGE, propertyMap);
284
285       mImageView[i].SetProperty(Actor::Property::SIZE, Vector3(0.0f, 0.0f, 0.0f));
286       mImageView[i].SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
287       mParent.Add(mImageView[i]);
288     }
289   }
290
291   void CreateMeshActors()
292   {
293     unsigned int numImages = !gNinePatch ? NUM_IMAGES : NUM_NINEPATCH_IMAGES;
294
295     //Create all the renderers
296     std::vector<Renderer> renderers(numImages);
297     Shader                shader   = Shader::New(VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE);
298     Geometry              geometry = DemoHelper::CreateTexturedQuad();
299     for(unsigned int i(0); i < numImages; ++i)
300     {
301       renderers[i] = CreateRenderer(i, geometry, shader);
302     }
303
304     //Create the actors
305     Window       window = mApplication.GetWindow();
306     unsigned int actorCount(mRowsPerPage * mColumnsPerPage * mPageCount);
307     mActor.resize(actorCount);
308     for(size_t i(0); i < actorCount; ++i)
309     {
310       mActor[i] = Actor::New();
311       mActor[i].AddRenderer(renderers[i % numImages]);
312       mActor[i].SetProperty(Actor::Property::SIZE, Vector3(0.0f, 0.0f, 0.0f));
313       mParent.Add(mActor[i]);
314     }
315   }
316
317   void OnAnimationEnd(Animation& source)
318   {
319     if(source == mShow)
320     {
321       ScrollAnimation();
322     }
323     else if(source == mScroll)
324     {
325       HideAnimation();
326     }
327     else
328     {
329       mApplication.Quit();
330     }
331   }
332
333   void ShowAnimation()
334   {
335     Window  window = mApplication.GetWindow();
336     Vector3 initialPosition(window.GetSize().GetWidth() * 0.5f, window.GetSize().GetHeight() * 0.5f, 1000.0f);
337
338     unsigned int totalColumns = mColumnsPerPage * mPageCount;
339
340     size_t count(0);
341     float  xpos, ypos;
342     mShow = Animation::New(0.0f);
343
344     float totalDuration(0.0f);
345     float durationPerActor(0.0f);
346     float delayBetweenActors = (totalDuration - durationPerActor) / (mRowsPerPage * mColumnsPerPage);
347
348     for(size_t i(0); i < totalColumns; ++i)
349     {
350       xpos = mSize.x * i;
351
352       for(size_t j(0); j < mRowsPerPage; ++j)
353       {
354         ypos = mSize.y * j;
355
356         float delay    = 0.0f;
357         float duration = 0.0f;
358         if(count < (static_cast<size_t>(mRowsPerPage) * mColumnsPerPage))
359         {
360           duration = durationPerActor;
361           delay    = delayBetweenActors * count;
362         }
363         if(gUseMesh)
364         {
365           mActor[count].SetProperty(Actor::Property::POSITION, initialPosition);
366           mActor[count].SetProperty(Actor::Property::SIZE, Vector3(0.0f, 0.0f, 0.0f));
367           mActor[count].SetProperty(Actor::Property::ORIENTATION, Quaternion(Quaternion(Radian(0.0f), Vector3::XAXIS)));
368           mShow.AnimateTo(Property(mActor[count], Actor::Property::POSITION), Vector3(xpos + mSize.x * 0.5f, ypos + mSize.y * 0.5f, 0.0f), AlphaFunction::EASE_OUT_BACK, TimePeriod(delay, duration));
369           mShow.AnimateTo(Property(mActor[count], Actor::Property::SIZE), mSize, AlphaFunction::EASE_OUT_BACK, TimePeriod(delay, duration));
370         }
371         else
372         {
373           mImageView[count].SetProperty(Actor::Property::POSITION, initialPosition);
374           mImageView[count].SetProperty(Actor::Property::SIZE, Vector3(0.0f, 0.0f, 0.0f));
375           mImageView[count].SetProperty(Actor::Property::ORIENTATION, Quaternion(Quaternion(Radian(0.0f), Vector3::XAXIS)));
376           mShow.AnimateTo(Property(mImageView[count], Actor::Property::POSITION), Vector3(xpos + mSize.x * 0.5f, ypos + mSize.y * 0.5f, 0.0f), AlphaFunction::EASE_OUT_BACK, TimePeriod(delay, duration));
377           mShow.AnimateTo(Property(mImageView[count], Actor::Property::SIZE), mSize, AlphaFunction::EASE_OUT_BACK, TimePeriod(delay, duration));
378         }
379         ++count;
380       }
381     }
382     mShow.Play();
383     mShow.FinishedSignal().Connect(this, &PerfScroll::OnAnimationEnd);
384   }
385
386   void ScrollAnimation()
387   {
388     Window  window = mApplication.GetWindow();
389     Vector3 windowSize(window.GetSize());
390
391     mScroll = Animation::New(gDuration);
392
393     mScroll.AnimateBy(Property(mParent, Actor::Property::POSITION), Vector3(-(gPageCount - 1.) * windowSize.x, 0.0f, 0.0f));
394     mScroll.Play();
395     mScroll.FinishedSignal().Connect(this, &PerfScroll::OnAnimationEnd);
396   }
397
398   void HideAnimation()
399   {
400     size_t       count(0);
401     unsigned int actorsPerPage(mRowsPerPage * mColumnsPerPage);
402     mHide = Animation::New(0.0f);
403
404     unsigned int totalColumns = mColumnsPerPage * mPageCount;
405
406     float totalDuration(0.0f);
407     float durationPerActor(0.0f);
408     float delayBetweenActors = (totalDuration - durationPerActor) / (mRowsPerPage * mColumnsPerPage);
409     for(size_t i(0); i < mRowsPerPage; ++i)
410     {
411       for(size_t j(0); j < totalColumns; ++j)
412       {
413         float delay    = 0.0f;
414         float duration = 0.0f;
415         if(count < actorsPerPage)
416         {
417           duration = durationPerActor;
418           delay    = delayBetweenActors * count;
419         }
420
421         if(gUseMesh)
422         {
423           mHide.AnimateTo(Property(mActor[count], Actor::Property::ORIENTATION), Quaternion(Radian(Degree(70.0f)), Vector3::XAXIS), AlphaFunction::EASE_OUT, TimePeriod(delay, duration));
424           mHide.AnimateBy(Property(mActor[count], Actor::Property::POSITION_Z), 1000.0f, AlphaFunction::EASE_OUT_BACK, TimePeriod(delay + delayBetweenActors * actorsPerPage + duration, duration));
425         }
426         else
427         {
428           mHide.AnimateTo(Property(mImageView[count], Actor::Property::ORIENTATION), Quaternion(Radian(Degree(70.0f)), Vector3::XAXIS), AlphaFunction::EASE_OUT, TimePeriod(delay, duration));
429           mHide.AnimateBy(Property(mImageView[count], Actor::Property::POSITION_Z), 1000.0f, AlphaFunction::EASE_OUT_BACK, TimePeriod(delay + delayBetweenActors * actorsPerPage + duration, duration));
430         }
431         ++count;
432       }
433     }
434
435     mHide.Play();
436     mHide.FinishedSignal().Connect(this, &PerfScroll::OnAnimationEnd);
437   }
438
439   void OnKeyEvent(const KeyEvent& event)
440   {
441     if(event.GetState() == KeyEvent::DOWN)
442     {
443       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
444       {
445         mApplication.Quit();
446       }
447     }
448   }
449
450 private:
451   Application& mApplication;
452
453   std::vector<Actor>     mActor;
454   std::vector<ImageView> mImageView;
455   Actor                  mParent;
456
457   Vector3      mSize;
458   unsigned int mRowsPerPage;
459   unsigned int mColumnsPerPage;
460   unsigned int mPageCount;
461
462   Animation mShow;
463   Animation mScroll;
464   Animation mHide;
465 };
466
467 int DALI_EXPORT_API main(int argc, char** argv)
468 {
469   Application application = Application::New(&argc, &argv);
470
471   for(int i(1); i < argc; ++i)
472   {
473     std::string arg(argv[i]);
474     if(arg.compare("--use-mesh") == 0)
475     {
476       gUseMesh = true;
477     }
478     else if(arg.compare("--nine-patch") == 0)
479     {
480       gNinePatch = true;
481     }
482     else if(arg.compare(0, 2, "-t") == 0)
483     {
484       gDuration = atof(arg.substr(2, arg.size()).c_str());
485     }
486   }
487
488   PerfScroll test(application);
489   application.MainLoop();
490
491   return 0;
492 }