1 /*
2  * Copyright (c) 2023 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 "rs_rcd_render_manager.h"
17 
18 #include <unordered_set>
19 #include "common/rs_optional_trace.h"
20 #include "common/rs_singleton.h"
21 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
22 #include "pipeline/round_corner_display/rs_message_bus.h"
23 #include "pipeline/rs_uni_render_thread.h"
24 #include "platform/common/rs_log.h"
25 #include "rs_rcd_render_visitor.h"
26 #include "rs_round_corner_display_manager.h"
27 
28 namespace OHOS {
29 namespace Rosen {
30 static std::unique_ptr<RSRcdRenderManager> g_rcdRenderManagerInstance =
31     std::make_unique<RSRcdRenderManager>();
32 
GetInstance()33 RSRcdRenderManager& RSRcdRenderManager::GetInstance()
34 {
35     return *g_rcdRenderManagerInstance;
36 }
37 
InitInstance()38 void RSRcdRenderManager::InitInstance()
39 {
40     g_rcdRenderManagerInstance->rcdRenderEnabled_ = true;
41 }
42 
GetRcdRenderEnabled() const43 bool RSRcdRenderManager::GetRcdRenderEnabled() const
44 {
45     return rcdRenderEnabled_;
46 }
47 
IsRcdProcessInfoValid(const RcdProcessInfo & info)48 bool RSRcdRenderManager::IsRcdProcessInfoValid(const RcdProcessInfo& info)
49 {
50     if (info.uniProcessor == nullptr) {
51         RS_LOGE("info uniProcessor is nullptr");
52         return false;
53     } else if (info.topLayer == nullptr || info.bottomLayer == nullptr) {
54         RS_LOGE("info toplayer or bottomlayer resource is nullptr");
55         return false;
56     }
57     return true;
58 }
59 
CheckExist(NodeId id,const RSRenderNodeMap & map)60 bool RSRcdRenderManager::CheckExist(NodeId id, const RSRenderNodeMap& map)
61 {
62     const auto& node = map.GetRenderNode<RSDisplayRenderNode>(id);
63     if (node == nullptr) {
64         return false;
65     }
66     return true;
67 }
68 
RemoveRcdResource(NodeId id)69 void RSRcdRenderManager::RemoveRcdResource(NodeId id)
70 {
71     // to remove the resource which rendertarget display node not exist
72     auto rmTask = [id, this]() {
73         {
74             std::lock_guard<std::mutex> lock(topNodeMapMut_);
75             topSurfaceNodeMap_.erase(id);
76         }
77         {
78             std::lock_guard<std::mutex> lock(bottomNodeMapMut_);
79             bottomSurfaceNodeMap_.erase(id);
80         }
81         RSSingleton<RoundCornerDisplayManager>::GetInstance().RemoveRCDResource(id);
82         RS_LOGI_IF(DEBUG_PIPELINE,
83             "[%{public}s] nodeId:%{public}" PRIu64 " not exist in nodeMap remove the rcd module \n",
84             __func__, id);
85     };
86     RSUniRenderThread::Instance().PostTask(rmTask);
87 }
88 
CheckRenderTargetNode(const RSContext & context)89 void RSRcdRenderManager::CheckRenderTargetNode(const RSContext& context)
90 {
91     const auto& nodeMap = context.GetNodeMap();
92     std::unordered_set<NodeId> idSets;
93     {
94         std::lock_guard<std::mutex> lock(topNodeMapMut_);
95         for (const auto& p : topSurfaceNodeMap_) {
96             idSets.insert(p.first);
97         }
98     }
99     {
100         std::lock_guard<std::mutex> lock(bottomNodeMapMut_);
101         for (const auto& p : bottomSurfaceNodeMap_) {
102             idSets.insert(p.first);
103         }
104     }
105     for (auto it = idSets.begin(); it != idSets.end(); it++) {
106         if (!CheckExist(*it, nodeMap)) {
107             // to remove the resource which rendertarget display node not exist
108             RemoveRcdResource(*it);
109         } else {
110             RS_LOGD("[%{public}s] nodeId:%{public}" PRIu64 " detected in nodeMap \n", __func__, *it);
111         }
112     }
113 }
114 
GetTopSurfaceNode(NodeId id)115 RSRcdSurfaceRenderNodePtr RSRcdRenderManager::GetTopSurfaceNode(NodeId id)
116 {
117     std::lock_guard<std::mutex> lock(topNodeMapMut_);
118     auto it = topSurfaceNodeMap_.find(id);
119     if (it != topSurfaceNodeMap_.end() && it->second != nullptr) {
120         return it->second;
121     }
122     return nullptr;
123 }
124 
GetBottomSurfaceNode(NodeId id)125 RSRcdSurfaceRenderNodePtr RSRcdRenderManager::GetBottomSurfaceNode(NodeId id)
126 {
127     std::lock_guard<std::mutex> lock(bottomNodeMapMut_);
128     auto it = bottomSurfaceNodeMap_.find(id);
129     if (it != bottomSurfaceNodeMap_.end() && it->second != nullptr) {
130         return it->second;
131     }
132     return nullptr;
133 }
134 
GetTopRenderNode(NodeId id)135 RSRcdSurfaceRenderNodePtr RSRcdRenderManager::GetTopRenderNode(NodeId id)
136 {
137     std::lock_guard<std::mutex> lock(topNodeMapMut_);
138     auto it = topSurfaceNodeMap_.find(id);
139     if (it != topSurfaceNodeMap_.end() && it->second != nullptr) {
140         return it->second;
141     }
142     // create and insert
143     auto topRcdNode = RSRcdSurfaceRenderNode::Create(TOP_RCD_NODE_ID, RCDSurfaceType::TOP);
144     topRcdNode->SetRenderTargetId(id);
145     topSurfaceNodeMap_[id] = topRcdNode;
146     RS_LOGI_IF(DEBUG_PIPELINE, "RCD: insert a top rendernode");
147     return topRcdNode;
148 }
149 
GetBottomRenderNode(NodeId id)150 RSRcdSurfaceRenderNodePtr RSRcdRenderManager::GetBottomRenderNode(NodeId id)
151 {
152     std::lock_guard<std::mutex> lock(bottomNodeMapMut_);
153     auto it = bottomSurfaceNodeMap_.find(id);
154     if (it != bottomSurfaceNodeMap_.end() && it->second != nullptr) {
155         return it->second;
156     }
157     // create and insert
158     auto bottomRcdNode = RSRcdSurfaceRenderNode::Create(BACKGROUND_RCD_NODE_ID, RCDSurfaceType::BOTTOM);
159     bottomRcdNode->SetRenderTargetId(id);
160     bottomSurfaceNodeMap_[id] = bottomRcdNode;
161     RS_LOGI_IF(DEBUG_PIPELINE, "RCD: insert a bottom rendernode");
162     return bottomRcdNode;
163 }
164 
DoProcessRenderTask(NodeId id,const RcdProcessInfo & info)165 void RSRcdRenderManager::DoProcessRenderTask(NodeId id, const RcdProcessInfo& info)
166 {
167     RS_TRACE_BEGIN("RSUniRender:DoRCDProcessTask");
168     if (!IsRcdProcessInfoValid(info)) {
169         RS_LOGE("RCD: RcdProcessInfo is incorrect");
170         RS_TRACE_END();
171         return;
172     }
173     auto visitor = std::make_shared<RSRcdRenderVisitor>();
174     visitor->SetUniProcessor(info.uniProcessor);
175     auto bottomRes = visitor->ProcessRcdSurfaceRenderNode(*GetBottomRenderNode(id), info.bottomLayer,
176         info.resourceChanged);
177     auto topRes = visitor->ProcessRcdSurfaceRenderNode(*GetTopRenderNode(id), info.topLayer, info.resourceChanged);
178     if (info.resourceChanged && bottomRes && topRes) {
179         RSSingleton<RsMessageBus>::GetInstance().SendMsg<NodeId, bool>(TOPIC_RCD_DISPLAY_HWRESOURCE, id, true);
180     }
181     RS_TRACE_END();
182 }
183 
DoProcessRenderMainThreadTask(NodeId id,const RcdProcessInfo & info)184 void RSRcdRenderManager::DoProcessRenderMainThreadTask(NodeId id, const RcdProcessInfo& info)
185 {
186     RS_TRACE_BEGIN("RSUniRender:DoRCDProcessMainThreadTask");
187     if (!IsRcdProcessInfoValid(info)) {
188         RS_LOGE("RCD: RcdProcessInfo in MainThread is incorrect");
189         RS_TRACE_END();
190         return;
191     }
192     auto visitor = std::make_shared<RSRcdRenderVisitor>();
193     visitor->SetUniProcessor(info.uniProcessor);
194     visitor->ProcessRcdSurfaceRenderNodeMainThread(*GetBottomRenderNode(id), info.resourceChanged);
195     visitor->ProcessRcdSurfaceRenderNodeMainThread(*GetTopRenderNode(id), info.resourceChanged);
196     RS_TRACE_END();
197 }
198 
199 } // namespace Rosen
200 } // namespace OHOS