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 SetActiveSurfaceRect(const RectI & rect)120 void SetActiveSurfaceRect(const RectI& rect) 121 { 122 auto dstRect = surfaceRect_.IntersectRect(rect); 123 lastActiveSurfaceRect_ = activeSurfaceRect_; 124 activeSurfaceRect_ = dstRect; 125 } 126 IsActiveSurfaceRectChanged()127 bool IsActiveSurfaceRectChanged() const 128 { 129 return lastActiveSurfaceRect_ != activeSurfaceRect_; 130 } 131 GetLastActiveSurfaceRect()132 const RectI& GetLastActiveSurfaceRect() const 133 { 134 return lastActiveSurfaceRect_; 135 } 136 GetActiveSurfaceRect()137 const RectI& GetActiveSurfaceRect() const 138 { 139 return activeSurfaceRect_; 140 } 141 SetSurfaceRect(const RectI & rect)142 bool SetSurfaceRect(const RectI& rect) 143 { 144 if (rect.IsEmpty()) { 145 return false; 146 } 147 surfaceRect_ = rect; 148 return true; 149 } 150 SetSurfaceSize(const int32_t width,const int32_t height)151 bool SetSurfaceSize(const int32_t width, const int32_t height) 152 { 153 return SetSurfaceRect(RectI(0, 0, width, height)); 154 } 155 GetSurfaceRect()156 RectI GetSurfaceRect() const 157 { 158 return surfaceRect_; 159 } 160 void MergeSurfaceRect(); 161 // Reset current frame dirtyregion to surfacerect to realize full refreshing 162 void ResetDirtyAsSurfaceSize(); 163 164 void UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType); 165 IsDebugRegionTypeEnable(DebugRegionType var)166 inline bool IsDebugRegionTypeEnable(DebugRegionType var) const 167 { 168 if (var < DebugRegionType::TYPE_MAX) { 169 return debugRegionEnabled_[var]; 170 } 171 return false; 172 } 173 // OnSync must be Executed after UpdateDirty API 174 void OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager); 175 176 // added for dirty region dfx 177 void UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE, 178 DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION, const RectI& rect = RectI()); 179 void GetDirtyRegionInfo(std::map<NodeId, RectI>& target, 180 RSRenderNodeType nodeType = RSRenderNodeType::CANVAS_NODE, 181 DirtyRegionType dirtyType = DirtyRegionType::UPDATE_DIRTY_REGION) const; 182 MarkAsTargetForDfx()183 void MarkAsTargetForDfx() 184 { 185 isDfxTarget_ = true; 186 } 187 IsTargetForDfx()188 bool IsTargetForDfx() { 189 return isDfxTarget_; 190 } 191 192 bool HasOffset(); 193 void SetOffset(int offsetX, int offsetY); 194 RectI GetOffsetedDirtyRegion() const; 195 GetMergedDirtyRegions()196 const std::vector<RectI>& GetMergedDirtyRegions() const 197 { 198 return mergedDirtyRegions_; 199 } 200 MergeDirtyHistoryInVirtual(unsigned int age)201 void MergeDirtyHistoryInVirtual(unsigned int age) 202 { 203 mergedDirtyInVirtualScreen_ = MergeHistory(age, currentFrameDirtyRegion_); 204 } 205 GetDirtyRegionInVirtual()206 RectI GetDirtyRegionInVirtual() const 207 { 208 return mergedDirtyInVirtualScreen_; 209 } 210 GetHwcDirtyRegion()211 RectI GetHwcDirtyRegion() const 212 { 213 return hwcDirtyRegion_; 214 } 215 216 private: 217 RectI MergeHistory(unsigned int age, RectI rect) const; 218 void PushHistory(RectI rect); 219 // get his rect according to index offset 220 RectI GetHistory(unsigned int i) const; 221 void AlignHistory(); 222 223 RectI lastActiveSurfaceRect_; // active rect of the canvas surface in the last frame 224 RectI activeSurfaceRect_; // active rect of the canvas surface 225 RectI surfaceRect_; // rect of the canvas surface 226 RectI dirtyRegion_; // dirtyregion after merge history 227 RectI currentFrameDirtyRegion_; // dirtyRegion in current frame 228 RectI hwcDirtyRegion_; // hwc dirty region used in virtual screen 229 RectI debugRect_; // dirtyRegion for showing currentFreshRate debug 230 RectI mergedDirtyInVirtualScreen_; 231 std::vector<RectI> visitedDirtyRegions_ = {}; // visited app's dirtyRegion 232 std::vector<RectI> cacheableFilterRects_ = {}; // node's region if filter cachable 233 std::vector<RectI> mergedDirtyRegions_ = {}; 234 235 // added for dfx 236 std::vector<std::map<NodeId, RectI>> dirtyCanvasNodeInfo_; 237 std::vector<std::map<NodeId, RectI>> dirtySurfaceNodeInfo_; 238 std::vector<bool> debugRegionEnabled_; 239 bool isDfxTarget_ = false; 240 std::vector<RectI> dirtyHistory_; 241 int historyHead_ = -1; 242 unsigned int historySize_ = 0; 243 const unsigned HISTORY_QUEUE_MAX_SIZE = 10; 244 // may add new set function for bufferAge 245 unsigned int bufferAge_ = 0; 246 bool isDirtyRegionAlignedEnable_ = false; 247 bool isFilterCacheRectValid_ = true; 248 bool isDisplayDirtyManager_ = false; 249 std::atomic<bool> isSync_ = false; 250 251 // Used for coordinate switch, i.e. dirtyRegion = dirtyRegion + offset. 252 // For example when dirtymanager is used in cachesurface when surfacenode's 253 // shadow and surfacenode are cached in a surface, dirty region's coordinate should start 254 // from shadow's left-top rather than that of displaynode. 255 // Normally, this value should be set to: 256 // offsetX_ = - surfacePos.x + shadowWidth 257 // offsetY_ = - surfacePos.y + shadowHeight 258 bool hasOffset_ = false; 259 int offsetX_ = 0; 260 int offsetY_ = 0; 261 }; 262 } // namespace Rosen 263 } // namespace OHOS 264 265 #endif // RENDER_SERVICE_CLIENT_CORE_PIPELINE_RS_DIRTY_REGION_MANAGER_H 266