1 /*
2 * Copyright (c) 2022 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 renderAccessStores_.insert_or_assign(pendingRef.hash, BASE_NS::move(pendingRef.renderDataStore));
43 }
44 pendingRenderAccess.clear();
45
46 // all valid stores can be accessed from render access stores without locks
47 // remove unused data stores and gather their hashes so that stores_ can be cleaned up as well.
48 for (auto it = renderAccessStores_.begin(); it != renderAccessStores_.end();) {
49 if (it->second->GetRefCount() > 2) { // in stores_, renderAccessStores_ and user, 2: min ref count
50 ++it;
51 } else {
52 pendingRenderAccess.push_back({ it->first, {} });
53 it = renderAccessStores_.erase(it);
54 }
55 }
56 if (!pendingRenderAccess.empty()) {
57 std::lock_guard<std::mutex> lock(mutex_);
58 for (const auto& ref : pendingRenderAccess) {
59 stores_.erase(ref.hash);
60 }
61 }
62 }
63
PreRender()64 void RenderDataStoreManager::PreRender()
65 {
66 // all valid stores can be accessed from render access stores without locks
67 for (const auto& ref : renderAccessStores_) {
68 ref.second->PreRender();
69 }
70 }
71
PostRender()72 void RenderDataStoreManager::PostRender()
73 {
74 // all valid stores can be accessed from render access stores without locks
75 for (const auto& ref : renderAccessStores_) {
76 ref.second->PostRender();
77 }
78 }
79
PreRenderBackend()80 void RenderDataStoreManager::PreRenderBackend()
81 {
82 // all valid stores can be accessed from render access stores without locks
83 for (const auto& ref : renderAccessStores_) {
84 ref.second->PreRenderBackend();
85 }
86 }
87
PostRenderBackend()88 void RenderDataStoreManager::PostRenderBackend()
89 {
90 // all valid stores can be accessed from render access stores without locks
91 for (const auto& ref : renderAccessStores_) {
92 ref.second->PostRenderBackend();
93 }
94 }
95
GetRenderDataStore(const string_view name) const96 BASE_NS::refcnt_ptr<IRenderDataStore> RenderDataStoreManager::GetRenderDataStore(const string_view name) const
97 {
98 if (name.empty()) {
99 return {};
100 }
101
102 auto const nameHash = hash(name);
103
104 std::lock_guard<std::mutex> lock(mutex_);
105
106 if (const auto iter = stores_.find(nameHash); iter != stores_.cend()) {
107 return iter->second;
108 } else {
109 #if (RENDER_VALIDATION_ENABLED == 1)
110 PLUGIN_LOG_ONCE_W(
111 name + "_RDS_NOT_FOUND__", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
112 #endif
113 return {};
114 }
115 }
116
GetRenderTimeRenderDataStore(const string_view name) const117 IRenderDataStore* RenderDataStoreManager::GetRenderTimeRenderDataStore(const string_view name) const
118 {
119 if (name.empty()) {
120 return nullptr;
121 }
122
123 // not locked
124
125 auto const nameHash = hash(name);
126 if (const auto iter = renderAccessStores_.find(nameHash); iter != renderAccessStores_.cend()) {
127 return iter->second.get();
128 } else {
129 #if (RENDER_VALIDATION_ENABLED == 1)
130 PLUGIN_LOG_ONCE_W(
131 name + "_RDS_NOT_FOUND", "RENDER_VALIDATION: render data store: (%s), not found", name.data());
132 #endif
133 return nullptr;
134 }
135 }
136
Create(const Uid & dataStoreTypeUid,const char * dataStoreName)137 BASE_NS::refcnt_ptr<IRenderDataStore> RenderDataStoreManager::Create(
138 const Uid& dataStoreTypeUid, const char* dataStoreName)
139 {
140 auto const dataStoreTypeHash = hash(dataStoreTypeUid);
141 if (auto const factoryIt = factories_.find(dataStoreTypeHash); factoryIt != factories_.end()) {
142 auto const dataStoreNameHash = hash(string_view(dataStoreName));
143 refcnt_ptr<IRenderDataStore> dataStore;
144
145 std::lock_guard<std::mutex> lock(mutex_);
146
147 if (auto const namedStoreIt = stores_.find(dataStoreNameHash); namedStoreIt != stores_.cend()) {
148 PLUGIN_LOG_D("Named data store already exists (type: %s) (name: %s)", to_string(dataStoreTypeUid).data(),
149 dataStoreName);
150 dataStore = namedStoreIt->second;
151 if (dataStore->GetUid() != dataStoreTypeUid) {
152 PLUGIN_LOG_E("Named data store (type: %s, name: %s) exists with different type (%s)",
153 to_string(dataStoreTypeUid).data(), dataStoreName, dataStore->GetTypeName().data());
154 dataStore = nullptr;
155 }
156 } else {
157 auto const dataStoreIt = stores_.insert_or_assign(dataStoreNameHash,
158 refcnt_ptr<IRenderDataStore>(factoryIt->second.createDataStore(renderContext_, dataStoreName)));
159 pointerToStoreHash_.insert_or_assign(dataStoreIt.first->second.get(), uint64_t { dataStoreNameHash });
160 dataStore = dataStoreIt.first->second;
161 }
162
163 pendingRenderAccess_.push_back({ dataStoreNameHash, dataStore });
164 return dataStore;
165 } else {
166 PLUGIN_LOG_E("render data store type not found (type: %s) (named: %s)", to_string(dataStoreTypeUid).data(),
167 dataStoreName);
168 }
169 return nullptr;
170 }
171
GetRenderDataStoreFlags() const172 IRenderDataStoreManager::RenderDataStoreFlags RenderDataStoreManager::GetRenderDataStoreFlags() const
173 {
174 return renderDataStoreFlags_;
175 }
176
AddRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)177 void RenderDataStoreManager::AddRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
178 {
179 // plugin load and factory addition is sequential
180 // not locked access
181
182 if (typeInfo.createDataStore) {
183 auto const dataStoreTypeHash = hash(typeInfo.uid);
184 factories_.insert({ dataStoreTypeHash, typeInfo });
185 } else {
186 PLUGIN_LOG_E("RenderDataStoreTypeInfo must provide non-null function pointers");
187 PLUGIN_ASSERT(typeInfo.createDataStore && "createDataStore cannot be null");
188 }
189 }
190
RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo & typeInfo)191 void RenderDataStoreManager::RemoveRenderDataStoreFactory(const RenderDataStoreTypeInfo& typeInfo)
192 {
193 // stores_ and pointerToStoreHash_ are modified under lock. renderAccessStores_ is assumed to be touched only from
194 // RenderFrame, so this doesn't help. This implies that plugins should be unloaded only while not rendering.
195 std::lock_guard lock(mutex_);
196
197 for (auto b = pointerToStoreHash_.begin(), e = pointerToStoreHash_.end(); b != e;) {
198 if (b->first->GetUid() == typeInfo.uid) {
199 stores_.erase(b->second);
200 renderAccessStores_.erase(b->second);
201 b = pointerToStoreHash_.erase(b);
202 } else {
203 ++b;
204 }
205 }
206 auto const dataStoreTypeHash = hash(typeInfo.uid);
207 factories_.erase(dataStoreTypeHash);
208 }
209
RenderNodeRenderDataStoreManager(const RenderDataStoreManager & renderDataStoreMgr)210 RenderNodeRenderDataStoreManager::RenderNodeRenderDataStoreManager(const RenderDataStoreManager& renderDataStoreMgr)
211 : renderDataStoreMgr_(renderDataStoreMgr)
212 {}
213
GetRenderDataStore(const string_view name) const214 IRenderDataStore* RenderNodeRenderDataStoreManager::GetRenderDataStore(const string_view name) const
215 {
216 return renderDataStoreMgr_.GetRenderTimeRenderDataStore(name);
217 }
218 RENDER_END_NAMESPACE()
219