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