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