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