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