• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "pipeline/rs_dirty_region_manager.h"
17 
18 namespace OHOS {
19 namespace Rosen {
RSDirtyRegionManager()20 RSDirtyRegionManager::RSDirtyRegionManager()
21 {
22     dirtyHistory_.resize(HISTORY_QUEUE_MAX_SIZE);
23     debugRegionEnabled_.resize(DebugRegionType::TYPE_MAX);
24 }
25 
MergeDirtyRect(const RectI & rect)26 void RSDirtyRegionManager::MergeDirtyRect(const RectI& rect)
27 {
28     if (rect.IsEmpty()) {
29         return;
30     }
31     if (currentFrameDirtyRegion_.IsEmpty()) {
32         currentFrameDirtyRegion_ = rect;
33     } else {
34         currentFrameDirtyRegion_ = currentFrameDirtyRegion_.JoinRect(rect);
35     }
36 }
37 
MergeDirtyRectAfterMergeHistory(const RectI & rect)38 void RSDirtyRegionManager::MergeDirtyRectAfterMergeHistory(const RectI& rect)
39 {
40     if (rect.IsEmpty()) {
41         return;
42     }
43     if (dirtyRegion_.IsEmpty()) {
44         dirtyRegion_ = rect;
45     } else {
46         dirtyRegion_ = dirtyRegion_.JoinRect(rect);
47     }
48 }
49 
UpdateVisitedDirtyRects(const std::vector<RectI> & rects)50 void RSDirtyRegionManager::UpdateVisitedDirtyRects(const std::vector<RectI>& rects)
51 {
52     if (rects.empty()) {
53         visitedDirtyRegions_.clear();
54         return;
55     }
56     visitedDirtyRegions_ = rects;
57 }
58 
GetIntersectedVisitedDirtyRect(const RectI & absRect) const59 RectI RSDirtyRegionManager::GetIntersectedVisitedDirtyRect(const RectI& absRect) const
60 {
61     RectI belowDirty = currentFrameDirtyRegion_;
62     for (auto subDirty : visitedDirtyRegions_) {
63         if (absRect.IsInsideOf(belowDirty)) {
64             return belowDirty;
65         }
66         belowDirty = belowDirty.JoinRect(subDirty.IntersectRect(absRect));
67     }
68     return belowDirty;
69 }
70 
UpdateCacheableFilterRect(const RectI & rect)71 void RSDirtyRegionManager::UpdateCacheableFilterRect(const RectI& rect)
72 {
73     if (rect.IsEmpty()) {
74         return;
75     }
76     cacheableFilterRects_.emplace_back(rect);
77 }
78 
IfCacheableFilterRectFullyCover(const RectI & targetRect)79 bool RSDirtyRegionManager::IfCacheableFilterRectFullyCover(const RectI& targetRect)
80 {
81     for (auto rect : cacheableFilterRects_) {
82         if (targetRect.IsInsideOf(rect)) {
83             return true;
84         }
85     }
86     return false;
87 }
88 
IntersectDirtyRect(const RectI & rect)89 void RSDirtyRegionManager::IntersectDirtyRect(const RectI& rect)
90 {
91     currentFrameDirtyRegion_ = currentFrameDirtyRegion_.IntersectRect(rect);
92 }
93 
ClipDirtyRectWithinSurface()94 void RSDirtyRegionManager::ClipDirtyRectWithinSurface()
95 {
96     int left = std::max(std::max(currentFrameDirtyRegion_.left_, 0), surfaceRect_.left_);
97     int top = std::max(std::max(currentFrameDirtyRegion_.top_, 0), surfaceRect_.top_);
98     int width = std::min(currentFrameDirtyRegion_.GetRight(), surfaceRect_.GetRight()) - left;
99     int height = std::min(currentFrameDirtyRegion_.GetBottom(), surfaceRect_.GetBottom()) - top;
100     // If new region is invalid, currentFrameDirtyRegion_ would be reset as [0, 0, 0, 0]
101     currentFrameDirtyRegion_ = ((width <= 0) || (height <= 0)) ? RectI() : RectI(left, top, width, height);
102 }
103 
GetCurrentFrameDirtyRegion()104 const RectI& RSDirtyRegionManager::GetCurrentFrameDirtyRegion()
105 {
106     return currentFrameDirtyRegion_;
107 }
108 
GetDirtyRegion() const109 const RectI& RSDirtyRegionManager::GetDirtyRegion() const
110 {
111     return dirtyRegion_;
112 }
113 
GetDirtyRegionFlipWithinSurface() const114 RectI RSDirtyRegionManager::GetDirtyRegionFlipWithinSurface() const
115 {
116     RectI glRect;
117     if (isDirtyRegionAlignedEnable_) {
118         glRect = GetPixelAlignedRect(dirtyRegion_);
119     } else {
120         glRect = dirtyRegion_;
121     }
122     // left-top to left-bottom corner(in current surface)
123     glRect.top_ = surfaceRect_.height_ - glRect.top_ - glRect.height_;
124     return glRect;
125 }
126 
GetRectFlipWithinSurface(const RectI & rect) const127 RectI RSDirtyRegionManager::GetRectFlipWithinSurface(const RectI& rect) const
128 {
129     RectI glRect = rect;
130     // left-top to left-bottom corner(in current surface)
131     glRect.top_ = surfaceRect_.height_ - rect.top_ - rect.height_;
132     return glRect;
133 }
134 
GetLatestDirtyRegion() const135 const RectI& RSDirtyRegionManager::GetLatestDirtyRegion() const
136 {
137     if (historyHead_ < 0) {
138         return dirtyRegion_;
139     }
140     return dirtyHistory_[historyHead_];
141 }
142 
GetPixelAlignedRect(const RectI & rect,int32_t alignedBits)143 RectI RSDirtyRegionManager::GetPixelAlignedRect(const RectI& rect, int32_t alignedBits)
144 {
145     RectI newRect = rect;
146     if (alignedBits > 1) {
147         int32_t left = (rect.left_ / alignedBits) * alignedBits;
148         int32_t top = (rect.top_ / alignedBits) * alignedBits;
149         int32_t width = ((rect.GetRight() + alignedBits - 1) / alignedBits) * alignedBits - left;
150         int32_t height = ((rect.GetBottom() + alignedBits - 1) / alignedBits) * alignedBits - top;
151         newRect = RectI(left, top, width, height);
152     }
153     return newRect;
154 }
155 
Clear()156 void RSDirtyRegionManager::Clear()
157 {
158     dirtyRegion_.Clear();
159     currentFrameDirtyRegion_.Clear();
160     visitedDirtyRegions_.clear();
161     cacheableFilterRects_.clear();
162     dirtyCanvasNodeInfo_.clear();
163     dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
164     dirtySurfaceNodeInfo_.clear();
165     dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
166     isDfxTarget_ = false;
167 }
168 
IsCurrentFrameDirty() const169 bool RSDirtyRegionManager::IsCurrentFrameDirty() const
170 {
171     return !currentFrameDirtyRegion_.IsEmpty();
172 }
173 
IsDirty() const174 bool RSDirtyRegionManager::IsDirty() const
175 {
176     return !dirtyRegion_.IsEmpty();
177 }
178 
UpdateDirty(bool enableAligned)179 void RSDirtyRegionManager::UpdateDirty(bool enableAligned)
180 {
181     if (enableAligned) {
182         UpdateDirtyByAligned();
183     }
184     // if last frame doesn't align and current frame need align, we should align history ditry regions.
185     if (!isDirtyRegionAlignedEnable_ && enableAligned) {
186         AlignHistory();
187     }
188     isDirtyRegionAlignedEnable_ = enableAligned;
189     PushHistory(currentFrameDirtyRegion_);
190     dirtyRegion_ = MergeHistory(bufferAge_, currentFrameDirtyRegion_);
191 }
192 
UpdateDirtyByAligned(int32_t alignedBits)193 void RSDirtyRegionManager::UpdateDirtyByAligned(int32_t alignedBits)
194 {
195     currentFrameDirtyRegion_ = GetPixelAlignedRect(currentFrameDirtyRegion_, alignedBits);
196 }
197 
UpdateDirtyRegionInfoForDfx(NodeId id,RSRenderNodeType nodeType,DirtyRegionType dirtyType,const RectI & rect)198 void RSDirtyRegionManager::UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType,
199     DirtyRegionType dirtyType, const RectI& rect)
200 {
201     if (dirtyType >= DirtyRegionType::TYPE_AMOUNT || dirtyType < 0 || rect.IsEmpty()) {
202         return;
203     }
204     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
205         dirtyCanvasNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
206     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
207         dirtySurfaceNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
208     }
209 }
210 
GetDirtyRegionInfo(std::map<NodeId,RectI> & target,RSRenderNodeType nodeType,DirtyRegionType dirtyType) const211 void RSDirtyRegionManager::GetDirtyRegionInfo(std::map<NodeId, RectI>& target,
212     RSRenderNodeType nodeType, DirtyRegionType dirtyType) const
213 {
214     target.clear();
215     if (dirtyType >= DirtyRegionType::TYPE_AMOUNT || dirtyType < 0) {
216         return;
217     }
218     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
219         target = dirtyCanvasNodeInfo_[dirtyType];
220     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
221         target = dirtySurfaceNodeInfo_[dirtyType];
222     }
223 }
224 
HasOffset()225 bool RSDirtyRegionManager::HasOffset()
226 {
227     return hasOffset_;
228 }
SetOffset(int offsetX,int offsetY)229 void RSDirtyRegionManager::SetOffset(int offsetX, int offsetY)
230 {
231     offsetX_ = offsetX;
232     offsetY_ = offsetY;
233 }
GetOffsetedDirtyRegion() const234 RectI RSDirtyRegionManager::GetOffsetedDirtyRegion() const
235 {
236     return GetDirtyRegion().Offset(offsetX_, offsetY_);
237 }
238 
SetBufferAge(const int age)239 bool RSDirtyRegionManager::SetBufferAge(const int age)
240 {
241     if (age < 0) {
242         bufferAge_ = 0; // reset invalid age
243         return false;
244     }
245     bufferAge_ = static_cast<unsigned int>(age);
246     return true;
247 }
248 
SetSurfaceSize(const int32_t width,const int32_t height)249 bool RSDirtyRegionManager::SetSurfaceSize(const int32_t width, const int32_t height)
250 {
251     if (width < 0 || height < 0) {
252         return false;
253     }
254     surfaceRect_ = RectI(0, 0, width, height);
255     return true;
256 }
257 
MergeSurfaceRect()258 void RSDirtyRegionManager::MergeSurfaceRect()
259 {
260     return MergeDirtyRect(GetSurfaceRect());
261 }
262 
ResetDirtyAsSurfaceSize()263 void RSDirtyRegionManager::ResetDirtyAsSurfaceSize()
264 {
265     dirtyRegion_ = surfaceRect_;
266 }
267 
UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)268 void RSDirtyRegionManager::UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)
269 {
270     debugRegionEnabled_.assign(DebugRegionType::TYPE_MAX, false);
271     switch (dirtyDebugType) {
272         case DirtyRegionDebugType::CURRENT_SUB:
273             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
274             break;
275         case DirtyRegionDebugType::CURRENT_WHOLE:
276             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
277             break;
278         case DirtyRegionDebugType::MULTI_HISTORY:
279             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
280             break;
281         case DirtyRegionDebugType::CURRENT_SUB_AND_WHOLE:
282             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
283             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
284             break;
285         case DirtyRegionDebugType::CURRENT_WHOLE_AND_MULTI_HISTORY:
286             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
287             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
288             break;
289         case DirtyRegionDebugType::EGL_DAMAGE:
290             debugRegionEnabled_[DebugRegionType::EGL_DAMAGE] = true;
291             break;
292         case DirtyRegionDebugType::DISABLED:
293         default:
294             break;
295     }
296 }
297 
MergeHistory(unsigned int age,RectI rect) const298 RectI RSDirtyRegionManager::MergeHistory(unsigned int age, RectI rect) const
299 {
300     if (age == 0 || age > historySize_) {
301         return surfaceRect_;
302     }
303     // GetHistory(historySize_) is equal to dirtyHistory_[historyHead_] (latest his rect)
304     // therefore, this loop merges rect with age frames' dirtyRect
305     // Attention: should not set i >= 0 for unsigned int!!!!!
306     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
307         auto subRect = GetHistory((i - 1));
308         if (subRect.IsEmpty()) {
309             continue;
310         }
311         if (rect.IsEmpty()) {
312             rect = subRect;
313             continue;
314         }
315         // only join valid his dirty region
316         rect = rect.JoinRect(subRect);
317     }
318     return rect;
319 }
320 
PushHistory(RectI rect)321 void RSDirtyRegionManager::PushHistory(RectI rect)
322 {
323     int next = (historyHead_ + 1) % HISTORY_QUEUE_MAX_SIZE;
324     dirtyHistory_[next] = rect;
325     if (historySize_ < HISTORY_QUEUE_MAX_SIZE) {
326         ++historySize_;
327     }
328     historyHead_ = next;
329 }
330 
GetHistory(unsigned int i) const331 RectI RSDirtyRegionManager::GetHistory(unsigned int i) const
332 {
333     if (i >= HISTORY_QUEUE_MAX_SIZE) {
334         i %= HISTORY_QUEUE_MAX_SIZE;
335     }
336     if (historySize_ > 0) {
337         i = (i + historyHead_) % historySize_;
338     }
339     return dirtyHistory_[i];
340 }
341 
AlignHistory()342 void RSDirtyRegionManager::AlignHistory()
343 {
344     for (uint8_t i = 0; i < dirtyHistory_.size(); i++) {
345         dirtyHistory_[i] = GetPixelAlignedRect(dirtyHistory_[i]);
346     }
347 }
348 
349 } // namespace Rosen
350 } // namespace OHOS
351