• 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(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
21 #include <condition_variable>
22 
23 #include "event_handler.h"
24 #include "draw/canvas.h"
25 #include "draw/surface.h"
26 #include "utils/rect.h"
27 
28 #include "common/rs_macros.h"
29 #include "common/rs_rect.h"
30 #include "pipeline/rs_dirty_region_manager.h"
31 #include "pipeline/rs_paint_filter_canvas.h"
32 #include "platform/common/rs_system_properties.h"
33 #include "render/rs_filter.h"
34 
35 namespace OHOS {
36 namespace Rosen {
37 class RSDrawingFilter;
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() = default;
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     // Call this function during the process phase to apply the filter. Depending on the cache state, it may either
62     // regenerate the cache or reuse the existing cache.
63     // Note: If srcRect or dstRect is empty, we'll use the DeviceClipRect as the corresponding rect.
64     void DrawFilter(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
65         bool manuallyHandleFilterCahe = false, bool shouldClearFilteredCache = true,
66         const std::optional<Drawing::RectI>& srcRect = std::nullopt,
67         const std::optional<Drawing::RectI>& dstRect = std::nullopt);
68 
69     // This function is similar to DrawFilter(), but instead of drawing anything on the canvas, it simply returns the
70     // cache data. This is used with effect component in RSPropertiesPainter::DrawBackgroundEffect.
71     const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> GeneratedCachedEffectData(RSPaintFilterCanvas& canvas,
72         const std::shared_ptr<RSDrawingFilter>& filter, const std::optional<Drawing::RectI>& srcRect = std::nullopt,
73         const std::optional<Drawing::RectI>& dstRect = std::nullopt);
74 
75     uint8_t CalcDirectionBias(const Drawing::Matrix& mat);
76     enum CacheType : uint8_t {
77         CACHE_TYPE_NONE              = 0,
78         CACHE_TYPE_SNAPSHOT          = 1,
79         CACHE_TYPE_FILTERED_SNAPSHOT = 2,
80         CACHE_TYPE_BOTH              = CACHE_TYPE_SNAPSHOT | CACHE_TYPE_FILTERED_SNAPSHOT,
81     };
82 
83     // Call this function to manually invalidate the cache. The next time DrawFilter() is called, it will regenerate the
84     // cache.
85     void ReleaseCacheOffTree();
86     void StopFilterPartialRender();
87     void InvalidateFilterCache(FilterCacheType clearType = FilterCacheType::BOTH);
88 
89     // To reduce memory usage, clear one of the cached images.
90     void CompactFilterCache();
91 
IsCacheValid()92     inline bool IsCacheValid() const
93     {
94         return cachedSnapshot_ != nullptr || cachedFilteredSnapshot_ != nullptr;
95     }
96 
97     static bool GetFilterInvalid();
98     static void SetFilterInvalid(bool invalidFilter);
99 
100     bool IsForceUseFilterCache() const;
101     void MarkFilterForceUseCache(bool forceUseCache = true);
102     bool IsForceClearFilterCache() const;
103     void MarkFilterForceClearCache();
104     void RecordFilterInfos(const std::shared_ptr<RSFilter>& rsFilter);
105     void MarkFilterRegionChanged();
106     void MarkFilterRegionInteractWithDirty();
107     void MarkForceClearCacheWithLastFrame();
108     void MarkFilterRegionIsLargeArea();
109     bool IsAIBarCacheValid();
110     void MarkEffectNode();
111     void MarkNeedClearFilterCache();
112     bool NeedPendingPurge() const;
113     bool IsSkippingFrame() const;
114     void MarkRotationChanged();
115     bool IsFilterCacheValidForOcclusion();
116     void MarkNodeIsOccluded(bool isOccluded);
117     bool IsFilterCacheValid() const;
118     void SwapDataAndInitStagingFlags(std::unique_ptr<RSFilterCacheManager>& cacheManager);
119     bool WouldDrawLargeAreaBlur();
120     bool WouldDrawLargeAreaBlurPrecisely();
GetFilterType()121     RSFilter::FilterType GetFilterType() const {
122         return filterType_;
123     }
124 
125 private:
126     void TakeSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
127         const Drawing::RectI& srcRect);
128     void GenerateFilteredSnapshot(
129         RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& dstRect);
130     bool DrawFilterWithoutSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter,
131         const Drawing::RectI& src, const Drawing::RectI& dst, bool shouldClearFilteredCache);
132     void DrawCachedFilteredSnapshot(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect,
133         const std::shared_ptr<RSDrawingFilter>& filter) const;
134     bool CanDiscardCanvas(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect) const;
135     // Validate the input srcRect and dstRect, and return the validated rects.
136     std::tuple<Drawing::RectI, Drawing::RectI> ValidateParams(RSPaintFilterCanvas& canvas,
137         const std::optional<Drawing::RectI>& srcRect, const std::optional<Drawing::RectI>& dstRect);
138     inline static void ClipVisibleRect(RSPaintFilterCanvas& canvas);
139     // Check if the cache is valid in current GrContext, since FilterCache will never be used in multi-thread
140     // environment, we don't need to attempt to reattach SkImages.
141     void CheckCachedImages(RSPaintFilterCanvas& canvas);
142 
143     const char* GetCacheState() const;
144 
145     void UpdateFlags(FilterCacheType type, bool cacheValid);
146     void ClearFilterCache();
147 
148     // We keep both the snapshot and filtered snapshot in the cache, and clear unneeded one in next frame.
149     // Note: rect in cachedSnapshot_ and cachedFilteredSnapshot_ is in device coordinate.
150     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot_ = nullptr;
151     std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot_ = nullptr;
152 
153     // Hash of previous filter, used to determine if we need to invalidate cachedFilteredSnapshot_.
154     uint32_t cachedFilterHash_ = 0;
155 
156     // Region of the cached image, used to determine if we need to invalidate the cache.
157     RectI snapshotRegion_; // Note: in device coordinate.
158 
159     // This flag is used to notify unirender_thread need to clear gpu memory.
160     static inline std::atomic_bool filterInvalid_ = false;
161 
162     // flags for clearing filter cache
163     // All stagingXXX variables should be read & written by render_service thread
164     bool stagingForceUseCache_ = false;
165     bool stagingForceClearCache_ = false;
166     uint32_t stagingCachedFilterHash_ = 0;
167     bool stagingFilterHashChanged_ = false;
168     bool stagingFilterRegionChanged_ = false;
169     bool stagingFilterInteractWithDirty_ = false;
170     bool stagingRotationChanged_ = false;
171     bool stagingForceClearCacheForLastFrame_ = false;
172     bool stagingIsAIBarInteractWithHWC_ = false;
173     bool stagingIsEffectNode_ = false;
174 
175     // clear one of snapshot cache and filtered cache after drawing
176     // All renderXXX variables should be read & written by render_thread or OnSync() function
177     bool renderClearFilteredCacheAfterDrawing_ = false;
178     bool renderFilterHashChanged_ = false;
179     bool renderForceClearCacheForLastFrame_ = false;
180     bool renderIsEffectNode_ = false;
181     bool renderIsSkipFrame_ = false;
182 
183     // the type cache needed clear before drawing
184     FilterCacheType stagingClearType_ = FilterCacheType::NONE;
185     FilterCacheType renderClearType_ = FilterCacheType::NONE;
186     FilterCacheType lastCacheType_ = FilterCacheType::NONE;
187     bool stagingIsOccluded_ = false;
188 
189     // force cache with cacheUpdateInterval_
190     bool stagingIsLargeArea_ = false;
191     bool canSkipFrame_ = false;
192     bool stagingIsSkipFrame_  = false;
193     RSFilter::FilterType filterType_ = RSFilter::NONE;
194 
195     // Cache age, used to determine if we can delay the cache update.
196     int cacheUpdateInterval_ = 0;
197     bool isFilterCacheValid_ = false; // catch status in current frame
198     // Whether we need to purge the cache after this frame.
199     bool pendingPurge_ = false;
200 
201 public:
202     static bool isCCMFilterCacheEnable_;
203     static bool isCCMEffectMergeEnable_;
204 };
205 } // namespace Rosen
206 } // namespace OHOS
207 #endif
208 
209 #endif // RENDER_SERVICE_BASE_PROPERTY_RS_FILTER_CACHE_MANAGER_H
210