• 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 (dirtyRegion_.IsEmpty()) {
32         dirtyRegion_ = rect;
33     } else {
34         dirtyRegion_ = dirtyRegion_.JoinRect(rect);
35     }
36 }
37 
IntersectDirtyRect(const RectI & rect)38 void RSDirtyRegionManager::IntersectDirtyRect(const RectI& rect)
39 {
40     dirtyRegion_ = dirtyRegion_.IntersectRect(rect);
41 }
42 
ClipDirtyRectWithinSurface()43 void RSDirtyRegionManager::ClipDirtyRectWithinSurface()
44 {
45     int left = std::max(std::max(dirtyRegion_.left_, 0), surfaceRect_.left_);
46     int top = std::max(std::max(dirtyRegion_.top_, 0), surfaceRect_.top_);
47     int width = std::min(dirtyRegion_.GetRight(), surfaceRect_.GetRight()) - left;
48     int height = std::min(dirtyRegion_.GetBottom(), surfaceRect_.GetBottom()) - top;
49     // If new region is invalid, dirtyRegion would be reset as [0, 0, 0, 0]
50     dirtyRegion_ = ((width <= 0) || (height <= 0)) ? RectI() : RectI(left, top, width, height);
51 }
52 
GetDirtyRegion() const53 const RectI& RSDirtyRegionManager::GetDirtyRegion() const
54 {
55     return dirtyRegion_;
56 }
57 
GetDirtyRegionFlipWithinSurface() const58 RectI RSDirtyRegionManager::GetDirtyRegionFlipWithinSurface() const
59 {
60     RectI glRect = dirtyRegion_;
61     // left-top to left-bottom corner(in current surface)
62     glRect.top_ = surfaceRect_.height_ - dirtyRegion_.top_ - dirtyRegion_.height_;
63     return glRect;
64 }
65 
GetRectFlipWithinSurface(const RectI & rect) const66 RectI RSDirtyRegionManager::GetRectFlipWithinSurface(const RectI& rect) const
67 {
68     RectI glRect = rect;
69     // left-top to left-bottom corner(in current surface)
70     glRect.top_ = surfaceRect_.height_ - rect.top_ - rect.height_;
71     return glRect;
72 }
73 
GetLatestDirtyRegion() const74 const RectI& RSDirtyRegionManager::GetLatestDirtyRegion() const
75 {
76     if (historyHead_ < 0) {
77         return dirtyRegion_;
78     }
79     return dirtyHistory_[historyHead_];
80 }
81 
GetPixelAlignedRect(const RectI & rect,int32_t alignedBits)82 RectI RSDirtyRegionManager::GetPixelAlignedRect(const RectI& rect, int32_t alignedBits)
83 {
84     RectI newRect = rect;
85     if (alignedBits > 1) {
86         int32_t left = (rect.left_ / alignedBits) * alignedBits;
87         int32_t top = (rect.top_ / alignedBits) * alignedBits;
88         int32_t width = ((rect.GetRight() + alignedBits - 1) / alignedBits) * alignedBits - left;
89         int32_t height = ((rect.GetBottom() + alignedBits - 1) / alignedBits) * alignedBits - top;
90         newRect = RectI(left, top, width, height);
91     }
92     return newRect;
93 }
94 
Clear()95 void RSDirtyRegionManager::Clear()
96 {
97     dirtyRegion_.Clear();
98     dirtyCanvasNodes_.clear();
99     dirtySurfaceNodes_.clear();
100     UpdateDebugRegionTypeEnable();
101 }
102 
IsDirty() const103 bool RSDirtyRegionManager::IsDirty() const
104 {
105     return (dirtyRegion_.width_ > 0) && (dirtyRegion_.height_ > 0);
106 }
107 
UpdateDirty()108 void RSDirtyRegionManager::UpdateDirty()
109 {
110     PushHistory(dirtyRegion_);
111     dirtyRegion_ = MergeHistory(bufferAge_, dirtyRegion_);
112 }
113 
UpdateDirtyByAligned(int32_t alignedBits)114 void RSDirtyRegionManager::UpdateDirtyByAligned(int32_t alignedBits)
115 {
116     dirtyRegion_ = GetPixelAlignedRect(dirtyRegion_, alignedBits);
117 }
118 
UpdateDirtyCanvasNodes(NodeId id,const RectI & rect)119 void RSDirtyRegionManager::UpdateDirtyCanvasNodes(NodeId id, const RectI& rect)
120 {
121     dirtyCanvasNodes_[id] = rect;
122 }
123 
UpdateDirtySurfaceNodes(NodeId id,const RectI & rect)124 void RSDirtyRegionManager::UpdateDirtySurfaceNodes(NodeId id, const RectI& rect)
125 {
126     dirtySurfaceNodes_[id] = rect;
127 }
128 
GetDirtyCanvasNodes(std::map<NodeId,RectI> & target) const129 void RSDirtyRegionManager::GetDirtyCanvasNodes(std::map<NodeId, RectI>& target) const
130 {
131     target = dirtyCanvasNodes_;
132 }
133 
GetDirtySurfaceNodes(std::map<NodeId,RectI> & target) const134 void RSDirtyRegionManager::GetDirtySurfaceNodes(std::map<NodeId, RectI>& target) const
135 {
136     target = dirtySurfaceNodes_;
137 }
138 
SetBufferAge(const int age)139 bool RSDirtyRegionManager::SetBufferAge(const int age)
140 {
141     if (age < 0) {
142         bufferAge_ = 0; // reset invalid age
143         return false;
144     }
145     bufferAge_ = static_cast<unsigned int>(age);
146     return true;
147 }
148 
SetSurfaceSize(const int32_t width,const int32_t height)149 bool RSDirtyRegionManager::SetSurfaceSize(const int32_t width, const int32_t height)
150 {
151     if (width < 0 || height < 0) {
152         return false;
153     }
154     surfaceRect_ = RectI(0, 0, width, height);
155     return true;
156 }
157 
ResetDirtyAsSurfaceSize()158 void RSDirtyRegionManager::ResetDirtyAsSurfaceSize()
159 {
160     dirtyRegion_ = surfaceRect_;
161 }
162 
UpdateDebugRegionTypeEnable()163 void RSDirtyRegionManager::UpdateDebugRegionTypeEnable()
164 {
165     DirtyRegionDebugType dirtyDebugType = RSSystemProperties::GetDirtyRegionDebugType();
166     debugRegionEnabled_.assign(DebugRegionType::TYPE_MAX, false);
167     switch (dirtyDebugType) {
168         case DirtyRegionDebugType::CURRENT_SUB:
169             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
170             break;
171         case DirtyRegionDebugType::CURRENT_WHOLE:
172             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
173             break;
174         case DirtyRegionDebugType::MULTI_HISTORY:
175             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
176             break;
177         case DirtyRegionDebugType::CURRENT_SUB_AND_WHOLE:
178             debugRegionEnabled_[DebugRegionType::CURRENT_SUB] = true;
179             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
180             break;
181         case DirtyRegionDebugType::CURRENT_WHOLE_AND_MULTI_HISTORY:
182             debugRegionEnabled_[DebugRegionType::CURRENT_WHOLE] = true;
183             debugRegionEnabled_[DebugRegionType::MULTI_HISTORY] = true;
184             break;
185         case DirtyRegionDebugType::EGL_DAMAGE:
186             debugRegionEnabled_[DebugRegionType::EGL_DAMAGE] = true;
187             break;
188         case DirtyRegionDebugType::DISABLED:
189         default:
190             break;
191     }
192 }
193 
MergeHistory(unsigned int age,RectI rect) const194 RectI RSDirtyRegionManager::MergeHistory(unsigned int age, RectI rect) const
195 {
196     if (age == 0 || age > historySize_) {
197         return surfaceRect_;
198     }
199     // GetHistory(historySize_) is equal to dirtyHistory_[historyHead_] (latest his rect)
200     // therefore, this loop merges rect with age frames' dirtyRect
201     // Attention: should not set i >= 0 for unsigned int!!!!!
202     for (unsigned int i = historySize_; i > historySize_ - age; --i) {
203         auto subRect = GetHistory((i - 1));
204         if (subRect.IsEmpty()) {
205             continue;
206         }
207         if (rect.IsEmpty()) {
208             rect = subRect;
209             continue;
210         }
211         // only join valid his dirty region
212         rect = rect.JoinRect(subRect);
213     }
214     return rect;
215 }
216 
PushHistory(RectI rect)217 void RSDirtyRegionManager::PushHistory(RectI rect)
218 {
219     int next = (historyHead_ + 1) % HISTORY_QUEUE_MAX_SIZE;
220     dirtyHistory_[next] = rect;
221     if (historySize_ < HISTORY_QUEUE_MAX_SIZE) {
222         ++historySize_;
223     }
224     historyHead_ = next;
225 }
226 
GetHistory(unsigned int i) const227 RectI RSDirtyRegionManager::GetHistory(unsigned int i) const
228 {
229     if (i >= HISTORY_QUEUE_MAX_SIZE) {
230         i %= HISTORY_QUEUE_MAX_SIZE;
231     }
232     if (historySize_ == HISTORY_QUEUE_MAX_SIZE) {
233         i = (i + historyHead_) % HISTORY_QUEUE_MAX_SIZE;
234     }
235     return dirtyHistory_[i];
236 }
237 } // namespace Rosen
238 } // namespace OHOS
239