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