• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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