• 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.h"
17 
18 #include "common/rs_common_def.h"
19 #include "common/rs_optional_trace.h"
20 #include "display_engine/rs_luminance_control.h"
21 #include "gfx/performance/rs_perfmonitor_reporter.h"
22 #include "pipeline/render_thread/rs_uni_render_thread.h"
23 #include "pipeline/render_thread/rs_uni_render_util.h"
24 #include "pipeline/rs_paint_filter_canvas.h"
25 #include "pipeline/rs_task_dispatcher.h"
26 #include "platform/common/rs_log.h"
27 #include "rs_trace.h"
28 #include "system/rs_system_parameters.h"
29 #include "pipeline/main_thread/rs_main_thread.h"
30 #include "include/gpu/vk/GrVulkanTrackerInterface.h"
31 
32 namespace OHOS::Rosen::DrawableV2 {
33 #ifdef RS_ENABLE_VK
34 #include "include/gpu/GrBackendSurface.h"
35 
36 #include "platform/ohos/backend/native_buffer_utils.h"
37 #include "platform/ohos/backend/rs_vulkan_context.h"
38 #endif
39 RSRenderNodeDrawable::Registrar RSRenderNodeDrawable::instance_;
40 thread_local bool RSRenderNodeDrawable::drawBlurForCache_ = false;
41 thread_local bool RSRenderNodeDrawable::isOpDropped_ = true;
42 thread_local bool RSRenderNodeDrawable::isOffScreenWithClipHole_ = false;
43 
44 namespace {
45 constexpr int32_t DRAWING_CACHE_MAX_UPDATE_TIME = 3;
46 constexpr float CACHE_FILL_ALPHA = 0.2f;
47 constexpr float CACHE_UPDATE_FILL_ALPHA = 0.8f;
48 constexpr int TRACE_LEVEL_PRINT_NODEID = 6;
49 }
RSRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)50 RSRenderNodeDrawable::RSRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
51     : RSRenderNodeDrawableAdapter(std::move(node))
52 {
53     auto task = [this] { this->RSRenderNodeDrawable::ClearCachedSurface(); };
54     RegisterClearSurfaceFunc(task);
55 }
56 
~RSRenderNodeDrawable()57 RSRenderNodeDrawable::~RSRenderNodeDrawable()
58 {
59     ClearCachedSurface();
60     ResetClearSurfaceFunc();
61 }
62 
OnGenerate(std::shared_ptr<const RSRenderNode> node)63 RSRenderNodeDrawable::Ptr RSRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
64 {
65     return new RSRenderNodeDrawable(std::move(node));
66 }
67 
Draw(Drawing::Canvas & canvas)68 void RSRenderNodeDrawable::Draw(Drawing::Canvas& canvas)
69 {
70     if (UNLIKELY(RSUniRenderThread::IsInCaptureProcess())) {
71         OnCapture(canvas);
72     } else {
73         OnDraw(canvas);
74     }
75 }
76 
77 /*
78  * This function will be called recursively many times, and the logic should be as concise as possible.
79  */
OnDraw(Drawing::Canvas & canvas)80 void RSRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
81 {
82     RECORD_GPU_RESOURCE_DRAWABLE_CALLER(GetId())
83     RSRenderNodeDrawable::TotalProcessedNodeCountInc();
84     Drawing::Rect bounds = GetRenderParams() ? GetRenderParams()->GetFrameRect() : Drawing::Rect(0, 0, 0, 0);
85 
86     DrawBackground(canvas, bounds);
87 
88     CollectInfoForUnobscuredUEC(canvas);
89 
90     DrawContent(canvas, bounds);
91 
92     DrawChildren(canvas, bounds);
93 
94     DrawForeground(canvas, bounds);
95 }
96 
97 /*
98  * This function will be called recursively many times, and the logic should be as concise as possible.
99  */
OnCapture(Drawing::Canvas & canvas)100 void RSRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
101 {
102     RSRenderNodeDrawable::OnDraw(canvas);
103 }
104 
GenerateCacheIfNeed(Drawing::Canvas & canvas,RSRenderParams & params)105 void RSRenderNodeDrawable::GenerateCacheIfNeed(Drawing::Canvas& canvas, RSRenderParams& params)
106 {
107     // check if drawing cache enabled
108     if (params.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE) {
109         RS_OPTIONAL_TRACE_NAME_FMT("RSCanvasRenderNodeDrawable::OnDraw id:%llu cacheType:%d cacheChanged:%d"
110                                    " size:[%.2f, %.2f] ChildHasVisibleFilter:%d ChildHasVisibleEffect:%d"
111                                    " shadowRect:[%.2f, %.2f, %.2f, %.2f] HasFilterOrEffect:%d",
112             params.GetId(), params.GetDrawingCacheType(), params.GetDrawingCacheChanged(), params.GetCacheSize().x_,
113             params.GetCacheSize().y_, params.ChildHasVisibleFilter(), params.ChildHasVisibleEffect(),
114             params.GetShadowRect().GetLeft(), params.GetShadowRect().GetTop(), params.GetShadowRect().GetWidth(),
115             params.GetShadowRect().GetHeight(), HasFilterOrEffect());
116     }
117 
118     RS_LOGI_IF(DEBUG_NODE, "RSRenderNodeDrawable::GenerateCacheCondition drawingCacheType:%{public}d"
119         " RSFreezeFlag:%{public}d OpincGetCachedMark:%{public}d", params.GetDrawingCacheType(),
120         params.GetRSFreezeFlag(), OpincGetCachedMark());
121     if (params.GetRSFreezeFlag()) {
122         RS_OPTIONAL_TRACE_NAME_FMT("RSCanvasRenderNodeDrawable::GenerateCacheIfNeed id:%llu"
123                                    " GetRSFreezeFlag:%d hasFilter:%d",
124             params.GetId(), params.GetRSFreezeFlag(), params.ChildHasVisibleFilter());
125     }
126 
127     // check drawing cache type (disabled: clear cache)
128     if ((params.GetDrawingCacheType() == RSDrawingCacheType::DISABLED_CACHE && !OpincGetCachedMark()) &&
129         !params.GetRSFreezeFlag()) {
130         ClearCachedSurface();
131         ClearDrawingCacheDataMap();
132         ClearDrawingCacheContiUpdateTimeMap();
133         return;
134     }
135 
136     {
137         std::scoped_lock<std::recursive_mutex> cacheLock(cacheMutex_);
138         if (cachedSurface_ == nullptr) {
139             // Remove node id in update time map to avoid update time exceeds DRAWING_CACHE_MAX_UPDATE_TIME
140             // (If cache disabled for node not on the tree, we clear cache in OnSync func, but we can't clear node
141             // id in drawingCacheUpdateTimeMap_ [drawable will not be visited in RT].
142             // If this node is marked node group by arkui again, we should first clear update time here, otherwise
143             // update time will accumulate.)
144             ClearDrawingCacheDataMap();
145             ClearDrawingCacheContiUpdateTimeMap();
146         }
147     }
148     // generate(first time)/update cache(cache changed) [TARGET -> DISABLED if >= MAX UPDATE TIME]
149     int32_t updateTimes = 0;
150     bool needUpdateCache = CheckIfNeedUpdateCache(params, updateTimes);
151     params.SetNeedUpdateCache(needUpdateCache);
152     int32_t continuousUpdateTimes = 0;
153     {
154         std::lock_guard<std::mutex> lock(drawingCacheContiUpdateTimeMapMutex_);
155         if (drawingCacheContinuousUpdateTimeMap_.count(nodeId_) > 0) {
156             continuousUpdateTimes = drawingCacheContinuousUpdateTimeMap_.at(nodeId_);
157         }
158     }
159     if (needUpdateCache && params.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE &&
160         continuousUpdateTimes > DRAWING_CACHE_MAX_UPDATE_TIME) {
161         RS_LOGD("RSRenderNodeDrawable::GenerateCacheCondition totalUpdateTimes:%{public}d "
162                 "continuousUpdateTimes:%{public}d needUpdateCache:%{public}d",
163                 updateTimes, continuousUpdateTimes, needUpdateCache);
164         RS_TRACE_NAME_FMT("DisableCache by continuous update time > 3, id:%" PRIu64 "", params.GetId());
165         params.SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
166         ClearCachedSurface();
167     }
168     // reset drawing cache changed false for render param if drawable is visited this frame
169     // if this drawble is skipped due to occlusion skip of app surface node, this flag should be kept for next frame
170     params.SetDrawingCacheChanged(false, true);
171     bool hasFilter = params.ChildHasVisibleFilter() || params.ChildHasVisibleEffect();
172     if ((params.GetDrawingCacheType() == RSDrawingCacheType::DISABLED_CACHE || (!needUpdateCache && !hasFilter))
173         && !OpincGetCachedMark() && !params.GetRSFreezeFlag()) {
174         return;
175     }
176 
177     if (needUpdateCache) {
178         filterInfoVec_.clear();
179     }
180     bool isForegroundFilterCache = params.GetForegroundFilterCache() != nullptr;
181     // in case of no filter
182     if (needUpdateCache && (!hasFilter || isForegroundFilterCache || params.GetRSFreezeFlag())) {
183         RS_TRACE_NAME_FMT("UpdateCacheSurface id:%" PRIu64 ", isForegroundFilter:%d", nodeId_, isForegroundFilterCache);
184         RSRenderNodeDrawableAdapter* root = curDrawingCacheRoot_;
185         curDrawingCacheRoot_ = this;
186         hasSkipCacheLayer_ = false;
187         UpdateCacheSurface(canvas, params);
188         curDrawingCacheRoot_ = root;
189         return;
190     }
191 
192     // in case of with filter
193     auto curCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
194     if (needUpdateCache) {
195         // 1. update cache without filer/shadow/effect & clip hole
196         auto canvasType = curCanvas->GetCacheType();
197         // set canvas type as OFFSCREEN to not draw filter/shadow/filter
198         curCanvas->SetCacheType(RSPaintFilterCanvas::CacheType::OFFSCREEN);
199         bool isOffScreenWithClipHole = isOffScreenWithClipHole_;
200         isOffScreenWithClipHole_ = true;
201         RS_TRACE_NAME_FMT("UpdateCacheSurface with filter id:%" PRIu64 "", nodeId_);
202         RSRenderNodeDrawableAdapter* root = curDrawingCacheRoot_;
203         curDrawingCacheRoot_ = this;
204         hasSkipCacheLayer_ = false;
205         UpdateCacheSurface(canvas, params);
206         // if this NodeGroup contains other nodeGroup with filter, we should reset the isOffScreenWithClipHole_
207         isOffScreenWithClipHole_ = isOffScreenWithClipHole;
208         curCanvas->SetCacheType(canvasType);
209         curDrawingCacheRoot_ = root;
210     }
211 }
212 
TraverseSubTreeAndDrawFilterWithClip(Drawing::Canvas & canvas,const RSRenderParams & params)213 void RSRenderNodeDrawable::TraverseSubTreeAndDrawFilterWithClip(Drawing::Canvas& canvas, const RSRenderParams& params)
214 {
215     if (filterInfoVec_.empty()) {
216         return;
217     }
218     RSRenderNodeDrawableAdapter* root = curDrawingCacheRoot_;
219     curDrawingCacheRoot_ = this;
220     filterNodeSize_ = filterInfoVec_.size();
221     Drawing::AutoCanvasRestore arc(canvas, true);
222     bool isOpDropped = isOpDropped_;
223     isOpDropped_ = false;
224     drawBlurForCache_ = true; // may use in uifirst subthread
225     auto drawableCacheType = GetCacheType();
226     SetCacheType(DrawableCacheType::NONE);
227     RS_TRACE_NAME_FMT("DrawBlurForCache id:%" PRIu64 "", nodeId_);
228 
229     DrawBackground(canvas, params.GetBounds());
230     Drawing::Region filterRegion;
231     for (auto& item : filterInfoVec_) {
232         for (auto& rect: item.rectVec_) {
233             Drawing::Region region;
234             region.SetRect(rect);
235             filterRegion.Op(region, Drawing::RegionOp::UNION);
236         }
237     }
238     Drawing::Path filetrPath;
239     filterRegion.GetBoundaryPath(&filetrPath);
240     canvas.ClipPath(filetrPath);
241     DrawContent(canvas, params.GetFrameRect());
242     DrawChildren(canvas, params.GetBounds());
243     curDrawingCacheRoot_->SetLastDrawnFilterNodeId(0);
244 
245     SetCacheType(drawableCacheType);
246     isOpDropped_ = isOpDropped;
247     drawBlurForCache_ = false;
248     curDrawingCacheRoot_ = root;
249 }
250 
CheckCacheTypeAndDraw(Drawing::Canvas & canvas,const RSRenderParams & params,bool isInCapture)251 void RSRenderNodeDrawable::CheckCacheTypeAndDraw(
252     Drawing::Canvas& canvas, const RSRenderParams& params, bool isInCapture)
253 {
254     RS_OPTIONAL_TRACE_BEGIN_LEVEL(TRACE_LEVEL_PRINT_NODEID, "CheckCacheTypeAndDraw nodeId[%llu]", nodeId_);
255     bool hasFilter = params.ChildHasVisibleFilter() || params.ChildHasVisibleEffect();
256     RS_LOGI_IF(DEBUG_NODE,
257         "RSRenderNodeDrawable::CheckCacheTAD hasFilter:%{public}d drawingCacheType:%{public}d",
258         hasFilter, params.GetDrawingCacheType());
259     auto originalCacheType = GetCacheType();
260     // can not draw cache because skipCacheLayer in capture process, such as security layers...
261     if (GetCacheType() != DrawableCacheType::NONE && hasSkipCacheLayer_ && isInCapture) {
262         SetCacheType(DrawableCacheType::NONE);
263     }
264     if (hasFilter && params.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE &&
265         params.GetForegroundFilterCache() == nullptr && GetCacheType() != DrawableCacheType::NONE) {
266         // traverse children to draw filter/shadow/effect
267         TraverseSubTreeAndDrawFilterWithClip(canvas, params);
268     }
269     // if children don't have any filter or effect, stop traversing
270     if (params.GetForegroundFilterCache() == nullptr && drawBlurForCache_ && curDrawingCacheRoot_ &&
271         curDrawingCacheRoot_->GetFilterNodeSize() == 0) {
272         RS_OPTIONAL_TRACE_NAME_FMT("CheckCacheTypeAndDraw id:%llu child without filter, skip", nodeId_);
273         RS_OPTIONAL_TRACE_END_LEVEL(TRACE_LEVEL_PRINT_NODEID);
274         return;
275     }
276     // in case of generating cache with filter in offscreen, clip hole for filter/shadow but drawing others
277     if (isOffScreenWithClipHole_) {
278         if (HasFilterOrEffect() && params.GetForegroundFilterCache() == nullptr) {
279             // clip hole for filter/shadow
280             DrawBackgroundWithoutFilterAndEffect(canvas, params);
281             DrawContent(canvas, params.GetFrameRect());
282             DrawChildren(canvas, params.GetBounds());
283             DrawForeground(canvas, params.GetBounds());
284             RS_OPTIONAL_TRACE_END_LEVEL(TRACE_LEVEL_PRINT_NODEID);
285             return;
286         }
287         CollectInfoForNodeWithoutFilter(canvas);
288     }
289     RS_LOGI_IF(DEBUG_NODE, "RSRenderNodeDrawable::CheckCacheTAD GetCacheType is %{public}hu", GetCacheType());
290     switch (GetCacheType()) {
291         case DrawableCacheType::NONE: {
292             DrawWithoutNodeGroupCache(canvas, params, originalCacheType);
293             break;
294         }
295         case DrawableCacheType::CONTENT: {
296             DrawWithNodeGroupCache(canvas, params);
297             break;
298         }
299         default:
300             break;
301     }
302     RS_OPTIONAL_TRACE_END_LEVEL(TRACE_LEVEL_PRINT_NODEID);
303 }
304 
DrawWithoutNodeGroupCache(Drawing::Canvas & canvas,const RSRenderParams & params,DrawableCacheType originalCacheType)305 void RSRenderNodeDrawable::DrawWithoutNodeGroupCache(
306     Drawing::Canvas& canvas, const RSRenderParams& params, DrawableCacheType originalCacheType)
307 {
308     if (drawBlurForCache_ && curDrawingCacheRoot_) {
309         auto& filterInfoVec = curDrawingCacheRoot_->GetfilterInfoVec();
310         auto begin = std::find_if(filterInfoVec.begin(), filterInfoVec.end(),
311             [nodeId = GetId()](const auto& item) -> bool { return item.nodeId_ == nodeId; });
312         if (begin == filterInfoVec.end()) {
313             CheckRegionAndDrawWithoutFilter(filterInfoVec, canvas, params);
314         } else {
315             CheckRegionAndDrawWithFilter(begin, filterInfoVec, canvas, params);
316         }
317     } else {
318         RSRenderNodeDrawable::OnDraw(canvas);
319     }
320     SetCacheType(originalCacheType);
321 }
322 
DrawWithNodeGroupCache(Drawing::Canvas & canvas,const RSRenderParams & params)323 void RSRenderNodeDrawable::DrawWithNodeGroupCache(Drawing::Canvas& canvas, const RSRenderParams& params)
324 {
325 #ifdef RS_ENABLE_PREFETCH
326             __builtin_prefetch(&cachedImage_, 0, 1);
327 #endif
328     RS_OPTIONAL_TRACE_NAME_FMT("DrawCachedImage id:%llu", nodeId_);
329     RS_LOGD("RSRenderNodeDrawable::CheckCacheTAD drawingCacheIncludeProperty is %{public}d",
330         params.GetDrawingCacheIncludeProperty());
331     if (hasSkipCacheLayer_ && curDrawingCacheRoot_) {
332         curDrawingCacheRoot_->SetSkipCacheLayer(true);
333     }
334     auto curCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
335     if (!curCanvas) {
336         RS_LOGD("RSRenderNodeDrawable::DrawWithNodeGroupCache curCanvas is null");
337         return;
338     }
339     if (LIKELY(!params.GetDrawingCacheIncludeProperty())) {
340         DrawBackground(canvas, params.GetBounds());
341         DrawCachedImage(*curCanvas, params.GetCacheSize());
342         DrawForeground(canvas, params.GetBounds());
343     } else if (params.GetForegroundFilterCache() != nullptr) {
344         DrawBeforeCacheWithForegroundFilter(canvas, params.GetBounds());
345         DrawCachedImage(*curCanvas, params.GetCacheSize(), params.GetForegroundFilterCache());
346         DrawAfterCacheWithForegroundFilter(canvas, params.GetBounds());
347     } else {
348         DrawBeforeCacheWithProperty(canvas, params.GetBounds());
349         DrawCachedImage(*curCanvas, params.GetCacheSize());
350         DrawAfterCacheWithProperty(canvas, params.GetBounds());
351     }
352     ClearDrawingCacheContiUpdateTimeMap();
353     UpdateCacheInfoForDfx(canvas, params.GetBounds(), params.GetId());
354 }
355 
CheckRegionAndDrawWithoutFilter(const std::vector<FilterNodeInfo> & filterInfoVec,Drawing::Canvas & canvas,const RSRenderParams & params)356 void RSRenderNodeDrawable::CheckRegionAndDrawWithoutFilter(
357     const std::vector<FilterNodeInfo>& filterInfoVec, Drawing::Canvas& canvas, const RSRenderParams& params)
358 {
359     if (!curDrawingCacheRoot_) {
360         return;
361     }
362     auto& withoutFilterMatrixMap = curDrawingCacheRoot_->GetWithoutFilterMatrixMap();
363     if (withoutFilterMatrixMap.find(GetId()) == withoutFilterMatrixMap.end()) {
364         RS_LOGE("RSRenderNodeDrawable::CheckRegionAndDrawWithoutFilter can not find matrix of cached node in "
365                 "withoutFilterMatrixMap, id:%{public}" PRIu64 "", GetId());
366         return;
367     }
368     auto matrix = withoutFilterMatrixMap.at(GetId());
369     Drawing::Rect dst;
370     matrix.MapRect(dst, params.GetBounds());
371     Drawing::RectI dstRect(static_cast<int>(dst.GetLeft()), static_cast<int>(dst.GetTop()),
372         static_cast<int>(dst.GetLeft() + dst.GetWidth()), static_cast<int>(dst.GetTop() + dst.GetHeight()));
373     auto filterBegin = std::find_if(filterInfoVec.begin(), filterInfoVec.end(),
374         [nodeId = curDrawingCacheRoot_->GetLastDrawnFilterNodeId()](
375             const auto& item) -> bool { return item.nodeId_ == nodeId; });
376     if (filterBegin == filterInfoVec.end()) {
377         filterBegin = filterInfoVec.begin();
378     } else {
379         filterBegin++; // check isIntersect with undrawn filters
380     }
381     if (IsIntersectedWithFilter(filterBegin, filterInfoVec, dstRect)) {
382         RSRenderNodeDrawable::OnDraw(canvas);
383     } else {
384         DrawChildren(canvas, params.GetBounds());
385     }
386 }
387 
CheckRegionAndDrawWithFilter(std::vector<FilterNodeInfo>::const_iterator & begin,const std::vector<FilterNodeInfo> & filterInfoVec,Drawing::Canvas & canvas,const RSRenderParams & params)388 void RSRenderNodeDrawable::CheckRegionAndDrawWithFilter(std::vector<FilterNodeInfo>::const_iterator& begin,
389     const std::vector<FilterNodeInfo>& filterInfoVec, Drawing::Canvas& canvas, const RSRenderParams& params)
390 {
391     if (!curDrawingCacheRoot_ || begin == filterInfoVec.end()) {
392         return;
393     }
394     curDrawingCacheRoot_->SetLastDrawnFilterNodeId(GetId());
395     CheckShadowRectAndDrawBackground(canvas, params);
396     curDrawingCacheRoot_->ReduceFilterNodeSize();
397     Drawing::Rect dst;
398     auto matrix = begin->matrix_;
399     matrix.MapRect(dst, params.GetBounds());
400     Drawing::RectI dstRect(static_cast<int>(dst.GetLeft()), static_cast<int>(dst.GetTop()),
401         static_cast<int>(dst.GetLeft() + dst.GetWidth()), static_cast<int>(dst.GetTop() + dst.GetHeight()));
402     begin++; // check isIntersect with undrawn filters
403     if (IsIntersectedWithFilter(begin, filterInfoVec, dstRect)) {
404         DrawContent(canvas, params.GetFrameRect());
405         DrawChildren(canvas, params.GetBounds());
406         // DrawChildren may reduce filterNodeSize, if still have filter in other subtree of
407         // curDrawingCacheRoot_, we should draw foreground here
408         if (curDrawingCacheRoot_->GetFilterNodeSize() > 0) {
409             auto filterBegin = std::find_if(filterInfoVec.begin(), filterInfoVec.end(),
410                 [nodeId = curDrawingCacheRoot_->GetLastDrawnFilterNodeId()](
411                     const auto& item) -> bool { return item.nodeId_ == nodeId; });
412             if (filterBegin != filterInfoVec.end()) {
413                 filterBegin++; // check isIntersect with undrawn filters
414             }
415             if (IsIntersectedWithFilter(filterBegin, filterInfoVec, dstRect)) {
416                 DrawForeground(canvas, params.GetBounds());
417             }
418         }
419     }
420 }
421 
IsIntersectedWithFilter(std::vector<FilterNodeInfo>::const_iterator & begin,const std::vector<FilterNodeInfo> & filterInfoVec,Drawing::RectI & dstRect)422 bool RSRenderNodeDrawable::IsIntersectedWithFilter(std::vector<FilterNodeInfo>::const_iterator& begin,
423     const std::vector<FilterNodeInfo>& filterInfoVec, Drawing::RectI& dstRect)
424 {
425     bool isIntersected = false;
426     for (auto iter = begin; iter != filterInfoVec.end() && !isIntersected; ++iter) {
427         for (auto rect : iter->rectVec_) {
428             if (rect.Intersect(dstRect)) {
429                 isIntersected = true;
430                 break;
431             }
432         }
433     }
434     return isIntersected;
435 }
436 
ClearDrawingCacheDataMap()437 void RSRenderNodeDrawable::ClearDrawingCacheDataMap()
438 {
439     {
440         std::lock_guard<std::mutex> lock(drawingCacheMapMutex_);
441         drawingCacheUpdateTimeMap_.erase(nodeId_);
442     }
443     // clear Rendergroup dfx data map
444     RSPerfMonitorReporter::GetInstance().ClearRendergroupDataMap(nodeId_);
445 }
446 
ClearDrawingCacheContiUpdateTimeMap()447 void RSRenderNodeDrawable::ClearDrawingCacheContiUpdateTimeMap()
448 {
449     std::lock_guard<std::mutex> lock(drawingCacheContiUpdateTimeMapMutex_);
450     drawingCacheContinuousUpdateTimeMap_.erase(nodeId_);
451 }
452 
UpdateCacheInfoForDfx(Drawing::Canvas & canvas,const Drawing::Rect & rect,NodeId id)453 void RSRenderNodeDrawable::UpdateCacheInfoForDfx(Drawing::Canvas& canvas, const Drawing::Rect& rect, NodeId id)
454 {
455     if (!isDrawingCacheDfxEnabled_) {
456         return;
457     }
458     Drawing::Rect dst;
459     canvas.GetTotalMatrix().MapRect(dst, rect);
460     RectI dfxRect(static_cast<int>(dst.GetLeft()), static_cast<int>(dst.GetTop()), static_cast<int>(dst.GetWidth()),
461         static_cast<int>(dst.GetHeight()));
462     int32_t updateTimes = 0;
463     {
464         std::lock_guard<std::mutex> lock(drawingCacheMapMutex_);
465         if (drawingCacheUpdateTimeMap_.count(nodeId_) > 0) {
466             updateTimes = drawingCacheUpdateTimeMap_.at(nodeId_);
467         }
468     }
469     {
470         std::lock_guard<std::mutex> lock(drawingCacheInfoMutex_);
471         drawingCacheInfos_[id] = std::make_pair(dfxRect, updateTimes);
472     }
473 }
474 
InitDfxForCacheInfo()475 void RSRenderNodeDrawable::InitDfxForCacheInfo()
476 {
477     isDrawingCacheEnabled_ = RSSystemParameters::GetDrawingCacheEnabled();
478     auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
479     if (LIKELY(uniParam)) {
480         isDrawingCacheDfxEnabled_ = uniParam->IsDrawingCacheDfxEnabled();
481     }
482     if (isDrawingCacheDfxEnabled_) {
483         std::lock_guard<std::mutex> lock(drawingCacheInfoMutex_);
484         drawingCacheInfos_.clear();
485         cacheUpdatedNodeMap_.clear();
486     }
487 
488 #ifdef DDGR_ENABLE_FEATURE_OPINC
489     autoCacheDrawingEnable_ = RSSystemProperties::GetAutoCacheDebugEnabled() && autoCacheEnable_;
490     autoCacheRenderNodeInfos_.clear();
491     opincRootTotalCount_ = 0;
492     isOpincDropNodeExt_ = true;
493 #endif
494 }
495 
DrawDfxForCacheInfo(RSPaintFilterCanvas & canvas,const std::unique_ptr<RSRenderParams> & params)496 void RSRenderNodeDrawable::DrawDfxForCacheInfo(
497     RSPaintFilterCanvas& canvas, const std::unique_ptr<RSRenderParams>& params)
498 {
499     if (isDrawingCacheEnabled_ && isDrawingCacheDfxEnabled_) {
500         auto displayParams = static_cast<RSDisplayRenderParams*>(params.get());
501         if (displayParams && displayParams->GetNeedOffscreen()) {
502             canvas.ConcatMatrix(displayParams->GetMatrix());
503         }
504         std::lock_guard<std::mutex> lock(drawingCacheInfoMutex_);
505         for (const auto& [id, cacheInfo] : drawingCacheInfos_) {
506             std::string extraInfo = ", updateTimes:" + std::to_string(cacheInfo.second);
507             bool cacheUpdated = cacheUpdatedNodeMap_.count(id) > 0;
508             auto color = cacheUpdated ? Drawing::Color::COLOR_RED : Drawing::Color::COLOR_BLUE;
509             float alpha = cacheUpdated ? CACHE_UPDATE_FILL_ALPHA : CACHE_FILL_ALPHA;
510             RSUniRenderUtil::DrawRectForDfx(canvas, cacheInfo.first, color, alpha, extraInfo);
511         }
512     }
513 
514     if (autoCacheDrawingEnable_ && !isDrawingCacheDfxEnabled_) {
515         for (const auto& info : autoCacheRenderNodeInfos_) {
516             RSUniRenderUtil::DrawRectForDfx(
517                 canvas, info.first, Drawing::Color::COLOR_BLUE, 0.2f, info.second); // alpha 0.2 by default
518         }
519     }
520 }
521 
SetCacheType(DrawableCacheType cacheType)522 void RSRenderNodeDrawable::SetCacheType(DrawableCacheType cacheType)
523 {
524     cacheType_ = cacheType;
525 }
526 
GetCacheType() const527 DrawableCacheType RSRenderNodeDrawable::GetCacheType() const
528 {
529     return cacheType_;
530 }
531 
GetCachedSurface(pid_t threadId) const532 std::shared_ptr<Drawing::Surface> RSRenderNodeDrawable::GetCachedSurface(pid_t threadId) const
533 {
534     std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
535     return threadId == cacheThreadId_ ? cachedSurface_ : nullptr;
536 }
537 
InitCachedSurface(Drawing::GPUContext * gpuContext,const Vector2f & cacheSize,pid_t threadId,bool isNeedFP16,GraphicColorGamut colorGamut)538 void RSRenderNodeDrawable::InitCachedSurface(Drawing::GPUContext* gpuContext, const Vector2f& cacheSize,
539     pid_t threadId, bool isNeedFP16, GraphicColorGamut colorGamut)
540 {
541     std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
542 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
543     if (gpuContext == nullptr) {
544         return;
545     }
546     ClearCachedSurface();
547     cacheThreadId_ = threadId;
548     int32_t width = 0;
549     int32_t height = 0;
550     if (IsComputeDrawAreaSucc()) {
551         auto& unionRect = GetOpListUnionArea();
552         width = static_cast<int32_t>(unionRect.GetWidth());
553         height = static_cast<int32_t>(unionRect.GetHeight());
554     } else {
555         width = static_cast<int32_t>(cacheSize.x_);
556         height = static_cast<int32_t>(cacheSize.y_);
557     }
558 
559 #ifdef RS_ENABLE_GL
560     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
561         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
562         Drawing::ImageInfo info = Drawing::ImageInfo::MakeN32Premul(width, height);
563         cachedSurface_ = Drawing::Surface::MakeRenderTarget(gpuContext, true, info);
564     }
565 #endif
566 #ifdef RS_ENABLE_VK
567     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
568         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
569         auto colorType = Drawing::ColorType::COLORTYPE_RGBA_8888;
570         VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
571         if (isNeedFP16) {
572             colorType = Drawing::ColorType::COLORTYPE_RGBA_F16;
573             format = VK_FORMAT_R16G16B16A16_SFLOAT;
574         }
575         cachedBackendTexture_ = RSUniRenderUtil::MakeBackendTexture(width, height, format);
576         auto vkTextureInfo = cachedBackendTexture_.GetTextureInfo().GetVKTextureInfo();
577         if (!cachedBackendTexture_.IsValid() || !vkTextureInfo) {
578             return;
579         }
580         vulkanCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(
581             RsVulkanContext::GetSingleton(), vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
582         auto colorSpace = RSBaseRenderEngine::ConvertColorGamutToDrawingColorSpace(colorGamut);
583         cachedSurface_ = Drawing::Surface::MakeFromBackendTexture(gpuContext, cachedBackendTexture_.GetTextureInfo(),
584             Drawing::TextureOrigin::BOTTOM_LEFT, 1, colorType, colorSpace,
585             NativeBufferUtils::DeleteVkImage, vulkanCleanupHelper_);
586     }
587 #endif
588 #else
589     cachedSurface_ =
590         Drawing::Surface::MakeRasterN32Premul(static_cast<int32_t>(cacheSize.x_), static_cast<int32_t>(cacheSize.y_));
591 #endif
592 }
593 
NeedInitCachedSurface(const Vector2f & newSize)594 bool RSRenderNodeDrawable::NeedInitCachedSurface(const Vector2f& newSize)
595 {
596     auto width = static_cast<int32_t>(newSize.x_);
597     auto height = static_cast<int32_t>(newSize.y_);
598     if (IsComputeDrawAreaSucc()) {
599         auto& unionRect = GetOpListUnionArea();
600         width = static_cast<int32_t>(unionRect.GetWidth());
601         height = static_cast<int32_t>(unionRect.GetHeight());
602     }
603     std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
604     if (cachedSurface_ == nullptr) {
605         return true;
606     }
607     auto cacheCanvas = cachedSurface_->GetCanvas();
608     if (cacheCanvas == nullptr) {
609         return true;
610     }
611     return cacheCanvas->GetWidth() != width || cacheCanvas->GetHeight() != height;
612 }
613 
614 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
615 struct SharedTextureContext {
SharedTextureContextOHOS::Rosen::DrawableV2::SharedTextureContext616     SharedTextureContext(std::shared_ptr<Drawing::Image> sharedImage)
617         : sharedImage_(std::move(sharedImage)) {}
618 
619 private:
620     std::shared_ptr<Drawing::Image> sharedImage_;
621 };
622 
DeleteSharedTextureContext(void * context)623 static void DeleteSharedTextureContext(void* context)
624 {
625     SharedTextureContext* cleanupHelper = static_cast<SharedTextureContext*>(context);
626     if (cleanupHelper != nullptr) {
627         delete cleanupHelper;
628     }
629 }
630 #endif
631 
GetCachedImage(RSPaintFilterCanvas & canvas)632 std::shared_ptr<Drawing::Image> RSRenderNodeDrawable::GetCachedImage(RSPaintFilterCanvas& canvas)
633 {
634     std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
635     if (!cachedSurface_ || !cachedImage_) {
636         RS_LOGE("RSRenderNodeDrawable::GetCachedImage invalid cachedSurface_");
637         return nullptr;
638     }
639 
640     // do not use threadId to judge image grcontext change
641     if (cachedImage_->IsValid(canvas.GetGPUContext().get())) {
642         return cachedImage_;
643     }
644 #ifdef RS_ENABLE_GL
645     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
646         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
647         if (canvas.GetGPUContext() == nullptr) {
648             return nullptr;
649         }
650         Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
651         Drawing::BitmapFormat info = Drawing::BitmapFormat{cachedImage_->GetColorType(), cachedImage_->GetAlphaType()};
652         SharedTextureContext* sharedContext = new SharedTextureContext(cachedImage_); // will move image
653         cachedImage_ = std::make_shared<Drawing::Image>();
654         bool ret = cachedImage_->BuildFromTexture(*canvas.GetGPUContext(), cachedBackendTexture_.GetTextureInfo(),
655             origin, info, nullptr, DeleteSharedTextureContext, sharedContext);
656         if (!ret) {
657             RS_LOGE("RSRenderNodeDrawable::GetCachedImage image BuildFromTexture failed");
658             return nullptr;
659         }
660     }
661 #endif
662 
663 #ifdef RS_ENABLE_VK
664     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
665         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
666         if (vulkanCleanupHelper_ == nullptr || canvas.GetGPUContext() == nullptr) {
667             return nullptr;
668         }
669         Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
670         Drawing::BitmapFormat info = Drawing::BitmapFormat{cachedImage_->GetColorType(), cachedImage_->GetAlphaType()};
671         cachedImage_ = std::make_shared<Drawing::Image>();
672         bool ret = cachedImage_->BuildFromTexture(*canvas.GetGPUContext(), cachedBackendTexture_.GetTextureInfo(),
673             origin, info, nullptr, NativeBufferUtils::DeleteVkImage, vulkanCleanupHelper_->Ref());
674         if (!ret) {
675             RS_LOGE("RSRenderNodeDrawable::GetCachedImage image BuildFromTexture failed");
676             return nullptr;
677         }
678     }
679 #endif
680     return cachedImage_;
681 }
682 
SetCacheImageByCapture(std::shared_ptr<Drawing::Image> image)683 void RSRenderNodeDrawable::SetCacheImageByCapture(std::shared_ptr<Drawing::Image> image)
684 {
685     std::lock_guard<std::mutex> lock(freezeByCaptureMutex_);
686     cachedImageByCapture_ = image;
687 }
688 
GetCacheImageByCapture() const689 std::shared_ptr<Drawing::Image> RSRenderNodeDrawable::GetCacheImageByCapture() const
690 {
691     std::lock_guard<std::mutex> lock(freezeByCaptureMutex_);
692     return cachedImageByCapture_;
693 }
694 
DrawCachedImage(RSPaintFilterCanvas & canvas,const Vector2f & boundSize,const std::shared_ptr<RSFilter> & rsFilter)695 void RSRenderNodeDrawable::DrawCachedImage(RSPaintFilterCanvas& canvas, const Vector2f& boundSize,
696     const std::shared_ptr<RSFilter>& rsFilter)
697 {
698     auto cacheImage = GetCachedImage(canvas);
699     std::lock_guard<std::mutex> lock(freezeByCaptureMutex_);
700     if (cachedImageByCapture_) {
701         // node has freezed, and to draw surfaceCapture image
702         cacheImage = cachedImageByCapture_;
703     }
704     if (cacheImage == nullptr) {
705         RS_LOGE("RSRenderNodeDrawable::DrawCachedImage image null");
706         return;
707     }
708     if (RSSystemProperties::GetRecordingEnabled()) {
709         if (cacheImage->IsTextureBacked()) {
710             RS_LOGI("RSRenderNodeDrawable::DrawCachedImage convert cacheImage from texture to raster image");
711             cacheImage = cacheImage->MakeRasterImage();
712         }
713     }
714     if (cacheImage == nullptr || cacheImage->GetWidth() == 0 || cacheImage->GetHeight() == 0) {
715         RS_LOGE("RSRenderNodeDrawable::DrawCachedImage invalid cacheimage");
716         return;
717     }
718     float scaleX = boundSize.x_ / static_cast<float>(cacheImage->GetWidth());
719     float scaleY = boundSize.y_ / static_cast<float>(cacheImage->GetHeight());
720     if (IsComputeDrawAreaSucc()) {
721         auto& unionRect = GetOpListUnionArea();
722         scaleX = unionRect.GetWidth() / static_cast<float>(cacheImage->GetWidth());
723         scaleY = unionRect.GetHeight() / static_cast<float>(cacheImage->GetHeight());
724     }
725 
726     Drawing::AutoCanvasRestore arc(canvas, true);
727     canvas.Scale(scaleX, scaleY);
728     Drawing::Brush brush;
729     canvas.AttachBrush(brush);
730     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
731     if (IsComputeDrawAreaSucc() && DrawAutoCache(canvas, *cacheImage,
732         samplingOptions, Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT)) {
733         canvas.DetachBrush();
734         DrawAutoCacheDfx(canvas, autoCacheRenderNodeInfos_);
735         return;
736     }
737     if (rsFilter != nullptr) {
738         RS_OPTIONAL_TRACE_NAME_FMT("RSRenderNodeDrawable::DrawCachedImage image width: %d, height: %d, %s",
739             cacheImage->GetWidth(), cacheImage->GetHeight(), rsFilter->GetDescription().c_str());
740         auto foregroundFilter = std::static_pointer_cast<RSDrawingFilterOriginal>(rsFilter);
741         foregroundFilter->DrawImageRect(canvas, cacheImage, Drawing::Rect(0, 0, cacheImage->GetWidth(),
742         cacheImage->GetHeight()), Drawing::Rect(0, 0, cacheImage->GetWidth(), cacheImage->GetHeight()));
743      } else {
744          canvas.DrawImage(*cacheImage, 0.0, 0.0, samplingOptions);
745      }
746     canvas.DetachBrush();
747 }
748 
ClearCachedSurface()749 void RSRenderNodeDrawable::ClearCachedSurface()
750 {
751     SetCacheType(DrawableCacheType::NONE);
752     std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
753     if (cachedSurface_ == nullptr) {
754         return;
755     }
756 
757     auto clearTask = [surface = cachedSurface_]() mutable { surface = nullptr; };
758     cachedSurface_ = nullptr;
759     cachedImage_ = nullptr;
760     RSTaskDispatcher::GetInstance().PostTask(cacheThreadId_.load(), clearTask);
761 
762 #ifdef RS_ENABLE_VK
763     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
764         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
765         vulkanCleanupHelper_ = nullptr;
766     }
767 #endif
768 }
769 
CheckIfNeedUpdateCache(RSRenderParams & params,int32_t & updateTimes)770 bool RSRenderNodeDrawable::CheckIfNeedUpdateCache(RSRenderParams& params, int32_t& updateTimes)
771 {
772     {
773         std::lock_guard<std::mutex> lock(drawingCacheMapMutex_);
774         if (drawingCacheUpdateTimeMap_.count(nodeId_) > 0) {
775             updateTimes = drawingCacheUpdateTimeMap_.at(nodeId_);
776         }
777     }
778 
779     RS_OPTIONAL_TRACE_NAME_FMT("CheckUpdateCache id:%llu updateTimes:%d type:%d cacheChanged:%d size:[%.2f, %.2f]",
780         nodeId_, updateTimes, params.GetDrawingCacheType(), params.GetDrawingCacheChanged(),
781         params.GetCacheSize().x_, params.GetCacheSize().y_);
782 
783     // node freeze
784     if (params.GetRSFreezeFlag()) {
785         return updateTimes == 0;
786     }
787 
788     if ((params.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE && params.NeedFilter() &&
789         params.GetDrawingCacheIncludeProperty()) || ROSEN_LE(params.GetCacheSize().x_, 0.f) ||
790         ROSEN_LE(params.GetCacheSize().y_, 0.f)) {
791         params.SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
792         ClearCachedSurface();
793         return false;
794     }
795 
796     if (NeedInitCachedSurface(params.GetCacheSize())) {
797         ClearCachedSurface();
798         return true;
799     }
800 
801     if (updateTimes == 0 || params.GetDrawingCacheChanged()) {
802         return true;
803     }
804     return false;
805 }
806 
UpdateCacheSurface(Drawing::Canvas & canvas,const RSRenderParams & params)807 void RSRenderNodeDrawable::UpdateCacheSurface(Drawing::Canvas& canvas, const RSRenderParams& params)
808 {
809     auto startTime = RSPerfMonitorReporter::GetInstance().StartRendergroupMonitor();
810     auto curCanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
811     pid_t threadId = gettid();
812     bool isHdrOn = false; // todo: temporary set false, fix in future
813     bool isScRGBEnable = RSSystemParameters::IsNeedScRGBForP3(curCanvas->GetTargetColorGamut()) &&
814         RSMainThread::Instance()->IsUIFirstOn();
815     bool isNeedFP16 = isHdrOn || isScRGBEnable;
816     auto cacheSurface = GetCachedSurface(threadId);
817     if (cacheSurface == nullptr) {
818         RS_TRACE_NAME_FMT("InitCachedSurface size:[%.2f, %.2f]", params.GetCacheSize().x_, params.GetCacheSize().y_);
819         InitCachedSurface(curCanvas->GetGPUContext().get(), params.GetCacheSize(), threadId, isNeedFP16,
820             curCanvas->GetTargetColorGamut());
821         cacheSurface = GetCachedSurface(threadId);
822         if (cacheSurface == nullptr) {
823             return;
824         }
825     }
826 
827     auto cacheCanvas = std::make_shared<RSPaintFilterCanvas>(cacheSurface.get());
828     if (!cacheCanvas) {
829         return;
830     }
831 
832     // copy current canvas properties into cacheCanvas
833     const auto& renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
834     if (renderEngine) {
835         cacheCanvas->SetHighContrast(renderEngine->IsHighContrastEnabled());
836     }
837     cacheCanvas->CopyConfigurationToOffscreenCanvas(*curCanvas);
838     cacheCanvas->CopyHDRConfiguration(*curCanvas);
839     // Using filter cache in multi-thread environment may cause GPU memory leak or invalid textures
840     // [PLANNNING] disable it in sub-thread.
841 
842     // When drawing CacheSurface, all child node should be drawn.
843     // So set isOpDropped_ = false here.
844     bool isOpDropped = isOpDropped_;
845     isOpDropped_ = false;
846     Drawing::AutoCanvasRestore arc(*cacheCanvas, true);
847     cacheCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
848 
849     OpincCanvasUnionTranslate(*cacheCanvas);
850     if (params.GetRSFreezeFlag()) {
851         cacheCanvas->SetDisableFilterCache(true);
852     }
853     // draw content + children
854     auto bounds = params.GetBounds();
855     ApplyForegroundColorIfNeed(*cacheCanvas, bounds);
856     if (LIKELY(!params.GetDrawingCacheIncludeProperty())) {
857         DrawContent(*cacheCanvas, params.GetFrameRect());
858         DrawChildren(*cacheCanvas, bounds);
859     } else if (params.GetForegroundFilterCache() != nullptr) {
860         DrawCacheWithForegroundFilter(*cacheCanvas, bounds);
861     } else {
862         DrawCacheWithProperty(*cacheCanvas, bounds);
863     }
864     ResumeOpincCanvasTranslate(*cacheCanvas);
865 
866     isOpDropped_ = isOpDropped;
867 
868     // get image & backend
869     {
870         std::scoped_lock<std::recursive_mutex> lock(cacheMutex_);
871         cachedImage_ = cacheSurface->GetImageSnapshot();
872         if (cachedImage_) {
873             SetCacheType(DrawableCacheType::CONTENT);
874         }
875     }
876 
877 #if RS_ENABLE_GL
878     // vk backend has been created when surface init.
879     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
880         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
881         cachedBackendTexture_ = cacheSurface->GetBackendTexture();
882     }
883 #endif
884     // update cache updateTimes
885     {
886         std::lock_guard<std::mutex> lock(drawingCacheMapMutex_);
887         drawingCacheUpdateTimeMap_[nodeId_]++;
888     }
889     {
890         std::lock_guard<std::mutex> lock(drawingCacheContiUpdateTimeMapMutex_);
891         drawingCacheContinuousUpdateTimeMap_[nodeId_]++;
892     }
893     {
894         std::lock_guard<std::mutex> lock(drawingCacheInfoMutex_);
895         cacheUpdatedNodeMap_.emplace(params.GetId(), true);
896     }
897 
898     RSPerfMonitorReporter::GetInstance().EndRendergroupMonitor(startTime, nodeId_,
899         drawingCacheUpdateTimeMap_[nodeId_]);
900 }
901 
GetTotalProcessedNodeCount()902 int RSRenderNodeDrawable::GetTotalProcessedNodeCount()
903 {
904     return totalProcessedNodeCount_;
905 }
906 
TotalProcessedNodeCountInc()907 void RSRenderNodeDrawable::TotalProcessedNodeCountInc()
908 {
909     ++totalProcessedNodeCount_;
910 }
911 
ClearTotalProcessedNodeCount()912 void RSRenderNodeDrawable::ClearTotalProcessedNodeCount()
913 {
914     totalProcessedNodeCount_ = 0;
915 }
916 
GetProcessedNodeCount()917 int RSRenderNodeDrawable::GetProcessedNodeCount()
918 {
919     return processedNodeCount_;
920 }
921 
ProcessedNodeCountInc()922 void RSRenderNodeDrawable::ProcessedNodeCountInc()
923 {
924     ++processedNodeCount_;
925 }
926 
ClearProcessedNodeCount()927 void RSRenderNodeDrawable::ClearProcessedNodeCount()
928 {
929     processedNodeCount_ = 0;
930 }
931 } // namespace OHOS::Rosen::DrawableV2
932