• 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 #include <string>
19 
20 #include "common/rs_occlusion_region.h"
21 #include "common/rs_optional_trace.h"
22 
23 #include "platform/common/rs_log.h"
24 namespace OHOS {
25 namespace Rosen {
RSDirtyRegionManager()26 RSDirtyRegionManager::RSDirtyRegionManager()
27 {
28     dirtyHistory_.resize(HISTORY_QUEUE_MAX_SIZE);
29     advancedDirtyHistory_.resize(HISTORY_QUEUE_MAX_SIZE);
30     debugRegionEnabled_.resize(DebugRegionType::TYPE_MAX);
31     dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
32     dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
33 }
34 
RSDirtyRegionManager(bool isDisplayDirtyManager)35 RSDirtyRegionManager::RSDirtyRegionManager(bool isDisplayDirtyManager)
36 {
37     dirtyHistory_.resize(HISTORY_QUEUE_MAX_SIZE);
38     advancedDirtyHistory_.resize(HISTORY_QUEUE_MAX_SIZE);
39     debugRegionEnabled_.resize(DebugRegionType::TYPE_MAX);
40     dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
41     dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
42     isDisplayDirtyManager_ = isDisplayDirtyManager;
43 }
44 
MergeDirtyRect(const RectI & rect,bool isDebugRect)45 void RSDirtyRegionManager::MergeDirtyRect(const RectI& rect, bool isDebugRect)
46 {
47     if (rect.IsEmpty()) {
48         return;
49     }
50     if (currentFrameDirtyRegion_.IsEmpty()) {
51         currentFrameDirtyRegion_ = rect;
52     } else {
53         currentFrameDirtyRegion_ = currentFrameDirtyRegion_.JoinRect(rect);
54     }
55     UpdateCurrentFrameAdvancedDirtyRegion(rect);
56     if (isDisplayDirtyManager_) {
57         mergedDirtyRegions_.emplace_back(rect);
58     }
59     if (isDebugRect) {
60         debugRect_ = rect;
61     }
62 }
63 
UpdateCurrentFrameAdvancedDirtyRegion(RectI rect)64 void RSDirtyRegionManager::UpdateCurrentFrameAdvancedDirtyRegion(RectI rect)
65 {
66     currentFrameAdvancedDirtyRegion_.emplace_back(rect);
67     if (static_cast<int>(currentFrameAdvancedDirtyRegion_.size()) > maxNumOfDirtyRects_) {
68         currentFrameAdvancedDirtyRegion_.clear();
69         currentFrameAdvancedDirtyRegion_.emplace_back(currentFrameDirtyRegion_);
70     }
71 }
72 
MergeHwcDirtyRect(const RectI & rect)73 void RSDirtyRegionManager::MergeHwcDirtyRect(const RectI& rect)
74 {
75     if (rect.IsEmpty()) {
76         return;
77     }
78     if (hwcDirtyRegion_.IsEmpty()) {
79         hwcDirtyRegion_ = rect;
80     } else {
81         hwcDirtyRegion_ = hwcDirtyRegion_.JoinRect(rect);
82     }
83     Occlusion::Region tempRegion = Occlusion::Region(Occlusion::Rect(rect));
84     for (auto& r : advancedDirtyRegion_) {
85         Occlusion::Region region = Occlusion::Region(Occlusion::Rect(r));
86         tempRegion.OrSelf(region);
87     }
88     advancedDirtyRegion_ = tempRegion.GetRegionRectIs();
89 }
90 
MergeDirtyRectIfIntersect(const RectI & rect)91 bool RSDirtyRegionManager::MergeDirtyRectIfIntersect(const RectI& rect)
92 {
93     if (!currentFrameDirtyRegion_.Intersect(rect)) {
94         return false;
95     }
96     currentFrameDirtyRegion_ = currentFrameDirtyRegion_.JoinRect(rect);
97     if (isDisplayDirtyManager_) {
98         mergedDirtyRegions_.emplace_back(rect);
99     }
100     return true;
101 }
102 
MergeDirtyRectAfterMergeHistory(const RectI & rect)103 void RSDirtyRegionManager::MergeDirtyRectAfterMergeHistory(const RectI& rect)
104 {
105     if (rect.IsEmpty()) {
106         return;
107     }
108     if (dirtyRegion_.IsEmpty()) {
109         dirtyRegion_ = rect;
110     } else {
111         dirtyRegion_ = dirtyRegion_.JoinRect(rect);
112     }
113 }
114 
UpdateVisitedDirtyRects(const std::vector<RectI> & rects)115 void RSDirtyRegionManager::UpdateVisitedDirtyRects(const std::vector<RectI>& rects)
116 {
117     if (rects.empty()) {
118         visitedDirtyRegions_.clear();
119         return;
120     }
121     visitedDirtyRegions_ = rects;
122 }
123 
GetIntersectedVisitedDirtyRect(const RectI & absRect) const124 RectI RSDirtyRegionManager::GetIntersectedVisitedDirtyRect(const RectI& absRect) const
125 {
126     RectI belowDirty = currentFrameDirtyRegion_;
127     for (const auto& subDirty : visitedDirtyRegions_) {
128         if (absRect.IsInsideOf(belowDirty)) {
129             return belowDirty;
130         }
131         belowDirty = belowDirty.JoinRect(subDirty.IntersectRect(absRect));
132     }
133     return belowDirty;
134 }
135 
UpdateCacheableFilterRect(const RectI & rect)136 void RSDirtyRegionManager::UpdateCacheableFilterRect(const RectI& rect)
137 {
138     if (rect.IsEmpty()) {
139         return;
140     }
141     cacheableFilterRects_.emplace_back(rect);
142 }
143 
IfCacheableFilterRectFullyCover(const RectI & targetRect)144 bool RSDirtyRegionManager::IfCacheableFilterRectFullyCover(const RectI& targetRect)
145 {
146     for (auto rect : cacheableFilterRects_) {
147         if (targetRect.IsInsideOf(rect)) {
148             return true;
149         }
150     }
151     return false;
152 }
153 
IntersectDirtyRect(const RectI & rect)154 void RSDirtyRegionManager::IntersectDirtyRect(const RectI& rect)
155 {
156     currentFrameDirtyRegion_ = currentFrameDirtyRegion_.IntersectRect(rect);
157     for (auto& frameRect : currentFrameAdvancedDirtyRegion_) {
158         frameRect = frameRect.IntersectRect(rect);
159     }
160 }
161 
ClipDirtyRectWithinSurface()162 void RSDirtyRegionManager::ClipDirtyRectWithinSurface()
163 {
164     auto clipRect = activeSurfaceRect_.IsEmpty() ? surfaceRect_ : activeSurfaceRect_;
165     int left = std::max(std::max(currentFrameDirtyRegion_.left_, 0), clipRect.left_);
166     int top = std::max(std::max(currentFrameDirtyRegion_.top_, 0), clipRect.top_);
167     int width = std::min(currentFrameDirtyRegion_.GetRight(), clipRect.GetRight()) - left;
168     int height = std::min(currentFrameDirtyRegion_.GetBottom(), clipRect.GetBottom()) - top;
169     // If new region is invalid, currentFrameDirtyRegion_ would be reset as [0, 0, 0, 0]
170     currentFrameDirtyRegion_ = ((width <= 0) || (height <= 0)) ? RectI() : RectI(left, top, width, height);
171 
172     for (auto& frameRect : currentFrameAdvancedDirtyRegion_) {
173         int left = std::max(std::max(frameRect.left_, 0), surfaceRect_.left_);
174         int top = std::max(std::max(frameRect.top_, 0), surfaceRect_.top_);
175         int width = std::min(frameRect.GetRight(), surfaceRect_.GetRight()) - left;
176         int height = std::min(frameRect.GetBottom(), surfaceRect_.GetBottom()) - top;
177         // If new region is invalid, frameRect would be reset as [0, 0, 0, 0]
178         frameRect = ((width <= 0) || (height <= 0)) ? RectI() : RectI(left, top, width, height);
179     }
180 }
181 
OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager)182 void RSDirtyRegionManager::OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager)
183 {
184     if (!targetManager) {
185         return;
186     }
187     RSDirtyRegionManager *ptr = targetManager.get();
188     ptr->lastActiveSurfaceRect_ = lastActiveSurfaceRect_;
189     ptr->activeSurfaceRect_ = activeSurfaceRect_;
190     ptr->surfaceRect_ = surfaceRect_;
191     ptr->dirtyRegion_ = dirtyRegion_;
192     ptr->advancedDirtyRegion_ = advancedDirtyRegion_;
193     ptr->advancedDirtyRegionType_ = advancedDirtyRegionType_;
194     ptr->hwcDirtyRegion_ = hwcDirtyRegion_;
195     ptr->currentFrameDirtyRegion_ = currentFrameDirtyRegion_;
196     ptr->uifirstFrameDirtyRegion_ = uifirstFrameDirtyRegion_;
197     ptr->currentFrameAdvancedDirtyRegion_ = currentFrameAdvancedDirtyRegion_;
198     ptr->maxNumOfDirtyRects_ = maxNumOfDirtyRects_;
199     ptr->dirtyRegionForQuickReject_ = {};
200     ptr->debugRect_ = debugRect_;
201     filterCollector_.OnSync(ptr->filterCollector_);
202     if (RSSystemProperties::GetDirtyRegionDebugType() != DirtyRegionDebugType::DISABLED) {
203         ptr->dirtySurfaceNodeInfo_ = dirtySurfaceNodeInfo_;
204         ptr->dirtyCanvasNodeInfo_ = dirtyCanvasNodeInfo_;
205         ptr->mergedDirtyRegions_ = mergedDirtyRegions_;
206     }
207     // To avoid the impact of the remaining surface dirty on global dirty when nodes are skipped the next frame.
208     Clear();
209     uifirstFrameDirtyRegion_.Clear();
210     // check if the switch is opened
211     UpdateMaxNumOfDirtyRectByState();
212 }
213 
GetDirtyRegionFlipWithinSurface() const214 RectI RSDirtyRegionManager::GetDirtyRegionFlipWithinSurface() const
215 {
216     RectI glRect;
217     if (isDirtyRegionAlignedEnable_) {
218         glRect = GetPixelAlignedRect(dirtyRegion_);
219     } else {
220         glRect = dirtyRegion_;
221     }
222 
223     if (!RSSystemProperties::IsUseVulkan()) {
224         // left-top to left-bottom corner(in current surface)
225         glRect.top_ = surfaceRect_.height_ - glRect.top_ - glRect.height_;
226     }
227     return glRect;
228 }
229 
GetRectFlipWithinSurface(const RectI & rect) const230 RectI RSDirtyRegionManager::GetRectFlipWithinSurface(const RectI& rect) const
231 {
232     RectI glRect = rect;
233 
234     if (!RSSystemProperties::IsUseVulkan()) {
235         // left-top to left-bottom corner(in current surface)
236         glRect.top_ = surfaceRect_.height_ - rect.top_ - rect.height_;
237     }
238     return glRect;
239 }
240 
GetLatestDirtyRegion() const241 const RectI& RSDirtyRegionManager::GetLatestDirtyRegion() const
242 {
243     if (historyHead_ < 0) {
244         return dirtyRegion_;
245     }
246     return dirtyHistory_[historyHead_];
247 }
248 
GetPixelAlignedRect(const RectI & rect,int32_t alignedBits)249 RectI RSDirtyRegionManager::GetPixelAlignedRect(const RectI& rect, int32_t alignedBits)
250 {
251     RectI newRect = rect;
252     if (alignedBits > 1) {
253         int32_t left = (rect.left_ / alignedBits) * alignedBits;
254         int32_t top = (rect.top_ / alignedBits) * alignedBits;
255         int32_t width = ((rect.GetRight() + alignedBits - 1) / alignedBits) * alignedBits - left;
256         int32_t height = ((rect.GetBottom() + alignedBits - 1) / alignedBits) * alignedBits - top;
257         newRect = RectI(left, top, width, height);
258     }
259     return newRect;
260 }
261 
Clear()262 void RSDirtyRegionManager::Clear()
263 {
264     dirtyRegion_.Clear();
265     advancedDirtyRegion_.clear();
266     currentFrameDirtyRegion_.Clear();
267     currentFrameAdvancedDirtyRegion_.clear();
268     hwcDirtyRegion_.Clear();
269     visitedDirtyRegions_.clear();
270     mergedDirtyRegions_.clear();
271     cacheableFilterRects_.clear();
272     dirtyCanvasNodeInfo_.clear();
273     dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
274     dirtySurfaceNodeInfo_.clear();
275     dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
276     isDfxTarget_ = false;
277     isFilterCacheRectValid_ = true;
278     filterCollector_.Clear();
279 }
280 
IsCurrentFrameDirty() const281 bool RSDirtyRegionManager::IsCurrentFrameDirty() const
282 {
283     return !currentFrameDirtyRegion_.IsEmpty() && currentFrameDirtyRegion_ != debugRect_;
284 }
285 
IsDirty() const286 bool RSDirtyRegionManager::IsDirty() const
287 {
288     return !dirtyRegion_.IsEmpty();
289 }
290 
UpdateDirty(bool enableAligned)291 void RSDirtyRegionManager::UpdateDirty(bool enableAligned)
292 {
293     if (enableAligned) {
294         UpdateDirtyByAligned();
295     }
296     // if last frame doesn't align and current frame need align, we should align history ditry regions.
297     if (!isDirtyRegionAlignedEnable_ && enableAligned) {
298         AlignHistory();
299     }
300     isDirtyRegionAlignedEnable_ = enableAligned;
301     PushHistory(currentFrameDirtyRegion_);
302     dirtyRegion_ = MergeHistory(bufferAge_, currentFrameDirtyRegion_);
303     MergeAdvancedDirtyHistory(bufferAge_);
304 }
305 
UpdateDirtyByAligned(int32_t alignedBits)306 void RSDirtyRegionManager::UpdateDirtyByAligned(int32_t alignedBits)
307 {
308     currentFrameDirtyRegion_ = GetPixelAlignedRect(currentFrameDirtyRegion_, alignedBits);
309     for (auto& rect : currentFrameAdvancedDirtyRegion_) {
310         rect = GetPixelAlignedRect(rect, alignedBits);
311     }
312 }
313 
UpdateDirtyRegionInfoForDfx(NodeId id,RSRenderNodeType nodeType,DirtyRegionType dirtyType,const RectI & rect)314 void RSDirtyRegionManager::UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType,
315     DirtyRegionType dirtyType, const RectI& rect)
316 {
317     if ((dirtyType >= dirtyCanvasNodeInfo_.size()) || (dirtyType >= DirtyRegionType::TYPE_AMOUNT) ||
318         (dirtyType < 0) || (rect.IsEmpty())) {
319         return;
320     }
321     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
322         dirtyCanvasNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
323     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
324         dirtySurfaceNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
325     }
326 }
327 
GetDirtyRegionInfo(std::map<NodeId,RectI> & target,RSRenderNodeType nodeType,DirtyRegionType dirtyType) const328 void RSDirtyRegionManager::GetDirtyRegionInfo(std::map<NodeId, RectI>& target,
329     RSRenderNodeType nodeType, DirtyRegionType dirtyType) const
330 {
331     target.clear();
332     if ((dirtyType >= dirtyCanvasNodeInfo_.size()) || (dirtyType >= DirtyRegionType::TYPE_AMOUNT) ||
333         (dirtyType < 0)) {
334         return;
335     }
336     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
337         target = dirtyCanvasNodeInfo_[dirtyType];
338     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
339         target = dirtySurfaceNodeInfo_[dirtyType];
340     }
341 }
342 
SetOffset(int offsetX,int offsetY)343 void RSDirtyRegionManager::SetOffset(int offsetX, int offsetY)
344 {
345     offsetX_ = offsetX;
346     offsetY_ = offsetY;
347 }
GetOffsetedDirtyRegion() const348 RectI RSDirtyRegionManager::GetOffsetedDirtyRegion() const
349 {
350     return GetDirtyRegion().Offset(offsetX_, offsetY_);
351 }
352 
SetBufferAge(const int age)353 bool RSDirtyRegionManager::SetBufferAge(const int age)
354 {
355     if (age < 0) {
356         bufferAge_ = 0; // reset invalid age
357         return false;
358     }
359     bufferAge_ = static_cast<unsigned int>(age);
360     return true;
361 }
362 
MergeSurfaceRect()363 void RSDirtyRegionManager::MergeSurfaceRect()
364 {
365     return MergeDirtyRect(activeSurfaceRect_.IsEmpty() ? surfaceRect_ : activeSurfaceRect_);
366 }
367 
ResetDirtyAsSurfaceSize()368 void RSDirtyRegionManager::ResetDirtyAsSurfaceSize()
369 {
370     const auto& rect = activeSurfaceRect_.IsEmpty() ? surfaceRect_ : activeSurfaceRect_;
371     dirtyRegion_ = rect;
372     currentFrameDirtyRegion_ = rect;
373     advancedDirtyRegion_ = {rect};
374     currentFrameAdvancedDirtyRegion_ = {rect};
375     dirtyRegionForQuickReject_ = {rect};
376 }
377 
UpdateMaxNumOfDirtyRectByState()378 void RSDirtyRegionManager::UpdateMaxNumOfDirtyRectByState()
379 {
380     if (isDisplayDirtyManager_) {
381         SetMaxNumOfDirtyRects((advancedDirtyRegionType_ == AdvancedDirtyRegionType::DISABLED) ?
382             RSAdvancedDirtyConfig::DISABLED_RECT_NUM_EACH_NODE : RSAdvancedDirtyConfig::MAX_RECT_NUM_EACH_NODE);
383     } else {
384         SetMaxNumOfDirtyRects((advancedDirtyRegionType_ == AdvancedDirtyRegionType::SET_ADVANCED_SURFACE_AND_DISPLAY) ?
385             RSAdvancedDirtyConfig::MAX_RECT_NUM_EACH_NODE : RSAdvancedDirtyConfig::DISABLED_RECT_NUM_EACH_NODE);
386     }
387 }
388 
UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)389 void RSDirtyRegionManager::UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)
390 {
391     debugRegionEnabled_.assign(DebugRegionType::TYPE_MAX, false);
392     switch (dirtyDebugType) {
393         case DirtyRegionDebugType::CURRENT_SUB:
394             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
395             break;
396         case DirtyRegionDebugType::CURRENT_WHOLE:
397             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
398             break;
399         case DirtyRegionDebugType::MULTI_HISTORY:
400             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
401             break;
402         case DirtyRegionDebugType::CURRENT_SUB_AND_WHOLE:
403             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
404             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
405             break;
406         case DirtyRegionDebugType::CURRENT_WHOLE_AND_MULTI_HISTORY:
407             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
408             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
409             break;
410         case DirtyRegionDebugType::EGL_DAMAGE:
411             debugRegionEnabled_[DebugRegionType::EGL_DAMAGE] = true;
412             break;
413         case DirtyRegionDebugType::DISABLED:
414         default:
415             break;
416     }
417 }
418 
MergeHistory(unsigned int age,RectI rect) const419 RectI RSDirtyRegionManager::MergeHistory(unsigned int age, RectI rect) const
420 {
421     if (age == 0 || age > historySize_) {
422         rect = rect.JoinRect(surfaceRect_);
423         age = historySize_;
424     }
425     // GetHistory(historySize_) is equal to dirtyHistory_[historyHead_] (latest his rect)
426     // therefore, this loop merges rect with age frames' dirtyRect
427     // Attention: should not set i >= 0 for unsigned int!!!!!
428     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
429         auto subRect = GetHistory((i - 1));
430         if (subRect.IsEmpty()) {
431             continue;
432         }
433         if (rect.IsEmpty()) {
434             rect = subRect;
435             continue;
436         }
437         // only join valid his dirty region
438         rect = rect.JoinRect(subRect);
439     }
440     return rect;
441 }
442 
MergeAdvancedDirtyHistory(unsigned int age)443 void RSDirtyRegionManager::MergeAdvancedDirtyHistory(unsigned int age)
444 {
445     if (age == 0 || age > historySize_) {
446         advancedDirtyRegion_ = {surfaceRect_};
447         return;
448     }
449     advancedDirtyRegion_ = {};
450     Occlusion::Region tempRegion = Occlusion::Region();
451     for (auto& rect : currentFrameAdvancedDirtyRegion_) {
452         if (rect.IsEmpty()) {
453             continue;
454         }
455         Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
456         tempRegion.OrSelf(region);
457     }
458 
459     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
460         auto rects = GetAdvancedDirtyHistory((i - 1));
461         if (rects.empty()) {
462             continue;
463         }
464         for (auto& rect : rects) {
465             if (rect.IsEmpty()) {
466                 continue;
467             }
468             Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
469             tempRegion.OrSelf(region);
470         }
471     }
472     if (advancedDirtyRegionType_ == AdvancedDirtyRegionType::DISABLED) {
473         advancedDirtyRegion_ = {tempRegion.GetBound().ToRectI()};
474     } else {
475         advancedDirtyRegion_ = tempRegion.GetRegionRectIs();
476     }
477 }
478 
PushHistory(RectI rect)479 void RSDirtyRegionManager::PushHistory(RectI rect)
480 {
481     int next = (historyHead_ + 1) % HISTORY_QUEUE_MAX_SIZE;
482     dirtyHistory_[next] = rect;
483     advancedDirtyHistory_[next] = currentFrameAdvancedDirtyRegion_;
484     if (historySize_ < HISTORY_QUEUE_MAX_SIZE) {
485         ++historySize_;
486     }
487     historyHead_ = next;
488 }
489 
GetHistory(unsigned int i) const490 RectI RSDirtyRegionManager::GetHistory(unsigned int i) const
491 {
492     if (i >= HISTORY_QUEUE_MAX_SIZE) {
493         i %= HISTORY_QUEUE_MAX_SIZE;
494     }
495     if (historySize_ > 0) {
496         i = (i + historyHead_) % historySize_;
497     }
498     return dirtyHistory_[i];
499 }
500 
GetAdvancedDirtyHistory(unsigned int i) const501 std::vector<RectI> RSDirtyRegionManager::GetAdvancedDirtyHistory(unsigned int i) const
502 {
503     if (i >= HISTORY_QUEUE_MAX_SIZE) {
504         i %= HISTORY_QUEUE_MAX_SIZE;
505     }
506     if (historySize_ > 0) {
507         i = (i + historyHead_) % historySize_;
508     }
509     return advancedDirtyHistory_[i];
510 }
511 
512 // for uifirst
GetUiLatestHistoryDirtyRegions(const int historyIndex) const513 const RectI RSDirtyRegionManager::GetUiLatestHistoryDirtyRegions(const int historyIndex) const
514 {
515     if (historyHead_ < 0) {
516         return {0, 0, 0, 0};
517     }
518     RectI resultRect = {0, 0, 0, 0};
519     for (int i = historyIndex - 1; i >= 0; i--) {
520         auto index = (historyHead_ - i + HISTORY_QUEUE_MAX_SIZE) % HISTORY_QUEUE_MAX_SIZE;
521         const RectI& tmpRect = dirtyHistory_[index];
522         resultRect = resultRect.JoinRect(tmpRect);
523     }
524     return resultRect;
525 }
526 
AlignHistory()527 void RSDirtyRegionManager::AlignHistory()
528 {
529     for (uint8_t i = 0; i < dirtyHistory_.size(); i++) {
530         dirtyHistory_[i] = GetPixelAlignedRect(dirtyHistory_[i]);
531     }
532 
533     for (auto& rects : advancedDirtyHistory_) {
534         for (auto& rect : rects) {
535             rect = GetPixelAlignedRect(rect);
536         }
537     }
538 }
539 
540 } // namespace Rosen
541 } // namespace OHOS
542