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
44 // Try to create ResourceLoader here, to ensure that we create it on main thread.
45 Dali::Scene3D::Internal::ImageResourceLoader::EnsureResourceLoaderCreated();
48 Dali::Scene3D::Loader::LoadResult GetModelLoadResult(std::string modelUri)
50 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
51 ModelCache& cache = mModelCache[modelUri];
52 return Dali::Scene3D::Loader::LoadResult{cache.resources, cache.scene, cache.metaData, cache.animationDefinitions, cache.amimationGroupDefinitions, cache.cameraParameters, cache.lights};
55 void LockModelLoadScene(std::string modelUri)
57 // To avoid dead-lock, do not use mModelCacheMutex here
58 auto& modelMutex = GetLoadSceneMutexInstance(modelUri);
62 void UnlockModelLoadScene(std::string modelUri)
64 // To avoid dead-lock, do not use mModelCacheMutex here
65 auto& modelMutex = GetLoadSceneMutexInstance(modelUri);
69 uint32_t GetModelCacheRefCount(std::string modelUri)
71 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
72 ModelCache& cache = mModelCache[modelUri];
73 return cache.refCount;
76 void ReferenceModelCache(std::string modelUri)
78 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
79 ModelCache& cache = mModelCache[modelUri];
83 void UnreferenceModelCache(std::string modelUri)
85 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
86 ModelCache& cache = mModelCache[modelUri];
87 if(cache.refCount > 0)
92 if(cache.refCount == 0)
94 mModelCache.erase(modelUri);
96 // Request image resource GC
97 Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
101 bool IsSceneLoaded(std::string modelUri)
103 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
104 ModelCache& cache = mModelCache[modelUri];
105 return cache.isSceneLoaded;
108 void SetSceneLoaded(std::string modelUri, bool isSceneLoaded)
110 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
111 ModelCache& cache = mModelCache[modelUri];
112 cache.isSceneLoaded = isSceneLoaded;
115 bool IsSceneLoading(std::string modelUri)
117 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
118 ModelCache& cache = mModelCache[modelUri];
119 return cache.isSceneLoading;
122 void SetSceneLoading(std::string modelUri, bool isSceneLoading)
124 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
125 ModelCache& cache = mModelCache[modelUri];
126 cache.isSceneLoading = isSceneLoading;
131 * A reference counted object may only be deleted by calling Unreference()
139 * @brief Retrieves the mutex object to synchronize the scene loading of the model
140 * with the given URI between multiple threads.
141 * @param[in] modelUri The unique model URI with its absolute path.
142 * @return The mutex object.
144 std::mutex& GetLoadSceneMutexInstance(std::string modelUri)
146 Dali::Mutex::ScopedLock lock(mModelCacheMutex);
147 ModelCache& cache = mModelCache[modelUri];
148 return cache.loadSceneMutex;
154 Dali::Scene3D::Loader::ResourceBundle resources{}; ///< The bundle to store resources in.
155 Dali::Scene3D::Loader::SceneDefinition scene{}; ///< The scene definition to populate.
156 Dali::Scene3D::Loader::SceneMetadata metaData{}; ///< The metadata of the scene.
158 std::vector<Dali::Scene3D::Loader::AnimationDefinition> animationDefinitions{}; ///< The list of animation definitions, in lexicographical order of their names.
159 std::vector<Dali::Scene3D::Loader::AnimationGroupDefinition> amimationGroupDefinitions{}; ///< The list of animation group definitions, in lexicographical order of their names.
160 std::vector<Dali::Scene3D::Loader::CameraParameters> cameraParameters{}; ///< The camera parameters that were loaded from the scene.
161 std::vector<Dali::Scene3D::Loader::LightParameters> lights{}; ///< The light parameters that were loaded from the scene.
163 uint32_t refCount{0}; ///< The reference count of this model cache.
164 std::mutex loadSceneMutex{}; ///< The mutex instance used to synchronise the loading of the scene for the same model in different threads.
166 bool isSceneLoaded{false}; ///< Whether the scene of the model has been loaded.
167 bool isSceneLoading{false}; ///< Whether the scene loading of the model is in progress.
170 // Note : We should use some container that the element memory pointer is not changed due to LoadResult and loadSceneMutex validation.
171 using ModelResourceCache = std::map<std::string, ModelCache>;
172 ModelResourceCache mModelCache;
174 Dali::Mutex mModelCacheMutex;
177 ModelCacheManager::ModelCacheManager() = default;
179 ModelCacheManager::~ModelCacheManager() = default;
181 ModelCacheManager ModelCacheManager::Get()
183 ModelCacheManager manager;
185 // Check whether the ModelCacheManager is already created
186 SingletonService singletonService(SingletonService::Get());
189 Dali::BaseHandle handle = singletonService.GetSingleton(typeid(ModelCacheManager));
192 // If so, downcast the handle of singleton to ModelCacheManager
193 manager = ModelCacheManager(dynamic_cast<ModelCacheManager::Impl*>(handle.GetObjectPtr()));
198 // If not, create the ModelCacheManager and register it as a singleton
199 manager = ModelCacheManager(new ModelCacheManager::Impl());
200 singletonService.Register(typeid(manager), manager);
207 ModelCacheManager::ModelCacheManager(ModelCacheManager::Impl* impl)
212 Dali::Scene3D::Loader::LoadResult ModelCacheManager::GetModelLoadResult(std::string modelUri)
214 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
215 return impl.GetModelLoadResult(modelUri);
218 void ModelCacheManager::LockModelLoadScene(std::string modelUri)
220 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
221 return impl.LockModelLoadScene(modelUri);
224 void ModelCacheManager::UnlockModelLoadScene(std::string modelUri)
226 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
227 return impl.UnlockModelLoadScene(modelUri);
230 uint32_t ModelCacheManager::GetModelCacheRefCount(std::string modelUri)
232 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
233 return impl.GetModelCacheRefCount(modelUri);
236 void ModelCacheManager::ReferenceModelCache(std::string modelUri)
238 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
239 impl.ReferenceModelCache(modelUri);
242 void ModelCacheManager::UnreferenceModelCache(std::string modelUri)
244 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
245 impl.UnreferenceModelCache(modelUri);
248 bool ModelCacheManager::IsSceneLoaded(std::string modelUri)
250 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
251 return impl.IsSceneLoaded(modelUri);
254 void ModelCacheManager::SetSceneLoaded(std::string modelUri, bool isSceneLoaded)
256 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
257 impl.SetSceneLoaded(modelUri, isSceneLoaded);
260 bool ModelCacheManager::IsSceneLoading(std::string modelUri)
262 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
263 return impl.IsSceneLoading(modelUri);
266 void ModelCacheManager::SetSceneLoading(std::string modelUri, bool isSceneLoading)
268 ModelCacheManager::Impl& impl = static_cast<ModelCacheManager::Impl&>(GetBaseObject());
269 impl.SetSceneLoading(modelUri, isSceneLoading);
272 } // namespace Dali::Scene3D::Internal