• 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 "rs_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 
GetCurrentFrameDirtyRegion()182 const RectI& RSDirtyRegionManager::GetCurrentFrameDirtyRegion()
183 {
184     return currentFrameDirtyRegion_;
185 }
186 
GetDirtyRegion() const187 const RectI& RSDirtyRegionManager::GetDirtyRegion() const
188 {
189     return dirtyRegion_;
190 }
191 
SetCurrentFrameDirtyRect(const RectI & dirtyRect)192 void RSDirtyRegionManager::SetCurrentFrameDirtyRect(const RectI& dirtyRect)
193 {
194     currentFrameDirtyRegion_ = dirtyRect;
195 }
196 
GetUifirstFrameDirtyRegion()197 const RectI& RSDirtyRegionManager::GetUifirstFrameDirtyRegion()
198 {
199     return uifirstFrameDirtyRegion_;
200 }
201 
SetUifirstFrameDirtyRect(const RectI & dirtyRect)202 void RSDirtyRegionManager::SetUifirstFrameDirtyRect(const RectI& dirtyRect)
203 {
204     uifirstFrameDirtyRegion_ = dirtyRect;
205 }
206 
OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager)207 void RSDirtyRegionManager::OnSync(std::shared_ptr<RSDirtyRegionManager> targetManager)
208 {
209     if (!targetManager) {
210         return;
211     }
212     RSDirtyRegionManager *ptr = targetManager.get();
213     ptr->lastActiveSurfaceRect_ = lastActiveSurfaceRect_;
214     ptr->activeSurfaceRect_ = activeSurfaceRect_;
215     ptr->surfaceRect_ = surfaceRect_;
216     ptr->dirtyRegion_ = dirtyRegion_;
217     ptr->advancedDirtyRegion_ = advancedDirtyRegion_;
218     ptr->hwcDirtyRegion_ = hwcDirtyRegion_;
219     ptr->currentFrameDirtyRegion_ = currentFrameDirtyRegion_;
220     ptr->uifirstFrameDirtyRegion_ = uifirstFrameDirtyRegion_;
221     ptr->currentFrameAdvancedDirtyRegion_ = currentFrameAdvancedDirtyRegion_;
222     ptr->maxNumOfDirtyRects_ = maxNumOfDirtyRects_;
223     ptr->dirtyRegionForQuickReject_ = {};
224     ptr->debugRect_ = debugRect_;
225     if (RSSystemProperties::GetDirtyRegionDebugType() != DirtyRegionDebugType::DISABLED) {
226         ptr->dirtySurfaceNodeInfo_ = dirtySurfaceNodeInfo_;
227         ptr->dirtyCanvasNodeInfo_ = dirtyCanvasNodeInfo_;
228         ptr->mergedDirtyRegions_ = mergedDirtyRegions_;
229     }
230     // To avoid the impact of the remaining surface dirty on global dirty when nodes are skipped the next frame.
231     Clear();
232     uifirstFrameDirtyRegion_.Clear();
233     // check if the switch is opened
234     UpdateMaxNumOfDirtyRectByState();
235 }
236 
GetDirtyRegionFlipWithinSurface() const237 RectI RSDirtyRegionManager::GetDirtyRegionFlipWithinSurface() const
238 {
239     RectI glRect;
240     if (isDirtyRegionAlignedEnable_) {
241         glRect = GetPixelAlignedRect(dirtyRegion_);
242     } else {
243         glRect = dirtyRegion_;
244     }
245 
246     if (!RSSystemProperties::IsUseVulkan()) {
247         // left-top to left-bottom corner(in current surface)
248         glRect.top_ = surfaceRect_.height_ - glRect.top_ - glRect.height_;
249     }
250     return glRect;
251 }
252 
GetRectFlipWithinSurface(const RectI & rect) const253 RectI RSDirtyRegionManager::GetRectFlipWithinSurface(const RectI& rect) const
254 {
255     RectI glRect = rect;
256 
257     if (!RSSystemProperties::IsUseVulkan()) {
258         // left-top to left-bottom corner(in current surface)
259         glRect.top_ = surfaceRect_.height_ - rect.top_ - rect.height_;
260     }
261     return glRect;
262 }
263 
GetLatestDirtyRegion() const264 const RectI& RSDirtyRegionManager::GetLatestDirtyRegion() const
265 {
266     if (historyHead_ < 0) {
267         return dirtyRegion_;
268     }
269     return dirtyHistory_[historyHead_];
270 }
271 
GetPixelAlignedRect(const RectI & rect,int32_t alignedBits)272 RectI RSDirtyRegionManager::GetPixelAlignedRect(const RectI& rect, int32_t alignedBits)
273 {
274     RectI newRect = rect;
275     if (alignedBits > 1) {
276         int32_t left = (rect.left_ / alignedBits) * alignedBits;
277         int32_t top = (rect.top_ / alignedBits) * alignedBits;
278         int32_t width = ((rect.GetRight() + alignedBits - 1) / alignedBits) * alignedBits - left;
279         int32_t height = ((rect.GetBottom() + alignedBits - 1) / alignedBits) * alignedBits - top;
280         newRect = RectI(left, top, width, height);
281     }
282     return newRect;
283 }
284 
Clear()285 void RSDirtyRegionManager::Clear()
286 {
287     dirtyRegion_.Clear();
288     advancedDirtyRegion_.clear();
289     currentFrameDirtyRegion_.Clear();
290     currentFrameAdvancedDirtyRegion_.clear();
291     hwcDirtyRegion_.Clear();
292     visitedDirtyRegions_.clear();
293     mergedDirtyRegions_.clear();
294     cacheableFilterRects_.clear();
295     dirtyCanvasNodeInfo_.clear();
296     dirtyCanvasNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
297     dirtySurfaceNodeInfo_.clear();
298     dirtySurfaceNodeInfo_.resize(DirtyRegionType::TYPE_AMOUNT);
299     isDfxTarget_ = false;
300     isFilterCacheRectValid_ = true;
301 }
302 
IsCurrentFrameDirty() const303 bool RSDirtyRegionManager::IsCurrentFrameDirty() const
304 {
305     return !currentFrameDirtyRegion_.IsEmpty() && currentFrameDirtyRegion_ != debugRect_;
306 }
307 
IsDirty() const308 bool RSDirtyRegionManager::IsDirty() const
309 {
310     return !dirtyRegion_.IsEmpty();
311 }
312 
UpdateDirty(bool enableAligned)313 void RSDirtyRegionManager::UpdateDirty(bool enableAligned)
314 {
315     if (enableAligned) {
316         UpdateDirtyByAligned();
317     }
318     // if last frame doesn't align and current frame need align, we should align history ditry regions.
319     if (!isDirtyRegionAlignedEnable_ && enableAligned) {
320         AlignHistory();
321     }
322     isDirtyRegionAlignedEnable_ = enableAligned;
323     PushHistory(currentFrameDirtyRegion_);
324     dirtyRegion_ = MergeHistory(bufferAge_, currentFrameDirtyRegion_);
325     MergeAdvancedDirtyHistory(bufferAge_);
326 }
327 
UpdateDirtyByAligned(int32_t alignedBits)328 void RSDirtyRegionManager::UpdateDirtyByAligned(int32_t alignedBits)
329 {
330     currentFrameDirtyRegion_ = GetPixelAlignedRect(currentFrameDirtyRegion_, alignedBits);
331     for (auto& rect : currentFrameAdvancedDirtyRegion_) {
332         rect = GetPixelAlignedRect(rect, alignedBits);
333     }
334 }
335 
UpdateDirtyRegionInfoForDfx(NodeId id,RSRenderNodeType nodeType,DirtyRegionType dirtyType,const RectI & rect)336 void RSDirtyRegionManager::UpdateDirtyRegionInfoForDfx(NodeId id, RSRenderNodeType nodeType,
337     DirtyRegionType dirtyType, const RectI& rect)
338 {
339     if ((dirtyType >= dirtyCanvasNodeInfo_.size()) || (dirtyType >= DirtyRegionType::TYPE_AMOUNT) ||
340         (dirtyType < 0) || (rect.IsEmpty())) {
341         return;
342     }
343     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
344         dirtyCanvasNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
345     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
346         dirtySurfaceNodeInfo_[dirtyType].emplace(std::make_pair(id, rect));
347     }
348 }
349 
GetDirtyRegionInfo(std::map<NodeId,RectI> & target,RSRenderNodeType nodeType,DirtyRegionType dirtyType) const350 void RSDirtyRegionManager::GetDirtyRegionInfo(std::map<NodeId, RectI>& target,
351     RSRenderNodeType nodeType, DirtyRegionType dirtyType) const
352 {
353     target.clear();
354     if ((dirtyType >= dirtyCanvasNodeInfo_.size()) || (dirtyType >= DirtyRegionType::TYPE_AMOUNT) ||
355         (dirtyType < 0)) {
356         return;
357     }
358     if (nodeType == RSRenderNodeType::CANVAS_NODE) {
359         target = dirtyCanvasNodeInfo_[dirtyType];
360     } else if (nodeType == RSRenderNodeType::SURFACE_NODE) {
361         target = dirtySurfaceNodeInfo_[dirtyType];
362     }
363 }
364 
HasOffset()365 bool RSDirtyRegionManager::HasOffset()
366 {
367     return hasOffset_;
368 }
SetOffset(int offsetX,int offsetY)369 void RSDirtyRegionManager::SetOffset(int offsetX, int offsetY)
370 {
371     offsetX_ = offsetX;
372     offsetY_ = offsetY;
373 }
GetOffsetedDirtyRegion() const374 RectI RSDirtyRegionManager::GetOffsetedDirtyRegion() const
375 {
376     return GetDirtyRegion().Offset(offsetX_, offsetY_);
377 }
378 
SetBufferAge(const int age)379 bool RSDirtyRegionManager::SetBufferAge(const int age)
380 {
381     if (age < 0) {
382         bufferAge_ = 0; // reset invalid age
383         return false;
384     }
385     bufferAge_ = static_cast<unsigned int>(age);
386     return true;
387 }
388 
MergeSurfaceRect()389 void RSDirtyRegionManager::MergeSurfaceRect()
390 {
391     return MergeDirtyRect(activeSurfaceRect_.IsEmpty() ? surfaceRect_ : activeSurfaceRect_);
392 }
393 
ResetDirtyAsSurfaceSize()394 void RSDirtyRegionManager::ResetDirtyAsSurfaceSize()
395 {
396     const auto& rect = activeSurfaceRect_.IsEmpty() ? surfaceRect_ : activeSurfaceRect_;
397     dirtyRegion_ = rect;
398     currentFrameDirtyRegion_ = rect;
399     advancedDirtyRegion_ = {rect};
400     currentFrameAdvancedDirtyRegion_ = {rect};
401     dirtyRegionForQuickReject_ = {rect};
402 }
403 
UpdateMaxNumOfDirtyRectByState()404 void RSDirtyRegionManager::UpdateMaxNumOfDirtyRectByState()
405 {
406     if (isDisplayDirtyManager_) {
407         SetMaxNumOfDirtyRects((advancedDirtyRegionType_ == AdvancedDirtyRegionType::DISABLED) ?
408             RSAdvancedDirtyConfig::DISABLED_RECT_NUM_EACH_NODE : RSAdvancedDirtyConfig::MAX_RECT_NUM_EACH_NODE);
409     } else {
410         SetMaxNumOfDirtyRects((advancedDirtyRegionType_ == AdvancedDirtyRegionType::SET_ADVANCED_SURFACE_AND_DISPLAY) ?
411             RSAdvancedDirtyConfig::MAX_RECT_NUM_EACH_NODE : RSAdvancedDirtyConfig::DISABLED_RECT_NUM_EACH_NODE);
412     }
413 }
414 
UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)415 void RSDirtyRegionManager::UpdateDebugRegionTypeEnable(DirtyRegionDebugType dirtyDebugType)
416 {
417     debugRegionEnabled_.assign(DebugRegionType::TYPE_MAX, false);
418     switch (dirtyDebugType) {
419         case DirtyRegionDebugType::CURRENT_SUB:
420             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
421             break;
422         case DirtyRegionDebugType::CURRENT_WHOLE:
423             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
424             break;
425         case DirtyRegionDebugType::MULTI_HISTORY:
426             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
427             break;
428         case DirtyRegionDebugType::CURRENT_SUB_AND_WHOLE:
429             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
430             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
431             break;
432         case DirtyRegionDebugType::CURRENT_WHOLE_AND_MULTI_HISTORY:
433             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
434             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
435             break;
436         case DirtyRegionDebugType::EGL_DAMAGE:
437             debugRegionEnabled_[DebugRegionType::EGL_DAMAGE] = true;
438             break;
439         case DirtyRegionDebugType::DISABLED:
440         default:
441             break;
442     }
443 }
444 
MergeHistory(unsigned int age,RectI rect) const445 RectI RSDirtyRegionManager::MergeHistory(unsigned int age, RectI rect) const
446 {
447     if (age == 0 || age > historySize_) {
448         rect = rect.JoinRect(surfaceRect_);
449         age = historySize_;
450     }
451     // GetHistory(historySize_) is equal to dirtyHistory_[historyHead_] (latest his rect)
452     // therefore, this loop merges rect with age frames' dirtyRect
453     // Attention: should not set i >= 0 for unsigned int!!!!!
454     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
455         auto subRect = GetHistory((i - 1));
456         if (subRect.IsEmpty()) {
457             continue;
458         }
459         if (rect.IsEmpty()) {
460             rect = subRect;
461             continue;
462         }
463         // only join valid his dirty region
464         rect = rect.JoinRect(subRect);
465     }
466     return rect;
467 }
468 
MergeAdvancedDirtyHistory(unsigned int age)469 void RSDirtyRegionManager::MergeAdvancedDirtyHistory(unsigned int age)
470 {
471     if (age == 0 || age > historySize_) {
472         RS_LOGW("RSDirtyRegionManager::MergeAdvancedDirtyHistory unvalid age : %{public}d"
473             "historySize : %{public}d", age, historySize_);
474         advancedDirtyRegion_ = {surfaceRect_};
475         return;
476     }
477     advancedDirtyRegion_ = {};
478     Occlusion::Region tempRegion = Occlusion::Region();
479     for (auto& rect : currentFrameAdvancedDirtyRegion_) {
480         if (rect.IsEmpty()) {
481             continue;
482         }
483         Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
484         tempRegion.OrSelf(region);
485     }
486 
487     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
488         auto rects = GetAdvancedDirtyHistory((i - 1));
489         if (rects.empty()) {
490             continue;
491         }
492         for (auto& rect : rects) {
493             if (rect.IsEmpty()) {
494                 continue;
495             }
496             Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
497             tempRegion.OrSelf(region);
498         }
499     }
500     advancedDirtyRegion_ = tempRegion.GetRegionRectIs();
501 }
502 
PushHistory(RectI rect)503 void RSDirtyRegionManager::PushHistory(RectI rect)
504 {
505     int next = (historyHead_ + 1) % HISTORY_QUEUE_MAX_SIZE;
506     dirtyHistory_[next] = rect;
507     advancedDirtyHistory_[next] = currentFrameAdvancedDirtyRegion_;
508     if (historySize_ < HISTORY_QUEUE_MAX_SIZE) {
509         ++historySize_;
510     }
511     historyHead_ = next;
512 }
513 
GetHistory(unsigned int i) const514 RectI RSDirtyRegionManager::GetHistory(unsigned int i) const
515 {
516     if (i >= HISTORY_QUEUE_MAX_SIZE) {
517         i %= HISTORY_QUEUE_MAX_SIZE;
518     }
519     if (historySize_ > 0) {
520         i = (i + historyHead_) % historySize_;
521     }
522     return dirtyHistory_[i];
523 }
524 
GetAdvancedDirtyHistory(unsigned int i) const525 std::vector<RectI> RSDirtyRegionManager::GetAdvancedDirtyHistory(unsigned int i) const
526 {
527     if (i >= HISTORY_QUEUE_MAX_SIZE) {
528         i %= HISTORY_QUEUE_MAX_SIZE;
529     }
530     if (historySize_ > 0) {
531         i = (i + historyHead_) % historySize_;
532     }
533     return advancedDirtyHistory_[i];
534 }
535 
AlignHistory()536 void RSDirtyRegionManager::AlignHistory()
537 {
538     for (uint8_t i = 0; i < dirtyHistory_.size(); i++) {
539         dirtyHistory_[i] = GetPixelAlignedRect(dirtyHistory_[i]);
540     }
541 
542     for (auto& rects : advancedDirtyHistory_) {
543         for (auto& rect : rects) {
544             rect = GetPixelAlignedRect(rect);
545         }
546     }
547 }
548 
549 } // namespace Rosen
550 } // namespace OHOS
551