• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_parallel_render_manager.h"
17 #include <cstddef>
18 #include <cstdint>
19 #include <memory>
20 #include <mutex>
21 
22 #include "EGL/egl.h"
23 #include "rs_render_task.h"
24 #include "pipeline/rs_base_render_engine.h"
25 #include "pipeline/rs_main_thread.h"
26 #include "pipeline/rs_uni_render_engine.h"
27 #include "pipeline/rs_uni_render_listener.h"
28 #include "pipeline/rs_uni_render_visitor.h"
29 #include "rs_parallel_render_ext.h"
30 #include "rs_trace.h"
31 
32 
33 namespace OHOS {
34 namespace Rosen {
35 
36 static constexpr uint32_t PARALLEL_THREAD_NUM = 3;
37 static constexpr int32_t MAX_CALC_COST_COUNT = 20;
38 
Instance()39 RSParallelRenderManager* RSParallelRenderManager::Instance()
40 {
41     static RSParallelRenderManager instance;
42     return &instance;
43 }
44 
RSParallelRenderManager()45 RSParallelRenderManager::RSParallelRenderManager()
46     : taskType_(TaskType::PROCESS_TASK),
47       parallelHardwareComposer_(std::make_unique<RSParallelHardwareComposer>())
48 {
49     if (parallelHardwareComposer_) {
50         InitAppWindowNodeMap();
51         parallelHardwareComposer_->Init(PARALLEL_THREAD_NUM);
52     }
53     if (ParallelRenderExtEnabled()) {
54         startTime_.assign(PARALLEL_THREAD_NUM, {});
55         stopTime_.assign(PARALLEL_THREAD_NUM, {});
56     }
57     readyBufferNum_ = 0;
58 #ifdef RS_ENABLE_VK
59     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
60         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
61         parallelDisplayNodes_.assign(PARALLEL_THREAD_NUM, nullptr);
62         backParallelDisplayNodes_.assign(PARALLEL_THREAD_NUM, nullptr);
63     }
64 #endif
65 }
66 
InitAppWindowNodeMap()67 void RSParallelRenderManager::InitAppWindowNodeMap()
68 {
69     auto appWindowNode = std::vector<std::shared_ptr<RSSurfaceRenderNode>>();
70     for (uint32_t i = 0; i < PARALLEL_THREAD_NUM; i++) {
71         appWindowNodesMap_[i] = appWindowNode;
72     }
73 }
74 
SetParallelMode(bool parallelMode)75 void RSParallelRenderManager::SetParallelMode(bool parallelMode)
76 {
77     parallelMode_ = parallelMode;
78     TryEnableParallelRendering();
79 }
80 
81 // You should always use GetParallelModeSafe() instead of GetParallelMode()
82 // except initialize variable 'isParallel' in 'rs_uni_render_visitor.cpp'
GetParallelModeSafe() const83 bool RSParallelRenderManager::GetParallelModeSafe() const
84 {
85     return GetParallelRenderingStatus() == ParallelStatus::ON;
86 }
87 
GetParallelMode() const88 bool RSParallelRenderManager::GetParallelMode() const
89 {
90     ParallelStatus status = GetParallelRenderingStatus();
91     return (status == ParallelStatus::ON) || (status == ParallelStatus::FIRSTFLUSH);
92 }
93 
94 #ifdef NEW_RENDER_CONTEXT
StartSubRenderThread(uint32_t threadNum,std::shared_ptr<RenderContextBase> context,std::shared_ptr<DrawingContext> drawingContext)95 void RSParallelRenderManager::StartSubRenderThread(uint32_t threadNum, std::shared_ptr<RenderContextBase> context,
96     std::shared_ptr<DrawingContext> drawingContext)
97 #else
98 void RSParallelRenderManager::StartSubRenderThread(uint32_t threadNum, RenderContext *context)
99 #endif
100 {
101     if (GetParallelRenderingStatus() == ParallelStatus::OFF) {
102         expectedSubThreadNum_ = threadNum;
103         flipCoin_ = std::vector<uint8_t>(expectedSubThreadNum_, 0);
104         firstFlush_ = true;
105         renderContext_ = context;
106 #ifdef NEW_RENDER_CONTEXT
107         drawingContext_ = drawingContext;
108 #endif
109 
110 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
111         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
112             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR || context) {
113 #endif
114             for (uint32_t i = 0; i < threadNum; ++i) {
115                 auto curThread = std::make_unique<RSParallelSubThread>(context, renderType_, i);
116                 curThread->StartSubThread();
117                 threadList_.push_back(std::move(curThread));
118             }
119 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
120         }
121 #endif
122 
123         processTaskManager_.Initialize(threadNum);
124         prepareTaskManager_.Initialize(threadNum);
125         calcCostTaskManager_.Initialize(threadNum);
126         compositionTaskManager_.Initialize(threadNum);
127     }
128 }
129 
EndSubRenderThread()130 void RSParallelRenderManager::EndSubRenderThread()
131 {
132     if (GetParallelRenderingStatus() == ParallelStatus::ON) {
133         for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
134             flipCoin_[i] = 1;
135         }
136         readySubThreadNum_ = expectedSubThreadNum_ = 0;
137         cvParallelRender_.notify_all();
138         packVisitor_ = nullptr;
139         packVisitorPrepare_ = nullptr;
140         calcCostVisitor_ = nullptr;
141         for (auto &thread : threadList_) {
142             thread->WaitSubMainThreadEnd();
143         }
144         std::vector<std::unique_ptr<RSParallelSubThread>>().swap(threadList_);
145         uniVisitor_ = nullptr;
146     }
147 }
148 
ReadySubThreadNumIncrement()149 void RSParallelRenderManager::ReadySubThreadNumIncrement()
150 {
151     ++readySubThreadNum_;
152 }
153 
GetParallelRenderingStatus() const154 ParallelStatus RSParallelRenderManager::GetParallelRenderingStatus() const
155 {
156     if (expectedSubThreadNum_ == 0) {
157         return ParallelStatus::OFF;
158     } else if (expectedSubThreadNum_ == readySubThreadNum_) {
159         return ParallelStatus::ON;
160     } else if (firstFlush_) {
161         return ParallelStatus::FIRSTFLUSH;
162     } else {
163         return ParallelStatus::WAITFIRSTFLUSH;
164     }
165 }
166 
CopyVisitorAndPackTask(RSUniRenderVisitor & visitor,RSDisplayRenderNode & node)167 void RSParallelRenderManager::CopyVisitorAndPackTask(RSUniRenderVisitor &visitor, RSDisplayRenderNode &node)
168 {
169     packVisitor_ = std::make_shared<RSParallelPackVisitor>(visitor);
170     displayNode_ = node.shared_from_this();
171     processTaskManager_.Reset();
172     processTaskManager_.LoadParallelPolicy(parallelPolicy_);
173     packVisitor_->ProcessDisplayRenderNode(node);
174     uniVisitor_ = &visitor;
175     taskType_ = TaskType::PROCESS_TASK;
176 }
177 
CopyPrepareVisitorAndPackTask(RSUniRenderVisitor & visitor,RSDisplayRenderNode & node)178 void RSParallelRenderManager::CopyPrepareVisitorAndPackTask(RSUniRenderVisitor &visitor, RSDisplayRenderNode &node)
179 {
180     packVisitorPrepare_ = std::make_shared<RSParallelPackVisitor>();
181     uniVisitor_ = &visitor;
182     displayNode_ = node.shared_from_this();
183     prepareTaskManager_.Reset();
184     packVisitorPrepare_->PrepareDisplayRenderNode(node);
185     taskType_ = TaskType::PREPARE_TASK;
186 }
187 
CopyCalcCostVisitorAndPackTask(RSUniRenderVisitor & visitor,RSDisplayRenderNode & node,bool isNeedCalc,bool doAnimate,bool isOpDropped)188 void RSParallelRenderManager::CopyCalcCostVisitorAndPackTask(RSUniRenderVisitor &visitor,
189     RSDisplayRenderNode &node, bool isNeedCalc, bool doAnimate, bool isOpDropped)
190 {
191     calcCostTaskManager_.Reset();
192     if (isNeedCalc) {
193         calcCostCount_ = MAX_CALC_COST_COUNT;
194     }
195     if (calcCostCount_ > 0) {
196         calcCostCount_--;
197     }
198     if (IsNeedCalcCost()) {
199         calcCostVisitor_ =  std::make_shared<RSParallelPackVisitor>(visitor);
200         uniVisitor_ = &visitor;
201         displayNode_ = node.shared_from_this();
202         calcCostVisitor_->CalcDisplayRenderNodeCost(node);
203         taskType_ = TaskType::CALC_COST_TASK;
204         GetCostFactor();
205         doAnimate_ = doAnimate;
206         isOpDropped_ = isOpDropped;
207         isSecurityDisplay_ = node.GetSecurityDisplay();
208     }
209 }
210 
IsNeedCalcCost() const211 bool RSParallelRenderManager::IsNeedCalcCost() const
212 {
213     return calcCostCount_ > 0;
214 }
215 
GetTaskType() const216 TaskType RSParallelRenderManager::GetTaskType() const
217 {
218     return taskType_;
219 }
220 
PackRenderTask(RSSurfaceRenderNode & node,TaskType type)221 void RSParallelRenderManager::PackRenderTask(RSSurfaceRenderNode &node, TaskType type)
222 {
223     switch (type) {
224         case TaskType::PREPARE_TASK:
225             prepareTaskManager_.PushRenderTask(
226                 std::make_unique<RSRenderTask>(node, RSRenderTask::RenderNodeStage::PREPARE));
227             break;
228         case TaskType::PROCESS_TASK:
229             processTaskManager_.PushRenderTask(
230                 std::make_unique<RSRenderTask>(node, RSRenderTask::RenderNodeStage::PROCESS));
231             break;
232         case TaskType::CALC_COST_TASK:
233             calcCostTaskManager_.PushRenderTask(
234                 std::make_unique<RSRenderTask>(node, RSRenderTask::RenderNodeStage::CALC_COST));
235             break;
236         default:
237             break;
238     }
239 }
240 
PackParallelCompositionTask(std::shared_ptr<RSNodeVisitor> visitor,const std::shared_ptr<RSBaseRenderNode> node)241 void RSParallelRenderManager::PackParallelCompositionTask(std::shared_ptr<RSNodeVisitor> visitor,
242                                                           const std::shared_ptr<RSBaseRenderNode> node)
243 {
244     uniParallelCompositionVisitor_ = std::static_pointer_cast<RSUniRenderVisitor>(visitor);
245     baseNode_ = node;
246     compositionTaskManager_.Reset();
247     auto children = node->GetSortedChildren();
248     for (auto iter = children->rbegin(); iter != children->rend(); iter++) {
249         std::shared_ptr<RSDisplayRenderNode> displayNode =
250             RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(*iter);
251         if (*iter == *children->begin()) {
252             mainDisplayNode_ = displayNode;
253             break;
254         }
255         compositionTaskManager_.PushCompositionTask(std::make_unique<RSCompositionTask>(displayNode));
256     }
257     taskType_ = TaskType::COMPOSITION_TASK;
258 }
259 
LoadBalanceAndNotify(TaskType type)260 void RSParallelRenderManager::LoadBalanceAndNotify(TaskType type)
261 {
262     InitAppWindowNodeMap();
263     switch (type) {
264         case TaskType::PREPARE_TASK:
265             prepareTaskManager_.LBCalcAndSubmitSuperTask(displayNode_);
266             break;
267         case TaskType::PROCESS_TASK:
268             processTaskManager_.LBCalcAndSubmitSuperTask(displayNode_);
269             break;
270         case TaskType::CALC_COST_TASK:
271             calcCostTaskManager_.LBCalcAndSubmitSuperTask(displayNode_);
272             break;
273         case TaskType::COMPOSITION_TASK:
274             compositionTaskManager_.LBCalcAndSubmitCompositionTask(baseNode_);
275             break;
276         default:
277             break;
278     }
279     for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
280         flipCoin_[i] = 1;
281     }
282     cvParallelRender_.notify_all();
283     if (type == TaskType::COMPOSITION_TASK) {
284         auto mainThread = RSMainThread::Instance();
285         if (mainThread == nullptr) {
286             RS_LOGE("RS main thread is nullptr.");
287             return;
288         }
289         std::shared_ptr<RSBaseRenderEngine> renderEngine = mainThread->GetRenderEngine();
290         uniParallelCompositionVisitor_->SetProcessorRenderEngine(renderEngine);
291         mainDisplayNode_->Process(uniParallelCompositionVisitor_);
292         uniParallelCompositionVisitor_ = nullptr;
293     }
294 }
295 
WaitPrepareEnd(RSUniRenderVisitor & visitor)296 void RSParallelRenderManager::WaitPrepareEnd(RSUniRenderVisitor &visitor)
297 {
298     for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
299         WaitSubMainThread(i);
300         visitor.CopyForParallelPrepare(threadList_[i]->GetUniVisitor());
301     }
302 }
303 
WaitProcessEnd()304 void RSParallelRenderManager::WaitProcessEnd()
305 {
306     for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
307         WaitSubMainThread(i);
308     }
309 }
310 
WaitCompositionEnd()311 void RSParallelRenderManager::WaitCompositionEnd()
312 {
313     for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
314         WaitSubMainThread(i);
315     }
316 }
317 
318 #ifdef USE_ROSEN_DRAWING
DrawImageMergeFuncForRosenDrawing(RSPaintFilterCanvas & canvas,std::shared_ptr<Drawing::Image> texture)319 bool RSParallelRenderManager::DrawImageMergeFuncForRosenDrawing(RSPaintFilterCanvas& canvas,
320     std::shared_ptr<Drawing::Image> texture)
321 {
322     if (canvas.GetGPUContext() == nullptr) {
323         return false;
324     }
325 
326     Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
327     auto sharedBackendTexture = texture->GetBackendTexture(false, &origin);
328     if (!sharedBackendTexture.IsValid()) {
329         RS_LOGE("Texture of subThread does not has GPU backend");
330         return false;
331     }
332     auto newImage = std::make_shared<Drawing::Image>();
333     if (newImage == nullptr) {
334         RS_LOGE("Texture of subThread create Drawing image fail");
335         return false;
336     }
337     Drawing::BitmapFormat fmt =
338         Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
339     bool ret = newImage->BuildFromTexture(*canvas.GetGPUContext(), sharedBackendTexture.GetTextureInfo(),
340         origin, fmt, nullptr);
341     if (!ret) {
342         return false;
343     }
344     canvas.DrawImage(*newImage, 0, 0, Drawing::SamplingOptions());
345     return true;
346 }
347 #endif
348 
DrawImageMergeFunc(RSPaintFilterCanvas & canvas)349 void RSParallelRenderManager::DrawImageMergeFunc(RSPaintFilterCanvas& canvas)
350 {
351     for (unsigned int i = 0; i < expectedSubThreadNum_; ++i) {
352         RS_TRACE_BEGIN("Wait Render finish");
353         WaitSubMainThread(i);
354         RS_TRACE_END();
355         if (i < processTaskManager_.GetTaskNum()) {
356             RS_TRACE_BEGIN("Wait Fence Ready");
357             threadList_[i]->WaitReleaseFence();
358             RS_TRACE_END();
359             auto texture = threadList_[i]->GetTexture();
360             if (texture == nullptr) {
361                 RS_LOGE("Texture of subThread(%{public}d) is nullptr", i);
362                 continue;
363             }
364 #ifndef USE_ROSEN_DRAWING
365             if (renderContext_ == nullptr) {
366                 RS_LOGE("RS main thread render context is nullptr");
367                 continue;
368             }
369 #ifdef NEW_RENDER_CONTEXT
370             auto mainGrContext = drawingContext_->GetDrawingContext();
371 #else
372             auto mainGrContext = renderContext_->GetGrContext();
373 #endif
374             if (mainGrContext == nullptr) {
375                 RS_LOGE("RS main thread GrDirectContext is nullptr");
376                 continue;
377             }
378             auto sharedBackendTexture = texture->getBackendTexture(false);
379             if (!sharedBackendTexture.isValid()) {
380                 RS_LOGE("Texture of subThread(%{public}d) does not has GPU backend", i);
381                 continue;
382             }
383             auto sharedTexture = SkImage::MakeFromTexture(mainGrContext, sharedBackendTexture,
384                 kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
385             if (sharedTexture == nullptr) {
386                 RS_LOGE("SharedTexture of subThread(%{public}d) is nullptr", i);
387             }
388             canvas.drawImage(sharedTexture, 0, 0);
389 #else
390             if (!DrawImageMergeFuncForRosenDrawing(canvas, texture)) {
391                 continue;
392             }
393 #endif
394             // For any one subMainThread' sksurface, we just clear transparent color of self drawing
395             // surface drawed in larger skSurface, such as skSurface 0 should clear self drawing surface
396             // areas drawed in skSurface 1.
397             auto clearTransparentColorSurfaceIndex = i + 1;
398             ClearSelfDrawingSurface(canvas, clearTransparentColorSurfaceIndex);
399 #ifndef USE_ROSEN_DRAWING
400             sharedTexture.reset();
401             sharedTexture = nullptr;
402             texture.reset();
403             texture = nullptr;
404 #else
405             texture.reset();
406             texture = nullptr;
407 #endif
408         }
409     }
410 }
411 
FlushOneBufferFunc()412 void RSParallelRenderManager::FlushOneBufferFunc()
413 {
414 #ifdef NEW_RENDER_CONTEXT
415     renderContext_->MakeCurrent(nullptr, EGL_NO_CONTEXT);
416 #else
417     renderContext_->ShareMakeCurrent(EGL_NO_CONTEXT);
418 #endif
419     for (unsigned int i = 0; i < threadList_.size(); ++i) {
420         if (threadList_[i] == nullptr) {
421             return;
422         }
423 #ifdef NEW_RENDER_CONTEXT
424         renderContext_->MakeCurrent(nullptr, threadList_[i]->GetSharedContext());
425 #else
426         renderContext_->ShareMakeCurrent(threadList_[i]->GetSharedContext());
427 #endif
428         RS_TRACE_BEGIN("Start Flush");
429 #ifndef USE_ROSEN_DRAWING
430         auto skSurface = threadList_[i]->GetSkSurface();
431         if (skSurface) {
432             skSurface->flush();
433         } else {
434             RS_LOGE("skSurface is nullptr, thread index:%{public}d", i);
435         }
436 #else
437         auto drSurface = threadList_[i]->GetDrawingSurface();
438         if (drSurface) {
439             auto canvas = drSurface->GetCanvas();
440             canvas->Flush();
441         } else {
442             RS_LOGE("skSurface is nullptr, thread index:%{public}d", i);
443         }
444 #endif
445         RS_TRACE_END();
446 #ifdef NEW_RENDER_CONTEXT
447         renderContext_->MakeCurrent(nullptr, EGL_NO_CONTEXT);
448 #else
449         renderContext_->ShareMakeCurrent(EGL_NO_CONTEXT);
450 #endif
451     }
452 #ifdef NEW_RENDER_CONTEXT
453     renderContext_->MakeCurrent();
454 #else
455     renderContext_->MakeSelfCurrent();
456 #endif
457 }
458 
MergeRenderResult(RSPaintFilterCanvas & canvas)459 void RSParallelRenderManager::MergeRenderResult(RSPaintFilterCanvas& canvas)
460 {
461     if (GetParallelRenderingStatus() == ParallelStatus::FIRSTFLUSH) {
462         firstFlush_ = false;
463         for (unsigned int i = 0; i < expectedSubThreadNum_; ++i) {
464             WaitSubMainThread(i);
465         }
466         return;
467     }
468     if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
469         DrawImageMergeFunc(canvas);
470     } else {
471         FlushOneBufferFunc();
472     }
473     if (parallelHardwareComposer_) {
474         parallelHardwareComposer_->Init(PARALLEL_THREAD_NUM);
475     }
476 }
477 
SetFrameSize(int width,int height)478 void RSParallelRenderManager::SetFrameSize(int width, int height)
479 {
480     width_ = width;
481     height_ = height;
482 }
483 
GetFrameSize(int & width,int & height) const484 void RSParallelRenderManager::GetFrameSize(int &width, int &height) const
485 {
486     width = width_;
487     height = height_;
488 }
489 
SubmitSuperTask(uint32_t taskIndex,std::unique_ptr<RSSuperRenderTask> superRenderTask)490 void RSParallelRenderManager::SubmitSuperTask(uint32_t taskIndex, std::unique_ptr<RSSuperRenderTask> superRenderTask)
491 {
492     if (taskIndex >= threadList_.size()) {
493         RS_LOGE("taskIndex geq thread num");
494         return;
495     }
496     threadList_[taskIndex]->SetSuperTask(std::move(superRenderTask));
497 }
498 
SubmitCompositionTask(uint32_t taskIndex,std::unique_ptr<RSCompositionTask> compositionTask)499 void RSParallelRenderManager::SubmitCompositionTask(uint32_t taskIndex,
500                                                     std::unique_ptr<RSCompositionTask> compositionTask)
501 {
502     if (taskIndex >= threadList_.size()) {
503         RS_LOGE("taskIndex geq thread num");
504         return;
505     }
506 
507     if (threadList_[taskIndex] != nullptr) {
508         threadList_[taskIndex]->SetCompositionTask(std::move(compositionTask));
509     }
510 }
511 
512 // called by submain threads
SubMainThreadNotify(int threadIndex)513 void RSParallelRenderManager::SubMainThreadNotify(int threadIndex)
514 {
515     flipCoin_[threadIndex] = 0;
516     std::unique_lock<std::mutex> lock(cvParallelRenderMutex_);
517     for (unsigned int i = 0; i < expectedSubThreadNum_; ++i) {
518         if (flipCoin_[i] != 0) {
519             return;
520         }
521     }
522     cvParallelRender_.notify_all();
523 }
524 
525 // called by main thread
WaitSubMainThread(uint32_t threadIndex)526 void RSParallelRenderManager::WaitSubMainThread(uint32_t threadIndex)
527 {
528     std::unique_lock<std::mutex> lock(parallelRenderMutex_);
529     cvParallelRender_.wait(lock, [&]() {
530         return !flipCoin_[threadIndex];
531     });
532 }
533 
534 // called by submain threads
SubMainThreadWait(uint32_t threadIndex)535 void RSParallelRenderManager::SubMainThreadWait(uint32_t threadIndex)
536 {
537     std::unique_lock<std::mutex> lock(parallelRenderMutex_);
538     cvParallelRender_.wait(lock, [&]() {
539         return flipCoin_[threadIndex];
540     });
541 }
542 
StartTiming(uint32_t subMainThreadIdx)543 void RSParallelRenderManager::StartTiming(uint32_t subMainThreadIdx)
544 {
545     if (ParallelRenderExtEnabled()) {
546         clock_gettime(CLOCK_THREAD_CPUTIME_ID, &startTime_[subMainThreadIdx]);
547     }
548 }
549 
StopTimingAndSetRenderTaskCost(uint32_t subMainThreadIdx,uint64_t loadId,TaskType type)550 void RSParallelRenderManager::StopTimingAndSetRenderTaskCost(
551     uint32_t subMainThreadIdx, uint64_t loadId, TaskType type)
552 {
553     if (!ParallelRenderExtEnabled()) {
554         return;
555     }
556     clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stopTime_[subMainThreadIdx]);
557     float cost =
558         (stopTime_[subMainThreadIdx].tv_sec * 1000.0f + stopTime_[subMainThreadIdx].tv_nsec * 1e-6) -
559         (startTime_[subMainThreadIdx].tv_sec * 1000.0f + startTime_[subMainThreadIdx].tv_nsec * 1e-6);
560     switch (type) {
561         case TaskType::PREPARE_TASK:
562             prepareTaskManager_.SetSubThreadRenderTaskLoad(subMainThreadIdx, loadId, cost);
563             break;
564         case TaskType::PROCESS_TASK:
565             processTaskManager_.SetSubThreadRenderTaskLoad(subMainThreadIdx, loadId, cost);
566             break;
567         case TaskType::CALC_COST_TASK:
568             calcCostTaskManager_.SetSubThreadRenderTaskLoad(subMainThreadIdx, loadId, cost);
569             break;
570         default:
571             break;
572     }
573 }
574 
ParallelRenderExtEnabled()575 bool RSParallelRenderManager::ParallelRenderExtEnabled()
576 {
577     return processTaskManager_.GetParallelRenderExtEnable();
578 }
579 
TryEnableParallelRendering()580 void RSParallelRenderManager::TryEnableParallelRendering()
581 {
582     auto renderEngine = RSMainThread::Instance()->GetRenderEngine();
583     if (!renderEngine) {
584         renderEngine = std::make_shared<RSUniRenderEngine>();
585         renderEngine->Init();
586     }
587     if (parallelMode_) {
588 #ifdef NEW_RENDER_CONTEXT
589         StartSubRenderThread(PARALLEL_THREAD_NUM, renderEngine->GetRenderContext(), renderEngine->GetDrawingContext());
590 #else
591         StartSubRenderThread(PARALLEL_THREAD_NUM, renderEngine->GetRenderContext().get());
592 #endif
593     } else {
594         EndSubRenderThread();
595     }
596 }
597 
CommitSurfaceNum(int surfaceNum)598 void RSParallelRenderManager::CommitSurfaceNum(int surfaceNum)
599 {
600     if (ParallelRenderExtEnabled() && (RSParallelRenderExt::setCoreLevelFunc_ != nullptr)) {
601         auto setCoreLevel = reinterpret_cast<void(*)(int)>(RSParallelRenderExt::setCoreLevelFunc_);
602         setCoreLevel(surfaceNum);
603     }
604 }
605 
WorkSerialTask(RSSurfaceRenderNode & node)606 void RSParallelRenderManager::WorkSerialTask(RSSurfaceRenderNode &node)
607 {
608     if (uniVisitor_) {
609         uniVisitor_->PrepareSurfaceRenderNode(node);
610     }
611 }
612 
GetParallelThreadNumber() const613 uint32_t RSParallelRenderManager::GetParallelThreadNumber() const
614 {
615     return PARALLEL_THREAD_NUM;
616 }
617 
AddSelfDrawingSurface(unsigned int subThreadIndex,bool isRRect,RectF rect,Vector4f cornerRadius)618 void RSParallelRenderManager::AddSelfDrawingSurface(unsigned int subThreadIndex, bool isRRect, RectF rect,
619     Vector4f cornerRadius)
620 {
621     if (parallelHardwareComposer_) {
622         auto shape = std::make_unique<RSParallelSelfDrawingSurfaceShape>(isRRect, rect, cornerRadius);
623         parallelHardwareComposer_->AddTransparentColorArea(subThreadIndex, std::move(shape));
624     }
625 }
626 
ClearSelfDrawingSurface(RSPaintFilterCanvas & canvas,unsigned int subThreadIndex)627 void RSParallelRenderManager::ClearSelfDrawingSurface(RSPaintFilterCanvas& canvas, unsigned int subThreadIndex)
628 {
629     if (parallelHardwareComposer_) {
630         parallelHardwareComposer_->ClearTransparentColor(canvas, subThreadIndex);
631     }
632 }
633 
WaitCalcCostEnd()634 void RSParallelRenderManager::WaitCalcCostEnd()
635 {
636     for (uint32_t i = 0; i < expectedSubThreadNum_; ++i) {
637         WaitSubMainThread(i);
638     }
639 }
640 
GetCostFactor()641 void RSParallelRenderManager::GetCostFactor()
642 {
643     if (costFactor_.size() > 0 && imageFactor_.size() > 0) {
644         return;
645     }
646     calcCostTaskManager_.GetCostFactor(costFactor_, imageFactor_);
647 }
648 
GetCost(RSRenderNode & node) const649 int32_t RSParallelRenderManager::GetCost(RSRenderNode &node) const
650 {
651     int32_t cost = 1;
652     const auto& property = node.GetRenderProperties();
653     if (ROSEN_EQ(property.GetAlpha(), 1.0f)) {
654         cost += costFactor_.count("alpha") > 0 ? costFactor_.find("alpha")->second : 1;
655     }
656     if (property.NeedFilter()) {
657         cost += costFactor_.count("filter") > 0 ? costFactor_.find("filter")->second : 1;
658     }
659     if (property.GetBgImage() != nullptr) {
660         int64_t size = floor(property.GetBgImageHeight() * property.GetBgImageWidth());
661         for (const auto &[imageSize, imageCost] : imageFactor_) {
662             if (size <= imageSize) {
663                 cost += imageCost;
664                 break;
665             }
666         }
667     }
668     return cost;
669 }
670 
GetSelfDrawNodeCost() const671 int32_t RSParallelRenderManager::GetSelfDrawNodeCost() const
672 {
673     return costFactor_.count("selfDraw") > 0 ? costFactor_.find("selfDraw")->second : 1;
674 }
675 
UpdateNodeCost(RSDisplayRenderNode & node)676 void RSParallelRenderManager::UpdateNodeCost(RSDisplayRenderNode &node)
677 {
678     parallelPolicy_.clear();
679     calcCostTaskManager_.UpdateNodeCost(node, parallelPolicy_);
680 }
681 
AddAppWindowNode(uint32_t surfaceIndex,std::shared_ptr<RSSurfaceRenderNode> appNode)682 void RSParallelRenderManager::AddAppWindowNode(uint32_t surfaceIndex, std::shared_ptr<RSSurfaceRenderNode> appNode)
683 {
684     if (surfaceIndex < PARALLEL_THREAD_NUM) {
685         appWindowNodesMap_[surfaceIndex].emplace_back(appNode);
686     }
687 }
688 
InitDisplayNodeAndRequestFrame(const std::shared_ptr<RSBaseRenderEngine> renderEngine,const ScreenInfo screenInfo)689 void RSParallelRenderManager::InitDisplayNodeAndRequestFrame(
690     const std::shared_ptr<RSBaseRenderEngine> renderEngine, const ScreenInfo screenInfo)
691 {
692 #ifdef RS_ENABLE_VK
693     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
694         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
695         return;
696     }
697     auto& context = RSMainThread::Instance()->GetContext();
698     parallelFrames_.clear();
699     std::swap(parallelDisplayNodes_, backParallelDisplayNodes_);
700     for (int i = 0; i < PARALLEL_THREAD_NUM; i++) {
701         if(!parallelDisplayNodes_[i]) {
702             RSDisplayNodeConfig config;
703             parallelDisplayNodes_[i] =
704                 std::make_shared<RSDisplayRenderNode>(i, config, context.weak_from_this());
705             parallelDisplayNodes_[i]->SetIsParallelDisplayNode(true);
706         }
707         if (!parallelDisplayNodes_[i]->IsSurfaceCreated()) {
708             sptr<IBufferConsumerListener> listener = new RSUniRenderListener(parallelDisplayNodes_[i]);
709             if (!parallelDisplayNodes_[i]->CreateSurface(listener)) {
710                 RS_LOGE("RSParallelRenderManager::InitDisplayNodeAndRequestFrame CreateSurface failed");
711                 return;
712             }
713         }
714         auto rsSurface = parallelDisplayNodes_[i]->GetRSSurface();
715         if (rsSurface == nullptr) {
716             RS_LOGE("RSParallelRenderManager::InitDisplayNodeAndRequestFrame No RSSurface found");
717             return;
718         }
719         rsSurface->SetColorSpace(uniVisitor_->GetColorGamut());
720         std::unique_ptr<RSRenderFrame> renderFrame =
721             renderEngine->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface),
722             RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo, true));
723         parallelFrames_.push_back(std::move(renderFrame));
724     }
725 #endif
726 }
727 
ProcessParallelDisplaySurface(RSUniRenderVisitor & visitor)728 void RSParallelRenderManager::ProcessParallelDisplaySurface(RSUniRenderVisitor &visitor)
729 {
730 #ifdef RS_ENABLE_VK
731     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
732         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
733         return;
734     }
735     for (int i = 0; i < PARALLEL_THREAD_NUM; i++) {
736         if (!parallelDisplayNodes_[i]) {
737             continue;
738         }
739         visitor.GetProcessor()->ProcessDisplaySurface(*parallelDisplayNodes_[i]);
740     }
741 #endif
742 }
743 
ReleaseBuffer()744 void RSParallelRenderManager::ReleaseBuffer()
745 {
746 #ifdef RS_ENABLE_VK
747     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
748         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
749         return;
750     }
751     for (int i = 0; i < PARALLEL_THREAD_NUM; i++) {
752         if (!parallelDisplayNodes_[i]) {
753             continue;
754         }
755         auto& surfaceHandler = static_cast<RSSurfaceHandler&>(*parallelDisplayNodes_[i]);
756         (void)RSBaseRenderUtil::ReleaseBuffer(surfaceHandler);
757     }
758 #endif
759 }
760 
NotifyUniRenderFinish()761 void RSParallelRenderManager::NotifyUniRenderFinish()
762 {
763 #ifdef RS_ENABLE_VK
764     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
765         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
766         return;
767     }
768     readyBufferNum_++;
769     if (readyBufferNum_ == PARALLEL_THREAD_NUM) {
770         RS_TRACE_NAME("RSParallelRenderManager::NotifyUniRenderFinish");
771         RSMainThread::Instance()->NotifyUniRenderFinish();
772         readyBufferNum_ = 0;
773     }
774 #endif
775 }
776 
GetParallelDisplayNode(uint32_t subMainThreadIdx)777 std::shared_ptr<RSDisplayRenderNode> RSParallelRenderManager::GetParallelDisplayNode(
778     uint32_t subMainThreadIdx)
779 {
780 #ifdef RS_ENABLE_VK
781     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
782         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
783         return nullptr;
784     }
785     return parallelDisplayNodes_[subMainThreadIdx];
786 #else
787     return nullptr;
788 #endif
789 }
790 
GetParallelFrame(uint32_t subMainThreadIdx)791 std::unique_ptr<RSRenderFrame> RSParallelRenderManager::GetParallelFrame(
792     uint32_t subMainThreadIdx)
793 {
794 #ifdef RS_ENABLE_VK
795     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
796         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
797         return nullptr;
798     }
799     return std::move(parallelFrames_[subMainThreadIdx]);
800 #else
801     return nullptr;
802 #endif
803 }
804 
ProcessFilterSurfaceRenderNode()805 void RSParallelRenderManager::ProcessFilterSurfaceRenderNode()
806 {
807     if (GetParallelModeSafe()) {
808         for (auto& node : filterSurfaceRenderNodes_) {
809             node->Process(uniVisitor_->shared_from_this());
810         }
811     }
812 }
813 } // namespace Rosen
814 } // namespace OHOS