• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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