• 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 #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 }