• 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 #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, &param);
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