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