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 struct DrawFilterParams { 62 bool needSnapshotOutset; 63 bool shouldClearFilteredCache; 64 }; 65 66 // Call this function during the process phase to apply the filter. Depending on the cache state, it may either 67 // regenerate the cache or reuse the existing cache. 68 // Note: If srcRect or dstRect is empty, we'll use the DeviceClipRect as the corresponding rect. 69 void DrawFilter(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, 70 const DrawFilterParams params = { true, false }, const std::optional<Drawing::RectI>& srcRect = std::nullopt, 71 const std::optional<Drawing::RectI>& dstRect = std::nullopt); 72 73 // This function is similar to DrawFilter(), but instead of drawing anything on the canvas, it simply returns the 74 // cache data. This is used with effect component in RSPropertiesPainter::DrawBackgroundEffect. 75 const std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> GeneratedCachedEffectData(RSPaintFilterCanvas& canvas, 76 const std::shared_ptr<RSDrawingFilter>& filter, const std::optional<Drawing::RectI>& srcRect = std::nullopt, 77 const std::optional<Drawing::RectI>& dstRect = std::nullopt); 78 79 uint8_t CalcDirectionBias(const Drawing::Matrix& mat); 80 enum CacheType : uint8_t { 81 CACHE_TYPE_NONE = 0, 82 CACHE_TYPE_SNAPSHOT = 1, 83 CACHE_TYPE_FILTERED_SNAPSHOT = 2, 84 CACHE_TYPE_BOTH = CACHE_TYPE_SNAPSHOT | CACHE_TYPE_FILTERED_SNAPSHOT, 85 }; 86 87 // Call this function to manually invalidate the cache. The next time DrawFilter() is called, it will regenerate the 88 // cache. 89 void ReleaseCacheOffTree(); 90 void StopFilterPartialRender(); 91 void InvalidateFilterCache(FilterCacheType clearType = FilterCacheType::BOTH); 92 93 // To reduce memory usage, clear one of the cached images. 94 void CompactFilterCache(bool shouldClearFilteredCache); 95 IsCacheValid()96 inline bool IsCacheValid() const 97 { 98 return cachedSnapshot_ != nullptr || cachedFilteredSnapshot_ != nullptr; 99 } 100 101 static bool GetFilterInvalid(); 102 static void SetFilterInvalid(bool invalidFilter); 103 104 private: 105 void TakeSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, 106 const Drawing::RectI& srcRect); 107 void GenerateFilteredSnapshot( 108 RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, const Drawing::RectI& dstRect); 109 bool DrawFilterWithoutSnapshot(RSPaintFilterCanvas& canvas, const std::shared_ptr<RSDrawingFilter>& filter, 110 const Drawing::RectI& src, const Drawing::RectI& dst, bool shouldClearFilteredCache); 111 void DrawCachedFilteredSnapshot(RSPaintFilterCanvas& canvas, const Drawing::RectI& dstRect) const; 112 // Validate the input srcRect and dstRect, and return the validated rects. 113 std::tuple<Drawing::RectI, Drawing::RectI> ValidateParams(RSPaintFilterCanvas& canvas, 114 const std::optional<Drawing::RectI>& srcRect, const std::optional<Drawing::RectI>& dstRect); 115 inline static void ClipVisibleRect(RSPaintFilterCanvas& canvas); 116 // Check if the cache is valid in current GrContext, since FilterCache will never be used in multi-thread 117 // environment, we don't need to attempt to reattach SkImages. 118 void CheckCachedImages(RSPaintFilterCanvas& canvas); 119 120 const char* GetCacheState() const; 121 122 // We keep both the snapshot and filtered snapshot in the cache, and clear unneeded one in next frame. 123 // Note: rect in cachedSnapshot_ and cachedFilteredSnapshot_ is in device coordinate. 124 std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedSnapshot_ = nullptr; 125 std::shared_ptr<RSPaintFilterCanvas::CachedEffectData> cachedFilteredSnapshot_ = nullptr; 126 127 // Hash of previous filter, used to determine if we need to invalidate cachedFilteredSnapshot_. 128 uint32_t cachedFilterHash_ = 0; 129 // Cache age, used to determine if we can delay the cache update. 130 int cacheUpdateInterval_ = 0; 131 // Whether we need to purge the cache after this frame. 132 bool pendingPurge_ = false; 133 // Region of the cached image, used to determine if we need to invalidate the cache. 134 RectI snapshotRegion_; // Note: in device coordinate. 135 136 // This flag is used to notify unirender_thread need to clear gpu memory. 137 static inline std::atomic_bool filterInvalid_ = false; 138 }; 139 } // namespace Rosen 140 } // namespace OHOS 141 #endif 142 143 #endif // RENDER_SERVICE_BASE_PROPERTY_RS_FILTER_CACHE_MANAGER_H 144