• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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