• 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_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