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