• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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