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