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