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_sub_thread_manager.h"
17
18 #include "pipeline/rs_main_thread.h"
19 #include "memory/rs_memory_manager.h"
20 #include "rs_trace.h"
21
22 namespace OHOS::Rosen {
23 static constexpr uint32_t SUB_THREAD_NUM = 3;
24
Instance()25 RSSubThreadManager* RSSubThreadManager::Instance()
26 {
27 static RSSubThreadManager instance;
28 return &instance;
29 }
30
Start(RenderContext * context)31 void RSSubThreadManager::Start(RenderContext *context)
32 {
33 if (!threadList_.empty()) {
34 return;
35 }
36 renderContext_ = context;
37 if (context) {
38 for (uint32_t i = 0; i < SUB_THREAD_NUM; ++i) {
39 auto curThread = std::make_shared<RSSubThread>(context, i);
40 curThread->Start();
41 threadList_.push_back(curThread);
42 }
43 }
44 }
45
PostTask(const std::function<void ()> & task,uint32_t threadIndex)46 void RSSubThreadManager::PostTask(const std::function<void()>& task, uint32_t threadIndex)
47 {
48 if (threadIndex >= threadList_.size()) {
49 RS_LOGE("taskIndex geq thread num");
50 return;
51 }
52 threadList_[threadIndex]->PostTask(task);
53 }
54
DumpMem(DfxString & log)55 void RSSubThreadManager::DumpMem(DfxString& log)
56 {
57 if (threadList_.empty()) {
58 return;
59 }
60 for (auto subThread : threadList_) {
61 if (!subThread) {
62 continue;
63 }
64 subThread->DumpMem(log);
65 }
66 }
67
SubmitSubThreadTask(const std::shared_ptr<RSDisplayRenderNode> & node,const std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)68 void RSSubThreadManager::SubmitSubThreadTask(const std::shared_ptr<RSDisplayRenderNode>& node,
69 const std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
70 {
71 RS_TRACE_NAME("RSSubThreadManager::SubmitSubThreadTask");
72 bool ifNeedRequestNextVsync = false;
73 if (node == nullptr) {
74 ROSEN_LOGE("RSSubThreadManager::SubmitSubThreadTask display node is null");
75 return;
76 }
77 if (subThreadNodes.empty()) {
78 ROSEN_LOGD("RSSubThreadManager::SubmitSubThreadTask subThread does not have any nodes");
79 if (needResetContext_) {
80 ResetSubThreadGrContext();
81 }
82 needResetContext_ = false;
83 return;
84 }
85 std::vector<std::unique_ptr<RSRenderTask>> renderTaskList;
86 auto cacheSkippedNodeMap = RSMainThread::Instance()->GetCacheCmdSkippedNodes();
87 for (const auto& child : subThreadNodes) {
88 if (!child->ShouldPaint()) {
89 RS_TRACE_NAME_FMT("SubmitTask skip node: [%s, %llu]", child->GetName().c_str(), child->GetId());
90 continue;
91 }
92 if (cacheSkippedNodeMap.count(child->GetId()) != 0 && child->HasCachedTexture()) {
93 RS_TRACE_NAME_FMT("SubmitTask cacheCmdSkippedNode: [%s, %llu]", child->GetName().c_str(), child->GetId());
94 continue;
95 }
96 nodeTaskState_[child->GetId()] = 1;
97 if (child->GetCacheSurfaceProcessedStatus() != CacheProcessStatus::DOING) {
98 child->SetCacheSurfaceProcessedStatus(CacheProcessStatus::WAITING);
99 }
100 renderTaskList.push_back(std::make_unique<RSRenderTask>(*child, RSRenderTask::RenderNodeStage::CACHE));
101 }
102 if (renderTaskList.size()) {
103 ifNeedRequestNextVsync = true;
104 }
105
106 std::vector<std::shared_ptr<RSSuperRenderTask>> superRenderTaskList;
107 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
108 superRenderTaskList.emplace_back(std::make_shared<RSSuperRenderTask>(node,
109 RSMainThread::Instance()->GetFrameCount()));
110 }
111
112 for (auto& renderTask : renderTaskList) {
113 auto renderNode = renderTask->GetNode();
114 auto surfaceNode = renderNode->ReinterpretCastTo<RSSurfaceRenderNode>();
115 if (surfaceNode == nullptr) {
116 ROSEN_LOGE("RSSubThreadManager::SubmitSubThreadTask surfaceNode is null");
117 continue;
118 }
119 auto threadIndex = surfaceNode->GetSubmittedSubThreadIndex();
120 if (threadIndex != INT_MAX && superRenderTaskList[threadIndex]) {
121 RS_TRACE_NAME("node:[ " + surfaceNode->GetName() + ", " + std::to_string(surfaceNode->GetId()) +
122 ", " + std::to_string(threadIndex) + " ]; ");
123 superRenderTaskList[threadIndex]->AddTask(std::move(renderTask));
124 } else {
125 if (superRenderTaskList[minLoadThreadIndex_]) {
126 RS_TRACE_NAME("node:[ " + surfaceNode->GetName() + ", " + std::to_string(surfaceNode->GetId()) +
127 ", " + std::to_string(minLoadThreadIndex_) + " ]; ");
128 superRenderTaskList[minLoadThreadIndex_]->AddTask(std::move(renderTask));
129 surfaceNode->SetSubmittedSubThreadIndex(minLoadThreadIndex_);
130 }
131 }
132 uint32_t minLoadThreadIndex = 0;
133 auto minNodesNum = superRenderTaskList[0]->GetTaskSize();
134 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
135 auto num = superRenderTaskList[i]->GetTaskSize();
136 if (num < minNodesNum) {
137 minNodesNum = num;
138 minLoadThreadIndex = i;
139 }
140 }
141 minLoadThreadIndex_ = minLoadThreadIndex;
142 }
143
144 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
145 auto subThread = threadList_[i];
146 subThread->PostTask([subThread, superRenderTaskList, i]() {
147 subThread->RenderCache(superRenderTaskList[i]);
148 });
149 }
150 needResetContext_ = true;
151 if (ifNeedRequestNextVsync) {
152 RSMainThread::Instance()->SetIsCachedSurfaceUpdated(true);
153 RSMainThread::Instance()->RequestNextVSync();
154 }
155 }
156
WaitNodeTask(uint64_t nodeId)157 void RSSubThreadManager::WaitNodeTask(uint64_t nodeId)
158 {
159 std::unique_lock<std::mutex> lock(parallelRenderMutex_);
160 cvParallelRender_.wait(lock, [&]() {
161 return !nodeTaskState_[nodeId];
162 });
163 }
164
NodeTaskNotify(uint64_t nodeId)165 void RSSubThreadManager::NodeTaskNotify(uint64_t nodeId)
166 {
167 {
168 std::unique_lock<std::mutex> lock(parallelRenderMutex_);
169 nodeTaskState_[nodeId] = 0;
170 }
171 cvParallelRender_.notify_one();
172 }
173
ResetSubThreadGrContext()174 void RSSubThreadManager::ResetSubThreadGrContext()
175 {
176 if (threadList_.empty()) {
177 return;
178 }
179 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
180 auto subThread = threadList_[i];
181 subThread->PostTask([subThread]() {
182 subThread->ResetGrContext();
183 });
184 }
185 }
186 }