forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cc: Replace Region with SimpleEnclosedRegion for occlusion tracking
Instead of using an arbitrary Region, which is costly (slow), use a new SimpleEnclosedRegion. This class tracks only a single Rect at a given time so it is very fast and small. It tries to get something like the largest rect enclosed in the actual Region (were we to track such a Region) in an online fashion, ie it doesn't remember anything except its current largest possible rect. BUG=405663 Review URL: https://codereview.chromium.org/202523002 Cr-Commit-Position: refs/heads/master@{#291292} git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291292 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
danakj@chromium.org
committed
Aug 22, 2014
1 parent
903cf84
commit d5467eb
Showing
28 changed files
with
1,545 additions
and
758 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright 2014 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "cc/base/simple_enclosed_region.h" | ||
|
||
#include "base/logging.h" | ||
#include "cc/base/region.h" | ||
|
||
namespace cc { | ||
|
||
static bool RectIsLargerArea(const gfx::Rect& a, const gfx::Rect b) { | ||
int64 a_area = static_cast<int64>(a.width()) * a.height(); | ||
int64 b_area = static_cast<int64>(b.width()) * b.height(); | ||
return a_area > b_area; | ||
} | ||
|
||
SimpleEnclosedRegion::SimpleEnclosedRegion(const Region& region) { | ||
for (Region::Iterator it(region); it.has_rect(); it.next()) | ||
Union(it.rect()); | ||
} | ||
|
||
SimpleEnclosedRegion::~SimpleEnclosedRegion() { | ||
} | ||
|
||
void SimpleEnclosedRegion::Subtract(const gfx::Rect& sub_rect) { | ||
// We want to keep as much of the current rect as we can, so find the one | ||
// largest rectangle inside |rect_| that does not intersect with |sub_rect|. | ||
if (!rect_.Intersects(sub_rect)) | ||
return; | ||
if (sub_rect.Contains(rect_)) { | ||
rect_ = gfx::Rect(); | ||
return; | ||
} | ||
|
||
int left = rect_.x(); | ||
int right = rect_.right(); | ||
int top = rect_.y(); | ||
int bottom = rect_.bottom(); | ||
|
||
int delta_left = sub_rect.x() - left; | ||
int delta_right = right - sub_rect.right(); | ||
int delta_top = sub_rect.y() - top; | ||
int delta_bottom = bottom - sub_rect.bottom(); | ||
|
||
// The horizontal rect is the larger of the two rectangles above or below | ||
// |sub_rect| and inside rect_. | ||
int horizontal_top = top; | ||
int horizontal_bottom = bottom; | ||
if (delta_top > delta_bottom) | ||
horizontal_bottom = sub_rect.y(); | ||
else | ||
horizontal_top = sub_rect.bottom(); | ||
// The vertical rect is the larger of the two rectangles to the left or the | ||
// right of |sub_rect| and inside rect_. | ||
int vertical_left = left; | ||
int vertical_right = right; | ||
if (delta_left > delta_right) | ||
vertical_right = sub_rect.x(); | ||
else | ||
vertical_left = sub_rect.right(); | ||
|
||
rect_.SetRect( | ||
left, horizontal_top, right - left, horizontal_bottom - horizontal_top); | ||
|
||
gfx::Rect vertical_rect( | ||
vertical_left, top, vertical_right - vertical_left, bottom - top); | ||
if (RectIsLargerArea(vertical_rect, rect_)) | ||
rect_ = vertical_rect; | ||
} | ||
|
||
void SimpleEnclosedRegion::Union(const gfx::Rect& new_rect) { | ||
// We want to keep track of a region but bound its complexity at a constant | ||
// size. We keep track of the largest rectangle seen by area. If we can add | ||
// the |new_rect| to this rectangle then we do that, as that is the cheapest | ||
// way to increase the area returned without increasing the complexity. | ||
if (new_rect.IsEmpty()) | ||
return; | ||
if (rect_.Contains(new_rect)) | ||
return; | ||
if (new_rect.Contains(rect_)) { | ||
rect_ = new_rect; | ||
return; | ||
} | ||
|
||
int left = rect_.x(); | ||
int top = rect_.y(); | ||
int right = rect_.right(); | ||
int bottom = rect_.bottom(); | ||
|
||
int new_left = new_rect.x(); | ||
int new_top = new_rect.y(); | ||
int new_right = new_rect.right(); | ||
int new_bottom = new_rect.bottom(); | ||
|
||
// This attempts to expand each edge of |rect_| if the |new_rect| entirely | ||
// covers or is adjacent to an entire edge of |rect_|. If this is true for | ||
// an edge of |rect_| then it can be expanded out to share that edge with the | ||
// same edge of |new_rect|. After, the same thing is done to try expand | ||
// |new_rect| relative to |rect_|. | ||
if (new_top <= top && new_bottom >= bottom) { | ||
if (new_left < left && new_right >= left) | ||
left = new_left; | ||
if (new_right > right && new_left <= right) | ||
right = new_right; | ||
} else if (new_left <= left && new_right >= right) { | ||
if (new_top < top && new_bottom >= top) | ||
top = new_top; | ||
if (new_bottom > bottom && new_top <= bottom) | ||
bottom = new_bottom; | ||
} else if (top <= new_top && bottom >= new_bottom) { | ||
if (left < new_left && right >= new_left) | ||
new_left = left; | ||
if (right > new_right && left <= new_right) | ||
new_right = right; | ||
} else if (left <= new_left && right >= new_right) { | ||
if (top < new_top && bottom >= new_top) | ||
new_top = top; | ||
if (bottom > new_bottom && top <= new_bottom) | ||
new_bottom = bottom; | ||
} | ||
|
||
rect_.SetRect(left, top, right - left, bottom - top); | ||
|
||
gfx::Rect adjusted_new_rect( | ||
new_left, new_top, new_right - new_left, new_bottom - new_top); | ||
if (RectIsLargerArea(adjusted_new_rect, rect_)) | ||
rect_ = adjusted_new_rect; | ||
} | ||
|
||
gfx::Rect SimpleEnclosedRegion::GetRect(size_t i) const { | ||
DCHECK_LT(i, GetRegionComplexity()); | ||
return rect_; | ||
} | ||
|
||
} // namespace cc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Copyright 2014 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CC_BASE_SIMPLE_ENCLOSED_REGION_H_ | ||
#define CC_BASE_SIMPLE_ENCLOSED_REGION_H_ | ||
|
||
#include <string> | ||
|
||
#include "cc/base/cc_export.h" | ||
#include "ui/gfx/rect.h" | ||
|
||
namespace cc { | ||
|
||
class Region; | ||
|
||
// A constant-sized approximation of a Region. The SimpleEnclosedRegion may | ||
// exclude points in its approximation (may have false negatives) but will never | ||
// include a point that would not be in the actual Region (no false positives). | ||
class CC_EXPORT SimpleEnclosedRegion { | ||
public: | ||
SimpleEnclosedRegion() : rect_() {} | ||
SimpleEnclosedRegion(const SimpleEnclosedRegion& region) | ||
: rect_(region.rect_) {} | ||
explicit SimpleEnclosedRegion(const gfx::Rect& rect) : rect_(rect) {} | ||
SimpleEnclosedRegion(int x, int y, int w, int h) : rect_(x, y, w, h) {} | ||
SimpleEnclosedRegion(int w, int h) : rect_(w, h) {} | ||
explicit SimpleEnclosedRegion(const Region& region); | ||
~SimpleEnclosedRegion(); | ||
|
||
const SimpleEnclosedRegion& operator=(const gfx::Rect& rect) { | ||
rect_ = rect; | ||
return *this; | ||
} | ||
const SimpleEnclosedRegion& operator=(const SimpleEnclosedRegion& region) { | ||
rect_ = region.rect_; | ||
return *this; | ||
} | ||
|
||
bool IsEmpty() const { return rect_.IsEmpty(); } | ||
void Clear() { rect_ = gfx::Rect(); } | ||
size_t GetRegionComplexity() const { return rect_.IsEmpty() ? 0 : 1; } | ||
|
||
bool Contains(const gfx::Point& point) const { return rect_.Contains(point); } | ||
bool Contains(const gfx::Rect& rect) const { return rect_.Contains(rect); } | ||
bool Contains(const SimpleEnclosedRegion& region) const { | ||
return rect_.Contains(region.rect_); | ||
} | ||
|
||
bool Intersects(const gfx::Rect& rect) const { | ||
return rect_.Intersects(rect); | ||
} | ||
bool Intersects(const SimpleEnclosedRegion& region) const { | ||
return rect_.Intersects(region.rect_); | ||
} | ||
|
||
void Subtract(const gfx::Rect& sub_rect); | ||
void Subtract(const SimpleEnclosedRegion& sub_region) { | ||
Subtract(sub_region.rect_); | ||
} | ||
void Union(const gfx::Rect& new_rect); | ||
void Union(const SimpleEnclosedRegion& new_region) { | ||
Union(new_region.rect_); | ||
} | ||
void Intersect(const gfx::Rect& in_rect) { return rect_.Intersect(in_rect); } | ||
void Intersect(const SimpleEnclosedRegion& in_region) { | ||
Intersect(in_region.rect_); | ||
} | ||
|
||
bool Equals(const SimpleEnclosedRegion& other) const { | ||
bool both_empty = rect_.IsEmpty() && other.rect_.IsEmpty(); | ||
return both_empty || rect_ == other.rect_; | ||
} | ||
|
||
gfx::Rect bounds() const { return rect_; } | ||
|
||
// The value of |i| must be less than GetRegionComplexity(). | ||
gfx::Rect GetRect(size_t i) const; | ||
|
||
std::string ToString() const { return rect_.ToString(); } | ||
|
||
private: | ||
gfx::Rect rect_; | ||
}; | ||
|
||
inline bool operator==(const SimpleEnclosedRegion& a, | ||
const SimpleEnclosedRegion& b) { | ||
return a.Equals(b); | ||
} | ||
|
||
inline bool operator!=(const SimpleEnclosedRegion& a, | ||
const SimpleEnclosedRegion& b) { | ||
return !(a == b); | ||
} | ||
|
||
inline SimpleEnclosedRegion SubtractSimpleEnclosedRegions( | ||
const SimpleEnclosedRegion& a, | ||
const SimpleEnclosedRegion& b) { | ||
SimpleEnclosedRegion result = a; | ||
result.Subtract(b); | ||
return result; | ||
} | ||
|
||
inline SimpleEnclosedRegion IntersectSimpleEnclosedRegions( | ||
const SimpleEnclosedRegion& a, | ||
const SimpleEnclosedRegion& b) { | ||
SimpleEnclosedRegion result = a; | ||
result.Intersect(b); | ||
return result; | ||
} | ||
|
||
inline SimpleEnclosedRegion UnionSimpleEnclosedRegions( | ||
const SimpleEnclosedRegion& a, | ||
const SimpleEnclosedRegion& b) { | ||
SimpleEnclosedRegion result = a; | ||
result.Union(b); | ||
return result; | ||
} | ||
|
||
} // namespace cc | ||
|
||
#endif // CC_BASE_SIMPLE_ENCLOSED_REGION_H_ |
Oops, something went wrong.