Add BUILD_EXAMPLE_NAME option explain for README.md
[platform/core/uifw/dali-demo.git] / examples / perf-scroll / perf-scroll.cpp
1 /*
2  * Copyright (c) 2021 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 #include <iostream>
21
22 // INTERNAL INCLUDES
23 #include "generated/perf-scroll-frag.h"
24 #include "generated/perf-scroll-vert.h"
25 #include "shared/utility.h"
26
27 using namespace Dali;
28 using namespace Dali::Toolkit;
29 using namespace std;
30
31 namespace
32 {
33 const char* IMAGE_PATH[] = {
34   DEMO_IMAGE_DIR "gallery-medium-1.jpg",
35   DEMO_IMAGE_DIR "gallery-medium-2.jpg",
36   DEMO_IMAGE_DIR "gallery-medium-3.jpg",
37   DEMO_IMAGE_DIR "gallery-medium-4.jpg",
38   DEMO_IMAGE_DIR "gallery-medium-5.jpg",
39   DEMO_IMAGE_DIR "gallery-medium-6.jpg",
40   DEMO_IMAGE_DIR "gallery-medium-7.jpg",
41   DEMO_IMAGE_DIR "gallery-medium-8.jpg",
42   DEMO_IMAGE_DIR "gallery-medium-9.jpg",
43   DEMO_IMAGE_DIR "gallery-medium-10.jpg",
44   DEMO_IMAGE_DIR "gallery-medium-11.jpg",
45   DEMO_IMAGE_DIR "gallery-medium-12.jpg",
46   DEMO_IMAGE_DIR "gallery-medium-13.jpg",
47   DEMO_IMAGE_DIR "gallery-medium-14.jpg",
48   DEMO_IMAGE_DIR "gallery-medium-15.jpg",
49   DEMO_IMAGE_DIR "gallery-medium-16.jpg",
50   DEMO_IMAGE_DIR "gallery-medium-17.jpg",
51   DEMO_IMAGE_DIR "gallery-medium-18.jpg",
52   DEMO_IMAGE_DIR "gallery-medium-19.jpg",
53   DEMO_IMAGE_DIR "gallery-medium-20.jpg",
54   DEMO_IMAGE_DIR "gallery-medium-21.jpg",
55   DEMO_IMAGE_DIR "gallery-medium-22.jpg",
56   DEMO_IMAGE_DIR "gallery-medium-23.jpg",
57   DEMO_IMAGE_DIR "gallery-medium-24.jpg",
58   DEMO_IMAGE_DIR "gallery-medium-25.jpg",
59   DEMO_IMAGE_DIR "gallery-medium-26.jpg",
60   DEMO_IMAGE_DIR "gallery-medium-27.jpg",
61   DEMO_IMAGE_DIR "gallery-medium-28.jpg",
62   DEMO_IMAGE_DIR "gallery-medium-29.jpg",
63   DEMO_IMAGE_DIR "gallery-medium-30.jpg",
64   DEMO_IMAGE_DIR "gallery-medium-31.jpg",
65   DEMO_IMAGE_DIR "gallery-medium-32.jpg",
66   DEMO_IMAGE_DIR "gallery-medium-33.jpg",
67   DEMO_IMAGE_DIR "gallery-medium-34.jpg",
68   DEMO_IMAGE_DIR "gallery-medium-35.jpg",
69   DEMO_IMAGE_DIR "gallery-medium-36.jpg",
70   DEMO_IMAGE_DIR "gallery-medium-37.jpg",
71   DEMO_IMAGE_DIR "gallery-medium-38.jpg",
72   DEMO_IMAGE_DIR "gallery-medium-39.jpg",
73   DEMO_IMAGE_DIR "gallery-medium-40.jpg",
74   DEMO_IMAGE_DIR "gallery-medium-41.jpg",
75   DEMO_IMAGE_DIR "gallery-medium-42.jpg",
76   DEMO_IMAGE_DIR "gallery-medium-43.jpg",
77   DEMO_IMAGE_DIR "gallery-medium-44.jpg",
78   DEMO_IMAGE_DIR "gallery-medium-45.jpg",
79   DEMO_IMAGE_DIR "gallery-medium-46.jpg",
80   DEMO_IMAGE_DIR "gallery-medium-47.jpg",
81   DEMO_IMAGE_DIR "gallery-medium-48.jpg",
82   DEMO_IMAGE_DIR "gallery-medium-49.jpg",
83   DEMO_IMAGE_DIR "gallery-medium-50.jpg",
84   DEMO_IMAGE_DIR "gallery-medium-51.jpg",
85   DEMO_IMAGE_DIR "gallery-medium-52.jpg",
86   DEMO_IMAGE_DIR "gallery-medium-53.jpg",
87 };
88
89 const char* NINEPATCH_IMAGE_PATH[] = {
90   DEMO_IMAGE_DIR "selection-popup-bg.1.9.png",
91   DEMO_IMAGE_DIR "selection-popup-bg.2.9.png",
92   DEMO_IMAGE_DIR "selection-popup-bg.3.9.png",
93   DEMO_IMAGE_DIR "selection-popup-bg.4.9.png",
94   DEMO_IMAGE_DIR "selection-popup-bg.5.9.png",
95   DEMO_IMAGE_DIR "selection-popup-bg.6.9.png",
96   DEMO_IMAGE_DIR "selection-popup-bg.7.9.png",
97   DEMO_IMAGE_DIR "selection-popup-bg.8.9.png",
98   DEMO_IMAGE_DIR "selection-popup-bg.9.9.png",
99   DEMO_IMAGE_DIR "selection-popup-bg.10.9.png",
100   DEMO_IMAGE_DIR "selection-popup-bg.11.9.png",
101   DEMO_IMAGE_DIR "selection-popup-bg.12.9.png",
102   DEMO_IMAGE_DIR "selection-popup-bg.13.9.png",
103   DEMO_IMAGE_DIR "selection-popup-bg.14.9.png",
104   DEMO_IMAGE_DIR "selection-popup-bg.15.9.png",
105   DEMO_IMAGE_DIR "selection-popup-bg.16.9.png",
106   DEMO_IMAGE_DIR "selection-popup-bg.17.9.png",
107   DEMO_IMAGE_DIR "selection-popup-bg.18.9.png",
108   DEMO_IMAGE_DIR "selection-popup-bg.19.9.png",
109   DEMO_IMAGE_DIR "selection-popup-bg.20.9.png",
110   DEMO_IMAGE_DIR "selection-popup-bg.21.9.png",
111   DEMO_IMAGE_DIR "selection-popup-bg.22.9.png",
112   DEMO_IMAGE_DIR "selection-popup-bg.23.9.png",
113   DEMO_IMAGE_DIR "selection-popup-bg.24.9.png",
114   DEMO_IMAGE_DIR "selection-popup-bg.25.9.png",
115   DEMO_IMAGE_DIR "selection-popup-bg.26.9.png",
116   DEMO_IMAGE_DIR "selection-popup-bg.27.9.png",
117   DEMO_IMAGE_DIR "selection-popup-bg.28.9.png",
118   DEMO_IMAGE_DIR "selection-popup-bg.29.9.png",
119   DEMO_IMAGE_DIR "selection-popup-bg.30.9.png",
120   DEMO_IMAGE_DIR "selection-popup-bg.31.9.png",
121   DEMO_IMAGE_DIR "selection-popup-bg.32.9.png",
122   DEMO_IMAGE_DIR "selection-popup-bg.33.9.png",
123   DEMO_IMAGE_DIR "button-disabled.9.png",
124   DEMO_IMAGE_DIR "button-down.9.png",
125   DEMO_IMAGE_DIR "button-down-disabled.9.png",
126   DEMO_IMAGE_DIR "button-up-1.9.png",
127   DEMO_IMAGE_DIR "button-up-2.9.png",
128   DEMO_IMAGE_DIR "button-up-3.9.png",
129   DEMO_IMAGE_DIR "button-up-4.9.png",
130   DEMO_IMAGE_DIR "button-up-5.9.png",
131   DEMO_IMAGE_DIR "button-up-6.9.png",
132   DEMO_IMAGE_DIR "button-up-7.9.png",
133   DEMO_IMAGE_DIR "button-up-8.9.png",
134   DEMO_IMAGE_DIR "button-up-9.9.png",
135   DEMO_IMAGE_DIR "button-up-10.9.png",
136   DEMO_IMAGE_DIR "button-up-11.9.png",
137   DEMO_IMAGE_DIR "button-up-12.9.png",
138   DEMO_IMAGE_DIR "button-up-13.9.png",
139   DEMO_IMAGE_DIR "button-up-14.9.png",
140   DEMO_IMAGE_DIR "button-up-15.9.png",
141   DEMO_IMAGE_DIR "button-up-16.9.png",
142   DEMO_IMAGE_DIR "button-up-17.9.png",
143 };
144
145 constexpr unsigned int NUM_IMAGES           = sizeof(IMAGE_PATH) / sizeof(char*);
146 constexpr unsigned int NUM_NINEPATCH_IMAGES = sizeof(NINEPATCH_IMAGE_PATH) / sizeof(char*);
147
148 struct VertexWithTexture
149 {
150   Vector2 position;
151   Vector2 texCoord;
152 };
153
154 bool gUseMesh(false);
155 bool gUseNinePatch(false);
156
157 constexpr unsigned int ROWS_PER_PAGE(15);
158 constexpr unsigned int COLUMNS_PER_PAGE(15);
159 constexpr unsigned int PAGE_COUNT(10);
160
161 float gScrollDuration(10.0f); ///< Default animation duration for the scroll, is modifiable with the -t option
162
163 Renderer CreateRenderer(unsigned int index, Geometry geometry, Shader shader)
164 {
165   Renderer    renderer   = Renderer::New(geometry, shader);
166   const char* imagePath  = !gUseNinePatch ? IMAGE_PATH[index] : NINEPATCH_IMAGE_PATH[index];
167   Texture     texture    = DemoHelper::LoadTexture(imagePath);
168   TextureSet  textureSet = TextureSet::New();
169   textureSet.SetTexture(0u, texture);
170   renderer.SetTextures(textureSet);
171   renderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF);
172   return renderer;
173 }
174
175 } // namespace
176
177 /**
178  * Test application to compare performance between ImageView & manually created Renderers
179  * By default, the application consist of 10 pages of 15x15 Images, this can be modified using the following command line arguments:
180  *  -t[duration] (seconds)
181  *  --use-mesh (Use Renderer API)
182  *  --nine-patch (Use nine-patch images in ImageView)
183  */
184 class PerfScroll : public ConnectionTracker
185 {
186 public:
187   PerfScroll(Application& application)
188   : mApplication(application),
189     mRowsPerPage(ROWS_PER_PAGE),
190     mColumnsPerPage(COLUMNS_PER_PAGE),
191     mPageCount(PAGE_COUNT)
192   {
193     // Connect to the Application's Init signal
194     mApplication.InitSignal().Connect(this, &PerfScroll::Create);
195   }
196
197   ~PerfScroll() = default;
198
199   // The Init signal is received once (only) during the Application lifetime
200   void Create(Application& application)
201   {
202     // Get a handle to the window
203     Window window = application.GetWindow();
204     window.SetBackgroundColor(Color::WHITE);
205     Vector2 windowSize = window.GetSize();
206
207     window.GetRootLayer().SetProperty(Layer::Property::DEPTH_TEST, false);
208
209     mSize = Vector3(windowSize.x / mColumnsPerPage, windowSize.y / mRowsPerPage, 0.0f);
210
211     // Respond to a click anywhere on the window
212     window.GetRootLayer().TouchedSignal().Connect(this, &PerfScroll::OnTouch);
213
214     // Respond to key events
215     window.KeyEventSignal().Connect(this, &PerfScroll::OnKeyEvent);
216
217     mParent = Actor::New();
218     mParent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
219     window.Add(mParent);
220
221     if(gUseMesh)
222     {
223       CreateMeshActors();
224     }
225     else
226     {
227       CreateImageViews();
228     }
229
230     PositionActors();
231     ScrollAnimation();
232   }
233
234   bool OnTouch(Actor actor, const TouchEvent& touch)
235   {
236     // quit the application
237     mApplication.Quit();
238     return true;
239   }
240
241   const char* ImagePath(int i)
242   {
243     return !gUseNinePatch ? IMAGE_PATH[i % NUM_IMAGES] : NINEPATCH_IMAGE_PATH[i % NUM_NINEPATCH_IMAGES];
244   }
245
246   void CreateImageViews()
247   {
248     Window       window = mApplication.GetWindow();
249     unsigned int actorCount(mRowsPerPage * mColumnsPerPage * mPageCount);
250     mActor.resize(actorCount);
251
252     for(size_t i(0); i < actorCount; ++i)
253     {
254       mActor[i] = ImageView::New();
255       Property::Map propertyMap;
256       propertyMap.Insert(Toolkit::ImageVisual::Property::URL, ImagePath(i));
257       propertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
258       mActor[i].SetProperty(Toolkit::ImageView::Property::IMAGE, propertyMap);
259       mActor[i].SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
260       mParent.Add(mActor[i]);
261     }
262   }
263
264   void CreateMeshActors()
265   {
266     unsigned int numImages = !gUseNinePatch ? NUM_IMAGES : NUM_NINEPATCH_IMAGES;
267
268     //Create all the renderers
269     std::vector<Renderer> renderers(numImages);
270     Shader                shader   = Shader::New(SHADER_PERF_SCROLL_VERT, SHADER_PERF_SCROLL_FRAG);
271     Geometry              geometry = DemoHelper::CreateTexturedQuad();
272     for(unsigned int i(0); i < numImages; ++i)
273     {
274       renderers[i] = CreateRenderer(i, geometry, shader);
275     }
276
277     //Create the actors
278     Window       window = mApplication.GetWindow();
279     unsigned int actorCount(mRowsPerPage * mColumnsPerPage * mPageCount);
280     mActor.resize(actorCount);
281     for(size_t i(0); i < actorCount; ++i)
282     {
283       mActor[i] = Actor::New();
284       mActor[i].AddRenderer(renderers[i % numImages]);
285       mParent.Add(mActor[i]);
286     }
287   }
288
289   void PositionActors()
290   {
291     Window  window = mApplication.GetWindow();
292     Vector3 initialPosition(window.GetSize().GetWidth() * 0.5f, window.GetSize().GetHeight() * 0.5f, 1000.0f);
293
294     unsigned int totalColumns = mColumnsPerPage * mPageCount;
295
296     size_t count(0);
297     float  xpos, ypos;
298
299     for(size_t i(0); i < totalColumns; ++i)
300     {
301       xpos = mSize.x * i;
302
303       for(size_t j(0); j < mRowsPerPage; ++j)
304       {
305         ypos = mSize.y * j;
306         mActor[count].SetProperty(Actor::Property::POSITION, Vector3(xpos + mSize.x * 0.5f, ypos + mSize.y * 0.5f, 0.0f));
307         mActor[count].SetProperty(Actor::Property::SIZE, mSize);
308         mActor[count].SetProperty(Actor::Property::ORIENTATION, Quaternion(Radian(0.0f), Vector3::XAXIS));
309         ++count;
310       }
311     }
312   }
313
314   void ScrollAnimation()
315   {
316     Window  window = mApplication.GetWindow();
317     Vector3 windowSize(window.GetSize());
318
319     Animation scrollAnimation = Animation::New(gScrollDuration);
320     scrollAnimation.AnimateBy(Property(mParent, Actor::Property::POSITION), Vector3(-(PAGE_COUNT - 1.) * windowSize.x, 0.0f, 0.0f));
321     scrollAnimation.Play();
322     scrollAnimation.FinishedSignal().Connect(this, [&](Animation&) { mApplication.Quit(); });
323   }
324
325   void OnKeyEvent(const KeyEvent& event)
326   {
327     if(event.GetState() == KeyEvent::DOWN)
328     {
329       if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK))
330       {
331         mApplication.Quit();
332       }
333     }
334   }
335
336 private:
337   Application& mApplication;
338
339   std::vector<Actor> mActor;
340   Actor              mParent;
341
342   Vector3 mSize;
343
344   const unsigned int mRowsPerPage;
345   const unsigned int mColumnsPerPage;
346   const unsigned int mPageCount;
347 };
348
349 int DALI_EXPORT_API main(int argc, char** argv)
350 {
351   for(int i(1); i < argc; ++i)
352   {
353     std::string arg(argv[i]);
354     if(arg.compare("--use-mesh") == 0)
355     {
356       gUseMesh = true;
357     }
358     else if(arg.compare("--nine-patch") == 0)
359     {
360       gUseNinePatch = true;
361     }
362     else if(arg.compare(0, 2, "-t") == 0)
363     {
364       auto newDuration = atof(arg.substr(2, arg.size()).c_str());
365       if(newDuration > 0.0f)
366       {
367         gScrollDuration = newDuration;
368       }
369     }
370     else if((arg.compare("--help") == 0) || (arg.compare("-h") == 0))
371     {
372       cout << "perf-scroll.example [OPTIONS]" << endl;
373       cout << "  Options:" << endl;
374       cout << "    --use-mesh    Uses the Rendering API directly to create actors" << endl;
375       cout << "    --nine-patch  Uses n-patch images instead" << endl;
376       cout << "    -t[seconds]   Replace [seconds] with the animation time required, i.e. -t4. Default is 10s." << endl;
377       cout << "    -h|--help     Help" << endl;
378       return 0;
379     }
380   }
381
382   Application application = Application::New(&argc, &argv);
383
384   PerfScroll test(application);
385   application.MainLoop();
386
387   return 0;
388 }