• 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 #ifndef RENDER_SERVICE_BASE_PROPERTY_RS_FILTER_CACHE_MANAGER_H
17 #define RENDER_SERVICE_BASE_PROPERTY_RS_FILTER_CACHE_MANAGER_H
18 
19 #include <atomic>
20 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
21 #include <condition_variable>
22 
23 #include "draw/canvas.h"
24 #include "draw/surface.h"
25 #include "utils/rect.h"
26 
27 #include "common/rs_macros.h"
28 #include "common/rs_rect.h"
29 #include "pipeline/rs_dirty_region_manager.h"
30 #include "pipeline/rs_paint_filter_canvas.h"
31 #include "platform/common/rs_system_properties.h"
32 #include "render/rs_filter.h"
33 
34 namespace OHOS {
35 namespace Rosen {
36 class RSDrawingFilter;
37 class RSHpaeFilterCacheManager;
38 // Note: we don't care about if the filter will be applied to background or foreground, the caller should take care of
39 // this. This means if both background and foreground need to apply filter, the caller should create two
40 // RSFilterCacheManager, pass the correct dirty region, and call the DrawFilter() in correct order.
41 // Warn: Using filter cache in multi-thread environment may cause GPU memory leak or invalid textures.
42 class RSB_EXPORT RSFilterCacheManager final {
43 public:
44     RSFilterCacheManager();
45     ~RSFilterCacheManager() = default;
46     RSFilterCacheManager(const RSFilterCacheManager&) = delete;
47     RSFilterCacheManager(const RSFilterCacheManager&&) = delete;
48     RSFilterCacheManager& operator=(const RSFilterCacheManager&) = delete;
49     RSFilterCacheManager& operator=(const RSFilterCacheManager&&) = delete;
50 
51     // Call these functions during the prepare phase to validate the cache state with the filter, if filter region is
52     // intersected with cached region, and if cached region is intersected with dirty region.
53     void UpdateCacheStateWithFilterHash(const std::shared_ptr<RSFilter>& filter);
54     void UpdateCacheStateWithFilterRegion(); // call when filter region out of cached region.
55     bool UpdateCacheStateWithDirtyRegion(
56         const RSDirtyRegionManager& dirtyManager); // call when dirty region intersects with cached region.
57     void UpdateCacheStateWithDirtyRegion();
58     const RectI& GetCachedImageRegion() const;
59     FilterCacheType GetCachedType() const;
60 
61     bool DrawFilterUsingHpae(RSPaintFilterCanvas& paintFilterCanvas, const std::shared_ptr<RSFilter>& filter,
62             const std::shared_ptr<RSHpaeFilterCacheManager>& hpaeCacheManager, NodeId nodeId);
63 
64     // Call this function during the process phase to apply the filter. Depending on the cache state, it may either
65     // regenerate the cache or reuse the existing cache.
66     // Note: If srcRect or dstRect is empty, we'll use the DeviceClipRect as the corresponding rect.
67     void DrawFilter(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, NodeId nodeId,
68         bool manuallyHandleFilterCache = false, bool shouldClearFilteredCache = true,
69         const std::optional<Drawing::RectI>& srcRect = std::nullopt,
70         const std::optional<Drawing::RectI>& dstRect = std::nullopt);
71 
72     // This function is similar to DrawFilter(), but instead of drawing anything on the canvas, it simply returns the
73     // cache data. This is used with effect component in RSPropertiesPainter::DrawBackgroundEffect.
74     const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> GeneratedCachedEffectData(RSPaintFilterCanvas& canvas,
75         const std::shared_ptr<RSDrawingFilter>& filter, const std::optional<Drawing::RectI>& srcRect = std::nullopt,
76         const std::optional<Drawing::RectI>& dstRect = std::nullopt);
77 
78     uint8_t CalcDirectionBias(const Drawing::Matrix& mat);
79     enum CacheType : uint8_t {
80         CACHE_TYPE_NONE              = 0,
81         CACHE_TYPE_SNAPSHOT          = 1,
82         CACHE_TYPE_FILTERED_SNAPSHOT = 2,
83         CACHE_TYPE_BOTH              = CACHE_TYPE_SNAPSHOT | CACHE_TYPE_FILTERED_SNAPSHOT,
84     };
85 
86     // Call this function to manually invalidate the cache. The next time DrawFilter() is called, it will regenerate the
87     // cache.
88     void ReleaseCacheOffTree();
89     void StopFilterPartialRender();
90     void InvalidateFilterCache(FilterCacheType clearType = FilterCacheType::BOTH);
91 
92     // To reduce memory usage, clear one of the cached images.
93     void CompactFilterCache();
94 
IsCacheValid()95     inline bool IsCacheValid() const
96     {
97         return cachedSnapshot_ != nullptr || cachedFilteredSnapshot_ != nullptr;
98     }
99 
100     static bool GetFilterInvalid();
101     static void SetFilterInvalid(bool invalidFilter);
102 
103     bool IsForceUseFilterCache() const;
104     void MarkFilterForceUseCache(bool forceUseCache = true);
105     bool IsForceClearFilterCache() const;
106     void MarkFilterForceClearCache();
107     void RecordFilterInfos(const std::shared_ptr<RSFilter>& rsFilter);
108     void MarkFilterRegionChanged();
109     void MarkFilterRegionInteractWithDirty();
110     void MarkForceClearCacheWithLastFrame();
111     void MarkFilterRegionIsLargeArea();
112     bool CheckAndUpdateAIBarCacheStatus(bool intersectHwcDamage);
113     void MarkEffectNode();
114     void MarkNeedClearFilterCache(NodeId nodeId);
115     bool NeedPendingPurge() const;
116     bool IsSkippingFrame() const;
117     void MarkRotationChanged();
118     bool IsFilterCacheValidForOcclusion();
119     void MarkNodeIsOccluded(bool isOccluded);
120     bool IsFilterCacheValid() const;
121     void SwapDataAndInitStagingFlags(std::unique_ptr<RSFilterCacheManager>& cacheManager);
122     bool WouldDrawLargeAreaBlur();
123     bool WouldDrawLargeAreaBlurPrecisely();
124 
GetCachedSnapshot()125     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> GetCachedSnapshot() const { return cachedSnapshot_; }
GetCachedFilteredSnapshot()126     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> GetCachedFilteredSnapshot() const {
127         return cachedFilteredSnapshot_; }
GetSnapshotRegion()128     RectI GetSnapshotRegion() const { return snapshotRegion_; }
129     void ResetFilterCache(std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot,
130         std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot, RectI snapshotRegion,
131         bool isHpaeCachedFilteredSnapshot = false);
132 
133     bool ForceUpadateCacheByHpae();
ClearCacheAfterDrawing()134     bool ClearCacheAfterDrawing() const { return renderClearFilteredCacheAfterDrawing_; }
135 
136     void MarkInForegroundFilterAndCheckNeedForceClearCache(NodeId offscreenCanvasNodeId);
GetFilterType()137     RSFilter::FilterType GetFilterType() const {
138         return filterType_;
139     }
140 
141     /** 1. the cache is generated by taking a new snapshot.
142         2. drawnRegion does not completely cover filter region
143         if all two conditions are met, the cache needs to be cleared.
144     */
145     void ClearEffectCacheWithDrawnRegion(const RSPaintFilterCanvas& canvas, const Drawing::RectI& filterBound);
146 private:
147     void TakeSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
148         const Drawing::RectI& srcRect);
149     void GenerateFilteredSnapshot(
150         RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& dstRect);
151     bool DrawFilterWithoutSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
152         const Drawing::RectI& src, const Drawing::RectI& dst, bool shouldClearFilteredCache);
153     void DrawCachedFilteredSnapshot(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect,
154         const std::shared_ptr<RSDrawingFilter>& filter) const;
155     bool CanDiscardCanvas(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect) const;
156     // Validate the input srcRect and dstRect, and return the validated rects.
157     std::tuple<Drawing::RectI, Drawing::RectI> ValidateParams(RSPaintFilterCanvas& canvas,
158         const std::optional<Drawing::RectI>& srcRect, const std::optional<Drawing::RectI>& dstRect);
159     inline static void ClipVisibleRect(RSPaintFilterCanvas& canvas);
160     // Check if the cache is valid in current GrContext, since FilterCache will never be used in multi-thread
161     // environment, we don't need to attempt to reattach SkImages.
162     void CheckCachedImages(RSPaintFilterCanvas& canvas);
163 
164     std::string GetCacheState() const;
165 
166     void UpdateFlags(FilterCacheType type, bool cacheValid);
167     void ClearFilterCache();
168 
169     // We keep both the snapshot and filtered snapshot in the cache, and clear unneeded one in next frame.
170     // Note: rect in cachedSnapshot_ and cachedFilteredSnapshot_ is in device coordinate.
171     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot_ = nullptr;
172     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot_ = nullptr;
173 
174     // Hash of previous filter, used to determine if we need to invalidate cachedFilteredSnapshot_.
175     uint32_t cachedFilterHash_ = 0;
176 
177     // Region of the cached image, used to determine if we need to invalidate the cache.
178     RectI snapshotRegion_; // Note: in device coordinate.
179 
180     // This flag is used to notify unirender_thread need to clear gpu memory.
181     static inline std::atomic_bool filterInvalid_ = false;
182 
183     // flags for clearing filter cache
184     // All stagingXXX variables should be read & written by render_service thread
185     bool stagingForceUseCache_ = false;
186     bool stagingForceClearCache_ = false;
187     uint32_t stagingCachedFilterHash_ = 0;
188     bool stagingFilterHashChanged_ = false;
189     bool stagingFilterRegionChanged_ = false;
190     bool stagingFilterInteractWithDirty_ = false;
191     bool stagingRotationChanged_ = false;
192     bool stagingForceClearCacheForLastFrame_ = false;
193     bool stagingIsAIBarInteractWithHWC_ = false;
194     bool stagingIsEffectNode_ = false;
195     NodeId stagingInForegroundFilter_ = INVALID_NODEID;
196 
197     // clear one of snapshot cache and filtered cache after drawing
198     // All renderXXX variables should be read & written by render_thread or OnSync() function
199     bool renderClearFilteredCacheAfterDrawing_ = false;
200     bool renderFilterHashChanged_ = false;
201     bool renderForceClearCacheForLastFrame_ = false;
202     bool renderIsEffectNode_ = false;
203     bool renderIsSkipFrame_ = false;
204 
205     // the type cache needed clear before drawing
206     FilterCacheType stagingClearType_ = FilterCacheType::NONE;
207     FilterCacheType renderClearType_ = FilterCacheType::NONE;
208     FilterCacheType lastCacheType_ = FilterCacheType::NONE;
209     bool stagingIsOccluded_ = false;
210 
211     // force cache with cacheUpdateInterval_
212     bool stagingIsLargeArea_ = false;
213     bool canSkipFrame_ = false;
214     bool stagingIsSkipFrame_  = false;
215     RSFilter::FilterType filterType_ = RSFilter::NONE;
216     bool forceUseCache_ = false;
217     bool belowDirty_ = false;
218 
219     // Cache age, used to determine if we can delay the cache update.
220     int cacheUpdateInterval_ = 0;
221     bool isFilterCacheValid_ = false; // catch status in current frame
222     // Whether we need to purge the cache after this frame.
223     bool pendingPurge_ = false;
224 
225     // last stagingInForegroundFilter_ value
226     NodeId lastInForegroundFilter_ = INVALID_NODEID;
227 
228     bool takeNewSnapshot_ = false;
229     std::shared_ptr<RSHpaeFilterCacheManager> hpaeCacheManager_;
230     bool isHpaeCachedFilteredSnapshot_ = false;
231     bool snapshotNeedUpdate_ = false;
232 public:
233     static bool isCCMFilterCacheEnable_;
234     static bool isCCMEffectMergeEnable_;
235 };
236 } // namespace Rosen
237 } // namespace OHOS
238 #endif
239 
240 #endif // RENDER_SERVICE_BASE_PROPERTY_RS_FILTER_CACHE_MANAGER_H
241