[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-scene3d-internal / utc-Dali-ModelCacheManager.cpp
1 /*
2  * Copyright (c) 2023 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 // Enable debug log for test coverage
19 #define DEBUG_ENABLED 1
20
21 #include <dali-scene3d/internal/common/image-resource-loader.h>
22 #include <dali-scene3d/internal/common/model-cache-manager.h>
23 #include <dali-scene3d/public-api/controls/model/model.h>
24 #include <dali-scene3d/public-api/loader/resource-bundle.h>
25 #include <dali-scene3d/public-api/loader/scene-definition.h>
26 #include <dali-toolkit-test-suite-utils.h>
27 #include <toolkit-event-thread-callback.h>
28 #include <toolkit-timer.h>
29 #include <string>
30
31 using namespace Dali;
32 using namespace Dali::Toolkit;
33 using namespace Dali::Scene3D::Internal;
34
35 namespace
36 {
37 /**
38  * For the AnimatedCube.gltf and its Assets
39  * Donated by Norbert Nopper for glTF testing.
40  * Take from https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnimatedCube
41  */
42 const char* TEST_GLTF_FILE_NAME = TEST_RESOURCE_DIR "/AnimatedCube.gltf";
43
44 static bool gResourceReadyCalled = false;
45
46 void OnResourceReady(Control control)
47 {
48   gResourceReadyCalled = true;
49 }
50 } // namespace
51
52 int UtcDaliModelCacheManagerLoadModel(void)
53 {
54   ToolkitTestApplication application;
55
56   ModelCacheManager cacheManager = ModelCacheManager::Get();
57   DALI_TEST_EQUALS(cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME), 0u, TEST_LOCATION);
58
59   // Load the first instance of the same model and add it to the scene
60   Scene3D::Model model1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
61   application.GetScene().Add(model1);
62
63   gResourceReadyCalled = false;
64   model1.ResourceReadySignal().Connect(&OnResourceReady);
65   DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
66
67   application.SendNotification();
68   application.Render();
69
70   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
71   application.SendNotification();
72   application.Render();
73
74   // Check that the loading has finished for mode1
75   DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
76
77   // Store the value of expect ref count with one model. Detail value could be changed with detail logic of cache.
78   uint32_t refCountWithOneModel = cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME);
79
80   // Check whether model reference is greate or equal with 1.
81   DALI_TEST_GREATER(refCountWithOneModel, 0u, TEST_LOCATION);
82   DALI_TEST_EQUALS(cacheManager.IsSceneLoading(TEST_GLTF_FILE_NAME), false, TEST_LOCATION);
83   DALI_TEST_EQUALS(cacheManager.IsSceneLoaded(TEST_GLTF_FILE_NAME), true, TEST_LOCATION);
84
85   // Load the second instance of the same model and add it to the scene
86   Scene3D::Model model2 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
87   application.GetScene().Add(model2);
88
89   gResourceReadyCalled = false;
90   model2.ResourceReadySignal().Connect(&OnResourceReady);
91   DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
92
93   application.SendNotification();
94   application.Render();
95
96   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
97   application.SendNotification();
98   application.Render();
99
100   // Check that the loading has finished for model2
101   DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
102
103   // Store the value of expect ref count with two models. Detail value could be changed with detail logic of cache.
104   uint32_t refCountWithTwoModels = cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME);
105
106   // Check whether model reference is greate or equal with reference with one model.
107   DALI_TEST_GREATER(refCountWithTwoModels, refCountWithOneModel, TEST_LOCATION);
108   DALI_TEST_EQUALS(cacheManager.IsSceneLoading(TEST_GLTF_FILE_NAME), false, TEST_LOCATION);
109   DALI_TEST_EQUALS(cacheManager.IsSceneLoaded(TEST_GLTF_FILE_NAME), true, TEST_LOCATION);
110
111   Actor meshActor1 = model1.FindChildByName("AnimatedCube");
112   Actor meshActor2 = model2.FindChildByName("AnimatedCube");
113   DALI_TEST_CHECK(meshActor1);
114   DALI_TEST_CHECK(meshActor2);
115
116   Renderer renderer1 = meshActor1.GetRendererAt(0u);
117   Renderer renderer2 = meshActor2.GetRendererAt(0u);
118   DALI_TEST_CHECK(renderer1);
119   DALI_TEST_CHECK(renderer2);
120
121   // Check that the two instances use the shared textures and geometries from the cache
122   DALI_TEST_EQUALS(renderer1.GetTextures(), renderer2.GetTextures(), TEST_LOCATION);
123   DALI_TEST_EQUALS(renderer1.GetGeometry(), renderer2.GetGeometry(), TEST_LOCATION);
124
125   // Destroy model1
126   model1.Unparent();
127   model1.Reset();
128
129   application.SendNotification();
130   application.Render();
131
132   // Check that the reference count of the cmodel cache is decreased after model1 is destroyed
133   DALI_TEST_EQUALS(cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME), refCountWithOneModel, TEST_LOCATION);
134
135   // Load another instance of the same model and add it to the scene
136   Scene3D::Model model3 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
137   application.GetScene().Add(model3);
138
139   gResourceReadyCalled = false;
140   model3.ResourceReadySignal().Connect(&OnResourceReady);
141   DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION);
142
143   application.SendNotification();
144   application.Render();
145
146   DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
147   application.SendNotification();
148   application.Render();
149
150   // Check that the loading has finished for model3
151   DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION);
152
153   // Check the value of expect ref count with two models.
154   DALI_TEST_EQUALS(cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME), refCountWithTwoModels, TEST_LOCATION);
155   DALI_TEST_EQUALS(cacheManager.IsSceneLoading(TEST_GLTF_FILE_NAME), false, TEST_LOCATION);
156   DALI_TEST_EQUALS(cacheManager.IsSceneLoaded(TEST_GLTF_FILE_NAME), true, TEST_LOCATION);
157
158   Actor meshActor3 = model3.FindChildByName("AnimatedCube");
159   DALI_TEST_CHECK(meshActor3);
160
161   Renderer renderer3 = meshActor3.GetRendererAt(0u);
162   DALI_TEST_CHECK(renderer3);
163
164   // Check that model2 and model3 use the shared textures and geometries from the cache
165   DALI_TEST_EQUALS(renderer2.GetTextures(), renderer3.GetTextures(), TEST_LOCATION);
166   DALI_TEST_EQUALS(renderer2.GetGeometry(), renderer3.GetGeometry(), TEST_LOCATION);
167
168   // Destroy model2 and model3
169   model2.Unparent();
170   model2.Reset();
171
172   model3.Unparent();
173   model3.Reset();
174
175   application.SendNotification();
176   application.Render();
177
178   // All reference count should be decreased.
179   DALI_TEST_EQUALS(cacheManager.GetModelCacheRefCount(TEST_GLTF_FILE_NAME), 0u, TEST_LOCATION);
180
181   // Collect garbages hardly.
182   Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect(true);
183   Test::EmitGlobalTimerSignal();
184
185   END_TEST;
186 }