[dali_2.3.39] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-VertexBuffer.cpp
1 /*
2  * Copyright (c) 2024 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-test-suite-utils.h>
19 #include <dali/devel-api/threading/thread.h>
20 #include <dali/public-api/dali-core.h>
21 #include <chrono>
22 using namespace std::chrono_literals;
23 using namespace Dali;
24
25 #include <mesh-builder.h>
26 #include <future>
27
28 struct VertexBufferUpdater
29 {
30   struct Diagnostics
31   {
32     bool     success{false};
33     uint32_t counter{0};
34     void*    lastPtr{nullptr};
35     size_t   lastSize{0};
36     size_t   lastReturned{0};
37   };
38
39   VertexBufferUpdater() = default;
40
41   uint32_t UpdateVertices(void* ptr, size_t size)
42   {
43     diagnostics.success      = true;
44     diagnostics.lastPtr      = ptr;
45     diagnostics.lastSize     = size;
46     diagnostics.lastReturned = returnSize;
47     diagnostics.counter++;
48
49     promise.set_value(diagnostics);
50     return returnSize;
51   }
52
53   void SetCallbackReturnValue(size_t size)
54   {
55     returnSize = size;
56   }
57
58   void Reset()
59   {
60     promise = std::promise<Diagnostics>();
61   }
62
63   std::unique_ptr<VertexBufferUpdateCallback> CreateCallback()
64   {
65     return VertexBufferUpdateCallback::New(this, &VertexBufferUpdater::UpdateVertices);
66   }
67
68   Diagnostics GetValue()
69   {
70     auto value = promise.get_future().get();
71
72     // reset promise automatically
73     promise = {};
74     return value;
75   }
76
77   Diagnostics GetValueWithTimeout()
78   {
79     auto future = promise.get_future();
80     auto status = future.wait_for(1s);
81     if(status == std::future_status::ready)
82     {
83       promise = {};
84       return promise.get_future().get();
85     }
86
87     promise = {};
88     // reset promise automatically
89     Diagnostics failure{};
90     failure.success = false;
91     return failure;
92   }
93
94   bool IsValueReady()
95   {
96     // fake-wait for two frames
97     auto status = promise.get_future().wait_for(32ms);
98     return status == std::future_status::ready;
99   }
100
101   Diagnostics               diagnostics;
102   size_t                    returnSize{0u};
103   std::promise<Diagnostics> promise;
104 };
105
106 void vertexBuffer_test_startup(void)
107 {
108   test_return_value = TET_UNDEF;
109 }
110
111 void vertexBuffer_test_cleanup(void)
112 {
113   test_return_value = TET_PASS;
114 }
115
116 int UtcDaliVertexBufferNew01(void)
117 {
118   TestApplication application;
119
120   Property::Map texturedQuadVertexFormat;
121   texturedQuadVertexFormat["aPosition"]    = Property::VECTOR2;
122   texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
123
124   VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
125
126   DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
127   END_TEST;
128 }
129
130 int UtcDaliVertexBufferNew02(void)
131 {
132   TestApplication application;
133   VertexBuffer    vertexBuffer;
134   DALI_TEST_EQUALS((bool)vertexBuffer, false, TEST_LOCATION);
135   END_TEST;
136 }
137
138 int UtcDaliVertexBufferDownCast01(void)
139 {
140   TestApplication application;
141
142   Property::Map texturedQuadVertexFormat;
143   texturedQuadVertexFormat["aPosition"]    = Property::VECTOR2;
144   texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
145
146   VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
147
148   BaseHandle   handle(vertexBuffer);
149   VertexBuffer vertexBuffer2 = VertexBuffer::DownCast(handle);
150   DALI_TEST_EQUALS((bool)vertexBuffer2, true, TEST_LOCATION);
151   END_TEST;
152 }
153
154 int UtcDaliVertexBufferDownCast02(void)
155 {
156   TestApplication application;
157
158   Handle       handle       = Handle::New(); // Create a custom object
159   VertexBuffer vertexBuffer = VertexBuffer::DownCast(handle);
160   DALI_TEST_EQUALS((bool)vertexBuffer, false, TEST_LOCATION);
161   END_TEST;
162 }
163
164 int UtcDaliVertexBufferCopyConstructor(void)
165 {
166   TestApplication application;
167
168   VertexBuffer vertexBuffer = CreateVertexBuffer();
169
170   VertexBuffer vertexBufferCopy(vertexBuffer);
171
172   DALI_TEST_EQUALS((bool)vertexBufferCopy, true, TEST_LOCATION);
173   DALI_TEST_EQUALS(vertexBufferCopy.GetSize(), 0u, TEST_LOCATION);
174
175   END_TEST;
176 }
177
178 int UtcDaliVertexBufferAssignmentOperator(void)
179 {
180   TestApplication application;
181
182   VertexBuffer vertexBuffer = CreateVertexBuffer();
183
184   VertexBuffer vertexBuffer2;
185   DALI_TEST_EQUALS((bool)vertexBuffer2, false, TEST_LOCATION);
186
187   vertexBuffer2 = vertexBuffer;
188   DALI_TEST_EQUALS((bool)vertexBuffer2, true, TEST_LOCATION);
189   DALI_TEST_EQUALS(vertexBuffer2.GetSize(), 0u, TEST_LOCATION);
190
191   END_TEST;
192 }
193
194 int UtcDaliVertexBufferMoveConstructor(void)
195 {
196   TestApplication application;
197
198   VertexBuffer vertexBuffer = CreateVertexBuffer();
199   DALI_TEST_CHECK(vertexBuffer);
200   DALI_TEST_EQUALS(1, vertexBuffer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
201   DALI_TEST_EQUALS(0u, vertexBuffer.GetSize(), TEST_LOCATION);
202
203   VertexBuffer move = std::move(vertexBuffer);
204   DALI_TEST_CHECK(move);
205   DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
206   DALI_TEST_EQUALS(0u, move.GetSize(), TEST_LOCATION);
207   DALI_TEST_CHECK(!vertexBuffer);
208
209   END_TEST;
210 }
211
212 int UtcDaliVertexBufferMoveAssignment(void)
213 {
214   TestApplication application;
215
216   VertexBuffer vertexBuffer = CreateVertexBuffer();
217   DALI_TEST_CHECK(vertexBuffer);
218   DALI_TEST_EQUALS(1, vertexBuffer.GetBaseObject().ReferenceCount(), TEST_LOCATION);
219   DALI_TEST_EQUALS(0u, vertexBuffer.GetSize(), TEST_LOCATION);
220
221   VertexBuffer move;
222   move = std::move(vertexBuffer);
223   DALI_TEST_CHECK(move);
224   DALI_TEST_EQUALS(1, move.GetBaseObject().ReferenceCount(), TEST_LOCATION);
225   DALI_TEST_EQUALS(0u, move.GetSize(), TEST_LOCATION);
226   DALI_TEST_CHECK(!vertexBuffer);
227
228   END_TEST;
229 }
230
231 int UtcDaliVertexBufferSetData01(void)
232 {
233   TestApplication application;
234
235   Property::Map texturedQuadVertexFormat;
236   texturedQuadVertexFormat["aPosition"]    = Property::VECTOR2;
237   texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
238
239   {
240     VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
241     DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
242
243     const float halfQuadSize = .5f;
244     struct TexturedQuadVertex
245     {
246       Vector2 position;
247       Vector2 textureCoordinates;
248     };
249     TexturedQuadVertex texturedQuadVertexData[4] = {
250       {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
251       {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
252       {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
253       {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)}};
254
255     vertexBuffer.SetData(texturedQuadVertexData, 4);
256
257     Geometry geometry = Geometry::New();
258     geometry.AddVertexBuffer(vertexBuffer);
259
260     Shader   shader   = CreateShader();
261     Renderer renderer = Renderer::New(geometry, shader);
262     Actor    actor    = Actor::New();
263     actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
264     actor.AddRenderer(renderer);
265     application.GetScene().Add(actor);
266
267     auto& drawTrace = application.GetGlAbstraction().GetDrawTrace();
268     drawTrace.Enable(true);
269
270     application.SendNotification();
271     application.Render(0);
272     application.Render();
273     application.SendNotification();
274
275     const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
276       application.GetGlAbstraction().GetBufferDataCalls();
277
278     DALI_TEST_CHECK(drawTrace.FindMethod("DrawArrays"));
279
280     DALI_TEST_EQUALS(bufferDataCalls.size(), 1u, TEST_LOCATION);
281
282     DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
283   }
284   // end of scope to let the buffer and geometry die; do another notification and render to get the deletion processed
285   application.SendNotification();
286   application.Render(0);
287
288   END_TEST;
289 }
290
291 int UtcDaliVertexBufferSetData02(void)
292 {
293   TestApplication application;
294
295   Property::Map texturedQuadVertexFormat;
296   texturedQuadVertexFormat["aPosition"]    = Property::VECTOR2;
297   texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
298
299   VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
300   DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
301
302   const float halfQuadSize = .5f;
303   struct TexturedQuadVertex
304   {
305     Vector2 position;
306     Vector2 textureCoordinates;
307   };
308   TexturedQuadVertex texturedQuadVertexData[4] = {
309     {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
310     {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
311     {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
312     {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)}};
313
314   vertexBuffer.SetData(texturedQuadVertexData, 4);
315
316   Geometry geometry = Geometry::New();
317   geometry.AddVertexBuffer(vertexBuffer);
318
319   Shader   shader   = CreateShader();
320   Renderer renderer = Renderer::New(geometry, shader);
321   Actor    actor    = Actor::New();
322   actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
323   actor.AddRenderer(renderer);
324   application.GetScene().Add(actor);
325
326   application.SendNotification();
327   application.Render();
328
329   auto&                                        gl                 = application.GetGlAbstraction();
330   const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls = gl.GetBufferSubDataCalls();
331   const TestGlAbstraction::BufferDataCalls&    bufferDataCalls    = gl.GetBufferDataCalls();
332
333   DALI_TEST_EQUALS(bufferSubDataCalls.size(), 0u, TEST_LOCATION);
334   DALI_TEST_EQUALS(bufferDataCalls.size(), 1u, TEST_LOCATION);
335   DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
336
337   gl.ResetBufferDataCalls();
338   gl.ResetBufferSubDataCalls();
339
340   // Re-upload the data on the vertexBuffer
341   vertexBuffer.SetData(texturedQuadVertexData, 4);
342
343   application.SendNotification();
344   application.Render(0);
345
346   DALI_TEST_EQUALS(bufferSubDataCalls.size(), 0u, TEST_LOCATION);
347   DALI_TEST_EQUALS(bufferDataCalls.size(), 1u, TEST_LOCATION);
348   DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
349
350   END_TEST;
351 }
352
353 int UtcDaliVertexBufferMapInitializerList(void)
354 {
355   TestApplication application;
356
357   Property::Map texturedQuadVertexFormat = Property::Map{{"aPosition", Property::VECTOR2},
358                                                          {"aTexCoord", Property::VECTOR2},
359                                                          {"aColor", Property::VECTOR4}};
360
361   try
362   {
363     VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
364     tet_result(TET_PASS);
365   }
366   catch(Dali::DaliException& e)
367   {
368     // Shouldn't assert any more
369     tet_result(TET_FAIL);
370   }
371   END_TEST;
372 }
373
374 int UtcDaliVertexBufferInvalidTypeN01(void)
375 {
376   TestApplication application;
377
378   Property::Map texturedQuadVertexFormat;
379   texturedQuadVertexFormat["aPosition"]    = Property::MAP;
380   texturedQuadVertexFormat["aVertexCoord"] = Property::STRING;
381
382   try
383   {
384     VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
385     tet_result(TET_FAIL);
386   }
387   catch(Dali::DaliException& e)
388   {
389     DALI_TEST_ASSERT(e, "Property::Type not supported in VertexBuffer", TEST_LOCATION);
390   }
391   END_TEST;
392 }
393
394 int UtcDaliVertexBufferInvalidTypeN02(void)
395 {
396   TestApplication application;
397
398   Property::Map texturedQuadVertexFormat = Property::Map{{"aPosition", Property::MAP},
399                                                          {"aTexCoord", Property::STRING},
400                                                          {"aColor", Property::VECTOR4}};
401
402   try
403   {
404     VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
405     tet_result(TET_FAIL);
406   }
407   catch(Dali::DaliException& e)
408   {
409     DALI_TEST_ASSERT(e, "Property::Type not supported in VertexBuffer", TEST_LOCATION);
410   }
411   END_TEST;
412 }
413
414 int UtcDaliVertexBufferSetDataNegative(void)
415 {
416   TestApplication    application;
417   Dali::VertexBuffer instance;
418   try
419   {
420     void*         arg1(nullptr);
421     unsigned long arg2(0u);
422     instance.SetData(arg1, arg2);
423     DALI_TEST_CHECK(false); // Should not get here
424   }
425   catch(...)
426   {
427     DALI_TEST_CHECK(true); // We expect an assert
428   }
429   END_TEST;
430 }
431
432 int UtcDaliVertexBufferGetSizeNegative(void)
433 {
434   TestApplication    application;
435   Dali::VertexBuffer instance;
436   try
437   {
438     instance.GetSize();
439     DALI_TEST_CHECK(false); // Should not get here
440   }
441   catch(...)
442   {
443     DALI_TEST_CHECK(true); // We expect an assert
444   }
445   END_TEST;
446 }
447
448 int UtcDaliVertexBufferSetDivisor(void)
449 {
450   TestApplication application;
451
452   Property::Map texturedQuadVertexFormat;
453   texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
454   texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
455
456   Property::Map instanceFormat{{"aTranslate", Property::VECTOR2}, {"aColor", Property::VECTOR4}};
457
458   VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
459   DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
460
461   DALI_TEST_EQUALS(0, vertexBuffer.GetDivisor(), TEST_LOCATION);
462
463   VertexBuffer instanceBuffer = VertexBuffer::New(instanceFormat);
464   DALI_TEST_EQUALS((bool)instanceBuffer, true, TEST_LOCATION);
465
466   const float halfQuadSize = .5f;
467   struct TexturedQuadVertex
468   {
469     Vector2 position;
470     Vector2 textureCoordinates;
471   };
472   TexturedQuadVertex texturedQuadVertexData[4] = {
473     {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
474     {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
475     {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
476     {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)}};
477
478   vertexBuffer.SetData(texturedQuadVertexData, 4);
479
480   struct InstanceData
481   {
482     Vector2 translate;
483     Vector4 color;
484   };
485
486   InstanceData instanceData[] = {{Vector2(12, 33), Color::WHITE},
487                                  {Vector2(-2000, 43), Color::BLUE},
488                                  {Vector2(200, 43), Color::GREEN},
489                                  {Vector2(-243, 43), Color::TURQUOISE},
490                                  {Vector2(192, 43), Color::CYAN},
491                                  {Vector2(-2000, 43), Color::MAGENTA},
492                                  {Vector2(-292, 393), Color::BLUE},
493                                  {Vector2(-499, 128), Color::BLUE},
494                                  {Vector2(328, 43), Color::BLUE},
495                                  {Vector2(726, 43), Color::BLUE}};
496   instanceBuffer.SetData(instanceData, sizeof(instanceData) / sizeof(InstanceData));
497   instanceBuffer.SetDivisor(1);
498   DALI_TEST_EQUALS(1, instanceBuffer.GetDivisor(), TEST_LOCATION);
499
500   Geometry geometry = Geometry::New();
501   geometry.AddVertexBuffer(vertexBuffer);
502   geometry.AddVertexBuffer(instanceBuffer);
503
504   Shader   shader   = CreateShader();
505   Renderer renderer = Renderer::New(geometry, shader);
506   Actor    actor    = Actor::New();
507   actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
508   actor.AddRenderer(renderer);
509   application.GetScene().Add(actor);
510
511   TestGlAbstraction& gl          = application.GetGlAbstraction();
512   auto&              bufferTrace = gl.GetBufferTrace();
513   auto&              drawTrace   = gl.GetDrawTrace();
514   bufferTrace.Enable(true);
515   drawTrace.Enable(true);
516
517   application.SendNotification();
518   application.Render();
519
520   TraceCallStack::NamedParams params;
521   params["divisor"] << "1";
522   DALI_TEST_CHECK(bufferTrace.FindMethodAndParams("VertexAttribDivisor", params));
523
524   tet_infoline("Test that by default, instancing isn't used");
525   TraceCallStack::NamedParams params2;
526   params2["instanceCount"] << 0;
527   DALI_TEST_CHECK(!drawTrace.FindMethodAndGetParameters("DrawArraysInstanced", params2));
528   DALI_TEST_CHECK(drawTrace.FindMethod("DrawArrays"));
529
530   tet_infoline("Test that instancing is used if Renderer requests an instance count");
531   drawTrace.Reset();
532
533   int instanceCount         = sizeof(instanceData) / sizeof(InstanceData);
534   renderer["instanceCount"] = instanceCount;
535   application.SendNotification();
536   application.Render();
537
538   TraceCallStack::NamedParams params3;
539   params3["instanceCount"] << instanceCount;
540   DALI_TEST_CHECK(drawTrace.FindMethodAndGetParameters("DrawArraysInstanced", params3));
541   DALI_TEST_CHECK(!drawTrace.FindMethod("DrawArrays"));
542   END_TEST;
543 }
544
545 int UtcDaliVertexBufferUpdateCallback(void)
546 {
547   TestApplication application;
548
549   // Create vertex buffer
550   VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map() = {
551                                                   {"aPosition", Property::Type::VECTOR2},
552                                                   {"aTexCoord", Property::Type::VECTOR2}});
553
554   // set callback
555   auto callback = std::make_unique<VertexBufferUpdater>();
556   vertexBuffer.SetVertexBufferUpdateCallback(callback->CreateCallback());
557
558   struct Vertex
559   {
560     Vector2 pos;
561     Vector2 uv;
562   };
563
564   std::vector<Vertex> vertices;
565   vertices.resize(16);
566   vertexBuffer.SetData(vertices.data(), 16);
567
568   Geometry geometry = Geometry::New();
569   geometry.AddVertexBuffer(vertexBuffer);
570   Shader   shader   = CreateShader();
571   Renderer renderer = Renderer::New(geometry, shader);
572   Actor    actor    = Actor::New();
573   actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
574   actor.AddRenderer(renderer);
575   application.GetScene().Add(actor);
576
577   auto& gl    = application.GetGlAbstraction();
578   auto& trace = gl.GetDrawTrace();
579   trace.Enable(true);
580   trace.EnableLogging(true);
581
582   callback->SetCallbackReturnValue(16 * sizeof(Vertex));
583
584   application.SendNotification();
585   application.Render();
586
587   auto value = callback->GetValue();
588
589   // Test whether callback ran
590   DALI_TEST_EQUALS(value.counter, 1, TEST_LOCATION);
591   DALI_TEST_EQUALS(value.lastSize, 16 * sizeof(Vertex), TEST_LOCATION);
592   DALI_TEST_EQUALS(value.lastReturned, 16 * sizeof(Vertex), TEST_LOCATION);
593   DALI_TEST_NOT_EQUALS(value.lastPtr, (void*)nullptr, 0, TEST_LOCATION);
594
595   // test whether draw call has been issued (return value indicates end of array to be drawn)
596   auto result = trace.FindMethod("DrawArrays");
597   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
598   result = trace.FindMethodAndParams("DrawArrays", "4, 0, 16");
599   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
600
601   // Test 2. Update and render only half of vertex buffer
602   callback->SetCallbackReturnValue(8 * sizeof(Vertex));
603   trace.Reset();
604
605   application.SendNotification();
606   application.Render();
607
608   value = callback->GetValue();
609   // Test whether callback ran
610   DALI_TEST_EQUALS(value.counter, 2, TEST_LOCATION);
611   DALI_TEST_EQUALS(value.lastSize, 16 * sizeof(Vertex), TEST_LOCATION);
612   DALI_TEST_EQUALS(value.lastReturned, 8 * sizeof(Vertex), TEST_LOCATION);
613   DALI_TEST_NOT_EQUALS(value.lastPtr, (void*)nullptr, 0, TEST_LOCATION);
614   result = trace.FindMethod("DrawArrays");
615   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
616   result = trace.FindMethodAndParams("DrawArrays", "4, 0, 8");
617   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
618
619   // Test 3. callback returns 0 elements to render, the draw call shouldn't happen.
620   callback->SetCallbackReturnValue(0);
621   trace.Reset();
622
623   application.SendNotification();
624   application.Render();
625
626   value = callback->GetValue();
627   // Test whether callback ran
628   DALI_TEST_EQUALS(value.counter, 3, TEST_LOCATION);
629   DALI_TEST_EQUALS(value.lastSize, 16 * sizeof(Vertex), TEST_LOCATION);
630   DALI_TEST_EQUALS(value.lastReturned, 0, TEST_LOCATION);
631   DALI_TEST_NOT_EQUALS(value.lastPtr, (void*)nullptr, 0, TEST_LOCATION);
632   result = trace.FindMethod("DrawArrays");
633   DALI_TEST_EQUALS(result, false, TEST_LOCATION);
634
635   // Test 4. removing callback, original behaviour should kick in
636   vertexBuffer.SetVertexBufferUpdateCallback(nullptr);
637   trace.Reset();
638   callback->Reset();
639
640   application.SendNotification();
641   application.Render();
642
643   auto valueReady = callback->IsValueReady();
644   DALI_TEST_EQUALS(valueReady, false, TEST_LOCATION);
645   DALI_TEST_EQUALS(callback->diagnostics.counter, 3, TEST_LOCATION);
646   result = trace.FindMethod("DrawArrays");
647   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
648   result = trace.FindMethodAndParams("DrawArrays", "4, 0, 16");
649   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
650
651   END_TEST;
652 }
653
654 int UtcDaliSetAndRemoveVertexBufferUpdateCallback(void)
655 {
656   TestApplication application;
657
658   // Create vertex buffer
659   VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map() = {
660                                                   {"aPosition", Property::Type::VECTOR2},
661                                                   {"aTexCoord", Property::Type::VECTOR2}});
662
663   // set callback
664   auto callback = std::make_unique<VertexBufferUpdater>();
665   vertexBuffer.SetVertexBufferUpdateCallback(callback->CreateCallback());
666
667   struct Vertex
668   {
669     Vector2 pos;
670     Vector2 uv;
671   };
672
673   std::vector<Vertex> vertices;
674   vertices.resize(16);
675   vertexBuffer.SetData(vertices.data(), 16);
676
677   Geometry geometry = Geometry::New();
678   geometry.AddVertexBuffer(vertexBuffer);
679   Shader   shader   = CreateShader();
680   Renderer renderer = Renderer::New(geometry, shader);
681   Actor    actor    = Actor::New();
682   actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
683   actor.AddRenderer(renderer);
684   application.GetScene().Add(actor);
685
686   auto& gl    = application.GetGlAbstraction();
687   auto& trace = gl.GetDrawTrace();
688   trace.Enable(true);
689   trace.EnableLogging(true);
690
691   callback->SetCallbackReturnValue(16 * sizeof(Vertex));
692
693   application.SendNotification();
694   application.Render();
695
696   auto value = callback->GetValue();
697
698   // Test whether callback ran
699   DALI_TEST_EQUALS(value.counter, 1, TEST_LOCATION);
700   DALI_TEST_EQUALS(value.lastSize, 16 * sizeof(Vertex), TEST_LOCATION);
701   DALI_TEST_EQUALS(value.lastReturned, 16 * sizeof(Vertex), TEST_LOCATION);
702   DALI_TEST_NOT_EQUALS(value.lastPtr, (void*)nullptr, 0, TEST_LOCATION);
703
704   // test whether draw call has been issued (return value indicates end of array to be drawn)
705   auto result = trace.FindMethod("DrawArrays");
706   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
707   result = trace.FindMethodAndParams("DrawArrays", "4, 0, 16");
708   DALI_TEST_EQUALS(result, true, TEST_LOCATION);
709
710   // Test 2. Update and render only half of vertex buffer
711   callback->SetCallbackReturnValue(8 * sizeof(Vertex));
712   trace.Reset();
713
714   // Remove the callback
715   vertexBuffer.ClearVertexBufferUpdateCallback();
716
717   application.SendNotification();
718   application.Render();
719
720   // Use 1sec timeout as callback won't be executed and future won't be filled
721   value = callback->GetValueWithTimeout();
722   // Test whether callback ran
723   DALI_TEST_EQUALS(value.success, false, TEST_LOCATION);
724
725   END_TEST;
726 }
727
728 int UtcDaliVertexBufferDestructWorkerThreadN(void)
729 {
730   TestApplication application;
731   tet_infoline("UtcDaliAnimationDestructWorkerThreadN Test, for line coverage");
732
733   try
734   {
735     class TestThread : public Thread
736     {
737     public:
738       virtual void Run()
739       {
740         tet_printf("Run TestThread\n");
741         // Destruct at worker thread.
742         mVertexBuffer.Reset();
743       }
744
745       Dali::VertexBuffer mVertexBuffer;
746     };
747     TestThread thread;
748
749     Dali::VertexBuffer vertexBuffer = VertexBuffer::New(Property::Map() = {
750                                                           {"aPosition", Property::Type::VECTOR2},
751                                                           {"aTexCoord", Property::Type::VECTOR2}});
752     thread.mVertexBuffer            = std::move(vertexBuffer);
753     vertexBuffer.Reset();
754
755     thread.Start();
756
757     thread.Join();
758   }
759   catch(...)
760   {
761   }
762
763   // Always success
764   DALI_TEST_CHECK(true);
765
766   END_TEST;
767 }