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 #define EGL_EGLEXT_PROTOTYPES
17 #include "rs_parallel_sub_thread.h"
18 #include <cstddef>
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 #include <sys/resource.h>
23 #include <sys/ioctl.h>
24 #include "GLES3/gl3.h"
25 #include "include/core/SkCanvas.h"
26 #include "include/core/SkColor.h"
27 #include "include/core/SkRect.h"
28 #include "EGL/egl.h"
29 #include "rs_trace.h"
30 #include "pipeline/rs_canvas_render_node.h"
31 #include "pipeline/rs_display_render_node.h"
32 #include "pipeline/rs_surface_render_node.h"
33 #include "rs_node_cost_manager.h"
34 #include "rs_parallel_render_manager.h"
35 #include "common/rs_obj_abs_geometry.h"
36 #include "pipeline/rs_uni_render_visitor.h"
37 #include "rs_parallel_render_ext.h"
38 #include "pipeline/rs_main_thread.h"
39 #include "pipeline/rs_uni_render_engine.h"
40
41 namespace OHOS {
42 namespace Rosen {
RSParallelSubThread(int threadIndex)43 RSParallelSubThread::RSParallelSubThread(int threadIndex)
44 : threadIndex_(threadIndex), subThread_(nullptr), renderType_(ParallelRenderType::DRAW_IMAGE) {}
45 #ifdef NEW_RENDER_CONTEXT
RSParallelSubThread(std::shared_ptr<RenderContextBase> context,ParallelRenderType renderType,int threadIndex)46 RSParallelSubThread::RSParallelSubThread(std::shared_ptr<RenderContextBase> context,
47 ParallelRenderType renderType, int threadIndex) : threadIndex_(threadIndex), subThread_(nullptr),
48 renderContext_(context), renderType_(renderType) {}
49 #else
RSParallelSubThread(RenderContext * context,ParallelRenderType renderType,int threadIndex)50 RSParallelSubThread::RSParallelSubThread(RenderContext *context, ParallelRenderType renderType, int threadIndex)
51 : threadIndex_(threadIndex), subThread_(nullptr), renderContext_(context), renderType_(renderType) {}
52 #endif
~RSParallelSubThread()53 RSParallelSubThread::~RSParallelSubThread()
54 {
55 if (renderContext_ != nullptr) {
56 #ifdef NEW_RENDER_CONTEXT
57 auto frame = renderContext_->GetRSRenderSurfaceFrame();
58 EGLDisplay eglDisplay = frame->eglState->eglDisplay;
59 eglDestroyContext(eglDisplay, eglShareContext_);
60 eglShareContext_ = EGL_NO_CONTEXT;
61 eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
62 #else
63 eglDestroyContext(renderContext_->GetEGLDisplay(), eglShareContext_);
64 eglShareContext_ = EGL_NO_CONTEXT;
65 eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
66 #endif
67 }
68 texture_ = nullptr;
69 canvas_ = nullptr;
70 #ifndef USE_ROSEN_DRAWING
71 skSurface_ = nullptr;
72 #else
73 surface_ = nullptr;
74 #endif
75 RS_LOGI("~RSParallelSubThread():%d", threadIndex_);
76 }
77
MainLoop()78 void RSParallelSubThread::MainLoop()
79 {
80 InitSubThread();
81 #ifdef RS_ENABLE_GL
82 CreateShareEglContext();
83 #endif
84 while (true) {
85 WaitTaskSync();
86 if (RSParallelRenderManager::Instance()->GetParallelRenderingStatus() == ParallelStatus::OFF) {
87 return;
88 }
89 // parallel rendering will be enable when the windows number is greater than 50
90 RSParallelRenderManager::Instance()->CommitSurfaceNum(50);
91 switch (RSParallelRenderManager::Instance()->GetTaskType()) {
92 case TaskType::PREPARE_TASK: {
93 RS_TRACE_BEGIN("SubThreadCostPrepare[" + std::to_string(threadIndex_) + "]");
94 StartPrepare();
95 Prepare();
96 RSParallelRenderManager::Instance()->SubMainThreadNotify(threadIndex_);
97 RS_TRACE_END();
98 break;
99 }
100 case TaskType::CALC_COST_TASK: {
101 RS_TRACE_BEGIN("SubThreadCalcCost[" + std::to_string(threadIndex_) + "]");
102 CalcCost();
103 RSParallelRenderManager::Instance()->SubMainThreadNotify(threadIndex_);
104 RS_TRACE_END();
105 break;
106 }
107 case TaskType::PROCESS_TASK: {
108 RS_TRACE_BEGIN("SubThreadCostProcess[" + std::to_string(threadIndex_) + "]");
109 StartRender();
110 Render();
111 ParallelStatus status = RSParallelRenderManager::Instance()->GetParallelRenderingStatus();
112 if (status == ParallelStatus::FIRSTFLUSH || status == ParallelStatus::WAITFIRSTFLUSH) {
113 RSParallelRenderManager::Instance()->SubMainThreadNotify(threadIndex_);
114 }
115 RS_TRACE_END();
116 Flush();
117 break;
118 }
119 case TaskType::COMPOSITION_TASK: {
120 StartComposition();
121 Composition();
122 RSParallelRenderManager::Instance()->SubMainThreadNotify(threadIndex_);
123 break;
124 }
125 default: {
126 break;
127 }
128 }
129 }
130 }
131
StartSubThread()132 void RSParallelSubThread::StartSubThread()
133 {
134 subThread_ = new std::thread(&RSParallelSubThread::MainLoop, this);
135 }
136
WaitTaskSync()137 void RSParallelSubThread::WaitTaskSync()
138 {
139 RSParallelRenderManager::Instance()->SubMainThreadWait(threadIndex_);
140 }
141
InitSubThread()142 void RSParallelSubThread::InitSubThread()
143 {
144 pthread_setname_np(pthread_self(), "SubMainThread");
145 struct sched_param param = {0};
146 // sched_priority interval: [1, 99]; higher number refers to a higher thread priority,
147 // set 2 as experience reference.
148 param.sched_priority = 2;
149 (void)sched_setscheduler(0, SCHED_FIFO, ¶m);
150 }
151
CreateShareEglContext()152 void RSParallelSubThread::CreateShareEglContext()
153 {
154 #ifdef RS_ENABLE_GL
155 if (renderContext_ == nullptr) {
156 RS_LOGE("renderContext_ is nullptr");
157 return;
158 }
159 #ifdef NEW_RENDER_CONTEXT
160 eglShareContext_ = renderContext_->CreateContext(true);
161 #else
162 eglShareContext_ = renderContext_->CreateShareContext();
163 #endif
164 if (eglShareContext_ == EGL_NO_CONTEXT) {
165 RS_LOGE("eglShareContext_ is EGL_NO_CONTEXT");
166 return;
167 }
168 if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
169 #ifdef NEW_RENDER_CONTEXT
170 auto frame = renderContext_->GetRSRenderSurfaceFrame();
171 EGLDisplay eglDisplay = frame->eglState->eglDisplay;
172 if (!eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
173 #else
174 if (!eglMakeCurrent(renderContext_->GetEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, eglShareContext_)) {
175 #endif
176 RS_LOGE("eglMakeCurrent failed");
177 return;
178 }
179 }
180 #endif
181 }
182
183 void RSParallelSubThread::StartPrepare()
184 {
185 InitUniVisitor();
186 }
187
188 void RSParallelSubThread::InitUniVisitor()
189 {
190 RSUniRenderVisitor *uniVisitor = RSParallelRenderManager::Instance()->GetUniVisitor();
191 if (uniVisitor == nullptr) {
192 RS_LOGE("uniVisitor is nullptr");
193 return;
194 }
195 visitor_ = std::make_shared<RSUniRenderVisitor>(*uniVisitor);
196 }
197
198 void RSParallelSubThread::Prepare()
199 {
200 if (threadTask_ == nullptr) {
201 RS_LOGE("threadTask is nullptr");
202 return;
203 }
204 while (threadTask_->GetTaskSize() > 0) {
205 RSParallelRenderManager::Instance()->StartTiming(threadIndex_);
206 auto task = threadTask_->GetNextRenderTask();
207 if (!task || (task->GetIdx() == 0)) {
208 RS_LOGE("surfaceNode is nullptr");
209 continue;
210 }
211 auto node = task->GetNode();
212 if (!node) {
213 RS_LOGE("surfaceNode is nullptr");
214 continue;
215 }
216 node->Prepare(visitor_);
217 RSParallelRenderManager::Instance()->StopTimingAndSetRenderTaskCost(
218 threadIndex_, task->GetIdx(), TaskType::PREPARE_TASK);
219 }
220 }
221
222 void RSParallelSubThread::CalcCost()
223 {
224 if (threadTask_ == nullptr) {
225 RS_LOGE("CalcCost thread task is null");
226 return;
227 }
228 RSUniRenderVisitor *uniVisitor = RSParallelRenderManager::Instance()->GetUniVisitor();
229 if (uniVisitor == nullptr) {
230 RS_LOGE("CalcCost visitor is null");
231 return;
232 }
233 std::shared_ptr<RSNodeCostManager> manager = std::make_shared<RSNodeCostManager>(
234 RSParallelRenderManager::Instance()->IsDoAnimate(),
235 RSParallelRenderManager::Instance()->IsOpDropped(),
236 RSParallelRenderManager::Instance()->IsSecurityDisplay());
237
238 while (threadTask_->GetTaskSize() > 0) {
239 RSParallelRenderManager::Instance()->StartTiming(threadIndex_);
240 auto task = threadTask_->GetNextRenderTask();
241 if (task == nullptr || task->GetIdx() == 0) {
242 RS_LOGI("CalcCost task is invalid");
243 continue;
244 }
245 auto node = task->GetNode();
246 if (node == nullptr) {
247 RS_LOGI("CalcCost node is null");
248 continue;
249 }
250 auto surfaceNodePtr = node->ReinterpretCastTo<RSSurfaceRenderNode>();
251 if (surfaceNodePtr == nullptr) {
252 RS_LOGI("CalcCost surface node is null");
253 continue;
254 }
255 manager->CalcNodeCost(*surfaceNodePtr);
256 surfaceNodePtr->SetNodeCost(manager->GetDirtyNodeCost());
257 RSParallelRenderManager::Instance()->StopTimingAndSetRenderTaskCost(
258 threadIndex_, task->GetIdx(), TaskType::CALC_COST_TASK);
259 }
260 }
261
262 void RSParallelSubThread::StartRender()
263 {
264 CreateResource();
265 }
266
267 void RSParallelSubThread::Render()
268 {
269 if (threadTask_ == nullptr) {
270 RS_LOGE("threadTask is nullptr");
271 return;
272 }
273 auto physicalDisplayNode = std::static_pointer_cast<RSDisplayRenderNode>(threadTask_->GetNode());
274 auto physicalGeoPtr = (
275 physicalDisplayNode->GetRenderProperties().GetBoundsGeometry());
276 #ifdef RS_ENABLE_GL
277 if (canvas_ == nullptr) {
278 RS_LOGE("Canvas is nullptr");
279 return;
280 }
281 #ifndef USE_ROSEN_DRAWING
282 int saveCount = canvas_->save();
283 if (RSMainThread::Instance()->GetRenderEngine()) {
284 canvas_->SetHighContrast(RSMainThread::Instance()->GetRenderEngine()->IsHighContrastEnabled());
285 }
286 if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
287 canvas_->clear(SK_ColorTRANSPARENT);
288 }
289 canvas_->save();
290 if (physicalGeoPtr != nullptr) {
291 canvas_->concat(physicalGeoPtr->GetMatrix());
292 canvas_->SetCacheType(physicalGeoPtr->IsNeedClientCompose() ? RSPaintFilterCanvas::CacheType::ENABLED
293 : RSPaintFilterCanvas::CacheType::DISABLED);
294 }
295 #else
296 auto saveCount = canvas_->GetSaveCount();
297 canvas_->Save();
298 if (RSMainThread::Instance()->GetRenderEngine()) {
299 canvas_->SetHighContrast(RSMainThread::Instance()->GetRenderEngine()->IsHighContrastEnabled());
300 }
301 if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
302 canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
303 }
304 canvas_->Save();
305 if (physicalGeoPtr != nullptr) {
306 canvas_->ConcatMatrix(physicalGeoPtr->GetMatrix());
307 canvas_->SetCacheType(physicalGeoPtr->IsNeedClientCompose() ? RSPaintFilterCanvas::CacheType::ENABLED
308 : RSPaintFilterCanvas::CacheType::DISABLED);
309 }
310 #endif
311 while (threadTask_->GetTaskSize() > 0) {
312 RSParallelRenderManager::Instance()->StartTiming(threadIndex_);
313 auto task = threadTask_->GetNextRenderTask();
314 if (!task || (task->GetIdx() == 0)) {
315 RS_LOGE("renderTask is nullptr");
316 continue;
317 }
318 auto node = task->GetNode();
319 if (!node) {
320 RS_LOGE("surfaceNode is nullptr");
321 continue;
322 }
323 node->Process(visitor_);
324 RSParallelRenderManager::Instance()->StopTimingAndSetRenderTaskCost(
325 threadIndex_, task->GetIdx(), TaskType::PROCESS_TASK);
326 }
327 #ifndef USE_ROSEN_DRAWING
328 canvas_->restoreToCount(saveCount);
329 #else
330 canvas_->RestoreToCount(saveCount);
331 #endif
332 #elif RS_ENABLE_VK
333 if (!displayNode_) {
334 RS_LOGE("RSParallelSubThread::Render displayNode_ nullptr");
335 return;
336 }
337 displayNode_->SetScreenId(physicalDisplayNode->GetScreenId());
338 displayNode_->SetDisplayOffset(
339 physicalDisplayNode->GetDisplayOffsetX(), physicalDisplayNode->GetDisplayOffsetY());
340 displayNode_->SetForceSoftComposite(physicalDisplayNode->IsForceSoftComposite());
341 auto geoPtr = (
342 displayNode_->GetRenderProperties().GetBoundsGeometry());
343 if (physicalGeoPtr && geoPtr) {
344 *geoPtr = *physicalGeoPtr;
345 geoPtr->UpdateByMatrixFromSelf();
346 }
347 while (threadTask_->GetTaskSize() > 0) {
348 auto task = threadTask_->GetNextRenderTask();
349 if (!task || (task->GetIdx() == 0)) {
350 RS_LOGE("renderTask is nullptr");
351 continue;
352 }
353 auto node = task->GetNode();
354 if (!node) {
355 RS_LOGE("surfaceNode is nullptr");
356 continue;
357 }
358 displayNode_->AddCrossParentChild(node);
359 }
360 displayNode_->Process(visitor_);
361 for (auto& child : displayNode_->GetChildren()) {
362 displayNode_->RemoveCrossParentChild(child, physicalDisplayNode);
363 }
364 #endif
365 }
366
367 void RSParallelSubThread::Flush()
368 {
369 threadTask_ = nullptr;
370 #ifdef RS_ENABLE_GL
371 #ifndef USE_ROSEN_DRAWING
372 if (skCanvas_ == nullptr) {
373 RS_LOGE("in Flush(), skCanvas is nullptr");
374 return;
375 }
376 if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
377 RS_TRACE_BEGIN("Flush");
378 #ifdef NEW_SKIA
379 if (grContext_) {
380 grContext_->flushAndSubmit(false);
381 }
382 #else
383 // skCanvas_->flush() may tasks a long time when window is zoomed in and out. So let flush operation of
384 // subMainThreads are executed in sequence to reduce probability rather than solve the question.
385 RSParallelRenderManager::Instance()->LockFlushMutex();
386 skCanvas_->flush();
387 RSParallelRenderManager::Instance()->UnlockFlushMutex();
388 #endif
389 RS_TRACE_END();
390 RS_TRACE_BEGIN("Create Fence");
391 #ifdef NEW_RENDER_CONTEXT
392 auto frame = renderContext_->GetRSRenderSurfaceFrame();
393 EGLDisplay eglDisplay = frame->eglState->eglDisplay;
394 eglSync_ = eglCreateSyncKHR(eglDisplay, EGL_SYNC_FENCE_KHR, nullptr);
395 #else
396 eglSync_ = eglCreateSyncKHR(renderContext_->GetEGLDisplay(), EGL_SYNC_FENCE_KHR, nullptr);
397 #endif
398 RS_TRACE_END();
399 texture_ = skSurface_->makeImageSnapshot();
400 skCanvas_->discard();
401 }
402 #else
403 if (drCanvas_ == nullptr) {
404 RS_LOGE("in Flush(), drCanvas is nullptr");
405 return;
406 }
407 if (renderType_ == ParallelRenderType::DRAW_IMAGE) {
408 RS_TRACE_BEGIN("Flush");
409 // drCanvas->flush() may tasks a long time when window is zoomed in and out. So let flush operation of
410 // subMainThreads are executed in sequence to reduce probability rather than solve the question.
411 RSParallelRenderManager::Instance()->LockFlushMutex();
412 drCanvas_->Flush();
413 RSParallelRenderManager::Instance()->UnlockFlushMutex();
414 RS_TRACE_END();
415 RS_TRACE_BEGIN("Create Fence");
416 #ifdef NEW_RENDER_CONTEXT
417 if (renderContext_ == nullptr) {
418 RS_LOGE("renderContext_ is nullptr");
419 return;
420 }
421 auto frame = renderContext_->GetRSRenderSurfaceFrame();
422 EGLDisplay eglDisplay = frame->eglState->eglDisplay;
423 eglSync_ = eglCreateSyncKHR(eglDisplay, EGL_SYNC_FENCE_KHR, nullptr);
424 #else
425 eglSync_ = eglCreateSyncKHR(renderContext_->GetEGLDisplay(), EGL_SYNC_FENCE_KHR, nullptr);
426 #endif
427 RS_TRACE_END();
428 texture_ = surface_->GetImageSnapshot();
429 }
430 #endif
431 #endif
432 // FIRSTFLUSH or WAITFIRSTFLUSH
433 ParallelStatus parallelStatus = RSParallelRenderManager::Instance()->GetParallelRenderingStatus();
434 if (parallelStatus == ParallelStatus::FIRSTFLUSH || parallelStatus == ParallelStatus::WAITFIRSTFLUSH) {
435 RSParallelRenderManager::Instance()->ReadySubThreadNumIncrement();
436 } else {
437 RSParallelRenderManager::Instance()->SubMainThreadNotify(threadIndex_);
438 }
439 }
440
441 bool RSParallelSubThread::WaitReleaseFence()
442 {
443 if (eglSync_ != EGL_NO_SYNC_KHR) {
444 #ifdef NEW_RENDER_CONTEXT
445 if (renderContext_ == nullptr) {
446 RS_LOGE("renderContext_ is nullptr");
447 return false;
448 }
449 auto frame = renderContext_->GetRSRenderSurfaceFrame();
450 EGLDisplay eglDisplay = frame->eglState->eglDisplay;
451 EGLint ret = eglWaitSyncKHR(eglDisplay, eglSync_, 0);
452 #else
453 EGLint ret = eglWaitSyncKHR(renderContext_->GetEGLDisplay(), eglSync_, 0);
454 #endif
455 if (ret == EGL_FALSE) {
456 ROSEN_LOGE("eglClientWaitSyncKHR error 0x%{public}x", eglGetError());
457 return false;
458 } else if (ret == EGL_TIMEOUT_EXPIRED_KHR) {
459 ROSEN_LOGE("create eglClientWaitSyncKHR timeout");
460 return false;
461 }
462 #ifdef NEW_RENDER_CONTEXT
463 eglDestroySyncKHR(eglDisplay, eglSync_);
464 #else
465 eglDestroySyncKHR(renderContext_->GetEGLDisplay(), eglSync_);
466 #endif
467 }
468 eglSync_ = EGL_NO_SYNC_KHR;
469 return true;
470 }
471
472 void RSParallelSubThread::CreateResource()
473 {
474 #ifdef RS_ENABLE_GL
475 int width, height;
476 RSParallelRenderManager::Instance()->GetFrameSize(width, height);
477 if (width != surfaceWidth_ || height != surfaceHeight_) {
478 RS_LOGE("CreateResource %d, new size [%d, %d], old size [%d, %d]",
479 threadIndex_, width, height, surfaceWidth_, surfaceHeight_);
480 surfaceWidth_ = width;
481 surfaceHeight_ = height;
482 #ifndef USE_ROSEN_DRAWING
483 AcquireSubSkSurface(surfaceWidth_, surfaceHeight_);
484 if (skSurface_ == nullptr) {
485 RS_LOGE("in CreateResource, skSurface is nullptr");
486 return;
487 }
488 skCanvas_ = skSurface_->getCanvas();
489 canvas_ = std::make_shared<RSPaintFilterCanvas>(skCanvas_);
490 canvas_->SetIsParallelCanvas(true);
491 #else
492 AcquireSubDrawingSurface(surfaceWidth_, surfaceHeight_);
493 if (surface_ == nullptr) {
494 RS_LOGE("in CreateResource, surface_ is nullptr");
495 return;
496 }
497 drCanvas_ = surface_->GetCanvas().get();
498 canvas_ = std::make_shared<RSPaintFilterCanvas>(drCanvas_);
499 canvas_->SetIsParallelCanvas(true);
500 #endif
501 }
502 visitor_ = std::make_shared<RSUniRenderVisitor>(canvas_, threadIndex_);
503 #elif RS_ENABLE_VK
504 displayNode_ = RSParallelRenderManager::Instance()->GetParallelDisplayNode(threadIndex_);
505 if (!displayNode_) {
506 RS_LOGE("RSParallelSubThread::CreateResource displayNode_ nullptr");
507 return;
508 }
509 visitor_ = std::make_shared<RSUniRenderVisitor>(nullptr, threadIndex_);
510 visitor_->SetRenderFrame(
511 RSParallelRenderManager::Instance()->GetParallelFrame(threadIndex_));
512 #endif
513 visitor_->CopyPropertyForParallelVisitor(
514 RSParallelRenderManager::Instance()->GetUniVisitor());
515 }
516
517 #ifndef USE_ROSEN_DRAWING
518 #ifdef NEW_SKIA
519 sk_sp<GrDirectContext> RSParallelSubThread::CreateShareGrContext()
520 #else
521 sk_sp<GrContext> RSParallelSubThread::CreateShareGrContext()
522 #endif
523 {
524 const GrGLInterface *grGlInterface = GrGLCreateNativeInterface();
525 sk_sp<const GrGLInterface> glInterface(grGlInterface);
526 if (glInterface.get() == nullptr) {
527 RS_LOGE("CreateShareGrContext failed");
528 return nullptr;
529 }
530
531 GrContextOptions options = {};
532 options.fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
533 options.fPreferExternalImagesOverES3 = true;
534 options.fDisableDistanceFieldPaths = true;
535 #ifdef NEW_SKIA
536 sk_sp<GrDirectContext> grContext = GrDirectContext::MakeGL(std::move(glInterface), options);
537 #else
538 sk_sp<GrContext> grContext = GrContext::MakeGL(std::move(glInterface), options);
539 #endif
540 if (grContext == nullptr) {
541 RS_LOGE("nullptr grContext is null");
542 return nullptr;
543 }
544 return grContext;
545 }
546 #else
547 std::shared_ptr<Drawing::GPUContext> RSParallelSubThread::CreateShareGPUContext()
548 {
549 auto drGPUContext = std::make_shared<Drawing::GPUContext>();
550 Drawing::GPUContextOptions options;
551 drGPUContext->BuildFromGL(options);
552 return drGPUContext;
553 }
554 #endif
555
556 #ifndef USE_ROSEN_DRAWING
557 void RSParallelSubThread::AcquireSubSkSurface(int width, int height)
558 {
559 if (grContext_ == nullptr) {
560 grContext_ = CreateShareGrContext();
561 }
562
563 if (grContext_ == nullptr) {
564 RS_LOGE("Share GrContext is not ready!!!");
565 return;
566 }
567
568 auto surfaceInfo = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
569 skSurface_ = SkSurface::MakeRenderTarget(grContext_.get(), SkBudgeted::kYes, surfaceInfo);
570 if (skSurface_ == nullptr) {
571 RS_LOGE("skSurface is not ready!!!");
572 return;
573 }
574 }
575 #else
576 void RSParallelSubThread::AcquireSubDrawingSurface(int width, int height)
577 {
578 if (drContext_ == nullptr) {
579 drContext_ = CreateShareGPUContext();
580 }
581
582 if (drContext_ == nullptr) {
583 RS_LOGE("Share GrContext is not ready!!!");
584 return;
585 }
586
587 Drawing::BitmapFormat format = { Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
588 Drawing::Bitmap bitmap;
589 bitmap.Build(width, height, format);
590
591 Drawing::Image image;
592 image.BuildFromBitmap(*drContext_, bitmap);
593
594 surface_ = std::make_shared<Drawing::Surface>();
595 if (!surface_->Bind(image)) {
596 RS_LOGE("surface is not ready!!!");
597 surface_ = nullptr;
598 return;
599 }
600 }
601 #endif
602
603 void RSParallelSubThread::StartComposition()
604 {
605 if (processorRenderEngine_ == nullptr) {
606 processorRenderEngine_ = std::make_shared<RSUniRenderEngine>();
607 processorRenderEngine_->Init();
608 }
609 compositionVisitor_ = std::make_shared<RSUniRenderVisitor>();
610 auto parallelRenderManager = RSParallelRenderManager::Instance();
611 if (parallelRenderManager->GetUniParallelCompositionVisitor() != nullptr) {
612 compositionVisitor_->CopyVisitorInfos(parallelRenderManager->GetUniParallelCompositionVisitor());
613 } else {
614 compositionVisitor_ = nullptr;
615 }
616 }
617
618 void RSParallelSubThread::Composition()
619 {
620 if (compositionTask_ == nullptr || compositionTask_->GetIdx() == 0) {
621 RS_LOGE("compositionTask is nullptr or displayNodeId is 0");
622 return;
623 }
624
625 auto node = compositionTask_->GetNode();
626 if (node == nullptr || compositionVisitor_ == nullptr) {
627 RS_LOGE("displayNode or visitor is nullptr.");
628 return;
629 }
630
631 compositionVisitor_->SetProcessorRenderEngine(processorRenderEngine_);
632 node->Process(compositionVisitor_);
633 compositionVisitor_ = nullptr;
634 compositionTask_ = nullptr;
635 }
636
637 EGLContext RSParallelSubThread::GetSharedContext() const
638 {
639 return eglShareContext_;
640 }
641
642 #ifndef USE_ROSEN_DRAWING
643 sk_sp<SkSurface> RSParallelSubThread::GetSkSurface() const
644 {
645 return skSurface_;
646 }
647 #else
648 std::shared_ptr<Drawing::Surface> RSParallelSubThread::GetDrawingSurface() const
649 {
650 return surface_;
651 }
652 #endif
653
654 void RSParallelSubThread::SetSuperTask(std::unique_ptr<RSSuperRenderTask> superRenderTask)
655 {
656 threadTask_ = std::move(superRenderTask);
657 }
658
659 void RSParallelSubThread::SetCompositionTask(std::unique_ptr<RSCompositionTask> compositionTask)
660 {
661 compositionTask_ = std::move(compositionTask);
662 }
663
664 #ifndef USE_ROSEN_DRAWING
665 sk_sp<SkImage> RSParallelSubThread::GetTexture() const
666 #else
667 std::shared_ptr<Drawing::Image> RSParallelSubThread::GetTexture() const
668 #endif
669 {
670 return texture_;
671 }
672 } // namespace Rosen
673 } // namespace OHOS