Merge "Add missing includes." into devel/master
[platform/core/uifw/dali-core.git] / automated-tests / src / dali-internal / utc-Dali-Internal-GeometryBatcher.cpp
1 #include <dali/public-api/dali-core.h>
2 #include <dali/devel-api/actors/actor-devel.h>
3 #include <dali/devel-api/rendering/renderer-devel.h>
4 #include <dali/internal/event/actors/actor-impl.h>
5 #include <dali/internal/update/manager/geometry-batcher.h>
6
7 #include <dali-test-suite-utils.h>
8
9 namespace
10 {
11
12 class MockActor : public Dali::Internal::Actor
13 {
14 public:
15   inline const Dali::Internal::SceneGraph::Node* GetNode()
16   {
17     return mNode;
18   }
19
20   inline const bool IsNodeBatchParent()
21   {
22     return mNode->mIsBatchParent;
23   }
24 };
25
26 Geometry CreateBatchQuadGeometryVector2( Vector4 texCoords )
27 {
28   const float halfWidth = 0.5f;
29   const float halfHeight = 0.5f;
30   struct QuadVertex {
31     QuadVertex( const Vector2& vertexPosition, const Vector2& vertexTexCoords )
32       : position( vertexPosition ),
33         texCoords( vertexTexCoords )
34     {}
35     Vector2 position;
36     Vector2 texCoords;
37   };
38
39   // special case, when texture takes whole space
40   if( texCoords == Vector4::ZERO )
41   {
42     texCoords = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
43   }
44
45   QuadVertex quadVertexData[6] =
46   {
47     QuadVertex( Vector2(-halfWidth,   -halfHeight ),   Vector2(texCoords.x, texCoords.y) ),
48     QuadVertex( Vector2( halfWidth,   -halfHeight ),   Vector2(texCoords.z, texCoords.y) ),
49     QuadVertex( Vector2(-halfWidth,    halfHeight ),   Vector2(texCoords.x, texCoords.w) ),
50     QuadVertex( Vector2( halfWidth,   -halfHeight ),   Vector2(texCoords.z, texCoords.y) ),
51     QuadVertex( Vector2(-halfWidth,    halfHeight ),   Vector2(texCoords.x, texCoords.w) ),
52     QuadVertex( Vector2( halfWidth,    halfHeight ),   Vector2(texCoords.z, texCoords.w) ),
53   };
54
55   Property::Map vertexFormat;
56   vertexFormat[ "aPosition" ] = Property::VECTOR2;
57   vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
58   PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
59   vertexBuffer.SetData( quadVertexData, 6 );
60
61   // create geometry as normal, single quad
62   Geometry geometry = Geometry::New();
63   geometry.AddVertexBuffer( vertexBuffer );
64   geometry.SetType( Geometry::TRIANGLES );
65
66   return geometry;
67 }
68
69 Geometry CreateBatchQuadGeometryVector3( Vector4 texCoords )
70 {
71   const float halfWidth = 0.5f;
72   const float halfHeight = 0.5f;
73   struct QuadVertex {
74     QuadVertex( const Vector3& vertexPosition, const Vector2& vertexTexCoords )
75       : position( vertexPosition ),
76         texCoords( vertexTexCoords )
77     {}
78     Vector3 position;
79     Vector2 texCoords;
80   };
81
82   // special case, when texture takes whole space
83   if( texCoords == Vector4::ZERO )
84   {
85     texCoords = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
86   }
87
88   QuadVertex quadVertexData[6] =
89   {
90     QuadVertex( Vector3(-halfWidth,   -halfHeight, 0.0f ),   Vector2(texCoords.x, texCoords.y) ),
91     QuadVertex( Vector3( halfWidth,   -halfHeight, 0.0f ),   Vector2(texCoords.z, texCoords.y) ),
92     QuadVertex( Vector3(-halfWidth,    halfHeight, 0.0f ),   Vector2(texCoords.x, texCoords.w) ),
93     QuadVertex( Vector3( halfWidth,   -halfHeight, 0.0f ),   Vector2(texCoords.z, texCoords.y) ),
94     QuadVertex( Vector3(-halfWidth,    halfHeight, 0.0f ),   Vector2(texCoords.x, texCoords.w) ),
95     QuadVertex( Vector3( halfWidth,    halfHeight, 0.0f ),   Vector2(texCoords.z, texCoords.w) ),
96   };
97
98   Property::Map vertexFormat;
99   vertexFormat[ "aPosition" ] = Property::VECTOR3;
100   vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
101   PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
102   vertexBuffer.SetData( quadVertexData, 6 );
103
104   // create geometry as normal, single quad
105   Geometry geometry = Geometry::New();
106   geometry.AddVertexBuffer( vertexBuffer );
107   geometry.SetType( Geometry::TRIANGLES );
108   return geometry;
109 }
110
111 Geometry CreateBatchQuadGeometryVector4( Vector4 texCoords )
112 {
113   const float halfWidth = 0.5f;
114   const float halfHeight = 0.5f;
115   struct QuadVertex {
116     QuadVertex( const Vector4& vertexPosition, const Vector2& vertexTexCoords )
117       : position( vertexPosition ),
118         texCoords( vertexTexCoords )
119     {}
120     Vector4 position;
121     Vector2 texCoords;
122   };
123
124   // special case, when texture takes whole space
125   if( texCoords == Vector4::ZERO )
126   {
127     texCoords = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
128   }
129
130   QuadVertex quadVertexData[6] =
131   {
132     QuadVertex( Vector4(-halfWidth,   -halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.x, texCoords.y) ),
133     QuadVertex( Vector4( halfWidth,   -halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.z, texCoords.y) ),
134     QuadVertex( Vector4(-halfWidth,    halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.x, texCoords.w) ),
135     QuadVertex( Vector4( halfWidth,   -halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.z, texCoords.y) ),
136     QuadVertex( Vector4(-halfWidth,    halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.x, texCoords.w) ),
137     QuadVertex( Vector4( halfWidth,    halfHeight, 0.0f, 1.0f ),   Vector2(texCoords.z, texCoords.w) ),
138   };
139
140   Property::Map vertexFormat;
141   vertexFormat[ "aPosition" ] = Property::VECTOR4;
142   vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
143   PropertyBuffer vertexBuffer = PropertyBuffer::New( vertexFormat );
144   vertexBuffer.SetData( quadVertexData, 6 );
145
146   // create geometry as normal, single quad
147   Geometry geometry = Geometry::New();
148   geometry.AddVertexBuffer( vertexBuffer );
149   geometry.SetType( Geometry::TRIANGLES );
150   return geometry;
151 }
152
153
154 void CreateShadersAndTextureSets( Shader* shaders, size_t shaderCount, TextureSet* textureSets, size_t textureSetCount )
155 {
156   for( size_t i = 0; i < shaderCount; ++i )
157   {
158     shaders[i] = Shader::New( "", "" );
159   }
160
161   for( size_t i = 0; i < textureSetCount; ++i )
162   {
163     textureSets[i] = TextureSet::New();
164   }
165 }
166
167 Vector4 WHOLE_IMAGE( 0.0f, 0.0f, 1.0f, 1.0f );
168
169 Actor CreateActor( Actor& parent, Shader& shader, TextureSet& textureSet, Vector3 position, Vector4 texCoords, Geometry(*geomfunc)(Vector4) = CreateBatchQuadGeometryVector2 )
170 {
171   Geometry geometry = geomfunc( texCoords );
172   Renderer renderer = Renderer::New( geometry, shader );
173
174   renderer.SetTextures( textureSet );
175   renderer.SetProperty( Dali::DevelRenderer::Property::BATCHING_ENABLED, true );
176
177   Actor actor = Actor::New();
178   actor.SetPosition( position );
179   parent.Add( actor );
180   actor.AddRenderer( renderer );
181   return actor;
182 }
183
184 Actor CreateActor( Vector3 position )
185 {
186   Actor actor = Actor::New();
187   actor.SetPosition( position );
188   return actor;
189 }
190
191
192 Actor CreateBatchParent( Vector3 pos )
193 {
194   Actor actor = Actor::New();
195   actor.SetProperty( DevelActor::Property::BATCH_PARENT, true );
196   actor.SetPosition( pos );
197   Stage::GetCurrent().Add( actor );
198   return actor;
199 }
200
201 void AddChildren( Actor parent, Actor* children, size_t size )
202 {
203   for( size_t i = 0; i < size; ++i )
204   {
205     parent.Add( children[i] );
206   }
207 }
208
209 }
210
211 int UtcDaliGeometryBatcherBatchLevel0(void)
212 {
213   TestApplication app;
214   TestGlAbstraction& glAbstraction = app.GetGlAbstraction();
215   glAbstraction.EnableDrawCallTrace( true );
216   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
217
218   Shader shaders[1];
219   TextureSet textureSets[1];
220
221   CreateShadersAndTextureSets( shaders, 1, textureSets, 1 );
222   Actor batchParent = CreateBatchParent( Vector3::ZERO );
223   batchParent.SetSize( Stage::GetCurrent().GetSize() );
224
225   Actor children[] = {
226     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
227     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
228     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
229     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE )
230   };
231
232   app.SendNotification();
233   app.Render( 16 );
234   app.SendNotification();
235   app.Render( 16 );
236
237   // should be 1 draw call
238   {
239     int result = drawTrace.CountMethod( "DrawElements");
240     DALI_TEST_CHECK( result == 1 );
241   }
242
243   // remove actor
244   batchParent.Remove( children[0] );
245   children[0].Reset();
246
247   // update
248   app.SendNotification();
249   app.Render( 16 );
250
251   // test geometry for that batch, 1 batch, 3 children, 18 elements in the buffer
252   //Dali::Internal::Actor& actor = GetImplementation( children[1] );
253   MockActor* mockActor = static_cast<MockActor*>( &GetImplementation( children[1] ) );
254   Dali::Internal::SceneGraph::GeometryBatcher* geometryBatcher = mockActor->GetNode()->mGeometryBatcher;
255   DALI_TEST_CHECK( geometryBatcher ); // must not be NULL
256
257   Dali::Internal::Render::Geometry* geometry = geometryBatcher->GetGeometry( 0 );
258   int elementCount = geometry->GetPropertyBuffer(0)->GetElementCount();
259   DALI_TEST_CHECK( elementCount == 18 );
260
261   // delete batch parent
262   Stage::GetCurrent().Remove( batchParent );
263   batchParent.Reset();
264
265   // update
266   app.SendNotification();
267   app.Render( 16 );
268
269   END_TEST;
270 }
271
272 int UtcDaliGeometryBatcherBatchMultipleTextureSet(void)
273 {
274   TestApplication app;
275   TestGlAbstraction& glAbstraction = app.GetGlAbstraction();
276   glAbstraction.EnableDrawCallTrace( true );
277   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
278
279   Shader shaders[1];
280   TextureSet textureSets[3];
281   CreateShadersAndTextureSets( shaders, 1, textureSets, 3 );
282
283   Actor batchParent = CreateBatchParent( Vector3::ZERO );
284   batchParent.SetSize( Stage::GetCurrent().GetSize() );
285
286   Actor children[] = {
287     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
288     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
289     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
290     CreateActor( batchParent, shaders[0], textureSets[0], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
291     CreateActor( batchParent, shaders[0], textureSets[1], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
292     CreateActor( batchParent, shaders[0], textureSets[2], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
293     CreateActor( batchParent, shaders[0], textureSets[2], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
294     CreateActor( batchParent, shaders[0], textureSets[1], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
295     CreateActor( batchParent, shaders[0], textureSets[1], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
296     CreateActor( batchParent, shaders[0], textureSets[1], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
297     CreateActor( batchParent, shaders[0], textureSets[2], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE ),
298     CreateActor( batchParent, shaders[0], textureSets[2], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE )
299   };
300
301   // must update twice
302   app.SendNotification();
303   app.Render( 16 );
304   app.SendNotification();
305   app.Render( 16 );
306
307   // should be 3 draw calls here
308   {
309     int result = drawTrace.CountMethod( "DrawElements");
310     DALI_TEST_CHECK( result == 3 );
311   }
312
313   // test assigned indices
314   {
315     bool indicesTest( true );
316     for( size_t i = 0; i < 12; ++i )
317     {
318       MockActor* mockActor = static_cast<MockActor*>( &GetImplementation( children[1] ) );
319       if( mockActor->GetNode()->mBatchIndex == BATCH_NULL_HANDLE )
320       {
321         indicesTest = false;
322       }
323     }
324     DALI_TEST_CHECK( indicesTest );
325   }
326
327   END_TEST;
328 }
329
330 int UtcDaliGeometryBatcherSettingBatchParent(void)
331 {
332   TestApplication app;
333
334   Shader shaders[1];
335   TextureSet textureSets[1];
336   CreateShadersAndTextureSets( shaders, 1, textureSets, 1 );
337
338   Actor batchParent = CreateBatchParent( Vector3::ZERO );
339   batchParent.SetSize( Stage::GetCurrent().GetSize() );
340   app.SendNotification();
341   app.Render( 16 );
342
343   MockActor* mockActor = static_cast<MockActor*>( &GetImplementation( batchParent ) );
344   DALI_TEST_CHECK( mockActor->IsNodeBatchParent() );
345
346   END_TEST;
347 }
348
349 int UtcDaliGeometryBatcherBatchMultipleParents(void)
350 {
351   TestApplication app;
352   TestGlAbstraction& glAbstraction = app.GetGlAbstraction();
353   glAbstraction.EnableDrawCallTrace( true );
354   TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
355
356   Shader shaders[2];
357   TextureSet textureSets[2];
358   CreateShadersAndTextureSets( shaders, 2, textureSets, 2 );
359
360   Actor batchParent0 = CreateBatchParent( Vector3::ZERO ); // Vector2
361   batchParent0.SetSize( Stage::GetCurrent().GetSize() );
362   Actor batchParent1 = CreateBatchParent( Vector3::ZERO ); // Vector3
363   batchParent1.SetSize( Stage::GetCurrent().GetSize() );
364   Actor batchParent2 = CreateBatchParent( Vector3::ZERO ); // Vector4
365   batchParent2.SetSize( Stage::GetCurrent().GetSize() );
366
367   CreateActor( batchParent0, shaders[0], textureSets[0], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE );
368   CreateActor( batchParent0, shaders[0], textureSets[0], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE );
369   CreateActor( batchParent0, shaders[0], textureSets[0], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE );
370   CreateActor( batchParent0, shaders[0], textureSets[0], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE );
371   CreateActor( batchParent0, shaders[0], textureSets[0], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE );
372   CreateActor( batchParent1, shaders[1], textureSets[1], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE,  CreateBatchQuadGeometryVector3 );
373   CreateActor( batchParent1, shaders[1], textureSets[1], Vector3( 10.0f, 0.0f, 0.0f ), WHOLE_IMAGE, CreateBatchQuadGeometryVector3 );
374   CreateActor( batchParent1, shaders[1], textureSets[1], Vector3( 20.0f, 0.0f, 0.0f ), WHOLE_IMAGE, CreateBatchQuadGeometryVector3 );
375   CreateActor( batchParent2, shaders[0], textureSets[1], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE, CreateBatchQuadGeometryVector4 );
376   CreateActor( batchParent2, shaders[0], textureSets[1], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE,  CreateBatchQuadGeometryVector4 );
377   CreateActor( batchParent2, shaders[0], textureSets[1], Vector3( 30.0f, 0.0f, 0.0f ), WHOLE_IMAGE, CreateBatchQuadGeometryVector4 );
378   CreateActor( batchParent2, shaders[0], textureSets[1], Vector3( 0.0f, 0.0f, 0.0f ), WHOLE_IMAGE,  CreateBatchQuadGeometryVector4 );
379
380   // must update twice
381   app.SendNotification();
382   app.Render( 16 );
383   app.SendNotification();
384   app.Render( 16 );
385
386   // should be 3 draw calls here
387   {
388     int result = drawTrace.CountMethod( "DrawElements");
389     DALI_TEST_EQUALS( result, 3, TEST_LOCATION );
390   }
391
392   // delete batch parent
393   Stage::GetCurrent().Remove( batchParent1 );
394   batchParent1.Reset();
395   drawTrace.Reset();
396   app.SendNotification();
397   app.Render( 16 );
398   // should be 2 draw calls here
399   {
400     int result = drawTrace.CountMethod( "DrawElements");
401     DALI_TEST_EQUALS( result, 2, TEST_LOCATION );
402   }
403
404   END_TEST;
405 }