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_render_node_drawable_adapter.h"
17 #include <mutex>
18 #include <sstream>
19
20 #include "skia_adapter/skia_canvas.h"
21
22 #include "common/rs_background_thread.h"
23 #include "common/rs_optional_trace.h"
24 #include "drawable/rs_misc_drawable.h"
25 #include "drawable/rs_render_node_shadow_drawable.h"
26 #include "params/rs_canvas_drawing_render_params.h"
27 #include "params/rs_effect_render_params.h"
28 #include "params/rs_logical_display_render_params.h"
29 #include "params/rs_screen_render_params.h"
30 #include "params/rs_surface_render_params.h"
31 #include "params/rs_rcd_render_params.h"
32 #include "pipeline/rs_context.h"
33 #include "pipeline/rs_render_node.h"
34 #include "pipeline/rs_render_node_gc.h"
35 #include "platform/common/rs_log.h"
36
37 #ifdef ROSEN_OHOS
38 #include "hisysevent.h"
39 #endif
40
41 namespace OHOS::Rosen::DrawableV2 {
42 static const size_t CMD_LIST_COUNT_WARNING_LIMIT = 5000;
43 std::map<RSRenderNodeType, RSRenderNodeDrawableAdapter::Generator> RSRenderNodeDrawableAdapter::GeneratorMap;
44 std::map<NodeId, RSRenderNodeDrawableAdapter::WeakPtr> RSRenderNodeDrawableAdapter::RenderNodeDrawableCache_;
45 RSRenderNodeDrawableAdapter::DrawableVec RSRenderNodeDrawableAdapter::toClearDrawableVec_;
46 RSRenderNodeDrawableAdapter::CmdListVec RSRenderNodeDrawableAdapter::toClearCmdListVec_;
47 std::unordered_map<NodeId, Drawing::Matrix> RSRenderNodeDrawableAdapter::unobscuredUECMatrixMap_;
48 #ifdef ROSEN_OHOS
49 thread_local RSRenderNodeDrawableAdapter* RSRenderNodeDrawableAdapter::curDrawingCacheRoot_ = nullptr;
50 #else
51 RSRenderNodeDrawableAdapter* RSRenderNodeDrawableAdapter::curDrawingCacheRoot_ = nullptr;
52 #endif
53
RSRenderNodeDrawableAdapter(std::shared_ptr<const RSRenderNode> && node)54 RSRenderNodeDrawableAdapter::RSRenderNodeDrawableAdapter(std::shared_ptr<const RSRenderNode>&& node)
55 : nodeType_(node->GetType()), renderNode_(std::move(node)) {}
56
57 RSRenderNodeDrawableAdapter::~RSRenderNodeDrawableAdapter() = default;
58
GetDrawableById(NodeId id)59 RSRenderNodeDrawableAdapter::SharedPtr RSRenderNodeDrawableAdapter::GetDrawableById(NodeId id)
60 {
61 std::lock_guard<std::mutex> lock(cacheMapMutex_);
62 if (const auto cacheIt = RenderNodeDrawableCache_.find(id); cacheIt != RenderNodeDrawableCache_.end()) {
63 if (const auto ptr = cacheIt->second.lock()) {
64 return ptr;
65 }
66 }
67 return nullptr;
68 }
69
GetDrawableVectorById(const std::unordered_set<NodeId> & ids)70 std::vector<RSRenderNodeDrawableAdapter::SharedPtr> RSRenderNodeDrawableAdapter::GetDrawableVectorById(
71 const std::unordered_set<NodeId>& ids)
72 {
73 std::vector<RSRenderNodeDrawableAdapter::SharedPtr> vec;
74 std::lock_guard<std::mutex> lock(cacheMapMutex_);
75 for (const auto& id : ids) {
76 if (const auto cacheIt = RenderNodeDrawableCache_.find(id); cacheIt != RenderNodeDrawableCache_.end()) {
77 if (const auto ptr = cacheIt->second.lock()) {
78 vec.push_back(ptr);
79 }
80 }
81 }
82 return vec;
83 }
84
OnGenerate(const std::shared_ptr<const RSRenderNode> & node)85 RSRenderNodeDrawableAdapter::SharedPtr RSRenderNodeDrawableAdapter::OnGenerate(
86 const std::shared_ptr<const RSRenderNode>& node)
87 {
88 if (node == nullptr) {
89 ROSEN_LOGE("RSRenderNodeDrawableAdapter::OnGenerate, node null");
90 return nullptr;
91 }
92 if (node->renderDrawable_ != nullptr) {
93 return node->renderDrawable_;
94 }
95 static const auto Destructor = [](RSRenderNodeDrawableAdapter* ptr) {
96 RemoveDrawableFromCache(ptr->nodeId_); // Remove from cache before deleting
97 RSRenderNodeGC::DrawableDestructor(ptr);
98 };
99 auto id = node->GetId();
100 // Try to get a cached drawable if it exists.
101 {
102 std::lock_guard<std::mutex> lock(cacheMapMutex_);
103 if (const auto cacheIt = RenderNodeDrawableCache_.find(id); cacheIt != RenderNodeDrawableCache_.end()) {
104 if (const auto ptr = cacheIt->second.lock()) {
105 ROSEN_LOGE("%{public}s, node id in Cache is %{public}" PRIu64
106 ", nodeType: %{public}u, drawableType: %{public}u", __func__, id, node->GetType(),
107 ptr->GetNodeType());
108 if (node->GetType() == ptr->GetNodeType()) {
109 return ptr;
110 }
111 }
112 RenderNodeDrawableCache_.erase(cacheIt);
113 }
114 }
115 // If we don't have a cached drawable, try to generate a new one and cache it.
116 const auto it = GeneratorMap.find(node->GetType());
117 if (it == GeneratorMap.end()) {
118 #ifndef ROSEN_ARKUI_X
119 ROSEN_LOGE("RSRenderNodeDrawableAdapter::OnGenerate, node type %{public}d is not supported", node->GetType());
120 #endif
121 return nullptr;
122 }
123 auto ptr = it->second(node);
124 auto sharedPtr = std::shared_ptr<RSRenderNodeDrawableAdapter>(ptr, Destructor);
125 node->renderDrawable_ = sharedPtr;
126 sharedPtr->nodeId_ = id;
127 InitRenderParams(node, sharedPtr);
128
129 {
130 std::lock_guard<std::mutex> lock(cacheMapMutex_);
131 RenderNodeDrawableCache_.emplace(id, sharedPtr);
132 }
133 return sharedPtr;
134 }
135
InitRenderParams(const std::shared_ptr<const RSRenderNode> & node,std::shared_ptr<RSRenderNodeDrawableAdapter> & sharedPtr)136 void RSRenderNodeDrawableAdapter::InitRenderParams(const std::shared_ptr<const RSRenderNode>& node,
137 std::shared_ptr<RSRenderNodeDrawableAdapter>& sharedPtr)
138 {
139 switch (node->GetType()) {
140 case RSRenderNodeType::SURFACE_NODE:
141 sharedPtr->renderParams_ = std::make_unique<RSSurfaceRenderParams>(sharedPtr->nodeId_);
142 sharedPtr->uifirstRenderParams_ = std::make_unique<RSSurfaceRenderParams>(sharedPtr->nodeId_);
143 break;
144 case RSRenderNodeType::SCREEN_NODE:
145 sharedPtr->renderParams_ = std::make_unique<RSScreenRenderParams>(sharedPtr->nodeId_);
146 sharedPtr->uifirstRenderParams_ = std::make_unique<RSScreenRenderParams>(sharedPtr->nodeId_);
147 break;
148 case RSRenderNodeType::EFFECT_NODE:
149 sharedPtr->renderParams_ = std::make_unique<RSEffectRenderParams>(sharedPtr->nodeId_);
150 sharedPtr->uifirstRenderParams_ = std::make_unique<RSEffectRenderParams>(sharedPtr->nodeId_);
151 break;
152 case RSRenderNodeType::ROUND_CORNER_NODE:
153 sharedPtr->renderParams_ = std::make_unique<RSRcdRenderParams>(sharedPtr->nodeId_);
154 sharedPtr->uifirstRenderParams_ = nullptr; // rcd node does not need uifirst params
155 break;
156 case RSRenderNodeType::CANVAS_DRAWING_NODE:
157 sharedPtr->renderParams_ = std::make_unique<RSCanvasDrawingRenderParams>(sharedPtr->nodeId_);
158 sharedPtr->uifirstRenderParams_ = std::make_unique<RSCanvasDrawingRenderParams>(sharedPtr->nodeId_);
159 break;
160 case RSRenderNodeType::LOGICAL_DISPLAY_NODE:
161 sharedPtr->renderParams_ = std::make_unique<RSLogicalDisplayRenderParams>(sharedPtr->nodeId_);
162 sharedPtr->uifirstRenderParams_ = std::make_unique<RSLogicalDisplayRenderParams>(sharedPtr->nodeId_);
163 break;
164 default:
165 sharedPtr->renderParams_ = std::make_unique<RSRenderParams>(sharedPtr->nodeId_);
166 sharedPtr->uifirstRenderParams_ = std::make_unique<RSRenderParams>(sharedPtr->nodeId_);
167 break;
168 }
169 sharedPtr->renderParams_->SetParamsType(RSRenderParamsType::RS_PARAM_OWNED_BY_DRAWABLE);
170 if (sharedPtr->uifirstRenderParams_) {
171 sharedPtr->uifirstRenderParams_->SetParamsType(RSRenderParamsType::RS_PARAM_OWNED_BY_DRAWABLE_UIFIRST);
172 }
173 }
174
OnGenerateShadowDrawable(const std::shared_ptr<const RSRenderNode> & node,const std::shared_ptr<RSRenderNodeDrawableAdapter> & drawable)175 RSRenderNodeDrawableAdapter::SharedPtr RSRenderNodeDrawableAdapter::OnGenerateShadowDrawable(
176 const std::shared_ptr<const RSRenderNode>& node, const std::shared_ptr<RSRenderNodeDrawableAdapter>& drawable)
177 {
178 static std::map<NodeId, RSRenderNodeDrawableAdapter::WeakPtr> shadowDrawableCache;
179 static std::mutex shadowCacheMapMutex;
180 static const auto Destructor = [](RSRenderNodeDrawableAdapter* ptr) {
181 {
182 std::lock_guard<std::mutex> lock(shadowCacheMapMutex);
183 shadowDrawableCache.erase(ptr->nodeId_); // Remove from cache before deleting
184 }
185 RSRenderNodeGC::DrawableDestructor(ptr);
186 };
187
188 if (node == nullptr) {
189 ROSEN_LOGE("RSRenderNodeDrawableAdapter::OnGenerateShadowDrawable, node null");
190 return nullptr;
191 }
192 auto id = node->GetId();
193 // Try to get a cached drawable if it exists.
194 {
195 std::lock_guard<std::mutex> lock(shadowCacheMapMutex);
196 if (const auto cacheIt = shadowDrawableCache.find(id); cacheIt != shadowDrawableCache.end()) {
197 if (const auto ptr = cacheIt->second.lock()) {
198 return ptr;
199 } else {
200 shadowDrawableCache.erase(cacheIt);
201 }
202 }
203 }
204
205 auto ptr = new RSRenderNodeShadowDrawable(node, drawable);
206 auto sharedPtr = std::shared_ptr<RSRenderNodeDrawableAdapter>(ptr, Destructor);
207 {
208 std::lock_guard<std::mutex> lock(shadowCacheMapMutex);
209 shadowDrawableCache.emplace(id, sharedPtr);
210 }
211 return sharedPtr;
212 }
213
DrawRangeImpl(Drawing::Canvas & canvas,const Drawing::Rect & rect,int8_t start,int8_t end) const214 void RSRenderNodeDrawableAdapter::DrawRangeImpl(
215 Drawing::Canvas& canvas, const Drawing::Rect& rect, int8_t start, int8_t end) const
216 {
217 if (drawCmdList_.empty() || start < 0 || end < 0 || start > end) {
218 return;
219 }
220
221 if (static_cast<uint32_t>(end) > drawCmdList_.size()) {
222 ROSEN_LOGE("RSRenderNodeDrawableAdapter::DrawRangeImpl, end is invalid");
223 return;
224 }
225
226 if (UNLIKELY(skipType_ != SkipType::NONE)) {
227 auto skipIndex_ = GetSkipIndex();
228 if (start <= skipIndex_ && end > skipIndex_) {
229 // skip index is in the range
230 for (auto i = start; i < skipIndex_; i++) {
231 drawCmdList_[i](&canvas, &rect);
232 }
233 for (auto i = skipIndex_ + 1; i < end; i++) {
234 drawCmdList_[i](&canvas, &rect);
235 }
236 return;
237 }
238 // skip index is not in the range, fall back to normal drawing
239 }
240
241 for (auto i = start; i < end; i++) {
242 #ifdef RS_ENABLE_PREFETCH
243 int prefetchIndex = i + 2;
244 if (prefetchIndex < end) {
245 __builtin_prefetch(&drawCmdList_[prefetchIndex], 0, 1);
246 }
247 #endif
248 drawCmdList_[i](&canvas, &rect);
249 }
250 }
251
DrawImpl(Drawing::Canvas & canvas,const Drawing::Rect & rect,int8_t index) const252 void RSRenderNodeDrawableAdapter::DrawImpl(Drawing::Canvas& canvas, const Drawing::Rect& rect, int8_t index) const
253 {
254 if (drawCmdList_.empty() || index < 0 || static_cast<uint32_t>(index) >= drawCmdList_.size()) {
255 return;
256 }
257
258 if (UNLIKELY(skipType_ != SkipType::NONE)) {
259 auto skipIndex_ = GetSkipIndex();
260 if (index == skipIndex_) {
261 return;
262 }
263 }
264
265 drawCmdList_[index](&canvas, &rect);
266 }
267
268 #ifdef SUBTREE_PARALLEL_ENABLE
269 // subtree parallel feature Interface
270 // quick draw thread use this Interface to acquire draw state, such as clip .etc
DrawQuickImpl(Drawing::Canvas & canvas,const Drawing::Rect & rect) const271 void RSRenderNodeDrawableAdapter::DrawQuickImpl(
272 Drawing::Canvas& canvas, const Drawing::Rect& rect) const
273 {
274 if (drawCmdList_.empty()) {
275 return;
276 }
277
278 if (drawCmdIndex_.transitionIndex_ != -1) {
279 drawCmdList_[drawCmdIndex_.transitionIndex_](&canvas, &rect);
280 }
281 if (drawCmdIndex_.envForeGroundColorIndex_ != -1) {
282 drawCmdList_[drawCmdIndex_.envForeGroundColorIndex_](&canvas, &rect);
283 }
284
285 // BG_START
286 if (drawCmdIndex_.bgSaveBoundsIndex_ == - 1 ||
287 (drawCmdIndex_.bgSaveBoundsIndex_ != -1 && drawCmdIndex_.bgRestoreBoundsIndex_ == -1)) {
288 if (drawCmdIndex_.clipToBoundsIndex_ != -1) {
289 drawCmdList_[drawCmdIndex_.clipToBoundsIndex_](&canvas, &rect);
290 }
291 if (drawCmdIndex_.backgroudStyleIndex_ != -1) {
292 drawCmdList_[drawCmdIndex_.backgroudStyleIndex_](&canvas, &rect);
293 }
294 }
295
296 if (drawCmdIndex_.envForegroundColorStrategyIndex_ != -1) {
297 drawCmdList_[drawCmdIndex_.envForegroundColorStrategyIndex_](&canvas, &rect);
298 }
299 if (drawCmdIndex_.frameOffsetIndex_ != -1) {
300 drawCmdList_[drawCmdIndex_.frameOffsetIndex_](&canvas, &rect);
301 }
302 if (drawCmdIndex_.clipToFrameIndex_ != -1) {
303 drawCmdList_[drawCmdIndex_.clipToFrameIndex_](&canvas, &rect);
304 }
305 if (drawCmdIndex_.customClipToFrameIndex_ != -1) {
306 drawCmdList_[drawCmdIndex_.customClipToFrameIndex_](&canvas, &rect);
307 }
308
309 if (drawCmdIndex_.contentIndex_ != -1) {
310 drawCmdList_[drawCmdIndex_.contentIndex_](&canvas, &rect);
311 }
312 }
313 #endif
314
DrawBackground(Drawing::Canvas & canvas,const Drawing::Rect & rect) const315 void RSRenderNodeDrawableAdapter::DrawBackground(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
316 {
317 DrawRangeImpl(canvas, rect, 0, drawCmdIndex_.backgroundEndIndex_);
318 }
319
DrawLeashWindowBackground(Drawing::Canvas & canvas,const Drawing::Rect & rect,bool isStencilPixelOcclusionCullingEnabled,int64_t stencilVal) const320 void RSRenderNodeDrawableAdapter::DrawLeashWindowBackground(Drawing::Canvas& canvas, const Drawing::Rect& rect,
321 bool isStencilPixelOcclusionCullingEnabled, int64_t stencilVal) const
322 {
323 if (!isStencilPixelOcclusionCullingEnabled) {
324 DrawRangeImpl(canvas, rect, 0, drawCmdIndex_.backgroundEndIndex_);
325 return;
326 }
327 DrawRangeImpl(canvas, rect, 0, drawCmdIndex_.shadowIndex_);
328 canvas.SetStencilVal(stencilVal);
329 DrawRangeImpl(canvas, rect, drawCmdIndex_.shadowIndex_, drawCmdIndex_.shadowIndex_ + 1);
330 canvas.SetStencilVal(Drawing::Canvas::INVALID_STENCIL_VAL);
331 DrawRangeImpl(canvas, rect, drawCmdIndex_.shadowIndex_ + 1, drawCmdIndex_.backgroundEndIndex_);
332 }
333
DrawContent(Drawing::Canvas & canvas,const Drawing::Rect & rect) const334 void RSRenderNodeDrawableAdapter::DrawContent(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
335 {
336 if (drawCmdList_.empty()) {
337 return;
338 }
339
340 auto index = drawCmdIndex_.contentIndex_;
341 if (index == -1) {
342 return;
343 }
344 drawCmdList_[index](&canvas, &rect);
345 }
346
DrawChildren(Drawing::Canvas & canvas,const Drawing::Rect & rect) const347 void RSRenderNodeDrawableAdapter::DrawChildren(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
348 {
349 if (drawCmdList_.empty()) {
350 return;
351 }
352
353 auto index = drawCmdIndex_.childrenIndex_;
354 if (index == -1) {
355 return;
356 }
357 drawCmdList_[index](&canvas, &rect);
358 }
359
DrawUifirstContentChildren(Drawing::Canvas & canvas,const Drawing::Rect & rect)360 void RSRenderNodeDrawableAdapter::DrawUifirstContentChildren(Drawing::Canvas& canvas, const Drawing::Rect& rect)
361 {
362 RSRenderNodeSingleDrawableLocker singleLocker(this);
363 if (UNLIKELY(!singleLocker.IsLocked())) {
364 singleLocker.DrawableOnDrawMultiAccessEventReport(__func__);
365 RS_LOGE("RSRenderNodeDrawableAdapter::DrawUifirstContentChildren node %{public}" PRIu64 " onDraw!!!", GetId());
366 if (RSSystemProperties::GetSingleDrawableLockerEnabled()) {
367 return;
368 }
369 }
370
371 if (uifirstDrawCmdList_.empty()) {
372 return;
373 }
374
375 const auto& drawCmdList = uifirstDrawCmdList_;
376 auto contentIdx = uifirstDrawCmdIndex_.contentIndex_;
377 auto childrenIdx = uifirstDrawCmdIndex_.childrenIndex_;
378 if (0 <= contentIdx && contentIdx < drawCmdList.size()) {
379 drawCmdList[contentIdx](&canvas, &rect);
380 }
381 if (0 <= childrenIdx && childrenIdx < drawCmdList.size()) {
382 drawCmdList[childrenIdx](&canvas, &rect);
383 }
384 }
385
DrawForeground(Drawing::Canvas & canvas,const Drawing::Rect & rect) const386 void RSRenderNodeDrawableAdapter::DrawForeground(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
387 {
388 DrawRangeImpl(canvas, rect, drawCmdIndex_.foregroundBeginIndex_, drawCmdIndex_.endIndex_);
389 }
390
DrawAll(Drawing::Canvas & canvas,const Drawing::Rect & rect) const391 void RSRenderNodeDrawableAdapter::DrawAll(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
392 {
393 DrawRangeImpl(canvas, rect, 0, drawCmdIndex_.endIndex_);
394 }
395
396 // can only run in sync mode
DumpDrawableTree(int32_t depth,std::string & out,const RSContext & context) const397 void RSRenderNodeDrawableAdapter::DumpDrawableTree(int32_t depth, std::string& out, const RSContext& context) const
398 {
399 // Exceed max depth for dumping drawable tree, refuse to dump and add a warning.
400 // Possible reason: loop in the drawable tree
401 constexpr int32_t MAX_DUMP_DEPTH = 256;
402 if (depth >= MAX_DUMP_DEPTH) {
403 ROSEN_LOGW("RSRenderNodeDrawableAdapter::DumpDrawableTree depth too large, stop dumping. current depth = %d, "
404 "nodeId = %" PRIu64, depth, nodeId_);
405 out += "===== WARNING: exceed max depth for dumping drawable tree =====\n";
406 return;
407 }
408
409 for (int32_t i = 0; i < depth; ++i) {
410 out += " ";
411 }
412 // dump node info/DrawableVec/renderParams etc.
413 auto renderNode = (depth == 0 && nodeId_ == INVALID_NODEID) ? context.GetGlobalRootRenderNode()
414 : context.GetNodeMap().GetRenderNode<RSRenderNode>(nodeId_);
415 if (renderNode == nullptr) {
416 out += "[" + std::to_string(nodeId_) + ": nullptr]\n";
417 return;
418 }
419 RSRenderNode::DumpNodeType(nodeType_, out);
420 out += "[" + std::to_string(nodeId_) + "]";
421 renderNode->DumpSubClassNode(out);
422 out += ", DrawableVec:[" + DumpDrawableVec(renderNode) + "]";
423 if (renderParams_ == nullptr) {
424 out += ", StagingParams null";
425 } else {
426 out += ", " + renderParams_->ToString();
427 }
428
429 if (skipType_ != SkipType::NONE) {
430 out += ", SkipType:" + std::to_string(static_cast<int>(skipType_));
431 out += ", SkipIndex:" + std::to_string(GetSkipIndex());
432 }
433 if (drawSkipType_ != DrawSkipType::NONE) {
434 out += ", DrawSkipType:" + std::to_string(static_cast<int>(drawSkipType_.load()));
435 }
436 out += ", ChildrenIndex:" + std::to_string(drawCmdIndex_.childrenIndex_);
437 out += "\n";
438
439 // Dump children drawable(s)
440 auto childrenDrawable = std::static_pointer_cast<RSChildrenDrawable>(
441 renderNode->drawableVec_[static_cast<int32_t>(RSDrawableSlot::CHILDREN)]);
442 if (childrenDrawable) {
443 const auto& childrenVec = childrenDrawable->needSync_ ? childrenDrawable->stagingChildrenDrawableVec_
444 : childrenDrawable->childrenDrawableVec_;
445 for (const auto& renderNodeDrawable : childrenVec) {
446 renderNodeDrawable->DumpDrawableTree(depth + 1, out, context);
447 }
448 }
449 }
450
451 // can only run in sync mode
DumpDrawableVec(const std::shared_ptr<RSRenderNode> & renderNode) const452 std::string RSRenderNodeDrawableAdapter::DumpDrawableVec(const std::shared_ptr<RSRenderNode>& renderNode) const
453 {
454 if (renderNode == nullptr) {
455 return "";
456 }
457 const auto& drawableVec = renderNode->drawableVec_;
458 std::string str;
459 for (uint8_t i = 0; i < drawableVec.size(); ++i) {
460 if (drawableVec[i]) {
461 str += std::to_string(i) + ", ";
462 }
463 }
464 // str has more than 2 chars
465 if (str.length() > 2) {
466 str.pop_back();
467 str.pop_back();
468 }
469
470 return str;
471 }
472
QuickReject(Drawing::Canvas & canvas,const RectF & localDrawRect)473 bool RSRenderNodeDrawableAdapter::QuickReject(Drawing::Canvas& canvas, const RectF& localDrawRect)
474 {
475 auto paintFilterCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
476 if (paintFilterCanvas->IsDirtyRegionStackEmpty()) {
477 return false;
478 }
479
480 Drawing::Rect dst;
481 canvas.GetTotalMatrix().MapRect(
482 dst, { localDrawRect.GetLeft(), localDrawRect.GetTop(), localDrawRect.GetRight(), localDrawRect.GetBottom() });
483 auto originalCanvas = paintFilterCanvas->GetOriginalCanvas();
484 if (originalCanvas && !paintFilterCanvas->GetOffscreenDataList().empty()) {
485 originalCanvas->GetTotalMatrix().MapRect(dst, dst);
486 }
487 Drawing::Region dstRegion;
488 if (!dstRegion.SetRect(dst.RoundOut()) && !dst.IsEmpty()) {
489 RS_LOGW("invalid dstDrawRect: %{public}s, RoundOut: %{public}s",
490 dst.ToString().c_str(), dst.RoundOut().ToString().c_str());
491 RS_OPTIONAL_TRACE_NAME_FMT("invalid dstDrawRect: %s, RoundOut: %s",
492 dst.ToString().c_str(), dst.RoundOut().ToString().c_str());
493 return false;
494 }
495 return !(paintFilterCanvas->GetCurDirtyRegion().IsIntersects(dstRegion));
496 }
497
CollectInfoForNodeWithoutFilter(Drawing::Canvas & canvas)498 void RSRenderNodeDrawableAdapter::CollectInfoForNodeWithoutFilter(Drawing::Canvas& canvas)
499 {
500 if (drawCmdList_.empty() || curDrawingCacheRoot_ == nullptr) {
501 return;
502 }
503 curDrawingCacheRoot_->withoutFilterMatrixMap_[GetId()] = canvas.GetTotalMatrix();
504 }
505
CollectInfoForUnobscuredUEC(Drawing::Canvas & canvas)506 void RSRenderNodeDrawableAdapter::CollectInfoForUnobscuredUEC(Drawing::Canvas& canvas)
507 {
508 if (!UECChildrenIds_ || UECChildrenIds_->empty()) {
509 return;
510 }
511 for (auto childId : *UECChildrenIds_) {
512 unobscuredUECMatrixMap_[childId] = canvas.GetTotalMatrix();
513 auto drawable = GetDrawableById(childId);
514 if (drawable) {
515 drawable->SetUIExtensionNeedToDraw(true);
516 }
517 }
518 }
519
DrawBackgroundWithoutFilterAndEffect(Drawing::Canvas & canvas,const RSRenderParams & params)520 void RSRenderNodeDrawableAdapter::DrawBackgroundWithoutFilterAndEffect(
521 Drawing::Canvas& canvas, const RSRenderParams& params)
522 {
523 if (uifirstDrawCmdList_.empty()) {
524 return;
525 }
526
527 auto backgroundIndex = drawCmdIndex_.backgroundEndIndex_;
528 auto bounds = params.GetBounds();
529 auto curCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
530 if (!curCanvas) {
531 RS_LOGD("RSRenderNodeDrawableAdapter::DrawBackgroundWithoutFilterAndEffect curCanvas is null");
532 return;
533 }
534 for (auto index = 0; index < backgroundIndex; ++index) {
535 if (index == drawCmdIndex_.shadowIndex_) {
536 if (!params.GetShadowRect().IsEmpty()) {
537 auto shadowRect = params.GetShadowRect();
538 RS_OPTIONAL_TRACE_NAME_FMT("ClipHoleForBlur shadowRect:[%.2f, %.2f, %.2f, %.2f]", shadowRect.GetLeft(),
539 shadowRect.GetTop(), shadowRect.GetWidth(), shadowRect.GetHeight());
540 Drawing::AutoCanvasRestore arc(*curCanvas, true);
541 curCanvas->ResetClip();
542 curCanvas->ClipRect(shadowRect);
543 curCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
544 UpdateFilterInfoForNodeGroup(curCanvas);
545 } else {
546 CollectInfoForNodeWithoutFilter(canvas);
547 drawCmdList_[index](&canvas, &bounds);
548 }
549 continue;
550 }
551 if (index != drawCmdIndex_.useEffectIndex_ || index != drawCmdIndex_.backgroundFilterIndex_) {
552 RS_OPTIONAL_TRACE_NAME_FMT(
553 "ClipHoleForBlur filterRect:[%.2f, %.2f]", bounds.GetWidth(), bounds.GetHeight());
554 Drawing::AutoCanvasRestore arc(*curCanvas, true);
555 curCanvas->ClipRect(bounds, Drawing::ClipOp::INTERSECT, false);
556 curCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
557 UpdateFilterInfoForNodeGroup(curCanvas);
558 } else {
559 drawCmdList_[index](&canvas, &bounds);
560 }
561 }
562 }
563
UpdateFilterInfoForNodeGroup(RSPaintFilterCanvas * curCanvas)564 void RSRenderNodeDrawableAdapter::UpdateFilterInfoForNodeGroup(RSPaintFilterCanvas* curCanvas)
565 {
566 if (curDrawingCacheRoot_ != nullptr) {
567 auto iter = std::find_if(curDrawingCacheRoot_->filterInfoVec_.begin(),
568 curDrawingCacheRoot_->filterInfoVec_.end(),
569 [nodeId = GetId()](const auto& item) -> bool { return item.nodeId_ == nodeId; });
570 if (iter != curDrawingCacheRoot_->filterInfoVec_.end()) {
571 iter->rectVec_.emplace_back(curCanvas->GetDeviceClipBounds());
572 } else {
573 curDrawingCacheRoot_->filterInfoVec_.emplace_back(
574 FilterNodeInfo(GetId(), curCanvas->GetTotalMatrix(), { curCanvas->GetDeviceClipBounds() }));
575 }
576 }
577 }
578
CheckShadowRectAndDrawBackground(Drawing::Canvas & canvas,const RSRenderParams & params)579 void RSRenderNodeDrawableAdapter::CheckShadowRectAndDrawBackground(
580 Drawing::Canvas& canvas, const RSRenderParams& params)
581 {
582 // The shadow without shadowRect has drawn in Nodegroup's cache, so we can't draw it again
583 if (!params.GetShadowRect().IsEmpty()) {
584 DrawBackground(canvas, params.GetBounds());
585 } else {
586 DrawRangeImpl(
587 canvas, params.GetBounds(), drawCmdIndex_.foregroundFilterBeginIndex_, drawCmdIndex_.backgroundEndIndex_);
588 }
589 }
590
DrawBeforeCacheWithForegroundFilter(Drawing::Canvas & canvas,const Drawing::Rect & rect) const591 void RSRenderNodeDrawableAdapter::DrawBeforeCacheWithForegroundFilter(Drawing::Canvas& canvas,
592 const Drawing::Rect& rect) const
593 {
594 DrawRangeImpl(canvas, rect, 0, static_cast<int8_t>(drawCmdIndex_.foregroundFilterBeginIndex_));
595 }
596
DrawCacheWithForegroundFilter(Drawing::Canvas & canvas,const Drawing::Rect & rect) const597 void RSRenderNodeDrawableAdapter::DrawCacheWithForegroundFilter(Drawing::Canvas& canvas,
598 const Drawing::Rect& rect) const
599 {
600 DrawRangeImpl(canvas, rect, drawCmdIndex_.foregroundFilterBeginIndex_,
601 drawCmdIndex_.foregroundFilterEndIndex_);
602 }
603
DrawAfterCacheWithForegroundFilter(Drawing::Canvas & canvas,const Drawing::Rect & rect) const604 void RSRenderNodeDrawableAdapter::DrawAfterCacheWithForegroundFilter(Drawing::Canvas& canvas,
605 const Drawing::Rect& rect) const
606 {
607 DrawRangeImpl(canvas, rect, drawCmdIndex_.foregroundFilterEndIndex_,
608 drawCmdIndex_.endIndex_);
609 }
610
DrawCacheWithProperty(Drawing::Canvas & canvas,const Drawing::Rect & rect) const611 void RSRenderNodeDrawableAdapter::DrawCacheWithProperty(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
612 {
613 DrawRangeImpl(canvas, rect, drawCmdIndex_.renderGroupBeginIndex_,
614 drawCmdIndex_.renderGroupEndIndex_);
615 }
616
DrawBeforeCacheWithProperty(Drawing::Canvas & canvas,const Drawing::Rect & rect) const617 void RSRenderNodeDrawableAdapter::DrawBeforeCacheWithProperty(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
618 {
619 DrawRangeImpl(canvas, rect, 0, static_cast<int8_t>(drawCmdIndex_.renderGroupBeginIndex_));
620 }
621
DrawAfterCacheWithProperty(Drawing::Canvas & canvas,const Drawing::Rect & rect) const622 void RSRenderNodeDrawableAdapter::DrawAfterCacheWithProperty(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
623 {
624 DrawRangeImpl(canvas, rect, drawCmdIndex_.renderGroupEndIndex_,
625 drawCmdIndex_.endIndex_);
626 }
627
HasFilterOrEffect() const628 bool RSRenderNodeDrawableAdapter::HasFilterOrEffect() const
629 {
630 return drawCmdIndex_.shadowIndex_ != -1 || drawCmdIndex_.backgroundFilterIndex_ != -1 ||
631 drawCmdIndex_.useEffectIndex_ != -1;
632 }
633
ClearResource()634 void RSRenderNodeDrawableAdapter::ClearResource()
635 {
636 RS_TRACE_NAME_FMT("ClearResource count drawable %d, cmdList %d",
637 toClearDrawableVec_.size(), toClearCmdListVec_.size());
638 toClearDrawableVec_.clear();
639 toClearCmdListVec_.clear();
640 }
641
AddToClearDrawables(DrawableVec & vec)642 void RSRenderNodeDrawableAdapter::AddToClearDrawables(DrawableVec &vec)
643 {
644 for (auto &drawable: vec) {
645 toClearDrawableVec_.push_back(drawable);
646 }
647 vec.clear();
648 }
649
AddToClearCmdList(CmdListVec & vec)650 void RSRenderNodeDrawableAdapter::AddToClearCmdList(CmdListVec &vec)
651 {
652 for (auto &cmdList: vec) {
653 toClearCmdListVec_.push_back(cmdList);
654 }
655 vec.clear();
656 if (toClearCmdListVec_.size() >= CMD_LIST_COUNT_WARNING_LIMIT) {
657 ROSEN_LOGW("%{public}s, cmdList count(%{public}zu) out of limit", __func__, toClearCmdListVec_.size());
658 }
659 }
660
GetSkipIndex() const661 int8_t RSRenderNodeDrawableAdapter::GetSkipIndex() const
662 {
663 switch (skipType_) {
664 case SkipType::SKIP_BACKGROUND_COLOR:
665 return drawCmdIndex_.backgroundColorIndex_;
666 case SkipType::SKIP_SHADOW:
667 return drawCmdIndex_.shadowIndex_;
668 case SkipType::NONE:
669 default:
670 return -1;
671 }
672 }
673
RemoveDrawableFromCache(const NodeId nodeId)674 void RSRenderNodeDrawableAdapter::RemoveDrawableFromCache(const NodeId nodeId)
675 {
676 std::lock_guard<std::mutex> lock(cacheMapMutex_);
677 RenderNodeDrawableCache_.erase(nodeId);
678 }
679
RegisterClearSurfaceFunc(ClearSurfaceTask task)680 void RSRenderNodeDrawableAdapter::RegisterClearSurfaceFunc(ClearSurfaceTask task)
681 {
682 clearSurfaceTask_ = task;
683 }
684
ResetClearSurfaceFunc()685 void RSRenderNodeDrawableAdapter::ResetClearSurfaceFunc()
686 {
687 clearSurfaceTask_ = nullptr;
688 }
689
TryClearSurfaceOnSync()690 void RSRenderNodeDrawableAdapter::TryClearSurfaceOnSync()
691 {
692 if (!clearSurfaceTask_) {
693 return;
694 }
695 clearSurfaceTask_();
696 }
697
IsFilterCacheValidForOcclusion() const698 bool RSRenderNodeDrawableAdapter::IsFilterCacheValidForOcclusion() const
699 {
700 bool val = false;
701 if (backgroundFilterDrawable_) {
702 val = val || backgroundFilterDrawable_->IsFilterCacheValidForOcclusion();
703 }
704 if (compositingFilterDrawable_) {
705 val = val || compositingFilterDrawable_->IsFilterCacheValidForOcclusion();
706 }
707 return val;
708 }
709
GetFilterCachedRegion() const710 const RectI RSRenderNodeDrawableAdapter::GetFilterCachedRegion() const
711 {
712 RectI rect{0, 0, 0, 0};
713 if (!RSSystemProperties::GetBlurEnabled()) {
714 ROSEN_LOGD("blur is disabled");
715 return rect;
716 }
717
718 if (compositingFilterDrawable_) {
719 return compositingFilterDrawable_->GetFilterCachedRegion();
720 } else if (backgroundFilterDrawable_) {
721 return backgroundFilterDrawable_->GetFilterCachedRegion();
722 } else {
723 return rect;
724 }
725 }
SetSkipCacheLayer(bool hasSkipCacheLayer)726 void RSRenderNodeDrawableAdapter::SetSkipCacheLayer(bool hasSkipCacheLayer)
727 {
728 hasSkipCacheLayer_ = hasSkipCacheLayer;
729 }
730
SetChildInBlackList(bool hasChildInBlackList)731 void RSRenderNodeDrawableAdapter::SetChildInBlackList(bool hasChildInBlackList)
732 {
733 hasChildInBlackList_ = hasChildInBlackList;
734 }
735
ApplyForegroundColorIfNeed(Drawing::Canvas & canvas,const Drawing::Rect & rect) const736 void RSRenderNodeDrawableAdapter::ApplyForegroundColorIfNeed(Drawing::Canvas& canvas, const Drawing::Rect& rect) const
737 {
738 if (drawCmdList_.empty()) {
739 return;
740 }
741 if (drawCmdIndex_.envForeGroundColorIndex_ != -1) {
742 drawCmdList_[drawCmdIndex_.envForeGroundColorIndex_](&canvas, &rect);
743 }
744 }
745
746 // will only called by OnDraw or OnSync
DrawableOnDrawMultiAccessEventReport(const std::string & func) const747 void RSRenderNodeSingleDrawableLocker::DrawableOnDrawMultiAccessEventReport(const std::string& func) const
748 {
749 #ifdef ROSEN_OHOS
750 auto tid = gettid();
751 MultiAccessReportInfo reportInfo;
752 if (drawable_) {
753 reportInfo.drawableNotNull = true;
754 reportInfo.nodeId = drawable_->GetId();
755 reportInfo.nodeType = drawable_->GetNodeType();
756 const auto& params = drawable_->GetRenderParams();
757 if (params) {
758 reportInfo.paramNotNull = true;
759 reportInfo.uifirstRootNodeId = params->GetUifirstRootNodeId();
760 reportInfo.firstLevelNodeId = params->GetFirstLevelNodeId();
761 }
762 }
763
764 auto task = [tid, func, reportInfo]() {
765 RS_TRACE_NAME_FMT("DrawableOnDrawMultiAccessEventReport HiSysEventWrite nodeId:%" PRIu64, reportInfo.nodeId);
766 std::ostringstream oss;
767 oss << "func:" << func << ",";
768 oss << "drawable:" << reportInfo.drawableNotNull << ",";
769 oss << "param:" << reportInfo.paramNotNull << ",";
770 if (reportInfo.drawableNotNull) {
771 oss << "id:" << reportInfo.nodeId << ",";
772 oss << "type:" << static_cast<int>(reportInfo.nodeType) << ",";
773 }
774 if (reportInfo.paramNotNull) {
775 oss << "URN:" << reportInfo.uifirstRootNodeId << ",";
776 oss << "FLN:" << reportInfo.firstLevelNodeId << ",";
777 }
778 oss << "tid:" << tid;
779 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::GRAPHIC, "RENDER_DRAWABLE_MULTI_ACCESS",
780 OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "MULTI_ACCESS_MSG", oss.str());
781 };
782 RSBackgroundThread::Instance().PostTask(task);
783 #endif
784 }
785 } // namespace OHOS::Rosen::DrawableV2
786