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