• 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 #ifndef RENDER_SERVICE_BASE_CORE_COMMON_RS_OCCLUSION_REGION_H
16 #define RENDER_SERVICE_BASE_CORE_COMMON_RS_OCCLUSION_REGION_H
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <vector>
21 #include <string>
22 
23 #include "rs_rect.h"
24 #include "common/rs_macros.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 namespace Occlusion {
29 class Rect {
30 public:
31     // assumption: left-top is [0,0]
32     int left_ = 0;
33     int top_ = 0;
34     int right_ = 0;
35     int bottom_ = 0;
36     static Rect _s_empty_rect_;
37     static Rect _s_invalid_rect_;
38 
Rect()39     Rect() : left_(0), top_(0), right_(0), bottom_(0) {}
Rect(int l,int t,int r,int b)40     Rect(int l, int t, int r, int b) : left_(l), top_(t), right_(r), bottom_(b) {}
Rect(const RectI & r)41     Rect(const RectI& r) : left_(r.left_), top_(r.top_), right_(r.GetRight()), bottom_(r.GetBottom()) {}
42 
IsEmpty()43     bool IsEmpty() const
44     {
45         return left_ >= right_ || top_ >= bottom_;
46     }
47 
48     bool operator==(const Rect& r) const
49     {
50         return left_ == r.left_ && top_ == r.top_ && right_ == r.right_ && bottom_ == r.bottom_;
51     }
52 
53     bool operator!=(const Rect& r) const
54     {
55         return !(*this == r);
56     }
57 
Intersect(const Rect & rect)58     Rect Intersect(const Rect& rect) const
59     {
60         int left = std::max(left_, rect.left_);
61         int top = std::max(top_, rect.top_);
62         int right = std::min(right_, rect.right_);
63         int bottom = std::min(bottom_, rect.bottom_);
64         if ((right - left <= 0) || (bottom - top <= 0)) {
65             return Rect(0, 0, 0, 0);
66         } else {
67             return Rect(left, top, right, bottom);
68         }
69     }
70 
IsIntersect(const Rect & rect)71     bool IsIntersect(const Rect& rect) const
72     {
73         int left = std::max(left_, rect.left_);
74         int top = std::max(top_, rect.top_);
75         int right = std::min(right_, rect.right_);
76         int bottom = std::min(bottom_, rect.bottom_);
77         return (right - left > 0) && (bottom - top > 0);
78     }
79 
GetRectInfo()80     std::string GetRectInfo() const
81     {
82         return std::string("[" +
83             std::to_string(left_) + ", " +
84             std::to_string(top_) + ", " +
85             std::to_string(right_ - left_) + ", " +
86             std::to_string(bottom_ - top_) + "]");
87     }
88 
ToRectI()89     RectI ToRectI() const
90     {
91         return RectI{left_, top_, right_ - left_, bottom_ - top_};
92     }
93 };
94 
95 std::ostream& operator<<(std::ostream& os, const Rect& r);
96 
97 /*
98     Event: Used for record a rect edge in/out event
99     y_: rect edge Y value
100     type: OPEN/CLOSE: lhs rect in/out; VOID_OPEN/VOID_CLOSE: rhs rect in/out
101 */
102 class Event {
103 public:
104     // Use different value to differentiate lhs and rhs ranges
105     enum Type { OPEN = 1, CLOSE = -1, VOID_OPEN = 2, VOID_CLOSE = -2 };
106     int y_ = 0;
107     Type type_ = Type::OPEN;
108     int left_ = 0;
109     int right_ = 0;
110 
Event(int y,Type type,int l,int r)111     Event(int y, Type type, int l, int r) : y_(y), type_(type), left_(l), right_(r) {}
112 };
113 bool EventSortByY(const Event& e1, const Event& e2);
114 
115 class Range {
116 public:
117     int start_ = 0;
118     int end_ = 0;
Range(int s,int e)119     Range(int s, int e) : start_(s), end_(e) {}
120     bool operator==(const Range& r)
121     {
122         return start_ == r.start_ && end_ == r.end_;
123     }
124 };
125 
126 class Node {
127 public:
128     int start_ = 0;
129     int end_ = 0;
130     int mid_ = 0;
131     int positive_count_ = 0; // used for counting current lhs ranges
132     int negative_count_ = 0; // used for counting current rhs ranges
133     Node* left_ = nullptr;
134     Node* right_ = nullptr;
135 
Node(int s,int e)136     Node(int s, int e) : start_(s), end_(e), mid_((s + e) >> 1) {}
~Node()137     ~Node()
138     {
139         if (left_ != nullptr) {
140             delete left_;
141             left_ = nullptr;
142         }
143         if (right_ != nullptr) {
144             delete right_;
145             right_ = nullptr;
146         }
147     }
148 
149     // push current node [start, end] into range result, merge last range if possible
PushRange(std::vector<Range> & res)150     inline void PushRange(std::vector<Range>& res)
151     {
152         if (res.size() > 0 && start_ == res[res.size() - 1].end_) {
153             // merge range with previous range if their end and start share same point
154             res[res.size() - 1].end_ = end_;
155         } else {
156             res.emplace_back(Range { start_, end_ });
157         }
158     }
159 
IsLeaf()160     inline bool IsLeaf()
161     {
162         return left_ == nullptr && right_ == nullptr;
163     }
164 
165     // update segment tree
166     void Update(int updateStart, int updateEnd, Event::Type type);
167     // get ranges where positive_count_ and negtive_count_ are both positive
168     void GetAndRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
169     // get ranges where positive_count_ or negtive_count_ is positive
170     void GetOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
171     // get ranges where either positive_count_ and negtive_count_ are both positive
172     void GetXOrRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
173     // get ranges where positive_count_ is positive and negtive_count_ not
174     void GetSubRange(std::vector<Range>& res, bool isParentNodePos, bool isParentNodeNeg);
175 };
176 
177 class RSB_EXPORT Region {
178 public:
179     enum OP {
180         // bit index 0: lhs
181         // bit index 1: lhs & rhs
182         // bit index 2: rhs
183         AND = 2, // 010
184         OR  = 7, // 111
185         XOR = 5, // 101
186         SUB = 1  // 001
187     };
188 
189     Region() = default;
Region(Rect r)190     Region(Rect r)
191     {
192         rects_.push_back(r);
193         bound_ = Rect { r };
194     }
195 
Region(const Region & reg)196     Region(const Region& reg) : rects_(reg.rects_), bound_(reg.bound_) {}
~Region()197     ~Region() {}
198 
GetRegionRects()199     std::vector<Rect> GetRegionRects() const
200     {
201         return rects_;
202     }
203 
GetRegionRects()204     std::vector<Rect>& GetRegionRects()
205     {
206         return rects_;
207     }
GetSize()208     int GetSize() const
209     {
210         return rects_.size();
211     }
GetBound()212     Rect GetBound() const
213     {
214         return bound_;
215     }
GetBoundRef()216     Rect& GetBoundRef()
217     {
218         return bound_;
219     }
IsEmpty()220     bool IsEmpty() const
221     {
222         return rects_.size() == 0;
223     }
GetRegionInfo()224     std::string GetRegionInfo() const
225     {
226         std::string info;
227         if (rects_.size() > 0) {
228             info = "Region " + std::to_string(rects_.size()) + ": ";
229             for (auto& r : rects_) {
230                 info.append(r.GetRectInfo());
231             }
232         } else {
233             info = "Region [Empty]";
234         }
235         return info;
236     }
237 
CBegin()238     inline std::vector<Rect>::const_iterator CBegin() const
239     {
240         return rects_.cbegin();
241     }
CEnd()242     inline std::vector<Rect>::const_iterator CEnd() const
243     {
244         return rects_.cend();
245     }
Begin()246     inline std::vector<Rect>::iterator Begin()
247     {
248         return rects_.begin();
249     }
End()250     inline std::vector<Rect>::const_iterator End()
251     {
252         return rects_.end();
253     }
Size()254     inline size_t Size() const
255     {
256         return rects_.size();
257     }
258 
259     // bound of all region rects
260     void MakeBound();
261 
IsIntersectWith(const Rect & r)262     bool IsIntersectWith(const Rect& r) const
263     {
264         for (const Rect& rect : rects_) {
265             if (rect.IsIntersect(r)) {
266                 return true;
267             }
268         }
269         return false;
270     }
271 
272     /* core Region logic operation function, the return region's rects is guaranteed no-intersection
273         (rect in rects_ do not intersect with each other)
274     */
275     void RegionOp(Region& r1, Region& r2, Region& res, Region::OP op);
276     void RegionOpLocal(Region& r1, Region& r2, Region& res, Region::OP op);
277     void RegionOpAccelate(Region& r1, Region& r2, Region& res, Region::OP op);
278 
279     Region& OperationSelf(Region& r, Region::OP op);
280     // replace region with and result
281     Region& AndSelf(Region& r);
282     // replace region with or result
283     Region& OrSelf(Region& r);
284     // replace region with xor result
285     Region& XOrSelf(Region& r);
286     // replace region with sub result
287     Region& SubSelf(Region& r);
288 
289     // return intersection region
290     Region And(Region& r);
291     // return merge region
292     Region Or(Region& r);
293     // return merge region subtract intersection region
294     Region Xor(Region& r);
295     // return region belongs to Region(lhs) but not Region(rhs)
296     Region Sub(Region& r);
297 
298 private:
299     class Rects {
300     public:
301         std::vector<Rect> preRects;
302         std::vector<Rect> curRects;
303         int preY = 0;
304         int curY = 0;
305     };
306     // get ranges from segmentTree node according to logical operation type
307     void getRange(std::vector<Range>& ranges, Node& node, OP op);
308     // update tmp rects and region according to current ranges
309     void UpdateRects(Rects& r, std::vector<Range>& ranges, std::vector<int>& indexAt, Region& res);
310 
311 private:
312     std::vector<Rect> rects_;
313     Rect bound_;
314     static bool _s_so_loaded_;
315 };
316 std::ostream& operator<<(std::ostream& os, const Region& r);
317 } // namespace Occlusion
318 } // namespace Rosen
319 } // namespace OHOS
320 #endif // RENDER_SERVICE_BASE_CORE_COMMON_RS_OCCLUSION_REGION_H