Added demo to compare performance between ImageActor and ImageView
[platform/core/uifw/dali-demo.git] / examples / benchmark / benchmark.cpp
1 /*
2  * Copyright (c) 2015 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/devel-api/rendering/renderer.h>
20 #include <dali/public-api/common/dali-common.h>
21 #include <dali/integration-api/resource-policies.h>
22 #include <dali/integration-api/debug.h>
23 #include <iostream>
24
25 using namespace Dali;
26 using namespace Dali::Toolkit;
27
28
29 namespace
30 {
31 const char* IMAGE_PATH[] = {
32                             DALI_IMAGE_DIR "gallery-medium-1.jpg",
33                             DALI_IMAGE_DIR "gallery-medium-2.jpg",
34                             DALI_IMAGE_DIR "gallery-medium-3.jpg",
35                             DALI_IMAGE_DIR "gallery-medium-4.jpg",
36                             DALI_IMAGE_DIR "gallery-medium-5.jpg",
37                             DALI_IMAGE_DIR "gallery-medium-6.jpg",
38                             DALI_IMAGE_DIR "gallery-medium-7.jpg",
39                             DALI_IMAGE_DIR "gallery-medium-8.jpg",
40                             DALI_IMAGE_DIR "gallery-medium-9.jpg",
41                             DALI_IMAGE_DIR "gallery-medium-10.jpg",
42                             DALI_IMAGE_DIR "gallery-medium-11.jpg",
43                             DALI_IMAGE_DIR "gallery-medium-12.jpg",
44                             DALI_IMAGE_DIR "gallery-medium-13.jpg",
45                             DALI_IMAGE_DIR "gallery-medium-14.jpg",
46                             DALI_IMAGE_DIR "gallery-medium-15.jpg",
47                             DALI_IMAGE_DIR "gallery-medium-16.jpg",
48                             DALI_IMAGE_DIR "gallery-medium-17.jpg",
49                             DALI_IMAGE_DIR "gallery-medium-18.jpg",
50                             DALI_IMAGE_DIR "gallery-medium-19.jpg",
51                             DALI_IMAGE_DIR "gallery-medium-20.jpg",
52                             DALI_IMAGE_DIR "gallery-medium-21.jpg",
53                             DALI_IMAGE_DIR "gallery-medium-22.jpg",
54                             DALI_IMAGE_DIR "gallery-medium-23.jpg",
55                             DALI_IMAGE_DIR "gallery-medium-24.jpg",
56                             DALI_IMAGE_DIR "gallery-medium-25.jpg",
57                             DALI_IMAGE_DIR "gallery-medium-26.jpg",
58                             DALI_IMAGE_DIR "gallery-medium-27.jpg",
59                             DALI_IMAGE_DIR "gallery-medium-28.jpg",
60                             DALI_IMAGE_DIR "gallery-medium-29.jpg",
61                             DALI_IMAGE_DIR "gallery-medium-30.jpg",
62                             DALI_IMAGE_DIR "gallery-medium-31.jpg",
63                             DALI_IMAGE_DIR "gallery-medium-32.jpg",
64                             DALI_IMAGE_DIR "gallery-medium-33.jpg",
65                             DALI_IMAGE_DIR "gallery-medium-34.jpg",
66                             DALI_IMAGE_DIR "gallery-medium-35.jpg",
67                             DALI_IMAGE_DIR "gallery-medium-36.jpg",
68                             DALI_IMAGE_DIR "gallery-medium-37.jpg",
69                             DALI_IMAGE_DIR "gallery-medium-38.jpg",
70                             DALI_IMAGE_DIR "gallery-medium-39.jpg",
71                             DALI_IMAGE_DIR "gallery-medium-40.jpg",
72                             DALI_IMAGE_DIR "gallery-medium-41.jpg",
73                             DALI_IMAGE_DIR "gallery-medium-42.jpg",
74                             DALI_IMAGE_DIR "gallery-medium-43.jpg",
75                             DALI_IMAGE_DIR "gallery-medium-44.jpg",
76                             DALI_IMAGE_DIR "gallery-medium-45.jpg",
77                             DALI_IMAGE_DIR "gallery-medium-46.jpg",
78                             DALI_IMAGE_DIR "gallery-medium-47.jpg",
79                             DALI_IMAGE_DIR "gallery-medium-48.jpg",
80                             DALI_IMAGE_DIR "gallery-medium-49.jpg",
81                             DALI_IMAGE_DIR "gallery-medium-50.jpg",
82                             DALI_IMAGE_DIR "gallery-medium-51.jpg",
83                             DALI_IMAGE_DIR "gallery-medium-52.jpg",
84                             DALI_IMAGE_DIR "gallery-medium-53.jpg",
85 };
86
87 const unsigned int NUM_IMAGES = sizeof(IMAGE_PATH) / sizeof(char*);
88
89 const float ANIMATION_TIME ( 5.0f ); // animation length in seconds
90
91 struct VertexWithTexture
92 {
93   Vector2 position;
94   Vector2 texCoord;
95 };
96
97 VertexWithTexture gQuadWithTexture[] = {
98                                         { Vector2( -0.5f, -0.5f ), Vector2( 0.0f, 0.0f ) },
99                                         { Vector2(  0.5f, -0.5f ), Vector2( 1.0f, 0.0f ) },
100                                         { Vector2( -0.5f,  0.5f ), Vector2( 0.0f, 1.0f ) },
101                                         { Vector2(  0.5f,  0.5f ), Vector2( 1.0f, 1.0f ) }
102 };
103
104 const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
105     attribute mediump vec2 aPosition;\n
106     attribute mediump vec2 aTexCoord;\n
107     uniform mediump mat4 uMvpMatrix;\n
108     uniform mediump vec3 uSize;\n
109     varying mediump vec2 vTexCoord;\n
110     void main()\n
111     {\n
112       vec4 position = vec4(aPosition,0.0,1.0)*vec4(uSize,1.0);\n
113       gl_Position = uMvpMatrix * position;\n
114       vTexCoord = aTexCoord;\n
115     }\n
116 );
117
118 const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
119     uniform lowp vec4 uColor;\n
120     uniform sampler2D sTexture;\n
121     varying mediump vec2 vTexCoord;\n
122
123     void main()\n
124     {\n
125       gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
126     }\n
127 );
128
129
130 Geometry& QuadMesh()
131 {
132   static Geometry mesh;
133   if( !mesh )
134   {
135     PropertyBuffer vertexBuffer;
136     Property::Map vertexFormat;
137     vertexFormat["aPosition"] = Property::VECTOR2;
138     vertexFormat["aTexCoord"] = Property::VECTOR2;
139
140     //Create a vertex buffer for vertex positions and texture coordinates
141     vertexBuffer = PropertyBuffer::New( vertexFormat, 4u );
142     vertexBuffer.SetData( gQuadWithTexture );
143
144     //Create the geometry
145     mesh = Geometry::New();
146     mesh.AddVertexBuffer( vertexBuffer );
147     mesh.SetGeometryType(Geometry::TRIANGLE_STRIP );
148   }
149   return mesh;
150 }
151
152 Renderer CreateRenderer( unsigned int index )
153 {
154   static Renderer renderers[NUM_IMAGES];
155   if( !renderers[index] )
156   {
157     //Create the renderer
158     Shader shader = Shader::New( VERTEX_SHADER_TEXTURE, FRAGMENT_SHADER_TEXTURE );
159     Image image = ResourceImage::New(IMAGE_PATH[index]);
160     Sampler textureSampler = Sampler::New( image, "sTexture" );
161     Material material = Material::New( shader );
162     material.AddSampler(textureSampler);
163     material.SetBlendMode( BlendingMode::OFF );
164     renderers[index] = Renderer::New( QuadMesh(), material );
165   }
166   return renderers[index];
167 }
168
169 Actor CreateMeshActor( unsigned int index)
170 {
171   Renderer renderer = CreateRenderer(index);
172   Actor meshActor = Actor::New();
173   meshActor.AddRenderer( renderer );
174   return meshActor;
175 }
176
177 bool gUseMesh(false);
178 bool gUseImageView(false);
179 unsigned int gRowsPerPage(25);
180 unsigned int gColumnsPerPage( 25 );
181 unsigned int gPageCount(13);
182
183
184 }
185 // Test application to compare performance between ImageActor and ImageView
186 // By default, the application consist of 10 pages of 25x25 ImageActors, this can be modified using the following command line arguments:
187 // -r NumberOfRows  (Modifies the number of rows per page)
188 // -c NumberOfColumns (Modifies the number of columns per page)
189 // -p NumberOfPages (Modifies the nimber of pages )
190 // --use-imageview ( Use ImageView instead of ImageActor )
191 // --use-mesh ( Use new renderer API (as ImageView) but shares renderers between actors when possible )
192
193 //
194 class Benchmark : public ConnectionTracker
195 {
196 public:
197
198   Benchmark( Application& application )
199 : mApplication( application ),
200   mRowsPerPage( gRowsPerPage ),
201   mColumnsPerPage( gColumnsPerPage ),
202   mPageCount( gPageCount )
203 {
204     // Connect to the Application's Init signal
205     mApplication.InitSignal().Connect( this, &Benchmark::Create );
206 }
207
208   ~Benchmark()
209   {
210     // Nothing to do here;
211   }
212
213   // The Init signal is received once (only) during the Application lifetime
214   void Create( Application& application )
215   {
216     // Get a handle to the stage
217     Stage stage = Stage::GetCurrent();
218     stage.SetBackgroundColor( Color::WHITE );
219     Vector2 stageSize = stage.GetSize();
220
221     stage.GetRootLayer().SetDepthTestDisabled(true);
222
223     mSize = Vector3( stageSize.x / mColumnsPerPage, stageSize.y / mRowsPerPage, 0.0f );
224
225     // Respond to a click anywhere on the stage
226     stage.GetRootLayer().TouchedSignal().Connect( this, &Benchmark::OnTouch );
227
228     if( gUseMesh )
229     {
230       CreateMeshActors();
231     }
232     else if( gUseImageView )
233     {
234       CreateImageViews();
235     }
236     else
237     {
238       CreateImageActors();
239     }
240
241     ShowAnimation();
242   }
243
244   bool OnTouch( Actor actor, const TouchEvent& touch )
245   {
246     // quit the application
247     mApplication.Quit();
248     return true;
249   }
250
251   void CreateImageActors()
252   {
253     Stage stage = Stage::GetCurrent();
254     unsigned int actorCount(mRowsPerPage*mColumnsPerPage * mPageCount);
255     mActor.resize(actorCount);
256
257     for( size_t i(0); i<actorCount; ++i )
258     {
259       Image image = ResourceImage::New(IMAGE_PATH[i % NUM_IMAGES]);
260       mActor[i] = ImageActor::New(image);
261       mActor[i].SetSize(Vector3(0.0f,0.0f,0.0f));
262       mActor[i].SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
263       stage.Add(mActor[i]);
264     }
265   }
266
267   void CreateImageViews()
268   {
269     Stage stage = Stage::GetCurrent();
270     unsigned int actorCount(mRowsPerPage*mColumnsPerPage * mPageCount);
271     mImageView.resize(actorCount);
272
273     for( size_t i(0); i<actorCount; ++i )
274     {
275       Image image = ResourceImage::New(IMAGE_PATH[i % NUM_IMAGES]);
276       mImageView[i] = ImageView::New(image);
277       mImageView[i].SetSize(Vector3(0.0f,0.0f,0.0f));
278       mImageView[i].SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
279       stage.Add(mImageView[i]);
280     }
281   }
282
283   void CreateMeshActors()
284   {
285     Stage stage = Stage::GetCurrent();
286     unsigned int actorCount(mRowsPerPage*mColumnsPerPage * mPageCount);
287     mActor.resize(actorCount);
288     for( size_t i(0); i<actorCount; ++i )
289     {
290       mActor[i] = CreateMeshActor(i % NUM_IMAGES);
291       mActor[i].SetSize(0.0f,0.0f,0.0f);
292
293       stage.Add(mActor[i]);
294     }
295   }
296
297   void OnAnimationEnd( Animation& source )
298   {
299     if( source == mShow )
300     {
301       ScrollAnimation();
302     }
303     else if( source == mScroll )
304     {
305       HideAnimation();
306     }
307     else
308     {
309       mApplication.Quit();
310     }
311   }
312
313   void ShowAnimation()
314   {
315     Stage stage = Stage::GetCurrent();
316     Vector3 initialPosition( stage.GetSize().x * 0.5f, stage.GetSize().y*0.5f, 1000.0f );
317
318     unsigned int totalColumns = mColumnsPerPage * mPageCount;
319
320     size_t count(0);
321     float xpos, ypos;
322     mShow = Animation::New(0.0f);
323
324     float totalDuration( 10.0f );
325     float durationPerActor( 0.5f );
326     float delayBetweenActors = ( totalDuration - durationPerActor) / (mRowsPerPage*mColumnsPerPage);
327     for( size_t i(0); i<totalColumns; ++i )
328     {
329       xpos = mSize.x * i;
330
331       for( size_t j(0);j<mRowsPerPage;++j)
332       {
333
334         ypos = mSize.y * j;
335
336         float delay = 0.0f;
337         float duration = 0.0f;
338         if( count < mRowsPerPage*mColumnsPerPage )
339         {
340           duration = durationPerActor;
341           delay = delayBetweenActors * count;
342         }
343         if( gUseImageView )
344         {
345           mImageView[count].SetPosition( initialPosition );
346           mImageView[count].SetSize( Vector3(0.0f,0.0f,0.0f) );
347           mImageView[count].SetOrientation( Quaternion( Radian(0.0f),Vector3::XAXIS));
348           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 ));
349           mShow.AnimateTo( Property( mImageView[count], Actor::Property::SIZE), mSize, AlphaFunction::EASE_OUT_BACK, TimePeriod( delay, duration ));
350         }
351         else
352         {
353           mActor[count].SetPosition( initialPosition );
354           mActor[count].SetSize( Vector3(0.0f,0.0f,0.0f) );
355           mActor[count].SetOrientation( Quaternion( Radian(0.0f),Vector3::XAXIS));
356           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 ));
357           mShow.AnimateTo( Property( mActor[count], Actor::Property::SIZE), mSize, AlphaFunction::EASE_OUT_BACK, TimePeriod( delay, duration ));
358         }
359         ++count;
360       }
361     }
362     mShow.Play();
363     mShow.FinishedSignal().Connect( this, &Benchmark::OnAnimationEnd );
364   }
365
366   void ScrollAnimation()
367   {
368     Stage stage = Stage::GetCurrent();
369     Vector3 stageSize( stage.GetSize() );
370
371     mScroll = Animation::New(10.0f);
372     size_t actorCount( mRowsPerPage*mColumnsPerPage*mPageCount);
373     for( size_t i(0); i<actorCount; ++i )
374     {
375       if( gUseImageView )
376       {
377         mScroll.AnimateBy( Property( mImageView[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(0.0f,3.0f));
378         mScroll.AnimateBy( Property( mImageView[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(3.0f,3.0f));
379         mScroll.AnimateBy( Property( mImageView[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(6.0f,2.0f));
380         mScroll.AnimateBy( Property( mImageView[i], Actor::Property::POSITION), Vector3( 12.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(8.0f,2.0f));
381       }
382       else
383       {
384         mScroll.AnimateBy( Property( mActor[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(0.0f,3.0f));
385         mScroll.AnimateBy( Property( mActor[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(3.0f,3.0f));
386         mScroll.AnimateBy( Property( mActor[i], Actor::Property::POSITION), Vector3(-4.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(6.0f,2.0f));
387         mScroll.AnimateBy( Property( mActor[i], Actor::Property::POSITION), Vector3( 12.0f*stageSize.x,0.0f, 0.0f), AlphaFunction::EASE_OUT, TimePeriod(8.0f,2.0f));
388       }
389     }
390     mScroll.Play();
391     mScroll.FinishedSignal().Connect( this, &Benchmark::OnAnimationEnd );
392   }
393
394   void HideAnimation()
395   {
396     size_t count(0);
397     unsigned int actorsPerPage( mRowsPerPage*mColumnsPerPage );
398     mHide = Animation::New(0.0f);
399
400     unsigned int totalColumns = mColumnsPerPage * mPageCount;
401
402     float totalDuration( 5.0f);
403     float durationPerActor( 0.5f );
404     float delayBetweenActors = ( totalDuration - durationPerActor) / (mRowsPerPage*mColumnsPerPage);
405     for( size_t i(0); i<mRowsPerPage; ++i )
406     {
407       for( size_t j(0);j<totalColumns;++j)
408       {
409         float delay = 0.0f;
410         float duration = 0.0f;
411         if( count < actorsPerPage )
412         {
413           duration = durationPerActor;
414           delay = delayBetweenActors * count;
415         }
416
417         if( gUseImageView )
418         {
419           mHide.AnimateTo( Property( mImageView[count], Actor::Property::ORIENTATION),  Quaternion( Radian( Degree( 70.0f ) ), Vector3::XAXIS ), AlphaFunction::EASE_OUT, TimePeriod( delay, duration ));
420           mHide.AnimateBy( Property( mImageView[count], Actor::Property::POSITION_Z), 1000.0f, AlphaFunction::EASE_OUT_BACK, TimePeriod( delay +delayBetweenActors*actorsPerPage + duration, duration ));
421         }
422         else
423         {
424           mHide.AnimateTo( Property( mActor[count], Actor::Property::ORIENTATION),  Quaternion( Radian( Degree( 70.0f ) ), Vector3::XAXIS ), AlphaFunction::EASE_OUT, TimePeriod( delay, duration ));
425           mHide.AnimateBy( Property( mActor[count], Actor::Property::POSITION_Z), 1000.0f, AlphaFunction::EASE_OUT_BACK, TimePeriod( delay +delayBetweenActors*actorsPerPage + duration, duration ));
426         }
427         ++count;
428       }
429     }
430
431     mHide.Play();
432     mHide.FinishedSignal().Connect( this, &Benchmark::OnAnimationEnd );
433   }
434
435 private:
436   Application&  mApplication;
437
438   std::vector<Actor>  mActor;
439   std::vector<ImageView>  mImageView;
440
441   Vector3             mSize;
442   unsigned int        mRowsPerPage;
443   unsigned int        mColumnsPerPage;
444   unsigned int        mPageCount;
445
446   Animation           mShow;
447   Animation           mScroll;
448   Animation           mHide;
449 };
450
451 void RunTest( Application& application )
452 {
453   Benchmark test( application );
454
455   application.MainLoop();
456 }
457
458 // Entry point for Linux & Tizen applications
459 //
460 int main( int argc, char **argv )
461 {
462   Application application = Application::New( &argc, &argv );
463
464   for( int i(1) ; i < argc; ++i )
465   {
466     std::string arg( argv[i] );
467     if( arg.compare("--use-mesh") == 0)
468     {
469       gUseMesh = true;
470     }
471     else if( arg.compare("--use-imageview") == 0)
472     {
473       gUseImageView = true;
474     }
475     else if( arg.compare(0, 2, "-r" ) == 0)
476     {
477       gRowsPerPage = atoi( arg.substr( 2, arg.size()).c_str());
478     }
479     else if( arg.compare(0, 2, "-c" ) == 0)
480     {
481       gColumnsPerPage = atoi( arg.substr( 2, arg.size()).c_str());
482     }
483     else if( arg.compare(0, 2, "-p" ) == 0)
484     {
485       gPageCount = atoi( arg.substr( 2, arg.size()).c_str());
486     }
487
488
489   }
490
491   RunTest( application );
492
493   return 0;
494 }