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