1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "render_data_store_manager.h"
17
18 #include <cstddef>
19
20 #include <base/util/uid_util.h>
21 #include <render/datastore/intf_render_data_store.h>
22 #include <render/intf_render_context.h>
23 #include <render/namespace.h>
24
25 #include "util/log.h"
26
27 using namespace BASE_NS;
28
RENDER_BEGIN_NAMESPACE()29 RENDER_BEGIN_NAMESPACE()
30 RenderDataStoreManager::RenderDataStoreManager(IRenderContext& renderContext) : renderContext_(renderContext) {}
31
CommitFrameData()32 void RenderDataStoreManager::CommitFrameData()
33 {
34 decltype(pendingRenderAccess_) pendingRenderAccess;
35 {
36 std::lock_guard<std::mutex> lock(mutex_);
37 pendingRenderAccess = std::move(pendingRenderAccess_);
38 }
39
40 // prepare access for render time access
41 for (auto& pendingRef : pendingRenderAccess) {
42 if (pendingRef.destroy) { // remove deferred destruction stores
43 renderAccessStores_.erase(pendingRef.hash);
44 } else {
45 PLUGIN_ASSERT(pendingRef.renderDataStore);
46 renderAccessStores_.insert_or_assign(pendingRef.hash, BASE_NS::move(pendingRef.renderDataStore));
47 }
48 }
49 pendingRenderAccess.clear();
50
51 // all valid stores can be accessed from render access stores without locks
52 for (auto it = renderAccessStores_.begin(); it != renderAccessStores_.end();) {
53 if (it->second->GetRefCount() > 2) { // 2 2 in stores_, renderAccessStores_ and user
54 ++it;
55 } else {
56 pendingRenderAccess.push_back({ it->first, {}, true });
57 it = renderAccessStores_.erase(it);
58 }
59 }
60 {
61 std::lock_guard<std::mutex> lock(mutex_);
62 for (const auto& ref : pendingRenderAccess) {
63 stores_.erase(ref.hash);
64 }
65 }
66 }
67
PreRender()68 void RenderDataStoreManager::PreRender()
69 {
70 // all valid stores can be accessed from render access stores without locks
71 for (const auto& ref : renderAccessStores_) {
72 ref.second->PreRender();
73 }
74 }
75
PostRender()76 void RenderDataStoreManager::PostRender()
77 {
78 // all valid stores can be accessed from render access stores without locks
79 for (const auto& ref : renderAccessStores_) {
80 ref.second->PostRender();
81 }
82 }
83
PreRenderBackend()84 void RenderDataStoreManager::PreRenderBackend()
85 {
86 // all valid stores can be accessed from render access stores without locks
87 for (const auto& ref : renderAccessStores_) {
88 ref.second->PreRenderBackend();
89 }
90 }
91
PostRenderBackend()92 void RenderDataStoreManager::PostRenderBackend()
93 {
94 // all valid stores can be accessed from render access stores without locks
95 for (const auto& ref : renderAccessStores_) {
96 ref.second->PostRenderBackend();
97 }
98
99 DeferredDestruction();
100 }
101
GetRenderDataStore(const string_view name) const102 BASE_NS::refcnt_ptr<IRenderDataStore> RenderDataStoreManager::GetRenderDataStore(const string_view name) const
103 {
104 if (name.empty()) {
105 return {};
106 }
107
108 auto const nameHash = hash(name);
109
110 std::lock_guard<std::mutex> lock(mutex_);
111
112 if (const auto iter = stores_.find(nameHash); iter != stores_.cend()) {
113 return iter->second;
114 } else {
115 #if (RENDER_VALIDATION_ENABLED == 1)
116 PLUGIN_LOG_ONCE_W(
117 name + "_RDS_NOT_FOUND__", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
118 #endif
119 return {};
120 }
121 }
122
GetRenderTimeRenderDataStore(const string_view name) const123 IRenderDataStore* RenderDataStoreManager::GetRenderTimeRenderDataStore(const string_view name) const
124 {
125 if (name.empty()) {
126 return nullptr;
127 }
128
129 // not locked
130
131 auto const nameHash = hash(name);
132 if (const auto iter = renderAccessStores_.find(nameHash); iter != renderAccessStores_.cend()) {
133 return iter->second.get();
134 } else {
135 #if (RENDER_VALIDATION_ENABLED == 1)
136 PLUGIN_LOG_ONCE_W(
137 name + "_RDS_NOT_FOUND", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
138 #endif
139 return nullptr;
140 }
141 }
142
Create(const Uid & dataStoreTypeUid,const char * dataStoreName)143 BASE_NS::refcnt_ptr<IRenderDataStore> RenderDataStoreManager::Create(
144 const Uid& dataStoreTypeUid, const char* dataStoreName)
145 {
146 auto const dataStoreTypeHash = hash(dataStoreTypeUid);
147 if (auto const factoryIt = factories_.find(dataStoreTypeHash); factoryIt != factories_.end()) {
148 auto const dataStoreNameHash = hash(string_view(dataStoreName));
149 refcnt_ptr<IRenderDataStore> dataStore;
150
151 std::lock_guard<std::mutex> lock(mutex_);
152
153 if (auto const namedStoreIt = stores_.find(dataStoreNameHash); namedStoreIt != stores_.cend()) {
154 PLUGIN_LOG_D("Named data store already exists (type: %s) (name: %s)", to_string(dataStoreTypeUid).data(),
155 dataStoreName);
156 dataStore = namedStoreIt->second;
157 if (dataStore->GetUid() != dataStoreTypeUid) {
158 PLUGIN_LOG_E("Named data store (type: %s, name: %s) exists with different type (%s)",
159 to_string(dataStoreTypeUid).data(), dataStoreName, dataStore->GetTypeName().data());
160 dataStore = nullptr;
161 }
162 } else {
163 auto const dataStoreIt = stores_.insert_or_assign(dataStoreNameHash,
164 refcnt_ptr<IRenderDataStore>(factoryIt->second.createDataStore(renderContext_, dataStoreName)));
165 pointerToStoreHash_.insert_or_assign(dataStoreIt.first->second.get(), uint64_t { dataStoreNameHash });
166 dataStore = dataStoreIt.first->second;
167 }
168
169 pendingRenderAccess_.push_back({ dataStoreNameHash, dataStore, false });
170 return dataStore;
171 } else {
172 PLUGIN_LOG_E("render data store type not found (type: %s) (named: %s)", to_string(dataStoreTypeUid).data(),
173 dataStoreName);
174 }
175 return nullptr;
176 }
177
GetRenderDataStoreFlags() const178 IRenderDataStoreManager::RenderDataStoreFlags RenderDataStoreManager::GetRenderDataStoreFlags() const
179 {
180 return renderDataStoreFlags_;
181 }
182
DeferredDestruction()183 void RenderDataStoreManager::DeferredDestruction()
184 {
185 std::lock_guard<std::mutex> lock(mutex_);
186
187 for (const auto& destroyRef : deferredDestructionDataStores_) {
188 if (auto const pos = factories_.find(destroyRef.dataStoreHash); pos != factories_.end()) {
189 if (auto const storeIt = pointerToStoreHash_.find(destroyRef.instance);
190 storeIt != pointerToStoreHash_.cend()) {
191 stores_.erase(storeIt->second);
192 pointerToStoreHash_.erase(storeIt);
193 }
194 }
195 }
196 deferredDestructionDataStores_.clear();
197 }
198
AddRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)199 void RenderDataStoreManager::AddRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
200 {
201 // plugin load and factory addition is sequential
202 // not locked access
203
204 if (typeInfo.createDataStore) {
205 auto const dataStoreTypeHash = hash(typeInfo.uid);
206 factories_.insert({ dataStoreTypeHash, typeInfo });
207 } else {
208 PLUGIN_LOG_E("RenderDataStoreTypeInfo must provide non-null function pointers");
209 PLUGIN_ASSERT(typeInfo.createDataStore && "createDataStore cannot be null");
210 }
211 }
212
RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)213 void RenderDataStoreManager::RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
214 {
215 for (auto b = pointerToStoreHash_.begin(), e = pointerToStoreHash_.end(); b != e;) {
216 if (b->first->GetUid() == typeInfo.uid) {
217 stores_.erase(b->second);
218 b = pointerToStoreHash_.erase(b);
219 } else {
220 ++b;
221 }
222 }
223 auto const dataStoreTypeHash = hash(typeInfo.uid);
224 factories_.erase(dataStoreTypeHash);
225 }
226
RenderNodeRenderDataStoreManager(const RenderDataStoreManager & renderDataStoreMgr)227 RenderNodeRenderDataStoreManager::RenderNodeRenderDataStoreManager(const RenderDataStoreManager& renderDataStoreMgr)
228 : renderDataStoreMgr_(renderDataStoreMgr)
229 {}
230
GetRenderDataStore(const string_view name) const231 IRenderDataStore* RenderNodeRenderDataStoreManager::GetRenderDataStore(const string_view name) const
232 {
233 return renderDataStoreMgr_.GetRenderTimeRenderDataStore(name);
234 }
235 RENDER_END_NAMESPACE()
236