• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "drawable/rs_surface_render_node_drawable.h"
17 
18 #include "acquire_fence_manager.h"
19 #include "impl_interface/region_impl.h"
20 #include "rs_trace.h"
21 #include "common/rs_color.h"
22 #include "common/rs_common_def.h"
23 #include "common/rs_optional_trace.h"
24 #include "common/rs_obj_abs_geometry.h"
25 #include "draw/brush.h"
26 #include "drawable/rs_display_render_node_drawable.h"
27 #include "memory/rs_tag_tracker.h"
28 #include "params/rs_display_render_params.h"
29 #include "params/rs_surface_render_params.h"
30 #include "pipeline/rs_paint_filter_canvas.h"
31 #include "pipeline/rs_surface_handler.h"
32 #include "pipeline/rs_surface_render_node.h"
33 #include "pipeline/rs_uni_render_thread.h"
34 #include "pipeline/rs_uni_render_util.h"
35 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
36 #include "pipeline/pointer_render/rs_pointer_render_manager.h"
37 #endif
38 
39 #include "platform/common/rs_log.h"
40 #include "platform/ohos/rs_node_stats.h"
41 #include "utils/rect.h"
42 #include "utils/region.h"
43 
44 #include "pipeline/rs_uifirst_manager.h"
45 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
46 #include "pipeline/rs_main_thread.h"
47 #ifdef RS_ENABLE_VK
48 #include "include/gpu/GrBackendSurface.h"
49 #include "platform/ohos/backend/native_buffer_utils.h"
50 #include "platform/ohos/backend/rs_vulkan_context.h"
51 #endif
52 
53 #include "luminance/rs_luminance_control.h"
54 #ifdef USE_VIDEO_PROCESSING_ENGINE
55 #include "metadata_helper.h"
56 #endif
57 namespace {
58 constexpr int32_t CORNER_SIZE = 4;
59 constexpr float GAMMA2_2 = 2.2f;
60 }
61 namespace OHOS::Rosen::DrawableV2 {
62 RSSurfaceRenderNodeDrawable::Registrar RSSurfaceRenderNodeDrawable::instance_;
63 
RSSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)64 RSSurfaceRenderNodeDrawable::RSSurfaceRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
65     : RSRenderNodeDrawable(std::move(node)), syncDirtyManager_(std::make_shared<RSDirtyRegionManager>())
66 {
67     auto nodeSp = std::const_pointer_cast<RSRenderNode>(node);
68     auto surfaceNode = std::static_pointer_cast<RSSurfaceRenderNode>(nodeSp);
69     name_ = surfaceNode->GetName();
70     surfaceNodeType_ = surfaceNode->GetSurfaceNodeType();
71 #ifndef ROSEN_CROSS_PLATFORM
72     consumerOnDraw_ = surfaceNode->GetRSSurfaceHandler()->GetConsumer();
73 #endif
74     surfaceHandlerUiFirst_ = std::make_shared<RSSurfaceHandler>(nodeId_);
75 }
76 
~RSSurfaceRenderNodeDrawable()77 RSSurfaceRenderNodeDrawable::~RSSurfaceRenderNodeDrawable()
78 {
79     ClearCacheSurfaceInThread();
80 }
81 
OnGenerate(std::shared_ptr<const RSRenderNode> node)82 RSRenderNodeDrawable::Ptr RSSurfaceRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
83 {
84     RS_TRACE_NAME("RSRenderNodeDrawable::Ptr RSSurfaceRenderNodeDrawable::OnGenerate");
85     return new RSSurfaceRenderNodeDrawable(std::move(node));
86 }
87 
OnGeneralProcess(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams,bool isSelfDrawingSurface)88 void RSSurfaceRenderNodeDrawable::OnGeneralProcess(
89     RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams, bool isSelfDrawingSurface)
90 {
91     auto bounds = surfaceParams.GetFrameRect();
92 
93     // 1. draw background
94     DrawBackground(canvas, bounds);
95 
96     // 2. draw self drawing node
97     if (surfaceParams.GetBuffer() != nullptr) {
98         DealWithSelfDrawingNodeBuffer(canvas, surfaceParams);
99     }
100 
101     if (isSelfDrawingSurface) {
102         canvas.Restore();
103     }
104 
105     // 3. Draw content of this node by the main canvas.
106     DrawContent(canvas, bounds);
107 
108     // 4. Draw children of this node by the main canvas.
109     DrawChildren(canvas, bounds);
110 
111     // 5. Draw foreground of this node by the main canvas.
112     DrawForeground(canvas, bounds);
113 }
114 
CalculateVisibleRegion(RSRenderThreadParams & uniParam,RSSurfaceRenderParams & surfaceParams,RSSurfaceRenderNodeDrawable & surfaceDrawable,bool isOffscreen) const115 Drawing::Region RSSurfaceRenderNodeDrawable::CalculateVisibleRegion(RSRenderThreadParams& uniParam,
116     RSSurfaceRenderParams& surfaceParams, RSSurfaceRenderNodeDrawable& surfaceDrawable, bool isOffscreen) const
117 {
118     Drawing::Region resultRegion;
119     if (!surfaceParams.IsMainWindowType()) {
120         return resultRegion;
121     }
122 
123     // FUTURE: return real region
124     if (isOffscreen) {
125         resultRegion.SetRect(Drawing::RectI(0, 0,
126         DRAWING_MAX_S32_FITS_IN_FLOAT, DRAWING_MAX_S32_FITS_IN_FLOAT));
127         return resultRegion;
128     }
129 
130     auto visibleRegion = surfaceParams.GetVisibleRegion();
131     if (uniParam.IsOcclusionEnabled() && visibleRegion.IsEmpty()) {
132         return resultRegion;
133     }
134     // The region is dirty region of this SurfaceNode.
135     Occlusion::Region surfaceNodeDirtyRegion(GetSyncDirtyManager()->GetDirtyRegion());
136     // The region is the result of global dirty region AND occlusion region.
137     Occlusion::Region globalDirtyRegion = GetGlobalDirtyRegion();
138     // This include dirty region and occlusion region when surfaceNode is mainWindow.
139     auto dirtyRegion = globalDirtyRegion.Or(surfaceNodeDirtyRegion);
140     auto visibleDirtyRegion = dirtyRegion.And(visibleRegion);
141     if (visibleDirtyRegion.IsEmpty()) {
142         RS_LOGD("RSSurfaceRenderNodeDrawable::OnDraw occlusion skip SurfaceName:%s NodeId:%" PRIu64 "",
143             surfaceDrawable.GetName().c_str(), surfaceParams.GetId());
144         return resultRegion;
145     }
146 
147     for (auto& rect : visibleDirtyRegion.GetRegionRects()) {
148         Drawing::Region tempRegion;
149         tempRegion.SetRect(Drawing::RectI(rect.left_, rect.top_, rect.right_, rect.bottom_));
150         resultRegion.Op(tempRegion, Drawing::RegionOp::UNION);
151     }
152     return resultRegion;
153 }
154 
155 // To be deleted after captureWindow being deleted
CheckIfNeedResetRotate(RSPaintFilterCanvas & canvas)156 bool RSSurfaceRenderNodeDrawable::CheckIfNeedResetRotate(RSPaintFilterCanvas& canvas)
157 {
158     auto matrix = canvas.GetTotalMatrix();
159     int angle = RSUniRenderUtil::GetRotationFromMatrix(matrix);
160     constexpr int ROTATION_90 = 90;
161     return angle != 0 && angle % ROTATION_90 == 0;
162 }
163 
164 // To be deleted after captureWindow being deleted
FindInstanceChildOfDisplay(std::shared_ptr<RSRenderNode> node)165 NodeId RSSurfaceRenderNodeDrawable::FindInstanceChildOfDisplay(std::shared_ptr<RSRenderNode> node)
166 {
167     if (node == nullptr || node->GetParent().lock() == nullptr) {
168         return INVALID_NODEID;
169     } else if (node->GetParent().lock()->GetType() == RSRenderNodeType::DISPLAY_NODE) {
170         return node->GetId();
171     } else {
172         return FindInstanceChildOfDisplay(node->GetParent().lock());
173     }
174 }
175 
176 // To be deleted after captureWindow being deleted
CacheImgForCapture(RSPaintFilterCanvas & canvas,RSDisplayRenderNodeDrawable & curDisplayNodeDrawable)177 void RSSurfaceRenderNodeDrawable::CacheImgForCapture(RSPaintFilterCanvas& canvas,
178     RSDisplayRenderNodeDrawable& curDisplayNodeDrawable)
179 {
180     auto& params = curDisplayNodeDrawable.GetRenderParams();
181     if (!params->GetSecurityDisplay() && canvas.GetSurface() != nullptr) {
182         bool resetRotate = CheckIfNeedResetRotate(canvas);
183         auto cacheImgForCapture = canvas.GetSurface()->GetImageSnapshot();
184         auto& mirroredNodeDrawable =
185             params->GetMirrorSourceDrawable().lock()
186                 ? static_cast<RSDisplayRenderNodeDrawable&>(*(params->GetMirrorSourceDrawable().lock()))
187                 : curDisplayNodeDrawable;
188         mirroredNodeDrawable.SetCacheImgForCapture(cacheImgForCapture);
189         mirroredNodeDrawable.SetResetRotate(resetRotate);
190     }
191 }
192 
PrepareOffscreenRender()193 bool RSSurfaceRenderNodeDrawable::PrepareOffscreenRender()
194 {
195     // cleanup
196     canvasBackup_ = nullptr;
197 
198     // check offscreen size
199     if (curCanvas_->GetSurface() == nullptr) {
200         RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, current surface is nullptr");
201         return false;
202     }
203     int offscreenWidth = curCanvas_->GetSurface()->Width();
204     int offscreenHeight = curCanvas_->GetSurface()->Height();
205     if (offscreenWidth <= 0 || offscreenHeight <= 0) {
206         RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid");
207         return false;
208     }
209 
210     int maxRenderSize = std::max(offscreenWidth, offscreenHeight);
211     // create offscreen surface and canvas
212     if (offscreenSurface_ == nullptr || maxRenderSize_ != maxRenderSize) {
213         RS_LOGD("PrepareOffscreenRender create offscreen surface offscreenSurface_,\
214             new [%{public}d, %{public}d %{public}d]", offscreenWidth, offscreenHeight, maxRenderSize);
215         RS_TRACE_NAME_FMT("PrepareOffscreenRender surface size: [%d, %d]", maxRenderSize, maxRenderSize);
216         maxRenderSize_ = maxRenderSize;
217         offscreenSurface_ = curCanvas_->GetSurface()->MakeSurface(maxRenderSize_, maxRenderSize_);
218     }
219     if (offscreenSurface_ == nullptr) {
220         RS_LOGE("RSSurfaceRenderNodeDrawable::PrepareOffscreenRender, offscreenSurface is nullptr");
221         return false;
222     }
223 
224     offscreenCanvas_ = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
225 
226     // copy HDR properties into offscreen canvas
227     offscreenCanvas_->CopyHDRConfiguration(*curCanvas_);
228     // copy current canvas properties into offscreen canvas
229     offscreenCanvas_->CopyConfigurationToOffscreenCanvas(*curCanvas_);
230 
231     // backup current canvas and replace with offscreen canvas
232     canvasBackup_ = curCanvas_;
233     curCanvas_ = offscreenCanvas_.get();
234     curCanvas_->SetDisableFilterCache(true);
235     arc_ = std::make_unique<RSAutoCanvasRestore>(curCanvas_, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
236     curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
237     return true;
238 }
239 
FinishOffscreenRender(const Drawing::SamplingOptions & sampling)240 void RSSurfaceRenderNodeDrawable::FinishOffscreenRender(const Drawing::SamplingOptions& sampling)
241 {
242     if (canvasBackup_ == nullptr) {
243         RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, canvasBackup_ is nullptr");
244         return;
245     }
246     if (offscreenSurface_ == nullptr) {
247         RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, offscreenSurface_ is nullptr");
248         return;
249     }
250     auto image = offscreenSurface_->GetImageSnapshot();
251     if (image == nullptr) {
252         RS_LOGE("RSSurfaceRenderNodeDrawable::FinishOffscreenRender, Surface::GetImageSnapshot is nullptr");
253         return;
254     }
255     // draw offscreen surface to current canvas
256     Drawing::Brush paint;
257     paint.SetAntiAlias(true);
258     canvasBackup_->AttachBrush(paint);
259     canvasBackup_->DrawImage(*image, 0, 0, sampling);
260     canvasBackup_->DetachBrush();
261     arc_ = nullptr;
262     curCanvas_ = canvasBackup_;
263 }
264 
IsHardwareEnabled()265 bool RSSurfaceRenderNodeDrawable::IsHardwareEnabled()
266 {
267     auto& hardwareDrawables =
268         RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
269     for (const auto& drawable : hardwareDrawables) {
270         if (!drawable || !drawable->GetRenderParams()) {
271             continue;
272         }
273         auto params = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
274         if (!params || !params->GetHardwareEnabled()) {
275             continue;
276         }
277         return true;
278     }
279     return false;
280 }
281 
OnDraw(Drawing::Canvas & canvas)282 void RSSurfaceRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
283 {
284     SetDrawSkipType(DrawSkipType::NONE);
285     if (!ShouldPaint()) {
286         SetDrawSkipType(DrawSkipType::SHOULD_NOT_PAINT);
287         RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw %s should not paint", name_.c_str());
288         return;
289     }
290 
291     auto rscanvas = reinterpret_cast<RSPaintFilterCanvas*>(&canvas);
292     if (!rscanvas) {
293         SetDrawSkipType(DrawSkipType::CANVAS_NULL);
294         RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw, rscanvas us nullptr");
295         return;
296     }
297     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
298     if (UNLIKELY(!uniParam)) {
299         SetDrawSkipType(DrawSkipType::RENDER_THREAD_PARAMS_NULL);
300         RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw uniParam is nullptr");
301         return;
302     }
303     auto surfaceParams = static_cast<RSSurfaceRenderParams*>(GetRenderParams().get());
304     if (!surfaceParams) {
305         SetDrawSkipType(DrawSkipType::RENDER_PARAMS_NULL);
306         RS_LOGE("RSSurfaceRenderNodeDrawable::OnDraw params is nullptr");
307         return;
308     }
309     if (surfaceParams->GetSkipDraw()) {
310         SetDrawSkipType(DrawSkipType::SURFACE_PARAMS_SKIP_DRAW);
311         RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw SkipDraw [%s] Id:%llu",
312             name_.c_str(), surfaceParams->GetId());
313         return;
314     }
315     auto renderEngine_ = RSUniRenderThread::Instance().GetRenderEngine();
316     auto unmappedCache = surfaceParams->GetBufferClearCacheSet();
317     if (unmappedCache.size() > 0) {
318         // remove imagecahce when its bufferQueue gobackground
319         renderEngine_->ClearCacheSet(unmappedCache);
320     }
321     if (autoCacheEnable_) {
322         nodeCacheType_ = NodeStrategyType::CACHE_NONE;
323     }
324     bool isUiFirstNode = rscanvas->GetIsParallelCanvas();
325     if (!isUiFirstNode && surfaceParams->GetOccludedByFilterCache()) {
326         SetDrawSkipType(DrawSkipType::FILTERCACHE_OCCLUSION_SKIP);
327         RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw filterCache occlusion skip [%s] %sAlpha: %f, "
328             "NodeId:%" PRIu64 "", name_.c_str(), surfaceParams->GetAbsDrawRect().ToString().c_str(),
329             surfaceParams->GetGlobalAlpha(), surfaceParams->GetId());
330         return;
331     }
332     hasSkipCacheLayer_ =
333         (surfaceParams->GetIsSecurityLayer() && !uniParam->GetSecExemption()) || surfaceParams->GetIsSkipLayer();
334     if (hasSkipCacheLayer_ && curDrawingCacheRoot_) {
335         curDrawingCacheRoot_->SetSkipCacheLayer(true);
336     }
337 
338     Drawing::Region curSurfaceDrawRegion = CalculateVisibleRegion(*uniParam, *surfaceParams, *this, isUiFirstNode);
339     if (!isUiFirstNode) {
340         MergeDirtyRegionBelowCurSurface(*uniParam, curSurfaceDrawRegion);
341     }
342 
343     if (!isUiFirstNode && uniParam->IsOpDropped() && surfaceParams->IsVisibleDirtyRegionEmpty(curSurfaceDrawRegion)) {
344         SetDrawSkipType(DrawSkipType::OCCLUSION_SKIP);
345         RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw occlusion skip SurfaceName:%s %sAlpha: %f, NodeId:"
346             "%" PRIu64 "", name_.c_str(), surfaceParams->GetAbsDrawRect().ToString().c_str(),
347             surfaceParams->GetGlobalAlpha(), surfaceParams->GetId());
348         return;
349     }
350     const auto &absDrawRect = surfaceParams->GetAbsDrawRect();
351     // warning : don't delete this trace or change trace level to optional !!!
352     RS_TRACE_NAME_FMT("RSSurfaceRenderNodeDrawable::OnDraw:[%s] (%d, %d, %d, %d)Alpha: %f", name_.c_str(),
353         absDrawRect.left_, absDrawRect.top_, absDrawRect.width_, absDrawRect.height_, surfaceParams->GetGlobalAlpha());
354 
355     RS_LOGD("RSSurfaceRenderNodeDrawable::OnDraw node:%{public}" PRIu64 ", name:%{public}s,"
356             "OcclusionVisible:%{public}d Bound:%{public}s",
357         surfaceParams->GetId(), name_.c_str(), surfaceParams->GetOcclusionVisible(),
358         surfaceParams->GetBounds().ToString().c_str());
359 
360     RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
361         surfaceParams->GetFirstLevelNodeId(), surfaceParams->GetUifirstRootNodeId(), nodeId_);
362     if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(*surfaceParams)) {
363         SetDrawSkipType(DrawSkipType::CHECK_MATCH_AND_WAIT_NOTIFY_FAIL);
364         return;
365     }
366 
367     if (DealWithUIFirstCache(*rscanvas, *surfaceParams, *uniParam)) {
368         SetDrawSkipType(DrawSkipType::UI_FIRST_CACHE_SKIP);
369         return;
370     }
371 
372     std::shared_ptr<Drawing::GPUContext> gpuContext = nullptr;
373     auto realTid = gettid();
374     if (realTid == RSUniRenderThread::Instance().GetTid()) {
375         gpuContext = RSUniRenderThread::Instance().GetRenderEngine()->GetRenderContext()->GetSharedDrGPUContext();
376     } else {
377         gpuContext = RSSubThreadManager::Instance()->GetGrContextFromSubThread(realTid);
378     }
379     RSTagTracker tagTracker(gpuContext.get(), surfaceParams->GetId(),
380         RSTagTracker::TAGTYPE::TAG_DRAW_SURFACENODE, surfaceParams->GetName());
381 
382     // Draw base pipeline start
383     RSAutoCanvasRestore acr(rscanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
384     bool needOffscreen = (realTid == RSUniRenderThread::Instance().GetTid()) &&
385         surfaceParams->GetNeedOffscreen() && !rscanvas->GetTotalMatrix().IsIdentity() &&
386         surfaceParams->IsAppWindow() && GetName().substr(0, 3) != "SCB" && !IsHardwareEnabled() &&
387         (surfaceParams->GetVisibleRegion().Area() == surfaceParams->GetOpaqueRegion().Area());
388     curCanvas_ = rscanvas;
389     if (needOffscreen) {
390         releaseCount_ = 0;
391         if (!PrepareOffscreenRender()) {
392             needOffscreen = false;
393         }
394     } else {
395         if (offscreenSurface_ != nullptr) {
396             releaseCount_++;
397             if (releaseCount_ == MAX_RELEASE_FRAME) {
398                 std::shared_ptr<Drawing::Surface> hold = offscreenSurface_;
399                 RSUniRenderThread::Instance().PostTask([hold] {});
400                 offscreenSurface_ = nullptr;
401                 releaseCount_ = 0;
402             }
403         }
404     }
405 
406     surfaceParams->ApplyAlphaAndMatrixToCanvas(*curCanvas_, !needOffscreen);
407 
408     bool isSelfDrawingSurface = surfaceParams->GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE &&
409         !surfaceParams->IsSpherizeValid();
410     if (isSelfDrawingSurface) {
411         SetSkip(surfaceParams->GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
412         // Restore in OnGeneralProcess
413         curCanvas_->Save();
414     }
415 
416     if (surfaceParams->IsMainWindowType()) {
417         RSRenderNodeDrawable::ClearTotalProcessedNodeCount();
418         RSRenderNodeDrawable::ClearProcessedNodeCount();
419         if (!surfaceParams->GetNeedOffscreen()) {
420             curCanvas_->PushDirtyRegion(curSurfaceDrawRegion);
421         }
422     }
423 
424     auto parentSurfaceMatrix = RSRenderParams::GetParentSurfaceMatrix();
425     RSRenderParams::SetParentSurfaceMatrix(curCanvas_->GetTotalMatrix());
426 
427     // add a blending disable rect op behind floating window, to enable overdraw buffer feature on special gpu.
428     if (surfaceParams->IsLeashWindow() && RSSystemProperties::GetGpuOverDrawBufferOptimizeEnabled()
429         && surfaceParams->IsGpuOverDrawBufferOptimizeNode()) {
430         EnableGpuOverDrawDrawBufferOptimization(*curCanvas_, surfaceParams);
431     }
432 
433     OnGeneralProcess(*curCanvas_, *surfaceParams, isSelfDrawingSurface);
434 
435     if (needOffscreen) {
436         Drawing::AutoCanvasRestore acr(*canvasBackup_, true);
437         if (surfaceParams->HasSandBox()) {
438             canvasBackup_->SetMatrix(surfaceParams->GetParentSurfaceMatrix());
439             canvasBackup_->ConcatMatrix(surfaceParams->GetMatrix());
440         } else {
441             canvasBackup_->ConcatMatrix(surfaceParams->GetMatrix());
442         }
443         FinishOffscreenRender(
444             Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NONE));
445         RS_LOGD("FinishOffscreenRender %{public}s node type %{public}d", surfaceParams->GetName().c_str(),
446             int(surfaceParams->GetSurfaceNodeType()));
447     }
448 
449     // Draw base pipeline end
450     if (surfaceParams->IsMainWindowType()) {
451         if (!surfaceParams->GetNeedOffscreen()) {
452             curCanvas_->PopDirtyRegion();
453         }
454         int processedNodes = RSRenderNodeDrawable::GetProcessedNodeCount();
455         AcquireFenceTracker::SetContainerNodeNum(processedNodes);
456         RS_TRACE_NAME_FMT("RSUniRenderThread::Render() the number of total ProcessedNodes: %d",
457             RSRenderNodeDrawable::GetTotalProcessedNodeCount());
458         const RSNodeStatsType nodeStats = CreateRSNodeStatsItem(
459             RSRenderNodeDrawable::GetTotalProcessedNodeCount(), GetId(), GetName());
460         RSNodeStats::GetInstance().AddNodeStats(nodeStats);
461     }
462 
463     RSRenderParams::SetParentSurfaceMatrix(parentSurfaceMatrix);
464 }
465 
MergeDirtyRegionBelowCurSurface(RSRenderThreadParams & uniParam,Drawing::Region & region)466 void RSSurfaceRenderNodeDrawable::MergeDirtyRegionBelowCurSurface(
467     RSRenderThreadParams& uniParam, Drawing::Region& region)
468 {
469     if (!renderParams_) {
470         return;
471     }
472     auto surfaceParams = static_cast<RSSurfaceRenderParams*>(renderParams_.get());
473     if (!surfaceParams) {
474         return;
475     }
476     auto visibleRegion = surfaceParams->GetVisibleRegion();
477     if (surfaceParams->IsMainWindowType() && visibleRegion.IsEmpty()) {
478         return;
479     }
480     if (surfaceParams->IsMainWindowType() || surfaceParams->IsLeashWindow()) {
481         auto& accumulatedDirtyRegion = uniParam.GetAccumulatedDirtyRegion();
482         Occlusion::Region calcRegion;
483         if ((surfaceParams->IsMainWindowType() && surfaceParams->IsParentScaling()) ||
484             surfaceParams->IsSubSurfaceNode() || uniParam.IsAllSurfaceVisibleDebugEnabled()) {
485             calcRegion = visibleRegion;
486         } else if (!surfaceParams->GetTransparentRegion().IsEmpty()) {
487             auto transparentRegion = surfaceParams->GetTransparentRegion();
488             calcRegion = visibleRegion.And(transparentRegion);
489         }
490         if (!calcRegion.IsEmpty()) {
491             auto dirtyRegion = calcRegion.And(accumulatedDirtyRegion);
492             if (!dirtyRegion.IsEmpty()) {
493                 for (auto& rect : dirtyRegion.GetRegionRects()) {
494                     Drawing::Region tempRegion;
495                     tempRegion.SetRect(Drawing::RectI(
496                         rect.left_, rect.top_, rect.right_, rect.bottom_));
497                     region.Op(tempRegion, Drawing::RegionOp::UNION);
498                 }
499             }
500         }
501         // [planing] surfaceDirtyRegion can be optimized by visibleDirtyRegion in some case.
502         auto surfaceDirtyRegion = Occlusion::Region {
503             Occlusion::Rect{ GetSyncDirtyManager()->GetDirtyRegion() } };
504         accumulatedDirtyRegion.OrSelf(surfaceDirtyRegion);
505         // add children window dirty here for uifirst leasf window will not traverse cached children
506         if (surfaceParams->GetUifirstNodeEnableParam() != MultiThreadCacheType::NONE) {
507             auto childrenDirtyRegion = Occlusion::Region {
508                 Occlusion::Rect{ surfaceParams->GetUifirstChildrenDirtyRectParam() } };
509             accumulatedDirtyRegion.OrSelf(childrenDirtyRegion);
510         }
511     }
512 }
513 
OnCapture(Drawing::Canvas & canvas)514 void RSSurfaceRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
515 {
516     if (!ShouldPaint()) {
517         return;
518     }
519 
520     auto surfaceParams = static_cast<RSSurfaceRenderParams*>(GetRenderParams().get());
521     if (!surfaceParams) {
522         RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture surfaceParams is nullptr");
523         return;
524     }
525 
526     // HidePrivacyContent is only for UICapture or NoneSystemCalling-WindowCapture
527     bool isHiddenScene = canvas.GetUICapture() ||
528         (RSUniRenderThread::GetCaptureParam().isSingleSurface_ &&
529         !RSUniRenderThread::GetCaptureParam().isSystemCalling_);
530     if ((surfaceNodeType_ == RSSurfaceNodeType::UI_EXTENSION_COMMON_NODE ||
531         surfaceNodeType_ == RSSurfaceNodeType::UI_EXTENSION_SECURE_NODE) &&
532         isHiddenScene && surfaceParams->GetHidePrivacyContent()) {
533         RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture surfacenode nodeId:[%{public}" PRIu64
534                 "] is not allowed to be captured", nodeId_);
535         return;
536     }
537 
538     RSUiFirstProcessStateCheckerHelper stateCheckerHelper(
539         surfaceParams->GetFirstLevelNodeId(), surfaceParams->GetUifirstRootNodeId(), nodeId_);
540     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
541     if (UNLIKELY(!uniParam)) {
542         RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture uniParam is nullptr");
543         return;
544     }
545 
546     auto rscanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
547     if (!rscanvas) {
548         RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture, rscanvas us nullptr");
549         return;
550     }
551     rscanvas->SetHighContrast(RSUniRenderThread::Instance().IsHighContrastTextModeOn());
552     // process white list
553     auto whiteList = RSUniRenderThread::Instance().GetWhiteList();
554     SetVirtualScreenWhiteListRootId(whiteList, surfaceParams->GetId());
555 
556     if (CheckIfSurfaceSkipInMirror(*surfaceParams)) {
557         return;
558     }
559 
560     if (uniParam->IsOcclusionEnabled() && surfaceParams->IsMainWindowType() &&
561         surfaceParams->GetVisibleRegionInVirtual().IsEmpty() && whiteList.empty() &&
562         UNLIKELY(RSUniRenderThread::GetCaptureParam().isMirror_)) {
563         RS_TRACE_NAME("RSSurfaceRenderNodeDrawable::OnCapture occlusion skip :[" + name_ + "] " +
564             surfaceParams->GetAbsDrawRect().ToString());
565         return;
566     }
567 
568     RS_TRACE_NAME("RSSurfaceRenderNodeDrawable::OnCapture:[" + name_ + "] " +
569         surfaceParams->GetAbsDrawRect().ToString() + "Alpha: " +
570         std::to_string(surfaceParams->GetGlobalAlpha()));
571     RSAutoCanvasRestore acr(rscanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
572 
573     // First node don't need to concat matrix for application
574     if (RSUniRenderThread::GetCaptureParam().isFirstNode_) {
575         // Planning: If node is a sandbox.
576         rscanvas->MultiplyAlpha(surfaceParams->GetAlpha());
577         RSUniRenderThread::GetCaptureParam().isFirstNode_ = false;
578     } else {
579         surfaceParams->ApplyAlphaAndMatrixToCanvas(*rscanvas);
580     }
581 
582     CaptureSurface(*rscanvas, *surfaceParams);
583     ResetVirtualScreenWhiteListRootId(surfaceParams->GetId());
584 }
585 
CheckIfSurfaceSkipInMirror(const RSSurfaceRenderParams & surfaceParams)586 bool RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror(const RSSurfaceRenderParams& surfaceParams)
587 {
588     if (!RSUniRenderThread::GetCaptureParam().isMirror_) {
589         return false;
590     }
591     // Check black list.
592     const auto& blackList = RSUniRenderThread::Instance().GetBlackList();
593     if (surfaceParams.IsLeashWindow() && blackList.find(surfaceParams.GetLeashPersistentId()) != blackList.end()) {
594         RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
595             (LeashPersistentId:[%{public}" PRIu64 "]) is in black list", surfaceParams.GetLeashPersistentId());
596         return true;
597     }
598     if (blackList.find(surfaceParams.GetId()) != blackList.end()) {
599         RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
600             (surfaceParamsId:[%{public}" PRIu64 "]) is in black list", surfaceParams.GetId());
601         return true;
602     }
603     // Check white list.
604     const auto& whiteList = RSUniRenderThread::Instance().GetWhiteList();
605     if (!whiteList.empty() && RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ == INVALID_NODEID) {
606         RS_LOGD("RSSurfaceRenderNodeDrawable::CheckIfSurfaceSkipInMirror: \
607             (id:[%{public}" PRIu64 "]) isn't in white list", surfaceParams.GetId());
608         return true;
609     }
610     // To be deleted after captureWindow being deleted.
611     // Check weather can be skipped due to using screen recording optimization.
612     if (EnableRecordingOptimization(surfaceParams)) {
613         return true;
614     }
615     return false;
616 }
617 
SetVirtualScreenWhiteListRootId(const std::unordered_set<NodeId> & whiteList,NodeId id)618 void RSSurfaceRenderNodeDrawable::SetVirtualScreenWhiteListRootId(
619     const std::unordered_set<NodeId>& whiteList, NodeId id)
620 {
621     if (whiteList.find(id) == whiteList.end()) {
622         return;
623     }
624     // don't update if it's ancestor has already set
625     if (RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ != INVALID_NODEID) {
626         return;
627     }
628     RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ = id;
629 }
630 
ResetVirtualScreenWhiteListRootId(NodeId id)631 void RSSurfaceRenderNodeDrawable::ResetVirtualScreenWhiteListRootId(NodeId id)
632 {
633     // only reset by the node which sets the flag
634     if (RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ == id) {
635         RSUniRenderThread::GetCaptureParam().rootIdInWhiteList_ = INVALID_NODEID;
636     }
637 }
638 
639 // To be deleted after captureWindow being deleted
EnableRecordingOptimization(const RSSurfaceRenderParams & surfaceParams)640 bool RSSurfaceRenderNodeDrawable::EnableRecordingOptimization(const RSSurfaceRenderParams& surfaceParams)
641 {
642     auto& threadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
643     if (UNLIKELY(!threadParams)) {
644         return false;
645     }
646     NodeId nodeId = threadParams->GetRootIdOfCaptureWindow();
647     bool hasCaptureImg = threadParams->GetHasCaptureImg();
648     if (nodeId == surfaceParams.GetId()) {
649         RS_LOGD("RSSurfaceRenderNodeDrawable::EnableRecordingOptimization: (id:[%{public}" PRIu64 "])",
650             surfaceParams.GetId());
651         threadParams->SetStartVisit(true);
652     }
653     if (!hasCaptureImg || threadParams->GetStartVisit()) {
654         return false;
655     }
656     RS_LOGD("RSSurfaceRenderNodeDrawable::EnableRecordingOptimization: (id:[%{public}" PRIu64 "]) Skip layer.",
657         surfaceParams.GetId());
658     return true;
659 }
660 
CaptureSurface(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)661 void RSSurfaceRenderNodeDrawable::CaptureSurface(RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
662 {
663     auto& uniParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
664     if (UNLIKELY(!uniParams)) {
665         RS_LOGE("RSSurfaceRenderNodeDrawable::CaptureSurface uniParams is nullptr");
666         return;
667     }
668     if ((surfaceParams.GetIsSecurityLayer() && !uniParams->GetSecExemption()) || surfaceParams.GetIsSkipLayer()) {
669         RS_LOGD("RSSurfaceRenderNodeDrawable::CaptureSurface: \
670             process RSSurfaceRenderNode(id:[%{public}" PRIu64 "] name:[%{public}s]) with security or skip layer.",
671             surfaceParams.GetId(), name_.c_str());
672         RS_TRACE_NAME("CaptureSurface with security or skip layer");
673         if (RSUniRenderThread::GetCaptureParam().isSingleSurface_) {
674             Drawing::Brush rectBrush;
675             rectBrush.SetColor(Drawing::Color::COLOR_WHITE);
676             canvas.AttachBrush(rectBrush);
677             canvas.DrawRect(Drawing::Rect(0, 0, surfaceParams.GetBounds().GetWidth(),
678                 surfaceParams.GetBounds().GetHeight()));
679             canvas.DetachBrush();
680         }
681         return;
682     }
683 
684     if (surfaceParams.GetIsProtectedLayer()) {
685         RS_LOGD("RSSurfaceRenderNodeDrawable::CaptureSurface: \
686             process RSSurfaceRenderNode(id:[%{public}" PRIu64 "] name:[%{public}s]) with protected layer.",
687             surfaceParams.GetId(), name_.c_str());
688         Drawing::Brush rectBrush;
689         rectBrush.SetColor(Drawing::Color::COLOR_BLACK);
690         canvas.AttachBrush(rectBrush);
691         canvas.DrawRect(Drawing::Rect(0, 0, surfaceParams.GetBounds().GetWidth(),
692             surfaceParams.GetBounds().GetHeight()));
693         canvas.DetachBrush();
694         return;
695     }
696 
697     bool hwcEnable = surfaceParams.GetHardwareEnabled();
698     surfaceParams.SetHardwareEnabled(false);
699     RS_LOGD("HDR hasHdrPresent_:%{public}d", canvas.IsCapture());
700     bool hasHidePrivacyContent = surfaceParams.HasPrivacyContentLayer() &&
701         RSUniRenderThread::GetCaptureParam().isSingleSurface_ &&
702         !RSUniRenderThread::GetCaptureParam().isSystemCalling_;
703     if (!(surfaceParams.HasSecurityLayer() || surfaceParams.HasSkipLayer() || surfaceParams.HasProtectedLayer() ||
704         hasHdrPresent_ || hasHidePrivacyContent) && DealWithUIFirstCache(canvas, surfaceParams, *uniParams)) {
705         surfaceParams.SetHardwareEnabled(hwcEnable);
706         return;
707     }
708     surfaceParams.SetHardwareEnabled(hwcEnable);
709 
710     // cannot useNodeMatchOptimize if leash window is on draw
711     auto cacheState = GetCacheSurfaceProcessedStatus();
712     auto useNodeMatchOptimize = cacheState != CacheProcessStatus::WAITING && cacheState != CacheProcessStatus::DOING;
713     if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(surfaceParams, useNodeMatchOptimize)) {
714         RS_LOGE("RSSurfaceRenderNodeDrawable::OnCapture CheckMatchAndWaitNotify failed");
715         return;
716     }
717 
718     bool isSelfDrawingSurface = surfaceParams.GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE &&
719         !surfaceParams.IsSpherizeValid();
720     if (isSelfDrawingSurface) {
721         SetSkip(surfaceParams.GetBuffer() != nullptr ? SkipType::SKIP_BACKGROUND_COLOR : SkipType::NONE);
722         // Restore in OnGeneralProcess
723         canvas.Save();
724     }
725 
726     auto parentSurfaceMatrix = RSRenderParams::GetParentSurfaceMatrix();
727     RSRenderParams::SetParentSurfaceMatrix(canvas.GetTotalMatrix());
728 
729     OnGeneralProcess(canvas, surfaceParams, isSelfDrawingSurface);
730 
731     RSRenderParams::SetParentSurfaceMatrix(parentSurfaceMatrix);
732 }
733 
GetAncestorDisplayColorGamut(const RSSurfaceRenderParams & surfaceParams)734 GraphicColorGamut RSSurfaceRenderNodeDrawable::GetAncestorDisplayColorGamut(const RSSurfaceRenderParams& surfaceParams)
735 {
736     GraphicColorGamut targetColorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
737     auto ancestorDrawable = surfaceParams.GetAncestorDisplayDrawable().lock();
738     if (!ancestorDrawable) {
739         RS_LOGE("ancestorDrawable return nullptr");
740         return targetColorGamut;
741     }
742     auto ancestorDisplayDrawable = std::static_pointer_cast<RSDisplayRenderNodeDrawable>(ancestorDrawable);
743     if (!ancestorDisplayDrawable) {
744         RS_LOGE("ancestorDisplayDrawable return nullptr");
745         return targetColorGamut;
746     }
747     auto& ancestorParam = ancestorDrawable->GetRenderParams();
748     if (!ancestorParam) {
749         RS_LOGE("ancestorParam return nullptr");
750         return targetColorGamut;
751     }
752 
753     auto renderParams = static_cast<RSDisplayRenderParams*>(ancestorParam.get());
754     targetColorGamut = renderParams->GetNewColorSpace();
755     RS_LOGD("params.targetColorGamut is %{public}d in DealWithSelfDrawingNodeBuffer", targetColorGamut);
756     return targetColorGamut;
757 }
758 
DealWithSelfDrawingNodeBuffer(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)759 void RSSurfaceRenderNodeDrawable::DealWithSelfDrawingNodeBuffer(
760     RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams)
761 {
762     if (surfaceParams.GetHardwareEnabled() && !RSUniRenderThread::IsInCaptureProcess()) {
763         if (!IsHardwareEnabledTopSurface() && !surfaceParams.IsLayerTop()) {
764             ClipHoleForSelfDrawingNode(canvas, surfaceParams);
765         }
766         return;
767     }
768     if (surfaceParams.IsInFixedRotation()) {
769         DrawBufferForRotationFixed(canvas, surfaceParams);
770         return;
771     }
772 
773     RSAutoCanvasRestore arc(&canvas);
774     surfaceParams.SetGlobalAlpha(1.0f);
775     pid_t threadId = gettid();
776     auto params = RSUniRenderUtil::CreateBufferDrawParam(*this, false, threadId);
777     params.targetColorGamut = GetAncestorDisplayColorGamut(surfaceParams);
778 #ifdef USE_VIDEO_PROCESSING_ENGINE
779     params.sdrNits = surfaceParams.GetSdrNit();
780     params.tmoNits = surfaceParams.GetDisplayNit();
781     params.displayNits = params.tmoNits / std::pow(surfaceParams.GetBrightnessRatio(), GAMMA2_2); // gamma 2.2
782 #endif
783 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
784     if (IsHardwareEnabledTopSurface() && RSUniRenderThread::Instance().GetRSRenderThreadParams()->HasMirrorDisplay()) {
785         RSPointerRenderManager::GetInstance().SetCacheImgForPointer(canvas.GetSurface()->GetImageSnapshot());
786     }
787 #endif
788 
789     DrawSelfDrawingNodeBuffer(canvas, surfaceParams, params);
790 }
791 
ClipHoleForSelfDrawingNode(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)792 void RSSurfaceRenderNodeDrawable::ClipHoleForSelfDrawingNode(RSPaintFilterCanvas& canvas,
793     RSSurfaceRenderParams& surfaceParams)
794 {
795     RSAutoCanvasRestore arc(&canvas);
796     auto bounds = surfaceParams.GetBounds();
797     canvas.ClipRect({std::round(bounds.GetLeft()), std::round(bounds.GetTop()),
798         std::round(bounds.GetRight()), std::round(bounds.GetBottom())});
799     canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
800 }
801 
DrawBufferForRotationFixed(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams)802 void RSSurfaceRenderNodeDrawable::DrawBufferForRotationFixed(RSPaintFilterCanvas& canvas,
803     RSSurfaceRenderParams& surfaceParams)
804 {
805     ClipHoleForSelfDrawingNode(canvas, surfaceParams);
806 
807     Drawing::Brush brush;
808     brush.SetBlendMode(Drawing::BlendMode::DST_OVER);
809     Drawing::SaveLayerOps layerOps(nullptr, &brush);
810     canvas.SaveLayer(layerOps);
811 
812     Drawing::Matrix inverse;
813     if (!(surfaceParams.GetLayerInfo().matrix.Invert(inverse))) {
814         RS_LOGE("DrawBufferForRotationFixed failed to get invert matrix");
815     }
816     canvas.ConcatMatrix(inverse);
817     auto params = RSUniRenderUtil::CreateBufferDrawParamForRotationFixed(*this, surfaceParams);
818     RSUniRenderThread::Instance().GetRenderEngine()->DrawSurfaceNodeWithParams(canvas, *this, params);
819     canvas.Restore();
820 }
821 
DrawSelfDrawingNodeBuffer(RSPaintFilterCanvas & canvas,const RSSurfaceRenderParams & surfaceParams,BufferDrawParam & params)822 void RSSurfaceRenderNodeDrawable::DrawSelfDrawingNodeBuffer(
823     RSPaintFilterCanvas& canvas, const RSSurfaceRenderParams& surfaceParams, BufferDrawParam& params)
824 {
825     auto bgColor = surfaceParams.GetBackgroundColor();
826     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
827     if ((surfaceParams.GetSelfDrawingNodeType() != SelfDrawingNodeType::VIDEO) &&
828         (bgColor != RgbPalette::Transparent())) {
829         Drawing::Brush brush;
830         brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
831         if (HasCornerRadius(surfaceParams)) {
832             auto bounds = RSPropertiesPainter::Rect2DrawingRect({ 0, 0,
833                 std::round(surfaceParams.GetBounds().GetWidth()), std::round(surfaceParams.GetBounds().GetHeight()) });
834             Drawing::SaveLayerOps layerOps(&bounds, nullptr);
835             canvas.SaveLayer(layerOps);
836             canvas.AttachBrush(brush);
837             canvas.DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(surfaceParams.GetRRect()));
838             canvas.DetachBrush();
839             renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
840             canvas.Restore();
841         } else {
842             canvas.AttachBrush(brush);
843             canvas.DrawRect(surfaceParams.GetBounds());
844             canvas.DetachBrush();
845             renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
846         }
847     } else {
848         renderEngine->DrawSurfaceNodeWithParams(canvas, *this, params);
849     }
850 }
851 
HasCornerRadius(const RSSurfaceRenderParams & surfaceParams) const852 bool RSSurfaceRenderNodeDrawable::HasCornerRadius(const RSSurfaceRenderParams& surfaceParams) const
853 {
854     auto rrect = surfaceParams.GetRRect();
855     for (auto index = 0; index < CORNER_SIZE; ++index) {
856         if (!ROSEN_EQ(rrect.radius_[index].x_, 0.f) || !ROSEN_EQ(rrect.radius_[index].y_, 0.f)) {
857             return true;
858         }
859     }
860     return false;
861 }
862 
DealWithUIFirstCache(RSPaintFilterCanvas & canvas,RSSurfaceRenderParams & surfaceParams,RSRenderThreadParams & uniParams)863 bool RSSurfaceRenderNodeDrawable::DealWithUIFirstCache(
864     RSPaintFilterCanvas& canvas, RSSurfaceRenderParams& surfaceParams, RSRenderThreadParams& uniParams)
865 {
866     auto enableType = surfaceParams.GetUifirstNodeEnableParam();
867     auto cacheState = GetCacheSurfaceProcessedStatus();
868     if ((!RSUniRenderThread::GetCaptureParam().isSnapshot_ && enableType == MultiThreadCacheType::NONE &&
869         // WAITING may change to DOING in subThread at any time
870         cacheState != CacheProcessStatus::WAITING && cacheState != CacheProcessStatus::DOING) ||
871         (RSUniRenderThread::GetCaptureParam().isSnapshot_ && !HasCachedTexture())) {
872         return false;
873     }
874     RS_TRACE_NAME_FMT("DrawUIFirstCache [%s] %lld, type %d",
875         name_.c_str(), surfaceParams.GetId(), enableType);
876     RSUifirstManager::Instance().AddReuseNode(surfaceParams.GetId());
877     Drawing::Rect bounds = GetRenderParams() ? GetRenderParams()->GetBounds() : Drawing::Rect(0, 0, 0, 0);
878     RSAutoCanvasRestore acr(&canvas);
879     // Alpha and matrix have been applied in func CaptureSurface
880     if (!RSUniRenderThread::GetCaptureParam().isSnapshot_ && !RSUniRenderThread::GetCaptureParam().isMirror_) {
881         canvas.MultiplyAlpha(surfaceParams.GetAlpha());
882         canvas.ConcatMatrix(surfaceParams.GetMatrix());
883     }
884     bool useDmaBuffer = UseDmaBuffer();
885     DrawBackground(canvas, bounds);
886     bool drawCacheSuccess = true;
887     if (surfaceParams.GetUifirstUseStarting() != INVALID_NODEID) {
888         drawCacheSuccess = DrawUIFirstCacheWithStarting(canvas, surfaceParams.GetUifirstUseStarting());
889     } else {
890         bool canSkipFirstWait = (enableType == MultiThreadCacheType::ARKTS_CARD) &&
891             uniParams.GetUIFirstCurrentFrameCanSkipFirstWait();
892         drawCacheSuccess = useDmaBuffer ?
893             DrawUIFirstCacheWithDma(canvas, surfaceParams) : DrawUIFirstCache(canvas, canSkipFirstWait);
894     }
895     if (!drawCacheSuccess) {
896         RS_TRACE_NAME_FMT("[%s] reuse failed!", name_.c_str());
897     }
898     DrawForeground(canvas, bounds);
899     if (uniParams.GetUIFirstDebugEnabled()) {
900         DrawUIFirstDfx(canvas, enableType, surfaceParams, drawCacheSuccess);
901     }
902     return true;
903 }
904 
DrawUIFirstDfx(RSPaintFilterCanvas & canvas,MultiThreadCacheType enableType,RSSurfaceRenderParams & surfaceParams,bool drawCacheSuccess)905 void RSSurfaceRenderNodeDrawable::DrawUIFirstDfx(RSPaintFilterCanvas& canvas, MultiThreadCacheType enableType,
906     RSSurfaceRenderParams& surfaceParams, bool drawCacheSuccess)
907 {
908     auto sizeDebug = surfaceParams.GetCacheSize();
909     Drawing::Brush rectBrush;
910     if (drawCacheSuccess) {
911         if (enableType == MultiThreadCacheType::ARKTS_CARD) {
912             // rgba: Alpha 128, blue 128
913             rectBrush.SetColor(Drawing::Color(0, 0, 128, 128));
914         } else {
915             // rgba: Alpha 128, green 128, blue 128
916             rectBrush.SetColor(Drawing::Color(0, 128, 128, 128));
917         }
918     } else {
919         // rgba: Alpha 128, red 128
920         rectBrush.SetColor(Drawing::Color(128, 0, 0, 128));
921     }
922     canvas.AttachBrush(rectBrush);
923     canvas.DrawRect(Drawing::Rect(0, 0, sizeDebug.x_, sizeDebug.y_));
924     canvas.DetachBrush();
925 }
926 
EnableGpuOverDrawDrawBufferOptimization(Drawing::Canvas & canvas,RSSurfaceRenderParams * surfaceParams)927 void RSSurfaceRenderNodeDrawable::EnableGpuOverDrawDrawBufferOptimization(Drawing::Canvas& canvas,
928     RSSurfaceRenderParams* surfaceParams)
929 {
930     const Vector4f& radius = surfaceParams->GetOverDrawBufferNodeCornerRadius();
931     if (radius.IsZero()) {
932         return;
933     }
934     RS_OPTIONAL_TRACE_NAME_FMT("EnableGpuOverDrawDrawBufferOptimization Id:%" PRIu64 "", surfaceParams->GetId());
935     const Drawing::Rect& bounds = surfaceParams->GetFrameRect();
936     Drawing::Brush brush;
937     // must set src blend mode, so overdraw buffer feature can enabled.
938     brush.SetBlendMode(Drawing::BlendMode::SRC);
939     // cause the rect will be covered by the child background node, so we just add a white rect
940     brush.SetColor(Drawing::Color::COLOR_WHITE);
941     canvas.AttachBrush(brush);
942     Drawing::AutoCanvasRestore arc(canvas, true);
943     canvas.Translate(radius.x_, radius.y_);
944     canvas.DrawRect(Drawing::Rect {0, 0, bounds.GetWidth() - 2 * radius.x_, bounds.GetHeight() - 2 * radius.y_});
945     canvas.DetachBrush();
946 }
947 
GetVisibleDirtyRegion() const948 const Occlusion::Region& RSSurfaceRenderNodeDrawable::GetVisibleDirtyRegion() const
949 {
950     return visibleDirtyRegion_;
951 }
952 
SetVisibleDirtyRegion(const Occlusion::Region & region)953 void RSSurfaceRenderNodeDrawable::SetVisibleDirtyRegion(const Occlusion::Region& region)
954 {
955     visibleDirtyRegion_ = region;
956 }
957 
SetAlignedVisibleDirtyRegion(const Occlusion::Region & alignedRegion)958 void RSSurfaceRenderNodeDrawable::SetAlignedVisibleDirtyRegion(const Occlusion::Region& alignedRegion)
959 {
960     alignedVisibleDirtyRegion_ = alignedRegion;
961 }
962 
SetGlobalDirtyRegion(Occlusion::Region region)963 void RSSurfaceRenderNodeDrawable::SetGlobalDirtyRegion(Occlusion::Region region)
964 {
965     if (!GetRenderParams()) {
966         return;
967     }
968     auto visibleRegion = GetRenderParams()->GetVisibleRegion();
969     globalDirtyRegion_ = visibleRegion.And(region);
970     globalDirtyRegionIsEmpty_ = globalDirtyRegion_.IsEmpty();
971 }
972 
GetGlobalDirtyRegion() const973 const Occlusion::Region& RSSurfaceRenderNodeDrawable::GetGlobalDirtyRegion() const
974 {
975     return globalDirtyRegion_;
976 }
977 
SetDirtyRegionAlignedEnable(bool enable)978 void RSSurfaceRenderNodeDrawable::SetDirtyRegionAlignedEnable(bool enable)
979 {
980     isDirtyRegionAlignedEnable_ = enable;
981 }
982 
SetDirtyRegionBelowCurrentLayer(Occlusion::Region & region)983 void RSSurfaceRenderNodeDrawable::SetDirtyRegionBelowCurrentLayer(Occlusion::Region& region)
984 {
985 #ifndef ROSEN_CROSS_PLATFORM
986     if (!renderParams_) {
987         return;
988     }
989     Occlusion::Rect dirtyRect { renderParams_->GetOldDirtyInSurface() };
990     Occlusion::Region dirtyRegion { dirtyRect };
991     dirtyRegionBelowCurrentLayer_ = dirtyRegion.And(region);
992     dirtyRegionBelowCurrentLayerIsEmpty_ = dirtyRegionBelowCurrentLayer_.IsEmpty();
993 #endif
994 }
995 
GetSyncDirtyManager() const996 std::shared_ptr<RSDirtyRegionManager> RSSurfaceRenderNodeDrawable::GetSyncDirtyManager() const
997 {
998     return syncDirtyManager_;
999 }
1000 
1001 #ifndef ROSEN_CROSS_PLATFORM
RegisterDeleteBufferListenerOnSync(sptr<IConsumerSurface> consumer)1002 void RSSurfaceRenderNodeDrawable::RegisterDeleteBufferListenerOnSync(sptr<IConsumerSurface> consumer)
1003 {
1004     auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
1005     if (!renderEngine || !consumerOnDraw_) {
1006         return;
1007     }
1008     renderEngine->RegisterDeleteBufferListener(consumerOnDraw_);
1009 }
1010 #endif
1011 
1012 } // namespace OHOS::Rosen::DrawableV2
1013