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