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