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