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 #include <chrono>
18
19 #include "common/rs_singleton.h"
20 #include "common/rs_optional_trace.h"
21 #include "pipeline/rs_main_thread.h"
22 #include "pipeline/rs_task_dispatcher.h"
23 #include "memory/rs_memory_manager.h"
24 #include "pipeline/round_corner_display/rs_round_corner_display.h"
25 #include "pipeline/round_corner_display/rs_sub_thread_rcd.h"
26 #include "pipeline/round_corner_display/rs_message_bus.h"
27
28 namespace OHOS::Rosen {
29 static constexpr uint32_t SUB_THREAD_NUM = 3;
30 static constexpr uint32_t WAIT_NODE_TASK_TIMEOUT = 5 * 1000; // 5s
31 constexpr const char* RELEASE_RESOURCE = "releaseResource";
32
Instance()33 RSSubThreadManager* RSSubThreadManager::Instance()
34 {
35 static RSSubThreadManager instance;
36 return &instance;
37 }
38
Start(RenderContext * context)39 void RSSubThreadManager::Start(RenderContext *context)
40 {
41 if (!threadList_.empty()) {
42 return;
43 }
44 renderContext_ = context;
45 if (context) {
46 for (uint32_t i = 0; i < SUB_THREAD_NUM; ++i) {
47 auto curThread = std::make_shared<RSSubThread>(context, i);
48 auto tid = curThread->Start();
49 threadIndexMap_.emplace(tid, i);
50 reThreadIndexMap_.emplace(i, tid);
51 threadList_.push_back(curThread);
52 auto taskDispatchFunc = [tid, this](const RSTaskDispatcher::RSTask& task, bool isSyncTask = false) {
53 RSSubThreadManager::Instance()->PostTask(task, threadIndexMap_[tid], isSyncTask);
54 };
55 RSTaskDispatcher::GetInstance().RegisterTaskDispatchFunc(tid, taskDispatchFunc);
56 }
57 }
58 }
StartFilterThread(RenderContext * context)59 void RSSubThreadManager::StartFilterThread(RenderContext* context)
60 {
61 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
62 if (!RSSystemProperties::GetFilterPartialRenderEnabled() || !RSUniRenderJudgement::IsUniRender()) {
63 RS_LOGD("RSSubThreadManager::StartFilterThread:Filter thread not run");
64 return;
65 }
66 if (filterThread != nullptr) {
67 return;
68 }
69 renderContext_ = context;
70 if (context) {
71 filterThread = std::make_shared<RSFilterSubThread>(context);
72 filterThread->Start();
73 }
74 #endif
75 }
76
StartColorPickerThread(RenderContext * context)77 void RSSubThreadManager::StartColorPickerThread(RenderContext* context)
78 {
79 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined (RS_ENABLE_VK))
80 if (!RSSystemProperties::GetColorPickerPartialEnabled() || !RSUniRenderJudgement::IsUniRender()) {
81 RS_LOGD("RSSubThreadManager::StartColorPickerThread:Filter thread not run");
82 return;
83 }
84 if (colorPickerThread_ != nullptr) {
85 return;
86 }
87 renderContext_ = context;
88 if (context) {
89 colorPickerThread_ = std::make_shared<RSFilterSubThread>(context);
90 colorPickerThread_->StartColorPicker();
91 }
92 #endif
93 }
94
StartRCDThread(RenderContext * context)95 void RSSubThreadManager::StartRCDThread(RenderContext* context)
96 {
97 renderContext_ = context;
98 if (context) {
99 RS_LOGD("RSSubThreadManager::StartRCDThread");
100 auto threadRcd = &(RSSingleton<RSSubThreadRCD>::GetInstance());
101 threadRcd->Start(context);
102 if (!isRcdServiceRegister_) {
103 auto& rcdInstance = RSSingleton<RoundCornerDisplay>::GetInstance();
104 auto& msgBus = RSSingleton<RsMessageBus>::GetInstance();
105 msgBus.RegisterTopic<uint32_t, uint32_t>(
106 TOPIC_RCD_DISPLAY_SIZE, &rcdInstance,
107 &RoundCornerDisplay::UpdateDisplayParameter);
108 msgBus.RegisterTopic<ScreenRotation>(
109 TOPIC_RCD_DISPLAY_ROTATION, &rcdInstance,
110 &RoundCornerDisplay::UpdateOrientationStatus);
111 msgBus.RegisterTopic<int>(
112 TOPIC_RCD_DISPLAY_NOTCH, &rcdInstance,
113 &RoundCornerDisplay::UpdateNotchStatus);
114 isRcdServiceRegister_ = true;
115 RS_LOGD("RSSubThreadManager::StartRCDThread Registed rcd renderservice end");
116 }
117 RS_LOGD("RSSubThreadManager::StartRCDThread Registed rcd renderservice already.");
118 }
119 }
120
PostTask(const std::function<void ()> & task,uint32_t threadIndex,bool isSyncTask)121 void RSSubThreadManager::PostTask(const std::function<void()>& task, uint32_t threadIndex, bool isSyncTask)
122 {
123 if (threadIndex >= threadList_.size()) {
124 RS_LOGE("taskIndex geq thread num");
125 return;
126 }
127 if (isSyncTask) {
128 threadList_[threadIndex]->PostSyncTask(task);
129 } else {
130 threadList_[threadIndex]->PostTask(task);
131 }
132 }
133
DumpMem(DfxString & log)134 void RSSubThreadManager::DumpMem(DfxString& log)
135 {
136 if (threadList_.empty()) {
137 return;
138 }
139 for (auto subThread : threadList_) {
140 if (!subThread) {
141 continue;
142 }
143 subThread->DumpMem(log);
144 }
145 if (filterThread) {
146 filterThread->DumpMem(log);
147 }
148 if (colorPickerThread_) {
149 colorPickerThread_->DumpMem(log);
150 }
151 }
152
GetAppGpuMemoryInMB()153 float RSSubThreadManager::GetAppGpuMemoryInMB()
154 {
155 if (threadList_.empty()) {
156 return 0.f;
157 }
158 float total = 0.f;
159 for (auto& subThread : threadList_) {
160 if (!subThread) {
161 continue;
162 }
163 total += subThread->GetAppGpuMemoryInMB();
164 }
165 if (filterThread) {
166 total += filterThread->GetAppGpuMemoryInMB();
167 }
168 if (colorPickerThread_) {
169 total += colorPickerThread_->GetAppGpuMemoryInMB();
170 }
171 return total;
172 }
173
SubmitFilterSubThreadTask()174 void RSSubThreadManager::SubmitFilterSubThreadTask()
175 {
176 if (filterThread) {
177 filterThread->FlushAndSubmit();
178 }
179 }
180
SetFenceSubThread(sptr<SyncFence> fence)181 void RSSubThreadManager::SetFenceSubThread(sptr<SyncFence> fence)
182 {
183 if (filterThread) {
184 filterThread->SetFence(fence);
185 }
186 }
187
SubmitSubThreadTask(const std::shared_ptr<RSDisplayRenderNode> & node,const std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)188 void RSSubThreadManager::SubmitSubThreadTask(const std::shared_ptr<RSDisplayRenderNode>& node,
189 const std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
190 {
191 RS_TRACE_NAME("RSSubThreadManager::SubmitSubThreadTask");
192 bool ifNeedRequestNextVsync = false;
193
194 if (node == nullptr) {
195 ROSEN_LOGE("RSSubThreadManager::SubmitSubThreadTask display node is null");
196 return;
197 }
198 if (subThreadNodes.empty()) {
199 return;
200 }
201 CancelReleaseResourceTask();
202 std::vector<std::unique_ptr<RSRenderTask>> renderTaskList;
203 auto cacheSkippedNodeMap = RSMainThread::Instance()->GetCacheCmdSkippedNodes();
204 for (const auto& child : subThreadNodes) {
205 if (!child) {
206 continue;
207 }
208 if (!child->ShouldPaint()) {
209 RS_OPTIONAL_TRACE_NAME_FMT("SubmitTask skip node: [%s, %llu]", child->GetName().c_str(), child->GetId());
210 continue;
211 }
212 if (!child->GetNeedSubmitSubThread()) {
213 RS_OPTIONAL_TRACE_NAME_FMT("subThreadNodes : static skip %s", child->GetName().c_str());
214 continue;
215 }
216 if (cacheSkippedNodeMap.count(child->GetId()) != 0 && child->HasCachedTexture()) {
217 RS_OPTIONAL_TRACE_NAME_FMT("SubmitTask cacheCmdSkippedNode: [%s, %llu]",
218 child->GetName().c_str(), child->GetId());
219 continue;
220 }
221 nodeTaskState_[child->GetId()] = 1;
222 if (child->GetCacheSurfaceProcessedStatus() != CacheProcessStatus::DOING) {
223 child->SetCacheSurfaceProcessedStatus(CacheProcessStatus::WAITING);
224 }
225 renderTaskList.push_back(std::make_unique<RSRenderTask>(*child, RSRenderTask::RenderNodeStage::CACHE));
226 }
227 if (renderTaskList.size()) {
228 ifNeedRequestNextVsync = true;
229 }
230
231 std::vector<std::shared_ptr<RSSuperRenderTask>> superRenderTaskList;
232 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
233 superRenderTaskList.emplace_back(std::make_shared<RSSuperRenderTask>(node,
234 RSMainThread::Instance()->GetFrameCount()));
235 }
236
237 for (auto& renderTask : renderTaskList) {
238 auto renderNode = renderTask->GetNode();
239 auto surfaceNode = renderNode->ReinterpretCastTo<RSSurfaceRenderNode>();
240 if (surfaceNode == nullptr) {
241 ROSEN_LOGE("RSSubThreadManager::SubmitSubThreadTask surfaceNode is null");
242 continue;
243 }
244 auto threadIndex = surfaceNode->GetSubmittedSubThreadIndex();
245 if (threadIndex != INT_MAX && superRenderTaskList[threadIndex]) {
246 RS_OPTIONAL_TRACE_NAME("node:[ " + surfaceNode->GetName() + ", " + std::to_string(surfaceNode->GetId()) +
247 ", " + std::to_string(threadIndex) + " ]; ");
248 superRenderTaskList[threadIndex]->AddTask(std::move(renderTask));
249 } else {
250 if (superRenderTaskList[minLoadThreadIndex_]) {
251 RS_OPTIONAL_TRACE_NAME("node:[ " + surfaceNode->GetName() +
252 ", " + std::to_string(surfaceNode->GetId()) +
253 ", " + std::to_string(minLoadThreadIndex_) + " ]; ");
254 superRenderTaskList[minLoadThreadIndex_]->AddTask(std::move(renderTask));
255 surfaceNode->SetSubmittedSubThreadIndex(minLoadThreadIndex_);
256 }
257 }
258 uint32_t minLoadThreadIndex = 0;
259 auto minNodesNum = superRenderTaskList[0]->GetTaskSize();
260 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
261 auto num = superRenderTaskList[i]->GetTaskSize();
262 if (num < minNodesNum) {
263 minNodesNum = num;
264 minLoadThreadIndex = i;
265 }
266 }
267 minLoadThreadIndex_ = minLoadThreadIndex;
268 }
269
270 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
271 auto subThread = threadList_[i];
272 subThread->PostTask([subThread, superRenderTaskList, i]() {
273 subThread->RenderCache(superRenderTaskList[i]);
274 });
275 }
276 needResetContext_ = true;
277 if (ifNeedRequestNextVsync) {
278 RSMainThread::Instance()->SetIsCachedSurfaceUpdated(true);
279 RSMainThread::Instance()->RequestNextVSync();
280 }
281 }
282
WaitNodeTask(uint64_t nodeId)283 void RSSubThreadManager::WaitNodeTask(uint64_t nodeId)
284 {
285 std::unique_lock<std::mutex> lock(parallelRenderMutex_);
286 cvParallelRender_.wait_for(lock, std::chrono::milliseconds(WAIT_NODE_TASK_TIMEOUT), [&]() {
287 return !nodeTaskState_[nodeId];
288 });
289 }
290
NodeTaskNotify(uint64_t nodeId)291 void RSSubThreadManager::NodeTaskNotify(uint64_t nodeId)
292 {
293 {
294 std::unique_lock<std::mutex> lock(parallelRenderMutex_);
295 nodeTaskState_[nodeId] = 0;
296 }
297 cvParallelRender_.notify_one();
298 }
299
ResetSubThreadGrContext()300 void RSSubThreadManager::ResetSubThreadGrContext()
301 {
302 if (threadList_.empty()) {
303 return;
304 }
305 if (!needResetContext_) {
306 return;
307 }
308 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
309 auto subThread = threadList_[i];
310 subThread->PostTask([subThread]() {
311 subThread->ResetGrContext();
312 }, RELEASE_RESOURCE);
313 }
314 needResetContext_ = false;
315 needCancelTask_ = true;
316 }
317
CancelReleaseResourceTask()318 void RSSubThreadManager::CancelReleaseResourceTask()
319 {
320 if (!needCancelTask_) {
321 return;
322 }
323 if (threadList_.empty()) {
324 return;
325 }
326 for (uint32_t i = 0; i < SUB_THREAD_NUM; i++) {
327 auto subThread = threadList_[i];
328 subThread->RemoveTask(RELEASE_RESOURCE);
329 }
330 needCancelTask_ = false;
331 }
332
ReleaseSurface(uint32_t threadIndex) const333 void RSSubThreadManager::ReleaseSurface(uint32_t threadIndex) const
334 {
335 if (threadList_.size() <= threadIndex) {
336 return;
337 }
338 auto subThread = threadList_[threadIndex];
339 subThread->PostTask([subThread]() {
340 subThread->ReleaseSurface();
341 });
342 }
343
344 #ifndef USE_ROSEN_DRAWING
AddToReleaseQueue(sk_sp<SkSurface> && surface,uint32_t threadIndex)345 void RSSubThreadManager::AddToReleaseQueue(sk_sp<SkSurface>&& surface, uint32_t threadIndex)
346 #else
347 void RSSubThreadManager::AddToReleaseQueue(std::shared_ptr<Drawing::Surface>&& surface, uint32_t threadIndex)
348 #endif
349 {
350 if (threadList_.size() <= threadIndex) {
351 return;
352 }
353 threadList_[threadIndex]->AddToReleaseQueue(std::move(surface));
354 }
355
CountSubMem(int pid)356 std::vector<MemoryGraphic> RSSubThreadManager::CountSubMem(int pid)
357 {
358 std::vector<MemoryGraphic> memsContainer;
359 if (threadList_.empty()) {
360 return memsContainer;
361 }
362
363 for (auto& subThread : threadList_) {
364 if (!subThread) {
365 MemoryGraphic memoryGraphic;
366 memsContainer.push_back(memoryGraphic);
367 continue;
368 }
369 memsContainer.push_back(subThread->CountSubMem(pid));
370 }
371 return memsContainer;
372 }
373
GetReThreadIndexMap() const374 std::unordered_map<uint32_t, pid_t> RSSubThreadManager::GetReThreadIndexMap() const
375 {
376 return reThreadIndexMap_;
377 }
378 }