2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-scene3d/internal/common/model-cache-manager.h>
22 #include <dali/devel-api/common/map-wrapper.h>
23 #include <dali/devel-api/common/singleton-service.h>
24 #include <dali/devel-api/threading/mutex.h>
25 #include <dali/public-api/object/base-object.h>
30 #include <dali-scene3d/internal/common/image-resource-loader.h>
31 #include <dali-scene3d/public-api/loader/load-result.h>
32 #include <dali-scene3d/public-api/loader/scene-definition.h>
34 namespace Dali::Scene3D::Internal
36 class ModelCacheManager::Impl : public Dali::BaseObject
46 Dali::Scene3D::Loader::LoadResult GetModelLoadResult(std::string modelUri)
48 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
49 ModelCache& cache = mModelCache[modelUri];
50 return Dali::Scene3D::Loader::LoadResult{cache.resources, cache.scene, cache.metaData, cache.animationDefinitions, cache.amimationGroupDefinitions, cache.cameraParameters, cache.lights};
53 void LockModelLoadScene(std::string modelUri)
55 // To avoid dead-lock, do not use mModelCacheMutex here
56 auto& modelMutex = GetLoadSceneMutexInstance(modelUri);
60 void UnlockModelLoadScene(std::string modelUri)
62 // To avoid dead-lock, do not use mModelCacheMutex here
63 auto& modelMutex = GetLoadSceneMutexInstance(modelUri);
67 uint32_t GetModelCacheRefCount(std::string modelUri)
69 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
70 ModelCache& cache = mModelCache[modelUri];
71 return cache.refCount;
74 void ReferenceModelCache(std::string modelUri)
76 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
77 ModelCache& cache = mModelCache[modelUri];
81 void UnreferenceModelCache(std::string modelUri)
83 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
84 ModelCache& cache = mModelCache[modelUri];
85 if(cache.refCount > 0)
90 if(cache.refCount == 0)
92 mModelCache.erase(modelUri);
94 // Request image resource GC
95 Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
99 bool IsSceneLoaded(std::string modelUri)
101 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
102 ModelCache& cache = mModelCache[modelUri];
103 return cache.isSceneLoaded;
106 void SetSceneLoaded(std::string modelUri, bool isSceneLoaded)
108 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
109 ModelCache& cache = mModelCache[modelUri];
110 cache.isSceneLoaded = isSceneLoaded;
113 bool IsSceneLoading(std::string modelUri)
115 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
116 ModelCache& cache = mModelCache[modelUri];
117 return cache.isSceneLoading;
120 void SetSceneLoading(std::string modelUri, bool isSceneLoading)
122 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
123 ModelCache& cache = mModelCache[modelUri];
124 cache.isSceneLoading = isSceneLoading;
129 * A reference counted object may only be deleted by calling Unreference()
137 * @brief Retrieves the mutex object to synchronize the scene loading of the model
138 * with the given URI between multiple threads.
139 * @param[in] modelUri The unique model URI with its absolute path.
140 * @return The mutex object.
142 std::mutex& GetLoadSceneMutexInstance(std::string modelUri)
144 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
145 ModelCache& cache = mModelCache[modelUri];
146 return cache.loadSceneMutex;
152 Dali::Scene3D::Loader::ResourceBundle resources{}; ///< The bundle to store resources in.
153 Dali::Scene3D::Loader::SceneDefinition scene{}; ///< The scene definition to populate.
154 Dali::Scene3D::Loader::SceneMetadata metaData{}; ///< The metadata of the scene.
156 std::vector<Dali::Scene3D::Loader::AnimationDefinition> animationDefinitions{}; ///< The list of animation definitions, in lexicographical order of their names.
157 std::vector<Dali::Scene3D::Loader::AnimationGroupDefinition> amimationGroupDefinitions{}; ///< The list of animation group definitions, in lexicographical order of their names.
158 std::vector<Dali::Scene3D::Loader::CameraParameters> cameraParameters{}; ///< The camera parameters that were loaded from the scene.
159 std::vector<Dali::Scene3D::Loader::LightParameters> lights{}; ///< The light parameters that were loaded from the scene.
161 uint32_t refCount{0}; ///< The reference count of this model cache.
162 std::mutex loadSceneMutex{}; ///< The mutex instance used to synchronise the loading of the scene for the same model in different threads.
164 bool isSceneLoaded{false}; ///< Whether the scene of the model has been loaded.
165 bool isSceneLoading{false}; ///< Whether the scene loading of the model is in progress.
168 // Note : We should use some container that the element memory pointer is not changed due to LoadResult and loadSceneMutex validation.
169 using ModelResourceCache = std::map<std::string, ModelCache>;
170 ModelResourceCache mModelCache;
172 Dali::Mutex mModelCacheMutex;
175 ModelCacheManager::ModelCacheManager() = default;
177 ModelCacheManager::~ModelCacheManager() = default;
179 ModelCacheManager ModelCacheManager::Get()
181 ModelCacheManager manager;
183 // Check whether the ModelCacheManager is already created
184 SingletonService singletonService(SingletonService::Get());
187 Dali::BaseHandle handle = singletonService.GetSingleton(typeid(ModelCacheManager));
190 // If so, downcast the handle of singleton to ModelCacheManager
191 manager = ModelCacheManager(dynamic_cast<ModelCacheManager::Impl*>(handle.GetObjectPtr()));
196 // If not, create the ModelCacheManager and register it as a singleton
197 manager = ModelCacheManager(new ModelCacheManager::Impl());
198 singletonService.Register(typeid(manager), manager);
205 ModelCacheManager::ModelCacheManager(ModelCacheManager::Impl* impl)
210 Dali::Scene3D::Loader::LoadResult ModelCacheManager::GetModelLoadResult(std::string modelUri)
212 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
213 return impl.GetModelLoadResult(modelUri);
216 void ModelCacheManager::LockModelLoadScene(std::string modelUri)
218 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
219 return impl.LockModelLoadScene(modelUri);
222 void ModelCacheManager::UnlockModelLoadScene(std::string modelUri)
224 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
225 return impl.UnlockModelLoadScene(modelUri);
228 uint32_t ModelCacheManager::GetModelCacheRefCount(std::string modelUri)
230 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
231 return impl.GetModelCacheRefCount(modelUri);
234 void ModelCacheManager::ReferenceModelCache(std::string modelUri)
236 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
237 impl.ReferenceModelCache(modelUri);
240 void ModelCacheManager::UnreferenceModelCache(std::string modelUri)
242 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
243 impl.UnreferenceModelCache(modelUri);
246 bool ModelCacheManager::IsSceneLoaded(std::string modelUri)
248 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
249 return impl.IsSceneLoaded(modelUri);
252 void ModelCacheManager::SetSceneLoaded(std::string modelUri, bool isSceneLoaded)
254 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
255 impl.SetSceneLoaded(modelUri, isSceneLoaded);
258 bool ModelCacheManager::IsSceneLoading(std::string modelUri)
260 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
261 return impl.IsSceneLoading(modelUri);
264 void ModelCacheManager::SetSceneLoading(std::string modelUri, bool isSceneLoading)
266 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
267 impl.SetSceneLoading(modelUri, isSceneLoading);
270 } // namespace Dali::Scene3D::Internal