1 /* 2 * Copyright (c) 2021-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 #ifndef RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_DIRTY_REGION_MANAGER_H 16 #define RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_DIRTY_REGION_MANAGER_H 17 18 #include <map> 19 #include <vector> 20 21 #include "common/rs_macros.h" 22 #include "common/rs_rect.h" 23 #include "platform/common/rs_system_properties.h" 24 25 namespace OHOS { 26 namespace Rosen { 27 // classify dfx debug options 28 enum DebugRegionType { 29 CURRENT_SUB = 0, 30 CURRENT_WHOLE, 31 MULTI_HISTORY, 32 EGL_DAMAGE, 33 TYPE_MAX 34 }; 35 36 // classify types that cause region dirty 37 enum DirtyRegionType { 38 UPDATE_DIRTY_REGION = 0, 39 OVERLAY_RECT, 40 FILTER_RECT, 41 SHADOW_RECT, 42 PREPARE_CLIP_RECT, 43 REMOVE_CHILD_RECT, 44 RENDER_PROPERTIES_RECT, 45 CANVAS_NODE_SKIP_RECT, 46 OUTLINE_RECT, 47 SUBTREE_SKIP_OUT_OF_PARENT_RECT, 48 TYPE_AMOUNT 49 }; 50 51 class RSB_EXPORT RSDirtyRegionManager final { 52 friend class RSFilterCacheManager; 53 public: 54 static constexpr int32_t ALIGNED_BITS = 32; 55 RSDirtyRegionManager(); 56 RSDirtyRegionManager(bool isDisplayDirtyManager); 57 ~RSDirtyRegionManager() = default; 58 // update/expand current frame dirtyregion 59 void MergeDirtyRect(const RectI& rect, bool isDebugRect = false); 60 // update/expand current frame dirtyregion if intersect 61 bool MergeDirtyRectIfIntersect(const RectI& rect); 62 // update/expand dirtyregion after merge history 63 void MergeDirtyRectAfterMergeHistory(const RectI& rect); 64 // clip dirtyregion in current frame 65 void IntersectDirtyRect(const RectI& rect); 66 // Clip currentframe dirtyRegion intersected with surfaceRect 67 void ClipDirtyRectWithinSurface(); 68 // clear allinfo except dirtyregion history 69 void Clear(); 70 // record hwc region for virtual screen 71 void MergeHwcDirtyRect(const RectI& rect); 72 73 // update current frame's visited dirtyregion 74 void UpdateVisitedDirtyRects(const std::vector<RectI>& rects); 75 RectI GetIntersectedVisitedDirtyRect(const RectI& absRect) const; 76 void UpdateCacheableFilterRect(const RectI& rect); 77 bool IfCacheableFilterRectFullyCover(const RectI& targetRect); IsCacheableFilterRectEmpty()78 bool IsCacheableFilterRectEmpty() const 79 { 80 return cacheableFilterRects_.empty(); 81 } 82 InvalidateFilterCacheRect()83 void InvalidateFilterCacheRect() 84 { 85 isFilterCacheRectValid_ = false; 86 } 87 IsFilterCacheRectValid()88 bool IsFilterCacheRectValid() 89 { 90 return isFilterCacheRectValid_; 91 } 92 93 // return current frame dirtyregion, can be changed in prepare and process (displaynode) stage 94 const RectI& GetCurrentFrameDirtyRegion(); 95 // return merged historical region 96 const RectI& GetDirtyRegion() const; 97 // return mapAbs dirtyRegion 98 const RectI& GetCurrentFrameMpsAbsDirtyRect() const; 99 void SetCurrentFrameDirtyRect(const RectI& dirtyRect); 100 /* return merged historical region upside down in left-bottom origin coordinate 101 reason: when use OpenGL SetDamageRegion, coordinate system conversion exists. 102 */ 103 RectI GetDirtyRegionFlipWithinSurface() const; 104 // return current frame's region from dirtyregion history 105 const RectI& GetLatestDirtyRegion() const; 106 // return merged historical region upside down in left-bottom origin coordinate 107 RectI GetRectFlipWithinSurface(const RectI& rect) const; 108 // get aligned rect as times of alignedBits 109 static RectI GetPixelAlignedRect(const RectI& rect, int32_t alignedBits = ALIGNED_BITS); 110 // return true if current frame dirtyregion is not empty 111 bool IsCurrentFrameDirty() const; 112 // return true if dirtyregion after merge history is not empty 113 bool IsDirty() const; 114 // push currentframe dirtyregion into history, and merge history according to bufferage 115 void UpdateDirty(bool enableAligned = false); 116 // align current frame dirtyregion before merge history 117 void UpdateDirtyByAligned(int32_t alignedBits = ALIGNED_BITS); 118 bool SetBufferAge(const int age); 119 bool SetSurfaceSize(const int32_t width, const int32_t height); GetSurfaceRect()120 RectI GetSurfaceRect() const 121 { 122 return surfaceRect_; 123 } 124 void MergeSurfaceRect(); 125 // Reset current frame dirtyregion to surfacerect to realize full refreshing 126 void ResetDirtyAsSurfaceSize(); 127 128 void UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType); 129 IsDebugRegionTypeEnable(DebugRegionType var)130 inline bool IsDebugRegionTypeEnable(DebugRegionType var) const 131 { 132 if (var < DebugRegionType::TYPE_MAX) { 133 return debugRegionEnabled_[var]; 134 } 135 return false; 136 } 137 // OnSync must be Executed after UpdateDirty API 138 void OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager); 139 140 // added for dirty region dfx 141 void UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE, 142 DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION, const RectI& rect = RectI()); 143 void GetDirtyRegionInfo(std::map<NodeId, RectI>& target, 144 RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE, 145 DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION) const; 146 MarkAsTargetForDfx()147 void MarkAsTargetForDfx() 148 { 149 isDfxTarget_ = true; 150 } 151 IsTargetForDfx()152 bool IsTargetForDfx() { 153 return isDfxTarget_; 154 } 155 156 bool HasOffset(); 157 void SetOffset(int offsetX, int offsetY); 158 RectI GetOffsetedDirtyRegion() const; 159 GetMergedDirtyRegions()160 const std::vector<RectI>& GetMergedDirtyRegions() const 161 { 162 return mergedDirtyRegions_; 163 } 164 MergeDirtyHistoryInVirtual(unsigned int age)165 void MergeDirtyHistoryInVirtual(unsigned int age) 166 { 167 mergedDirtyInVirtualScreen_ = MergeHistory(age, currentFrameDirtyRegion_); 168 } 169 GetDirtyRegionInVirtual()170 RectI GetDirtyRegionInVirtual() const 171 { 172 return mergedDirtyInVirtualScreen_; 173 } 174 GetHwcDirtyRegion()175 RectI GetHwcDirtyRegion() const 176 { 177 return hwcDirtyRegion_; 178 } 179 180 private: 181 RectI MergeHistory(unsigned int age, RectI rect) const; 182 void PushHistory(RectI rect); 183 // get his rect according to index offset 184 RectI GetHistory(unsigned int i) const; 185 void AlignHistory(); 186 187 RectI surfaceRect_; // dirtyregion clipbounds 188 RectI dirtyRegion_; // dirtyregion after merge history 189 RectI currentFrameDirtyRegion_; // dirtyRegion in current frame 190 RectI hwcDirtyRegion_; // hwc dirty region used in virtual screen 191 RectI debugRect_; // dirtyRegion for showing currentFreshRate debug 192 RectI mergedDirtyInVirtualScreen_; 193 std::vector<RectI> visitedDirtyRegions_ = {}; // visited app's dirtyRegion 194 std::vector<RectI> cacheableFilterRects_ = {}; // node's region if filter cachable 195 std::vector<RectI> mergedDirtyRegions_ = {}; 196 197 // added for dfx 198 std::vector<std::map<NodeId, RectI>> dirtyCanvasNodeInfo_; 199 std::vector<std::map<NodeId, RectI>> dirtySurfaceNodeInfo_; 200 std::vector<bool> debugRegionEnabled_; 201 bool isDfxTarget_ = false; 202 std::vector<RectI> dirtyHistory_; 203 int historyHead_ = -1; 204 unsigned int historySize_ = 0; 205 const unsigned HISTORY_QUEUE_MAX_SIZE = 10; 206 // may add new set function for bufferAge 207 unsigned int bufferAge_ = 0; 208 bool isDirtyRegionAlignedEnable_ = false; 209 bool isFilterCacheRectValid_ = true; 210 bool isDisplayDirtyManager_ = false; 211 std::atomic<bool> isSync_ = false; 212 213 // Used for coordinate switch, i.e. dirtyRegion = dirtyRegion + offset. 214 // For example when dirtymanager is used in cachesurface when surfacenode's 215 // shadow and surfacenode are cached in a surface, dirty region's coordinate should start 216 // from shadow's left-top rather than that of displaynode. 217 // Normally, this value should be set to: 218 // offsetX_ = - surfacePos.x + shadowWidth 219 // offsetY_ = - surfacePos.y + shadowHeight 220 bool hasOffset_ = false; 221 int offsetX_ = 0; 222 int offsetY_ = 0; 223 }; 224 } // namespace Rosen 225 } // namespace OHOS 226 227 #endif // RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_DIRTY_REGION_MANAGER_H 228