1 /*
2 * Copyright (c) 2022-2023 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 "common/rs_occlusion_region.h"
17 #include "common/rs_occlusion_region_helper.h"
18
19 #include <map>
20 #include <set>
21 #include "platform/common/rs_innovation.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 namespace Occlusion {
26 namespace {
Align(int num,int alignmentSize,bool upward)27 inline int Align(int num, int alignmentSize, bool upward)
28 {
29 if (alignmentSize <= 1) {
30 return num;
31 }
32 int remainder = num % alignmentSize;
33 if (remainder == 0) {
34 return num;
35 }
36 return (num > 0 && upward) ? (num + (alignmentSize - remainder)) : (num - remainder);
37 }
38
AlignUp(int num,int alignmentSize)39 inline int AlignUp(int num, int alignmentSize)
40 {
41 return Align(num, alignmentSize, true);
42 }
43
AlignDown(int num,int alignmentSize)44 inline int AlignDown(int num, int alignmentSize)
45 {
46 return Align(num, alignmentSize, false);
47 }
48 }
49
operator <<(std::ostream & os,const Rect & r)50 std::ostream& operator<<(std::ostream& os, const Rect& r)
51 {
52 os << "{" << r.left_ << "," << r.top_ << "," << r.right_ << "," << r.bottom_ << "}";
53 return os;
54 }
55
EventSortByY(const Event & e1,const Event & e2)56 bool EventSortByY(const Event& e1, const Event& e2)
57 {
58 if (e1.y_ == e2.y_) {
59 return e1.type_ < e2.type_;
60 }
61 return e1.y_ < e2.y_;
62 }
63
Update(int updateStart,int updateEnd,Event::Type type)64 void Node::Update(int updateStart, int updateEnd, Event::Type type)
65 {
66 if (updateStart >= updateEnd) {
67 return;
68 }
69 if (updateStart == start_ && updateEnd == end_) {
70 if (type == Event::Type::OPEN || type == Event::Type::CLOSE) {
71 positive_count_ += type;
72 } else {
73 negative_count_ += type;
74 }
75 } else {
76 if (left_ == nullptr) {
77 left_ = new Node { start_, mid_ };
78 }
79 if (right_ == nullptr) {
80 right_ = new Node { mid_, end_ };
81 }
82 // In case the heap memory allocation fails
83 if (left_ != nullptr) {
84 left_->Update(updateStart, mid_ < updateEnd ? mid_ : updateEnd, type);
85 }
86 if (right_ != nullptr) {
87 right_->Update(mid_ > updateStart ? mid_ : updateStart, updateEnd, type);
88 }
89 }
90 }
91
GetAndRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)92 void Node::GetAndRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
93 {
94 bool isPos = isParentNodePos || (positive_count_ > 0);
95 bool isNeg = isParentNodeNeg || (negative_count_ > 0);
96 if (isPos && isNeg) {
97 PushRange(res);
98 } else {
99 if (left_ != nullptr) {
100 left_->GetAndRange(res, isPos, isNeg);
101 }
102 if (right_ != nullptr) {
103 right_->GetAndRange(res, isPos, isNeg);
104 }
105 }
106 }
107
GetOrRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)108 void Node::GetOrRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
109 {
110 bool isPos = isParentNodePos || (positive_count_ > 0);
111 bool isNeg = isParentNodeNeg || (negative_count_ > 0);
112 if (isPos || isNeg) {
113 PushRange(res);
114 } else {
115 if (left_ != nullptr) {
116 left_->GetOrRange(res, isPos, isNeg);
117 }
118 if (right_ != nullptr) {
119 right_->GetOrRange(res, isPos, isNeg);
120 }
121 }
122 }
123
GetXOrRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)124 void Node::GetXOrRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
125 {
126 bool isPos = isParentNodePos || (positive_count_ > 0);
127 bool isNeg = isParentNodeNeg || (negative_count_ > 0);
128 if (((isPos && !isNeg) || (!isPos && isNeg)) && IsLeaf()) {
129 PushRange(res);
130 } else if (isPos && isNeg) {
131 return;
132 } else {
133 if (left_ != nullptr) {
134 left_->GetXOrRange(res, isPos, isNeg);
135 }
136 if (right_ != nullptr) {
137 right_->GetXOrRange(res, isPos, isNeg);
138 }
139 }
140 }
141
GetSubRange(std::vector<Range> & res,bool isParentNodePos=false,bool isParentNodeNeg=false)142 void Node::GetSubRange(std::vector<Range>& res, bool isParentNodePos = false, bool isParentNodeNeg = false)
143 {
144 bool isPos = isParentNodePos || (positive_count_ > 0);
145 bool isNeg = isParentNodeNeg || (negative_count_ > 0);
146 if (IsLeaf() && isPos && !isNeg) {
147 PushRange(res);
148 } else if (isNeg) {
149 return;
150 } else {
151 if (left_ != nullptr) {
152 left_->GetSubRange(res, isPos, isNeg);
153 }
154 if (right_ != nullptr) {
155 right_->GetSubRange(res, isPos, isNeg);
156 }
157 }
158 }
159
MakeEnumerate(std::set<int> & ys,std::map<int,int> & indexOf,std::vector<int> & indexAt)160 void MakeEnumerate(std::set<int>& ys, std::map<int, int>& indexOf, std::vector<int>& indexAt)
161 {
162 auto it = ys.begin();
163 int index = 0;
164 while (it != ys.end()) {
165 indexOf[*it] = index++;
166 indexAt.push_back(*it);
167 ++it;
168 }
169 return;
170 }
171
getRange(std::vector<Range> & ranges,Node & node,Region::OP op)172 void Region::getRange(std::vector<Range>& ranges, Node& node, Region::OP op)
173 {
174 switch (op) {
175 case Region::OP::AND:
176 node.GetAndRange(ranges);
177 break;
178 case Region::OP::OR:
179 node.GetOrRange(ranges);
180 break;
181 case Region::OP::XOR:
182 node.GetXOrRange(ranges);
183 break;
184 case Region::OP::SUB:
185 node.GetSubRange(ranges);
186 break;
187 default:
188 break;
189 }
190 return;
191 }
192
UpdateRects(Rects & r,std::vector<Range> & ranges,std::vector<int> & indexAt,Region & res)193 void Region::UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res)
194 {
195 uint32_t i = 0;
196 uint32_t j = 0;
197 while (i < r.preRects.size() && j < ranges.size()) {
198 if (r.preRects[i].left_ == indexAt[ranges[j].start_] && r.preRects[i].right_ == indexAt[ranges[j].end_]) {
199 r.curRects.emplace_back(Rect { r.preRects[i].left_, r.preRects[i].top_, r.preRects[i].right_, r.curY });
200 i++;
201 j++;
202 } else if (r.preRects[i].right_ < indexAt[ranges[j].end_]) {
203 res.GetRegionRectsRef().push_back(r.preRects[i]);
204 i++;
205 } else {
206 r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY });
207 j++;
208 }
209 }
210 for (; j < ranges.size(); j++) {
211 r.curRects.emplace_back(Rect { indexAt[ranges[j].start_], r.preY, indexAt[ranges[j].end_], r.curY });
212 }
213 for (; i < r.preRects.size(); i++) {
214 res.GetRegionRectsRef().push_back(r.preRects[i]);
215 }
216 r.preRects.clear();
217 r.preRects.swap(r.curRects);
218 return;
219 }
220
MakeBound()221 void Region::MakeBound()
222 {
223 if (rects_.size()) {
224 // Tell compiler there is no alias.
225 int left = rects_[0].left_;
226 int top = rects_[0].top_;
227 int right = rects_[0].right_;
228 int bottom = rects_[0].bottom_;
229 for (const auto& r : rects_) {
230 left = std::min(r.left_, left);
231 top = std::min(r.top_, top);
232 right = std::max(r.right_, right);
233 bottom = std::max(r.bottom_, bottom);
234 }
235 bound_.left_ = left;
236 bound_.top_ = top;
237 bound_.right_ = right;
238 bound_.bottom_ = bottom;
239 }
240 }
241
GetAlignedRegion(int alignmentSize) const242 Region Region::GetAlignedRegion(int alignmentSize) const
243 {
244 Region alignedRegion;
245 for (const auto& rect : rects_) {
246 Rect alignedRect(AlignDown(rect.left_, alignmentSize), AlignDown(rect.top_, alignmentSize),
247 AlignUp(rect.right_, alignmentSize), AlignUp(rect.bottom_, alignmentSize));
248 Region alignedSubRegion{alignedRect};
249 alignedRegion.OrSelf(alignedSubRegion);
250 }
251 return alignedRegion;
252 }
253
RegionOp(Region & r1,Region & r2,Region & res,Region::OP op)254 void Region::RegionOp(Region& r1, Region& r2, Region& res, Region::OP op)
255 {
256 if (r1.IsEmpty()) {
257 if (op == Region::OP::AND || op == Region::OP::SUB) {
258 res = Region();
259 } else {
260 res = r2;
261 }
262 return;
263 }
264 if (r2.IsEmpty()) {
265 if (op == Region::OP::AND) {
266 res = Region();
267 } else {
268 res = r1;
269 }
270 return;
271 }
272 RegionOpAccelate(r1, r2, res, op);
273 }
274
RegionOpLocal(Region & r1,Region & r2,Region & res,Region::OP op)275 void Region::RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op)
276 {
277 r1.MakeBound();
278 r2.MakeBound();
279 res.GetRegionRectsRef().clear();
280 std::vector<Event> events;
281 std::set<int> xs;
282
283 for (auto& r : r1.GetRegionRects()) {
284 events.emplace_back(Event { r.top_, Event::Type::OPEN, r.left_, r.right_ });
285 events.emplace_back(Event { r.bottom_, Event::Type::CLOSE, r.left_, r.right_ });
286 xs.insert(r.left_);
287 xs.insert(r.right_);
288 }
289 for (auto& r : r2.GetRegionRects()) {
290 events.emplace_back(Event { r.top_, Event::Type::VOID_OPEN, r.left_, r.right_ });
291 events.emplace_back(Event { r.bottom_, Event::Type::VOID_CLOSE, r.left_, r.right_ });
292 xs.insert(r.left_);
293 xs.insert(r.right_);
294 }
295
296 if (events.size() == 0) {
297 return;
298 }
299
300 std::map<int, int> indexOf;
301 std::vector<int> indexAt;
302 MakeEnumerate(xs, indexOf, indexAt);
303 sort(events.begin(), events.end(), EventSortByY);
304
305 Node rootNode { 0, static_cast<int>(indexOf.size() - 1) };
306
307 std::vector<Range> ranges;
308 Rects r;
309 r.preY = events[0].y_;
310 r.curY = events[0].y_;
311 for (auto& e : events) {
312 r.curY = e.y_;
313 ranges.clear();
314 getRange(ranges, rootNode, op);
315 if (r.curY > r.preY) {
316 UpdateRects(r, ranges, indexAt, res);
317 }
318 rootNode.Update(indexOf[e.left_], indexOf[e.right_], e.type_);
319 r.preY = r.curY;
320 }
321 copy(r.preRects.begin(), r.preRects.end(), back_inserter(res.GetRegionRectsRef()));
322 res.MakeBound();
323 }
324
RegionOpAccelate(Region & r1,Region & r2,Region & res,Region::OP op)325 void Region::RegionOpAccelate(Region& r1, Region& r2, Region& res, Region::OP op)
326 {
327 RectsPtr lhs(r1.CBegin(), r1.Size());
328 RectsPtr rhs(r2.CBegin(), r2.Size());
329 Assembler assembler(res);
330 OuterLooper outer(lhs, rhs);
331 Rect current(0, 0, 0, 0); // init value is irrelevant
332 do {
333 InnerLooper inner(outer);
334 RectType relationship = outer.NextScanline(current.top_, current.bottom_);
335 if (op == Region::OP::AND && relationship != RectType::LHS_RHS_BOTH) {
336 continue;
337 }
338 if (op == Region::OP::SUB && relationship == RectType::RHS_ONLY) {
339 continue;
340 }
341 inner.Init(relationship);
342 do {
343 RectType rectType = inner.NextRect(current.left_, current.right_);
344 if (((static_cast<uint32_t>(op) & static_cast<uint32_t>(rectType)) != 0) && !current.IsEmpty()) {
345 assembler.Insert(current);
346 }
347 } while (!inner.IsDone());
348 } while (!outer.isDone());
349 assembler.FlushVerticalSpan();
350 return;
351 }
352
OperationSelf(Region & r,Region::OP op)353 Region& Region::OperationSelf(Region& r, Region::OP op)
354 {
355 Region r1(*this);
356 RegionOp(r1, r, *this, op);
357 return *this;
358 }
359
AndSelf(Region & r)360 Region& Region::AndSelf(Region& r)
361 {
362 return OperationSelf(r, Region::OP::AND);
363 }
364
OrSelf(Region & r)365 Region& Region::OrSelf(Region& r)
366 {
367 return OperationSelf(r, Region::OP::OR);
368 }
369
XOrSelf(Region & r)370 Region& Region::XOrSelf(Region& r)
371 {
372 return OperationSelf(r, Region::OP::XOR);
373 }
374
SubSelf(Region & r)375 Region& Region::SubSelf(Region& r)
376 {
377 return OperationSelf(r, Region::OP::SUB);
378 }
379
And(Region & r)380 Region Region::And(Region& r)
381 {
382 Region res;
383 RegionOp(*this, r, res, Region::OP::AND);
384 return res;
385 }
386
Or(Region & r)387 Region Region::Or(Region& r)
388 {
389 Region res;
390 RegionOp(*this, r, res, Region::OP::OR);
391 return res;
392 }
393
Xor(Region & r)394 Region Region::Xor(Region& r)
395 {
396 Region res;
397 RegionOp(*this, r, res, Region::OP::XOR);
398 return res;
399 }
400
Sub(Region & r)401 Region Region::Sub(Region& r)
402 {
403 Region res;
404 RegionOp(*this, r, res, Region::OP::SUB);
405 return res;
406 }
407
operator <<(std::ostream & os,const Region & r)408 std::ostream& operator<<(std::ostream& os, const Region& r)
409 {
410 os << "{";
411 os << r.GetSize() << ": ";
412 for (const Rect& rect : r.GetRegionRects()) {
413 os << rect;
414 }
415 os << "}" << std::endl;
416 return os;
417 }
418
Area() const419 int Region::Area() const
420 {
421 int areaSum = 0;
422 for (const auto& rect : GetRegionRects()) {
423 areaSum += rect.Area();
424 }
425 return areaSum;
426 }
427
IntersectArea(const Rect & r) const428 int Region::IntersectArea(const Rect& r) const
429 {
430 if (r.IsEmpty()) {
431 return 0;
432 }
433 int areaSum = 0;
434 for (const auto& rect : GetRegionRects()) {
435 areaSum += rect.IntersectArea(r);
436 }
437 return areaSum;
438 }
439
440 } // namespace Occlusion
441 } // namespace Rosen
442 } // namespace OHOS
443