1 /*
2 * Copyright (c) 2023 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 "render/rs_filter_cache_manager.h"
17 #include "rs_trace.h"
18 #include "common/rs_common_def.h"
19 #include "common/rs_occlusion_region.h"
20 #include "render/rs_filter.h"
21 #include "utils/rect.h"
22
23 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
24 #ifdef USE_M133_SKIA
25 #include "include/gpu/ganesh/GrBackendSurface.h"
26 #else
27 #include "include/gpu/GrBackendSurface.h"
28 #endif
29 #include "src/image/SkImage_Base.h"
30
31 #include "common/rs_optional_trace.h"
32 #include "hpae_base/rs_hpae_base_data.h"
33 #include "hpae_base/rs_hpae_filter_cache_manager.h"
34 #include "platform/common/rs_log.h"
35 #include "platform/common/rs_system_properties.h"
36 #include "render/rs_drawing_filter.h"
37 #include "render/rs_high_performance_visual_engine.h"
38 #include "render/rs_render_magnifier_filter.h"
39 #include "render/rs_skia_filter.h"
40 #include "drawable/rs_property_drawable_utils.h"
41 #include "memory/rs_tag_tracker.h"
42
43 namespace OHOS {
44 namespace Rosen {
45
46 constexpr int AIBAR_CACHE_UPDATE_INTERVAL = 5;
47 constexpr int ROTATION_CACHE_UPDATE_INTERVAL = 1;
48
49 bool RSFilterCacheManager::isCCMFilterCacheEnable_ = true;
50 bool RSFilterCacheManager::isCCMEffectMergeEnable_ = true;
51
RSFilterCacheManager()52 RSFilterCacheManager::RSFilterCacheManager()
53 {
54 hpaeCacheManager_ = std::make_shared<RSHpaeFilterCacheManager>();
55 }
56
GetCacheState() const57 std::string RSFilterCacheManager::GetCacheState() const
58 {
59 if (cachedFilteredSnapshot_ != nullptr) {
60 return "Filtered image found in cache. Reusing cached result." +
61 cachedFilteredSnapshot_->GetInfo();
62 } else if (cachedSnapshot_ != nullptr) {
63 return "Snapshot found in cache. Generating filtered image using cached data." +
64 cachedSnapshot_->GetInfo();
65 } else {
66 return "No valid cache found.";
67 }
68 }
69
UpdateCacheStateWithFilterHash(const std::shared_ptr<RSFilter> & filter)70 void RSFilterCacheManager::UpdateCacheStateWithFilterHash(const std::shared_ptr<RSFilter>& filter)
71 {
72 RS_OPTIONAL_TRACE_FUNC();
73 auto filterHash = filter->Hash();
74 if (cachedFilteredSnapshot_ == nullptr || cachedFilterHash_ == filterHash) {
75 return;
76 }
77 // filter changed, clear the filtered snapshot.
78 ROSEN_LOGD("RSFilterCacheManager::UpdateCacheStateWithFilterHash Cache expired. Reason: Cached filtered hash "
79 "%{public}X does not match new hash %{public}X.",
80 cachedFilterHash_, filterHash);
81 cachedFilteredSnapshot_.reset();
82 }
83
UpdateCacheStateWithFilterRegion()84 void RSFilterCacheManager::UpdateCacheStateWithFilterRegion()
85 {
86 if (!IsCacheValid()) {
87 return;
88 }
89 RS_OPTIONAL_TRACE_FUNC();
90
91 ROSEN_LOGD("RSFilterCacheManager::UpdateCacheStateWithFilterRegion Cache expired. Reason: Filter region is not "
92 "within the cached region.");
93 InvalidateFilterCache();
94 }
95
UpdateCacheStateWithDirtyRegion()96 void RSFilterCacheManager::UpdateCacheStateWithDirtyRegion()
97 {
98 if (!IsCacheValid()) {
99 return;
100 }
101 RS_OPTIONAL_TRACE_FUNC();
102 if (cacheUpdateInterval_ > 0) {
103 ROSEN_LOGD("RSFilterCacheManager::UpdateCacheStateWithDirtyRegion Delaying cache "
104 "invalidation for %{public}d frames.",
105 cacheUpdateInterval_);
106 pendingPurge_ = true;
107 } else {
108 InvalidateFilterCache();
109 }
110 }
111
UpdateCacheStateWithDirtyRegion(const RSDirtyRegionManager & dirtyManager)112 bool RSFilterCacheManager::UpdateCacheStateWithDirtyRegion(const RSDirtyRegionManager& dirtyManager)
113 {
114 if (!IsCacheValid()) {
115 return false;
116 }
117 RS_OPTIONAL_TRACE_FUNC();
118 auto& cachedImageRect = GetCachedImageRegion();
119 if (dirtyManager.currentFrameDirtyRegion_.Intersect(cachedImageRect) ||
120 std::any_of(dirtyManager.visitedDirtyRegions_.begin(), dirtyManager.visitedDirtyRegions_.end(),
121 [&cachedImageRect](const RectI& rect) { return rect.Intersect(cachedImageRect); })) {
122 // The underlying image is affected by the dirty region, determine if the cache should be invalidated by cache
123 // age. [PLANNING]: also take into account the filter radius / cache size / percentage of intersected area.
124 if (cacheUpdateInterval_ > 0) {
125 ROSEN_LOGD("RSFilterCacheManager::UpdateCacheStateWithDirtyRegion Delaying cache "
126 "invalidation for %{public}d frames.",
127 cacheUpdateInterval_);
128 pendingPurge_ = true;
129 } else {
130 InvalidateFilterCache();
131 }
132 return false;
133 }
134 if (pendingPurge_) {
135 ROSEN_LOGD("RSFilterCacheManager::UpdateCacheStateWithDirtyRegion MergeDirtyRect at %{public}d frames",
136 cacheUpdateInterval_);
137 InvalidateFilterCache();
138 return true;
139 } else {
140 return false;
141 }
142 }
143
CanDiscardCanvas(RSPaintFilterCanvas & canvas,const Drawing::RectI & dstRect) const144 bool RSFilterCacheManager::CanDiscardCanvas(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect) const
145 {
146 /* Check that drawing will be in full canvas and no issues with clip */
147 return (RSSystemProperties::GetDiscardCanvasBeforeFilterEnabled() && canvas.IsClipRect() &&
148 canvas.GetDeviceClipBounds() == dstRect && canvas.GetWidth() == dstRect.GetWidth() &&
149 canvas.GetHeight() == dstRect.GetHeight() && dstRect.GetLeft() == 0 && dstRect.GetTop() == 0);
150 }
151
DrawFilterWithoutSnapshot(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSDrawingFilter> & filter,const Drawing::RectI & src,const Drawing::RectI & dst,bool shouldClearFilteredCache)152 bool RSFilterCacheManager::DrawFilterWithoutSnapshot(RSPaintFilterCanvas& canvas,
153 const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& src, const Drawing::RectI& dst,
154 bool shouldClearFilteredCache)
155 {
156 if (!RSSystemProperties::GetDrawFilterWithoutSnapshotEnabled() || !shouldClearFilteredCache ||
157 cachedSnapshot_ == nullptr || cachedSnapshot_->cachedImage_ == nullptr) {
158 return false;
159 }
160 RS_OPTIONAL_TRACE_FUNC();
161
162 /* Reuse code from RSPropertiesPainter::DrawFilter() when cache manager is not available */
163 auto clipIBounds = dst;
164 Drawing::AutoCanvasRestore acr(canvas, true);
165 canvas.ResetMatrix();
166 // Only draw within the visible rect.
167 ClipVisibleRect(canvas);
168 Drawing::Rect srcRect = Drawing::Rect(0, 0, cachedSnapshot_->cachedImage_->GetWidth(),
169 cachedSnapshot_->cachedImage_->GetHeight());
170 Drawing::Rect dstRect = clipIBounds;
171 RS_OPTIONAL_TRACE_NAME_FMT("DrawFilterWithoutSnapshot srcRect:%s, dstRect:%s",
172 srcRect.ToString().c_str(), dstRect.ToString().c_str());
173 ROSEN_LOGD("DrawFilterWithoutSnapshot srcRect:%{public}s, dstRect:%{public}s",
174 srcRect.ToString().c_str(), dstRect.ToString().c_str());
175 bool discardCanvas = CanDiscardCanvas(canvas, dst);
176 filter->DrawImageRect(canvas, cachedSnapshot_->cachedImage_, srcRect, dstRect, { discardCanvas, false });
177 filter->PostProcess(canvas);
178 cachedFilterHash_ = filter->Hash();
179 return true;
180 }
181
DrawFilterUsingHpae(RSPaintFilterCanvas & paintFilterCanvas,const std::shared_ptr<RSFilter> & filter,const std::shared_ptr<RSHpaeFilterCacheManager> & hpaeCacheManager,NodeId nodeId)182 bool RSFilterCacheManager::DrawFilterUsingHpae(RSPaintFilterCanvas& paintFilterCanvas,
183 const std::shared_ptr<RSFilter>& filter,
184 const std::shared_ptr<RSHpaeFilterCacheManager>& hpaeCacheManager, NodeId nodeId)
185 {
186 if (!hpaeCacheManager) {
187 return false;
188 }
189 if (nodeId != RSHpaeBaseData::GetInstance().GetBlurNodeId()) {
190 return false;
191 }
192 hpaeCacheManager->ResetFilterCache(GetCachedSnapshot(),
193 GetCachedFilteredSnapshot(), GetSnapshotRegion());
194 if (0 == hpaeCacheManager->DrawFilter(paintFilterCanvas, filter, ClearCacheAfterDrawing())) {
195 ResetFilterCache(hpaeCacheManager->GetCachedSnapshot(),
196 hpaeCacheManager->GetCachedFilteredSnapshot(), hpaeCacheManager->GetSnapshotRegion(), true);
197 RSHpaeBaseData::GetInstance().SetBlurContentChanged(hpaeCacheManager->BlurContentChanged());
198 return true;
199 } else {
200 hpaeCacheManager->InvalidateFilterCache(FilterCacheType::BOTH);
201 }
202
203 return false;
204 }
205
DrawFilter(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSDrawingFilter> & filter,NodeId nodeId,bool manuallyHandleFilterCache,bool shouldClearFilteredCache,const std::optional<Drawing::RectI> & srcRect,const std::optional<Drawing::RectI> & dstRect)206 void RSFilterCacheManager::DrawFilter(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
207 NodeId nodeId, bool manuallyHandleFilterCache, bool shouldClearFilteredCache,
208 const std::optional<Drawing::RectI>& srcRect,
209 const std::optional<Drawing::RectI>& dstRect)
210 {
211 takeNewSnapshot_ = false;
212 RS_OPTIONAL_TRACE_FUNC();
213 if (nodeId !=0 && DrawFilterUsingHpae(canvas, filter, hpaeCacheManager_, nodeId)) {
214 return;
215 }
216
217 if (canvas.GetDeviceClipBounds().IsEmpty()) {
218 return;
219 }
220 const auto& [src, dst] = ValidateParams(canvas, srcRect, dstRect);
221 if (src.IsEmpty() || dst.IsEmpty()) {
222 return;
223 }
224
225 RS_TRACE_NAME_FMT("RSFilterCacheManager::DrawFilter status: %s", GetCacheState().c_str());
226 #ifdef RS_ENABLE_GPU
227 RSTagTracker tagTracker(canvas.GetGPUContext(), RSTagTracker::SOURCETYPE::SOURCE_FILTERCACHEENABLEVMA);
228 #endif
229 if (!IsCacheValid()) {
230 TakeSnapshot(canvas, filter, src);
231 }
232 if (cachedFilteredSnapshot_ == nullptr || cachedFilteredSnapshot_->cachedImage_ == nullptr) {
233 if (manuallyHandleFilterCache ? DrawFilterWithoutSnapshot(canvas, filter, src, dst, shouldClearFilteredCache)
234 :DrawFilterWithoutSnapshot(canvas, filter, src, dst, renderClearFilteredCacheAfterDrawing_)) {
235 return;
236 } else {
237 GenerateFilteredSnapshot(canvas, filter, dst);
238 }
239 }
240 DrawCachedFilteredSnapshot(canvas, dst, filter);
241 }
242
GeneratedCachedEffectData(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSDrawingFilter> & filter,const std::optional<Drawing::RectI> & srcRect,const std::optional<Drawing::RectI> & dstRect)243 const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> RSFilterCacheManager::GeneratedCachedEffectData(
244 RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
245 const std::optional<Drawing::RectI>& srcRect, const std::optional<Drawing::RectI>& dstRect)
246 {
247 takeNewSnapshot_ = false;
248 RS_OPTIONAL_TRACE_FUNC();
249 if (canvas.GetDeviceClipBounds().IsEmpty()) {
250 return nullptr;
251 }
252 const auto& [src, dst] = ValidateParams(canvas, srcRect, dstRect);
253 if (src.IsEmpty() || dst.IsEmpty()) {
254 return nullptr;
255 }
256 RS_TRACE_NAME_FMT("RSFilterCacheManager::GeneratedCachedEffectData status: %s", GetCacheState().c_str());
257 if (!IsCacheValid()) {
258 TakeSnapshot(canvas, filter, src);
259 } else if (snapshotNeedUpdate_) {
260 if (canvas.GetSurface()) {
261 RS_TRACE_NAME_FMT("ForceTakeSnapshot: %s", src.ToString().c_str());
262 auto snapshot = canvas.GetSurface()->GetImageSnapshot(src, false);
263 filter->PreProcess(snapshot);
264 cachedSnapshot_ = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(snapshot), src);
265 cachedFilteredSnapshot_.reset();
266 }
267 }
268 snapshotNeedUpdate_ = RSHpaeBaseData::GetInstance().GetBlurContentChanged() &&
269 (!forceUseCache_)&&(filterType_ != RSFilter::AIBAR);
270
271 if (cachedFilteredSnapshot_ == nullptr || cachedFilteredSnapshot_->cachedImage_ == nullptr) {
272 GenerateFilteredSnapshot(canvas, filter, dst);
273 }
274 // Keep a reference to the cached image, since CompactCache may invalidate it.
275 auto cachedFilteredSnapshot = cachedFilteredSnapshot_;
276 return cachedFilteredSnapshot;
277 }
278
TakeSnapshot(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSDrawingFilter> & filter,const Drawing::RectI & srcRect)279 void RSFilterCacheManager::TakeSnapshot(
280 RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& srcRect)
281 {
282 auto drawingSurface = canvas.GetSurface();
283 if (drawingSurface == nullptr) {
284 return;
285 }
286 RS_OPTIONAL_TRACE_FUNC();
287
288 // shrink the srcRect by 1px to avoid edge artifacts.
289 Drawing::RectI snapshotIBounds = srcRect;
290
291 auto magnifierShaderFilter = filter->GetShaderFilterWithType(RSUIFilterType::MAGNIFIER);
292 if (magnifierShaderFilter != nullptr) {
293 auto tmpFilter = std::static_pointer_cast<RSMagnifierShaderFilter>(magnifierShaderFilter);
294 snapshotIBounds.Offset(tmpFilter->GetMagnifierOffsetX(), tmpFilter->GetMagnifierOffsetY());
295 }
296 std::shared_ptr<Drawing::Image> snapshot;
297 auto aibarShaderFilter = filter->GetShaderFilterWithType(RSUIFilterType::AIBAR);
298 if ((aibarShaderFilter != nullptr) && (HveFilter::GetHveFilter().GetSurfaceNodeSize() > 0)) {
299 snapshot = HveFilter::GetHveFilter().SampleLayer(canvas, srcRect);
300 } else {
301 RS_TRACE_NAME_FMT("RSFilterCacheManager::TakeSnapshot surface wh: [%d, %d], snapshotIBounds: %s",
302 drawingSurface->Width(), drawingSurface->Height(), snapshotIBounds.ToString().c_str());
303 snapshot = drawingSurface->GetImageSnapshot(snapshotIBounds, false);
304 }
305 if (snapshot == nullptr) {
306 ROSEN_LOGD("RSFilterCacheManager::TakeSnapshot failed to make an image snapshot.");
307 return;
308 }
309 if (RSSystemProperties::GetImageGpuResourceCacheEnable(snapshot->GetWidth(), snapshot->GetHeight())) {
310 ROSEN_LOGD("TakeSnapshot cache image resource(width:%{public}d, height:%{public}d).", snapshot->GetWidth(),
311 snapshot->GetHeight());
312 snapshot->HintCacheGpuResource();
313 }
314 filter->PreProcess(snapshot);
315
316 // Update the cache state.
317 takeNewSnapshot_ = true;
318 snapshotRegion_ = RectI(srcRect.GetLeft(), srcRect.GetTop(), srcRect.GetWidth(), srcRect.GetHeight());
319 cachedSnapshot_ = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(snapshot), snapshotIBounds);
320 cachedFilterHash_ = 0;
321 }
322
GenerateFilteredSnapshot(RSPaintFilterCanvas & canvas,const std::shared_ptr<RSDrawingFilter> & filter,const Drawing::RectI & dstRect)323 void RSFilterCacheManager::GenerateFilteredSnapshot(
324 RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& dstRect)
325 {
326 auto surface = canvas.GetSurface();
327 if (surface == nullptr || cachedSnapshot_ == nullptr || cachedSnapshot_->cachedImage_ == nullptr) {
328 return;
329 }
330 // The cache type has been validated, so filterRegion_ and cachedImage_ should be valid. There is no need to check
331 // them again.
332 RS_OPTIONAL_TRACE_FUNC();
333 ROSEN_LOGD("RSFilterCacheManager::GenerateFilteredSnapshot");
334 // Create an offscreen canvas with the same size as the filter region.
335 auto offscreenRect = dstRect;
336 auto offscreenSurface = surface->MakeSurface(offscreenRect.GetWidth(), offscreenRect.GetHeight());
337 if (offscreenSurface == nullptr) {
338 RS_LOGD("RSFilterCacheManager::GenerateFilteredSnapshot offscreenSurface is nullptr");
339 return;
340 }
341 RSPaintFilterCanvas offscreenCanvas(offscreenSurface.get());
342
343 // Src rect and dst rect, with origin at (0, 0).
344 auto src = Drawing::Rect(0, 0, cachedSnapshot_->cachedRect_.GetWidth(), cachedSnapshot_->cachedRect_.GetHeight());
345 auto dst = Drawing::Rect(0, 0, offscreenRect.GetWidth(), offscreenRect.GetHeight());
346
347 // Draw the cached snapshot on the offscreen canvas, apply the filter, and post-process.
348 filter->DrawImageRect(offscreenCanvas, cachedSnapshot_->cachedImage_, src, dst, { false, true });
349 filter->PostProcess(offscreenCanvas);
350
351 // Update the cache state with the filtered snapshot.
352 auto filteredSnapshot = offscreenSurface->GetImageSnapshot();
353 if (filteredSnapshot == nullptr) {
354 ROSEN_LOGE("RSFilterCacheManager::GenerateFilteredSnapshot failed to get filteredSnapshot.");
355 return;
356 }
357 if (RSSystemProperties::GetImageGpuResourceCacheEnable(filteredSnapshot->GetWidth(),
358 filteredSnapshot->GetHeight())) {
359 ROSEN_LOGD("GenerateFilteredSnapshot cache image resource(width:%{public}d, height:%{public}d).",
360 filteredSnapshot->GetWidth(), filteredSnapshot->GetHeight());
361 filteredSnapshot->HintCacheGpuResource();
362 }
363 if (RSSystemProperties::GetRecordingEnabled()) {
364 if (filteredSnapshot->IsTextureBacked()) {
365 RS_LOGI("RSFilterCacheManager::GenerateFilteredSnapshot cachedImage from texture to raster image");
366 filteredSnapshot = filteredSnapshot->MakeRasterImage();
367 }
368 }
369 cachedFilteredSnapshot_ =
370 std::make_shared<RSPaintFilterCanvas::CachedEffectData>(std::move(filteredSnapshot), offscreenRect);
371 isHpaeCachedFilteredSnapshot_ = false;
372 }
373
DrawCachedFilteredSnapshot(RSPaintFilterCanvas & canvas,const Drawing::RectI & dstRect,const std::shared_ptr<RSDrawingFilter> & filter) const374 void RSFilterCacheManager::DrawCachedFilteredSnapshot(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect,
375 const std::shared_ptr<RSDrawingFilter>& filter) const
376 {
377 if (cachedFilteredSnapshot_ == nullptr || cachedFilteredSnapshot_->cachedImage_ == nullptr) {
378 return;
379 }
380 RS_OPTIONAL_TRACE_FUNC();
381 // Draw in device coordinates.
382 Drawing::AutoCanvasRestore autoRestore(canvas, true);
383 canvas.ResetMatrix();
384
385 // Only draw within the visible rect.
386 ClipVisibleRect(canvas);
387
388 // The cache type and parameters has been validated, dstRect must be subset of cachedFilteredSnapshot_->cachedRect_.
389 Drawing::Rect dst = {dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom()};
390 Drawing::Rect src = {dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom()};
391 if (isHpaeCachedFilteredSnapshot_) {
392 src = cachedFilteredSnapshot_->cachedRect_;
393 }
394 src.Offset(-cachedFilteredSnapshot_->cachedRect_.GetLeft(), -cachedFilteredSnapshot_->cachedRect_.GetTop());
395 RS_OPTIONAL_TRACE_NAME_FMT("DrawCachedFilteredSnapshot cachedRect_:%s, src:%s, dst:%s",
396 cachedFilteredSnapshot_->cachedRect_.ToString().c_str(), src.ToString().c_str(), dst.ToString().c_str());
397 Drawing::Brush brush;
398 brush.SetAntiAlias(true);
399 canvas.AttachBrush(brush);
400 if (CanDiscardCanvas(canvas, dstRect) && brush.GetColor().GetAlphaF() == 1.0 && filter &&
401 filter->GetFilterType() == RSFilter::MATERIAL) {
402 canvas.Discard();
403 }
404 canvas.DrawImageRect(*cachedFilteredSnapshot_->cachedImage_, src, dst, Drawing::SamplingOptions(),
405 Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
406 canvas.DetachBrush();
407 }
408
InvalidateFilterCache(FilterCacheType clearType)409 void RSFilterCacheManager::InvalidateFilterCache(FilterCacheType clearType)
410 {
411 if (clearType == FilterCacheType::BOTH) {
412 cachedSnapshot_.reset();
413 cachedFilteredSnapshot_.reset();
414 RS_OPTIONAL_TRACE_NAME_FMT("RSFilterCacheManager::InvalidateFilterCache BOTH");
415 return;
416 }
417 if (clearType == FilterCacheType::SNAPSHOT) {
418 cachedSnapshot_.reset();
419 RS_OPTIONAL_TRACE_NAME_FMT("RSFilterCacheManager::InvalidateFilterCache SNAPSHOT");
420 return;
421 }
422 if (clearType == FilterCacheType::FILTERED_SNAPSHOT) {
423 cachedFilteredSnapshot_.reset();
424 }
425 }
426
GetFilterInvalid()427 bool RSFilterCacheManager::GetFilterInvalid()
428 {
429 return filterInvalid_;
430 }
431
SetFilterInvalid(bool invalidFilter)432 void RSFilterCacheManager::SetFilterInvalid(bool invalidFilter)
433 {
434 filterInvalid_ = invalidFilter;
435 }
436
IsForceUseFilterCache() const437 bool RSFilterCacheManager::IsForceUseFilterCache() const
438 {
439 return stagingForceUseCache_;
440 }
441
MarkFilterForceUseCache(bool forceUseCache)442 void RSFilterCacheManager::MarkFilterForceUseCache(bool forceUseCache)
443 {
444 stagingForceUseCache_ = forceUseCache;
445 }
446
IsForceClearFilterCache() const447 bool RSFilterCacheManager::IsForceClearFilterCache() const
448 {
449 return stagingForceClearCache_;
450 }
451
MarkFilterForceClearCache()452 void RSFilterCacheManager::MarkFilterForceClearCache()
453 {
454 stagingForceClearCache_ = true;
455 }
456
RecordFilterInfos(const std::shared_ptr<RSFilter> & rsFilter)457 void RSFilterCacheManager::RecordFilterInfos(const std::shared_ptr<RSFilter>& rsFilter)
458 {
459 auto filter = std::static_pointer_cast<RSDrawingFilter>(rsFilter);
460 if (filter == nullptr) {
461 return;
462 }
463 stagingFilterHashChanged_ = stagingCachedFilterHash_ != filter->Hash();
464 if (stagingFilterHashChanged_) {
465 stagingCachedFilterHash_ = filter->Hash();
466 }
467 filterType_ = filter->GetFilterType();
468 canSkipFrame_ = filter->CanSkipFrame();
469 }
470
MarkFilterRegionChanged()471 void RSFilterCacheManager::MarkFilterRegionChanged()
472 {
473 stagingFilterRegionChanged_ = true;
474 }
475
MarkFilterRegionInteractWithDirty()476 void RSFilterCacheManager::MarkFilterRegionInteractWithDirty()
477 {
478 stagingFilterInteractWithDirty_ = true;
479 }
480
MarkForceClearCacheWithLastFrame()481 void RSFilterCacheManager::MarkForceClearCacheWithLastFrame()
482 {
483 stagingForceClearCacheForLastFrame_ = true;
484 }
485
MarkFilterRegionIsLargeArea()486 void RSFilterCacheManager::MarkFilterRegionIsLargeArea()
487 {
488 stagingIsLargeArea_ = true;
489 }
490
MarkInForegroundFilterAndCheckNeedForceClearCache(NodeId offscreenCanvasNodeId)491 void RSFilterCacheManager::MarkInForegroundFilterAndCheckNeedForceClearCache(NodeId offscreenCanvasNodeId)
492 {
493 stagingInForegroundFilter_ = offscreenCanvasNodeId;
494 if (stagingInForegroundFilter_ != lastInForegroundFilter_ && lastCacheType_ != FilterCacheType::NONE) {
495 MarkFilterForceClearCache();
496 }
497 }
498
UpdateFlags(FilterCacheType type,bool cacheValid)499 void RSFilterCacheManager::UpdateFlags(FilterCacheType type, bool cacheValid)
500 {
501 stagingClearType_ = type;
502 isFilterCacheValid_ = cacheValid;
503 if (!cacheValid) {
504 cacheUpdateInterval_ = stagingRotationChanged_ ? ROTATION_CACHE_UPDATE_INTERVAL :
505 (filterType_ == RSFilter::AIBAR ? AIBAR_CACHE_UPDATE_INTERVAL :
506 (stagingIsLargeArea_ && canSkipFrame_ ? RSSystemProperties::GetFilterCacheUpdateInterval() : 0));
507 pendingPurge_ = false;
508 return;
509 }
510 if (stagingIsAIBarInteractWithHWC_) {
511 if (cacheUpdateInterval_ > 0) {
512 cacheUpdateInterval_--;
513 pendingPurge_ = true;
514 }
515 } else {
516 if ((stagingFilterInteractWithDirty_ || stagingRotationChanged_) && cacheUpdateInterval_ > 0) {
517 cacheUpdateInterval_--;
518 pendingPurge_ = true;
519 }
520 }
521 stagingIsAIBarInteractWithHWC_ = false;
522 }
523
CheckAndUpdateAIBarCacheStatus(bool intersectHwcDamage)524 bool RSFilterCacheManager::CheckAndUpdateAIBarCacheStatus(bool intersectHwcDamage)
525 {
526 if (filterType_ != RSFilter::AIBAR) {
527 return false;
528 }
529 if (intersectHwcDamage) {
530 stagingIsAIBarInteractWithHWC_ = true;
531 }
532 RS_OPTIONAL_TRACE_NAME_FMT("RSFilterCacheManager::CheckAndUpdateAIBarCacheStatus \
533 cacheUpdateInterval_:%d forceClearCacheForLastFrame_:%d",
534 cacheUpdateInterval_, stagingForceClearCacheForLastFrame_);
535 // Determines if the cache is invalid based on:
536 // - Cache update interval is less than or equal to 0
537 // - Staging force cache clear flag being set for last frame
538 // - The previous frame triggered a frame skipping
539 bool cacheInvalid = cacheUpdateInterval_ <= 0 || stagingForceClearCacheForLastFrame_ ||
540 (!intersectHwcDamage && pendingPurge_);
541 if (cacheInvalid) {
542 return false;
543 } else {
544 MarkFilterForceUseCache(true);
545 return true;
546 }
547 }
548
MarkEffectNode()549 void RSFilterCacheManager::MarkEffectNode()
550 {
551 stagingIsEffectNode_ = true;
552 }
553
SwapDataAndInitStagingFlags(std::unique_ptr<RSFilterCacheManager> & cacheManager)554 void RSFilterCacheManager::SwapDataAndInitStagingFlags(std::unique_ptr<RSFilterCacheManager>& cacheManager)
555 {
556 if (cacheManager == nullptr) {
557 return;
558 }
559 // stagingParams to renderParams
560 cacheManager->renderFilterHashChanged_ = stagingFilterHashChanged_;
561 cacheManager->renderForceClearCacheForLastFrame_ = stagingForceClearCacheForLastFrame_;
562 cacheManager->renderIsEffectNode_ = stagingIsEffectNode_;
563 cacheManager->renderIsSkipFrame_ = stagingIsSkipFrame_;
564 cacheManager->renderClearType_ = stagingClearType_;
565
566 cacheManager->stagingFilterRegionChanged_ = stagingFilterRegionChanged_;
567 cacheManager->filterType_ = filterType_;
568 cacheManager->stagingIsOccluded_ = stagingIsOccluded_;
569 cacheManager->ClearFilterCache();
570 cacheManager->forceUseCache_ = stagingForceUseCache_;
571 cacheManager->belowDirty_ = stagingFilterInteractWithDirty_;
572
573 // renderParams to stagingParams
574 lastCacheType_ = cacheManager->lastCacheType_;
575
576 // save staging param value
577 lastInForegroundFilter_ = stagingInForegroundFilter_;
578
579 // stagingParams init
580 stagingFilterHashChanged_ = false;
581 stagingForceClearCacheForLastFrame_ = false;
582 stagingIsEffectNode_ = false;
583 stagingIsSkipFrame_ = false;
584 stagingClearType_ = FilterCacheType::BOTH;
585
586 stagingFilterRegionChanged_ = false;
587 stagingFilterInteractWithDirty_ = false;
588 stagingRotationChanged_ = false;
589 stagingForceClearCache_ = false;
590 stagingForceUseCache_ = false;
591 stagingIsOccluded_ = false;
592
593 stagingIsLargeArea_ = false;
594 isFilterCacheValid_ = false;
595
596 stagingInForegroundFilter_ = false;
597 }
598
MarkNeedClearFilterCache(NodeId nodeId)599 void RSFilterCacheManager::MarkNeedClearFilterCache(NodeId nodeId)
600 {
601 RS_TRACE_NAME_FMT("RSFilterCacheManager::MarkNeedClearFilterCache nodeId[%llu] forceUseCache_:%d,"
602 "forceClearCache_:%d, hashChanged:%d, regionChanged_:%d, belowDirty_:%d,"
603 "lastCacheType:%d, cacheUpdateInterval_:%d, canSkip:%d, isLargeArea:%d, filterType_:%d, pendingPurge_:%d,"
604 "forceClearCacheWithLastFrame:%d, rotationChanged:%d, offscreenCanvasNodeId:%llu", nodeId,
605 stagingForceUseCache_, stagingForceClearCache_, stagingFilterHashChanged_,
606 stagingFilterRegionChanged_, stagingFilterInteractWithDirty_,
607 lastCacheType_, cacheUpdateInterval_, canSkipFrame_, stagingIsLargeArea_,
608 filterType_, pendingPurge_, stagingForceClearCacheForLastFrame_, stagingRotationChanged_,
609 stagingInForegroundFilter_);
610
611 ROSEN_LOGD("RSFilterDrawable::MarkNeedClearFilterCache, forceUseCache_:%{public}d,"
612 "forceClearCache_:%{public}d, hashChanged:%{public}d, regionChanged_:%{public}d, belowDirty_:%{public}d,"
613 "lastCacheType:%{public}hhu, cacheUpdateInterval_:%{public}d, canSkip:%{public}d, isLargeArea:%{public}d,"
614 "filterType_:%{public}d, pendingPurge_:%{public}d,"
615 "forceClearCacheWithLastFrame:%{public}d, rotationChanged:%{public}d,"
616 "offscreenCanvasNodeId:%{public}" PRIu64,
617 stagingForceUseCache_, stagingForceClearCache_,
618 stagingFilterHashChanged_, stagingFilterRegionChanged_, stagingFilterInteractWithDirty_,
619 lastCacheType_, cacheUpdateInterval_, canSkipFrame_, stagingIsLargeArea_,
620 filterType_, pendingPurge_, stagingForceClearCacheForLastFrame_, stagingRotationChanged_,
621 stagingInForegroundFilter_);
622
623 // if do not request NextVsync, close skip
624 if (stagingForceClearCacheForLastFrame_) {
625 cacheUpdateInterval_ = 0;
626 }
627
628 stagingIsSkipFrame_ = stagingIsLargeArea_ && canSkipFrame_ && !stagingFilterRegionChanged_;
629
630 // no valid cache
631 if (lastCacheType_ == FilterCacheType::NONE) {
632 UpdateFlags(FilterCacheType::BOTH, false);
633 return;
634 }
635 // No need to invalidate cache if background image is not null or freezed
636 if (stagingForceUseCache_) {
637 UpdateFlags(FilterCacheType::NONE, true);
638 return;
639 }
640
641 // clear both two type cache: 1. force clear 2. filter region changed 3.skip-frame finished
642 // 4. background changed and effectNode rotated will enable skip-frame, the last frame need to update.
643 if (stagingForceClearCache_ || (stagingFilterRegionChanged_ && !stagingRotationChanged_) || NeedPendingPurge() ||
644 ((stagingFilterInteractWithDirty_ || stagingRotationChanged_) && cacheUpdateInterval_ <= 0)) {
645 UpdateFlags(FilterCacheType::BOTH, false);
646 return;
647 }
648
649 // clear snapshot cache last frame and clear filtered cache current frame
650 if (lastCacheType_ == FilterCacheType::FILTERED_SNAPSHOT && stagingFilterHashChanged_) {
651 UpdateFlags(FilterCacheType::FILTERED_SNAPSHOT, false);
652 return;
653 }
654
655 // when blur filter changes, we need to clear filtered cache if it valid.
656 UpdateFlags(stagingFilterHashChanged_ ?
657 FilterCacheType::FILTERED_SNAPSHOT : FilterCacheType::NONE, true);
658 }
659
NeedPendingPurge() const660 bool RSFilterCacheManager::NeedPendingPurge() const
661 {
662 return !stagingFilterInteractWithDirty_ && pendingPurge_;
663 }
664
ClearFilterCache()665 void RSFilterCacheManager::ClearFilterCache()
666 {
667 // 1. clear memory when region changed and is not the first time occured.
668 bool needClearMemoryForGpu = stagingFilterRegionChanged_ && GetCachedType() != FilterCacheType::NONE;
669 if (filterType_ == RSFilter::AIBAR && stagingIsOccluded_) {
670 InvalidateFilterCache(FilterCacheType::BOTH);
671 } else {
672 InvalidateFilterCache(renderClearType_);
673 }
674 // 2. clear memory when region changed without skip frame.
675 needClearMemoryForGpu = needClearMemoryForGpu && GetCachedType() == FilterCacheType::NONE;
676 if (needClearMemoryForGpu) {
677 SetFilterInvalid(true);
678 }
679
680 // whether to clear blur images. true: clear blur image, false: clear snapshot
681 bool isSaveSnapshot = renderFilterHashChanged_ || GetCachedType() == FilterCacheType::NONE;
682 bool isAIbarWithLastFrame = filterType_ == RSFilter::AIBAR && renderForceClearCacheForLastFrame_; // last vsync
683
684 if ((filterType_ != RSFilter::AIBAR || isAIbarWithLastFrame) && isSaveSnapshot) {
685 renderClearFilteredCacheAfterDrawing_ = true; // hold snapshot
686 } else {
687 renderClearFilteredCacheAfterDrawing_ = false; // hold blur image
688 }
689 if (renderIsEffectNode_ || renderIsSkipFrame_) { renderClearFilteredCacheAfterDrawing_ = renderFilterHashChanged_; }
690 lastCacheType_ = stagingIsOccluded_ ? GetCachedType() : (renderClearFilteredCacheAfterDrawing_ ?
691 FilterCacheType::SNAPSHOT : FilterCacheType::FILTERED_SNAPSHOT);
692 RS_TRACE_NAME_FMT("RSFilterCacheManager::ClearFilterCache, clearType:%d,"
693 " isOccluded_:%d, lastCacheType:%d needClearMemoryForGpu:%d ClearFilteredCacheAfterDrawing:%d",
694 renderClearType_, stagingIsOccluded_, lastCacheType_, needClearMemoryForGpu,
695 renderClearFilteredCacheAfterDrawing_);
696 ROSEN_LOGD("RSFilterCacheManager::ClearFilterCache, clearType:%{public}d,"
697 " isOccluded_:%{public}d, lastCacheType:%{public}d needClearMemoryForGpu:%{public}d"
698 " ClearFilteredCacheAfterDrawing:%{public}d",
699 static_cast<int>(renderClearType_), stagingIsOccluded_, static_cast<int>(lastCacheType_),
700 needClearMemoryForGpu, renderClearFilteredCacheAfterDrawing_);
701 }
702
IsSkippingFrame() const703 bool RSFilterCacheManager::IsSkippingFrame() const
704 {
705 return (stagingFilterInteractWithDirty_ || stagingRotationChanged_) && cacheUpdateInterval_ > 0;
706 }
707
MarkRotationChanged()708 void RSFilterCacheManager::MarkRotationChanged()
709 {
710 stagingRotationChanged_ = true;
711 }
712
713 // called after OnSync()
IsFilterCacheValidForOcclusion()714 bool RSFilterCacheManager::IsFilterCacheValidForOcclusion()
715 {
716 auto cacheType = GetCachedType();
717 RS_OPTIONAL_TRACE_NAME_FMT("RSFilterCacheManager::IsFilterCacheValidForOcclusion cacheType:%d renderClearType_:%d",
718 cacheType, renderClearType_);
719 ROSEN_LOGD("RSFilterCacheManager::IsFilterCacheValidForOcclusion cacheType:%{public}d renderClearType_:%{public}d",
720 static_cast<int>(cacheType), static_cast<int>(renderClearType_));
721
722 return cacheType != FilterCacheType::NONE;
723 }
724
MarkNodeIsOccluded(bool isOccluded)725 void RSFilterCacheManager::MarkNodeIsOccluded(bool isOccluded)
726 {
727 stagingIsOccluded_ = isOccluded;
728 }
729
IsFilterCacheValid() const730 bool RSFilterCacheManager::IsFilterCacheValid() const
731 {
732 return isFilterCacheValid_;
733 }
734
WouldDrawLargeAreaBlur()735 bool RSFilterCacheManager::WouldDrawLargeAreaBlur()
736 {
737 RS_TRACE_NAME_FMT("wouldDrawLargeAreaBlur stagingIsLargeArea:%d canSkipFrame:%d"
738 " stagingUpdateInterval:%d stagingFilterInteractWithDirty:%d",
739 stagingIsLargeArea_, canSkipFrame_, cacheUpdateInterval_, stagingFilterInteractWithDirty_);
740 ROSEN_LOGD("wouldDrawLargeAreaBlur stagingIsLargeArea:%{public}d canSkipFrame:%{public}d"
741 " stagingUpdateInterval:%{public}d stagingFilterInteractWithDirty:%{public}d",
742 stagingIsLargeArea_, canSkipFrame_, cacheUpdateInterval_, stagingFilterInteractWithDirty_);
743 if (stagingIsLargeArea_) {
744 if (!canSkipFrame_) {
745 return true;
746 }
747 return cacheUpdateInterval_ == 1 && stagingFilterInteractWithDirty_;
748 }
749 return false;
750 }
751
WouldDrawLargeAreaBlurPrecisely()752 bool RSFilterCacheManager::WouldDrawLargeAreaBlurPrecisely()
753 {
754 RS_TRACE_NAME_FMT("wouldDrawLargeAreaBlurPrecisely stagingIsLargeArea:%d stagingForceClearCache:%d"
755 " canSkipFrame:%d stagingFilterHashChanged:%d stagingFilterInteractWithDirty:%d stagingFilterRegionChanged:%d"
756 " stagingUpdateInterval:%d stagingLastCacheType:%d", stagingIsLargeArea_,
757 stagingForceClearCache_, canSkipFrame_, stagingFilterHashChanged_, stagingFilterInteractWithDirty_,
758 stagingFilterRegionChanged_, cacheUpdateInterval_, lastCacheType_);
759 if (!stagingIsLargeArea_) {
760 return false;
761 }
762 if (stagingForceClearCache_) {
763 return true;
764 }
765 if (!canSkipFrame_ && !stagingFilterHashChanged_) {
766 return true;
767 }
768 if (!stagingFilterInteractWithDirty_ && !stagingFilterHashChanged_ && !stagingFilterRegionChanged_) {
769 return false;
770 }
771 if (cacheUpdateInterval_ == 0) {
772 return true;
773 }
774 if (lastCacheType_ == FilterCacheType::FILTERED_SNAPSHOT && stagingFilterHashChanged_) {
775 return true;
776 }
777 return false;
778 }
779
ReleaseCacheOffTree()780 void RSFilterCacheManager::ReleaseCacheOffTree()
781 {
782 RS_OPTIONAL_TRACE_FUNC();
783 cachedSnapshot_.reset();
784 cachedFilteredSnapshot_.reset();
785 }
786
GetCachedType() const787 FilterCacheType RSFilterCacheManager::GetCachedType() const
788 {
789 if (cachedSnapshot_ == nullptr && cachedFilteredSnapshot_ == nullptr) {
790 return FilterCacheType::NONE;
791 }
792 if (cachedSnapshot_ != nullptr) {
793 return FilterCacheType::SNAPSHOT;
794 }
795
796 if (cachedFilteredSnapshot_ != nullptr) {
797 return FilterCacheType::FILTERED_SNAPSHOT;
798 }
799 return FilterCacheType::BOTH;
800 }
801
ClipVisibleRect(RSPaintFilterCanvas & canvas)802 inline void RSFilterCacheManager::ClipVisibleRect(RSPaintFilterCanvas& canvas)
803 {
804 auto visibleRectF = canvas.GetVisibleRect();
805 visibleRectF.Round();
806 Drawing::RectI visibleIRect = {(int)visibleRectF.GetLeft(), (int)visibleRectF.GetTop(),
807 (int)visibleRectF.GetRight(), (int)visibleRectF.GetBottom()};
808 auto deviceClipRect = canvas.GetDeviceClipBounds();
809 if (!visibleIRect.IsEmpty() && deviceClipRect.Intersect(visibleIRect)) {
810 canvas.ClipIRect(visibleIRect, Drawing::ClipOp::INTERSECT);
811 }
812 }
813
GetCachedImageRegion() const814 const RectI& RSFilterCacheManager::GetCachedImageRegion() const
815 {
816 static const auto emptyRect = RectI();
817 return IsCacheValid() ? snapshotRegion_ : emptyRect;
818 }
819
IsCacheInvalid(const RSPaintFilterCanvas::CachedEffectData & cache,RSPaintFilterCanvas & canvas)820 inline static bool IsCacheInvalid(const RSPaintFilterCanvas::CachedEffectData& cache, RSPaintFilterCanvas& canvas)
821 {
822 return cache.cachedImage_ == nullptr || !cache.cachedImage_->IsValid(canvas.GetGPUContext().get());
823 }
824
CheckCachedImages(RSPaintFilterCanvas & canvas)825 void RSFilterCacheManager::CheckCachedImages(RSPaintFilterCanvas& canvas)
826 {
827 if (cachedSnapshot_ != nullptr && IsCacheInvalid(*cachedSnapshot_, canvas)) {
828 ROSEN_LOGE("RSFilterCacheManager::CheckCachedImages cachedSnapshot_ is invalid");
829 cachedSnapshot_.reset();
830 }
831
832 if (cachedFilteredSnapshot_ != nullptr && IsCacheInvalid(*cachedFilteredSnapshot_, canvas)) {
833 ROSEN_LOGE("RSFilterCacheManager::CheckCachedImages cachedFilteredSnapshot_ is invalid");
834 cachedFilteredSnapshot_.reset();
835 }
836 }
837
ValidateParams(RSPaintFilterCanvas & canvas,const std::optional<Drawing::RectI> & srcRect,const std::optional<Drawing::RectI> & dstRect)838 std::tuple<Drawing::RectI, Drawing::RectI> RSFilterCacheManager::ValidateParams(
839 RSPaintFilterCanvas& canvas, const std::optional<Drawing::RectI>& srcRect,
840 const std::optional<Drawing::RectI>& dstRect)
841 {
842 Drawing::RectI src;
843 Drawing::RectI dst;
844 auto deviceRect = Drawing::RectI(0, 0, canvas.GetImageInfo().GetWidth(), canvas.GetImageInfo().GetHeight());
845 if (!srcRect.has_value()) {
846 src = canvas.GetRoundInDeviceClipBounds();
847 } else {
848 src = srcRect.value();
849 src.Intersect(deviceRect);
850 }
851 if (!dstRect.has_value()) {
852 dst = src;
853 } else {
854 dst = dstRect.value();
855 dst.Intersect(deviceRect);
856 }
857 RS_OPTIONAL_TRACE_NAME_FMT("RSFilterCacheManager::ValidateParams src:%s, dst:%s",
858 src.ToString().c_str(), dst.ToString().c_str());
859 ROSEN_LOGD("RSFilterCacheManager::ValidateParams src:%{public}s, dst:%{public}s",
860 src.ToString().c_str(), dst.ToString().c_str());
861 return { src, dst };
862 }
863
ResetFilterCache(std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot,std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot,RectI snapshotRegion,bool isHpaeCachedFilteredSnapshot)864 void RSFilterCacheManager::ResetFilterCache(std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot,
865 std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot, RectI snapshotRegion,
866 bool isHpaeCachedFilteredSnapshot)
867 {
868 RS_TRACE_NAME_FMT("ResetFilterCache:[%p,%p]", cachedSnapshot.get(), cachedFilteredSnapshot.get());
869 if (cachedSnapshot && cachedSnapshot->cachedImage_) {
870 cachedSnapshot_ = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(cachedSnapshot->cachedImage_,
871 cachedSnapshot->cachedRect_);
872 } else {
873 cachedSnapshot_.reset();
874 }
875 if (cachedFilteredSnapshot && cachedFilteredSnapshot->cachedImage_) {
876 cachedFilteredSnapshot_ = std::make_shared<RSPaintFilterCanvas::CachedEffectData>(
877 cachedFilteredSnapshot->cachedImage_, cachedFilteredSnapshot->cachedRect_);
878 isHpaeCachedFilteredSnapshot_ = isHpaeCachedFilteredSnapshot;
879 } else {
880 cachedFilteredSnapshot.reset();
881 isHpaeCachedFilteredSnapshot_ =false;
882 }
883 snapshotRegion_ = snapshotRegion;
884 }
ForceUpadateCacheByHpae()885 bool RSFilterCacheManager::ForceUpadateCacheByHpae()
886 {
887 if (belowDirty_) {
888 return false;
889 }
890 if (forceUseCache_ || filterType_ == RSFilter::AIBAR) {
891 return false;
892 }
893 return RSHpaeBaseData::GetInstance().GetBlurContentChanged();
894 }
895
CompactFilterCache()896 void RSFilterCacheManager::CompactFilterCache()
897 {
898 if (ForceUpadateCacheByHpae()) {
899 RS_TRACE_NAME("blur content changed");
900 renderClearFilteredCacheAfterDrawing_ = true;
901 }
902 InvalidateFilterCache(renderClearFilteredCacheAfterDrawing_ ?
903 FilterCacheType::FILTERED_SNAPSHOT : FilterCacheType::SNAPSHOT);
904 }
905
ClearEffectCacheWithDrawnRegion(const RSPaintFilterCanvas & canvas,const Drawing::RectI & filterBound)906 void RSFilterCacheManager::ClearEffectCacheWithDrawnRegion(
907 const RSPaintFilterCanvas& canvas, const Drawing::RectI& filterBound)
908 {
909 if (!takeNewSnapshot_) {
910 return;
911 }
912 auto drawnRegion = canvas.GetDrawnRegion();
913 Occlusion::Region filterRegion(
914 Occlusion::Rect(filterBound.left_, filterBound.top_, filterBound.right_, filterBound.bottom_));
915 const bool isCacheInvalid = !filterRegion.Sub(drawnRegion).IsEmpty() && !filterRegion.And(drawnRegion).IsEmpty();
916 if (isCacheInvalid) {
917 InvalidateFilterCache(FilterCacheType::BOTH);
918 }
919 }
920 } // namespace Rosen
921 } // namespace OHOS
922 #endif