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