• 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_canvas_render_node_drawable.h"
17 
18 #include "rs_trace.h"
19 
20 #include "common/rs_optional_trace.h"
21 #include "feature/uifirst/rs_uifirst_manager.h"
22 #include "pipeline/render_thread/rs_uni_render_thread.h"
23 #include "pipeline/rs_canvas_render_node.h"
24 #include "pipeline/rs_paint_filter_canvas.h"
25 #include "pipeline/rs_render_node_allocator.h"
26 #include "platform/common/rs_log.h"
27 #include "utils/rect.h"
28 #include "utils/region.h"
29 #include "include/gpu/vk/GrVulkanTrackerInterface.h"
30 #include "rs_root_render_node_drawable.h"
31 
32 #ifdef SUBTREE_PARALLEL_ENABLE
33 #include "rs_parallel_manager.h"
34 #endif
35 namespace OHOS::Rosen::DrawableV2 {
36 RSCanvasRenderNodeDrawable::Registrar RSCanvasRenderNodeDrawable::instance_;
37 
RSCanvasRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)38 RSCanvasRenderNodeDrawable::RSCanvasRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
39     : RSRenderNodeDrawable(std::move(node))
40 {}
41 
OnGenerate(std::shared_ptr<const RSRenderNode> node)42 RSRenderNodeDrawable::Ptr RSCanvasRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
43 {
44     auto generator = [] (std::shared_ptr<const RSRenderNode> node,
45         RSRenderNodeAllocator::DrawablePtr front) -> RSRenderNodeAllocator::DrawablePtr {
46             if (front != nullptr) {
47                 return new (front)RSCanvasRenderNodeDrawable(std::move(node));
48             }
49             return new RSCanvasRenderNodeDrawable(std::move(node));
50     };
51     return RSRenderNodeAllocator::Instance().CreateRSRenderNodeDrawable(node, generator);
52 }
53 
54 #ifdef SUBTREE_PARALLEL_ENABLE
QuickGetDrawState(RSPaintFilterCanvas * rscanvas)55 bool RSCanvasRenderNodeDrawable::QuickGetDrawState(RSPaintFilterCanvas* rscanvas)
56 {
57     if (!rscanvas->IsQuickGetDrawState()) {
58         return false;
59     }
60     Drawing::Rect bounds = GetRenderParams() ? GetRenderParams()->GetFrameRect() : Drawing::Rect(0, 0, 0, 0);
61     if (SkipCulledNodeOrEntireSubtree(*rscanvas, bounds)) {
62         return true;
63     }
64 
65     RSParallelManager::Singleton().OnQuickDraw(this, *rscanvas);
66     return true;
67 }
68 #endif
69 
IsUiRangeCaptureEndNode(Drawing::Canvas & canvas)70 bool RSCanvasRenderNodeDrawable::IsUiRangeCaptureEndNode(Drawing::Canvas& canvas)
71 {
72     auto& captureParam = RSUniRenderThread::GetCaptureParam();
73     return (canvas.GetUICapture() && captureParam.endNodeId_ != INVALID_NODEID &&
74         GetId() == captureParam.endNodeId_);
75 }
76 
77 /*
78  * This function will be called recursively many times, and the logic should be as concise as possible.
79  */
OnDraw(Drawing::Canvas & canvas)80 void RSCanvasRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
81 {
82 #ifdef RS_ENABLE_GPU
83     SetDrawSkipType(DrawSkipType::NONE);
84     bool shouldPaint = ShouldPaint() || IsUiRangeCaptureEndNode(canvas);
85     if (!shouldPaint) {
86         SetDrawSkipType(DrawSkipType::SHOULD_NOT_PAINT);
87         return;
88     }
89     const auto& params = GetRenderParams();
90     if (params == nullptr) {
91         SetDrawSkipType(DrawSkipType::RENDER_PARAMS_NULL);
92         return;
93     }
94     Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
95     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
96     if (params->GetStartingWindowFlag() && paintFilterCanvas) { // do not draw startingwindows in subthread
97         if (paintFilterCanvas->GetIsParallelCanvas()) {
98             SetDrawSkipType(DrawSkipType::PARALLEL_CANVAS_SKIP);
99             return;
100         }
101     }
102 
103     auto linkedDrawable = std::static_pointer_cast<RSRootRenderNodeDrawable>(
104         params->GetLinkedRootNodeDrawable().lock());
105     auto isOpincDraw = GetOpincDrawCache().PreDrawableCacheState(*params, isOpincDropNodeExt_);
106     RSAutoCanvasRestore acr(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
107     params->ApplyAlphaAndMatrixToCanvas(*paintFilterCanvas);
108     float hdrBrightness = paintFilterCanvas->GetHDRBrightness();
109     paintFilterCanvas->SetHDRBrightness(params->GetHDRBrightness());
110     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
111     SetOcclusionCullingEnabled((!uniParam || uniParam->IsOpDropped()) && GetOpDropped() &&
112         isOpincDraw && !params->HasUnobscuredUEC() && LIKELY(linkedDrawable == nullptr));
113     if (IsOcclusionCullingEnabled() && QuickReject(canvas, params->GetLocalDrawRect())) {
114         SetDrawSkipType(DrawSkipType::OCCLUSION_SKIP);
115         return;
116     }
117 
118 #ifdef SUBTREE_PARALLEL_ENABLE
119     if (QuickGetDrawState(paintFilterCanvas)) {
120         return;
121     }
122 #endif
123 
124     RSRenderNodeSingleDrawableLocker singleLocker(this);
125     if (UNLIKELY(!singleLocker.IsLocked())) {
126         singleLocker.DrawableOnDrawMultiAccessEventReport(__func__);
127         RS_LOGE("RSCanvasRenderNodeDrawable::OnDraw node %{public}" PRIu64 " onDraw!!!", GetId());
128         if (RSSystemProperties::GetSingleDrawableLockerEnabled()) {
129             SetDrawSkipType(DrawSkipType::MULTI_ACCESS);
130             return;
131         }
132     }
133 
134     // [Attention] Only used in PC window resize scene now
135     if (UNLIKELY(linkedDrawable != nullptr)) {
136         linkedDrawable->DrawWindowKeyFrameOffscreenBuffer(*paintFilterCanvas, params->GetFrameRect(),
137             params->GetAlpha(), params->GetRSFreezeFlag());
138         return;
139     }
140 
141     if (LIKELY(isDrawingCacheEnabled_)) {
142         GetOpincDrawCache().BeforeDrawCache(canvas, *params, isOpincDropNodeExt_);
143         if (!drawBlurForCache_) {
144             GenerateCacheIfNeed(canvas, *params);
145         }
146         CheckCacheTypeAndDraw(canvas, *params);
147         GetOpincDrawCache().AfterDrawCache(canvas, *params, isOpincDropNodeExt_, opincRootTotalCount_);
148         GetOpincDrawCache().DrawOpincDisabledDfx(canvas, *params);
149     } else {
150         RSRenderNodeDrawable::OnDraw(canvas);
151     }
152     paintFilterCanvas->SetHDRBrightness(hdrBrightness);
153     RSRenderNodeDrawable::ProcessedNodeCountInc();
154 #endif
155 }
156 
157 /*
158  * This function will be called recursively many times, and the logic should be as concise as possible.
159  */
OnCapture(Drawing::Canvas & canvas)160 void RSCanvasRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
161 {
162 #ifdef RS_ENABLE_GPU
163     auto& captureParam = RSUniRenderThread::GetCaptureParam();
164     bool shouldPaint = ShouldPaint() || IsUiRangeCaptureEndNode(canvas);
165     if (!shouldPaint) {
166         return;
167     }
168     const auto& params = GetRenderParams();
169     auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
170     RSAutoCanvasRestore acr(paintFilterCanvas, RSPaintFilterCanvas::SaveType::kCanvasAndAlpha);
171     params->ApplyAlphaAndMatrixToCanvas(*paintFilterCanvas);
172     if (!RSUiFirstProcessStateCheckerHelper::CheckMatchAndWaitNotify(*params, false)) {
173         SetDrawSkipType(DrawSkipType::CHECK_MATCH_AND_WAIT_NOTIFY_FAIL);
174         RS_LOGE("RSCanvasRenderNodeDrawable::OnCapture CheckMatchAndWaitNotify failed");
175         return;
176     }
177     RSRenderNodeSingleDrawableLocker singleLocker(this);
178     if (UNLIKELY(!singleLocker.IsLocked())) {
179         singleLocker.DrawableOnDrawMultiAccessEventReport(__func__);
180         RS_LOGE("RSCanvasRenderNodeDrawable::OnCapture node %{public}" PRIu64 " onDraw!!!", GetId());
181         if (RSSystemProperties::GetSingleDrawableLockerEnabled()) {
182             return;
183         }
184     }
185     if (RSRenderNodeDrawable::DealWithWhiteListNodes(canvas)) {
186         return;
187     }
188     bool stopDrawForRangeCapture = (canvas.GetUICapture() &&
189         captureParam.endNodeId_ == GetId() &&
190         captureParam.endNodeId_ != INVALID_NODEID);
191     if (captureParam.isSoloNodeUiCapture_ || stopDrawForRangeCapture) {
192         RSRenderNodeDrawable::OnDraw(canvas);
193         return;
194     }
195     if (LIKELY(isDrawingCacheEnabled_)) {
196         if (canvas.GetUICapture() && !drawBlurForCache_) {
197             GenerateCacheIfNeed(canvas, *params);
198         }
199         CheckCacheTypeAndDraw(canvas, *params, true);
200     } else {
201         RSRenderNodeDrawable::OnDraw(canvas);
202     }
203     RSRenderNodeDrawable::SnapshotProcessedNodeCountInc();
204 #endif
205 }
206 } // namespace OHOS::Rosen::DrawableV2
207