diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-22 01:16:43 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-08-22 01:21:15 +0000 |
commit | d5467eb7835eccd7b1e1a65096c9b1f37c70fcb2 (patch) | |
tree | db295fcc90bc936cf52818bffd73d7560c80f0f3 /cc | |
parent | 903cf847d2d66f33e1f2cdab5f45a1b07558fa7a (diff) | |
download | chromium_src-d5467eb7835eccd7b1e1a65096c9b1f37c70fcb2.zip chromium_src-d5467eb7835eccd7b1e1a65096c9b1f37c70fcb2.tar.gz chromium_src-d5467eb7835eccd7b1e1a65096c9b1f37c70fcb2.tar.bz2 |
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
Diffstat (limited to 'cc')
28 files changed, 1545 insertions, 758 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index c2f1cf4..fb4c1f2 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -55,6 +55,8 @@ component("cc") { "base/scoped_ptr_algorithm.h", "base/scoped_ptr_deque.h", "base/scoped_ptr_vector.h", + "base/simple_enclosed_region.cc", + "base/simple_enclosed_region.h", "base/swap_promise.h", "base/swap_promise_monitor.cc", "base/swap_promise_monitor.h", @@ -646,6 +648,7 @@ test("cc_unittests") { "base/region_unittest.cc", "base/rolling_time_delta_history_unittest.cc", "base/scoped_ptr_vector_unittest.cc", + "base/simple_enclosed_region_unittest.cc", "base/tiling_data_unittest.cc", "base/util_unittest.cc", "debug/micro_benchmark_controller_unittest.cc", diff --git a/cc/base/region.cc b/cc/base/region.cc index 79c30ec..2484cc2 100644 --- a/cc/base/region.cc +++ b/cc/base/region.cc @@ -3,8 +3,10 @@ // found in the LICENSE file. #include "cc/base/region.h" + #include "base/debug/trace_event_argument.h" #include "base/values.h" +#include "cc/base/simple_enclosed_region.h" namespace cc { @@ -80,6 +82,13 @@ void Region::Subtract(const Region& region) { skregion_.op(region.skregion_, SkRegion::kDifference_Op); } +void Region::Subtract(const SimpleEnclosedRegion& region) { + for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { + skregion_.op(gfx::RectToSkIRect(region.GetRect(i)), + SkRegion::kDifference_Op); + } +} + void Region::Union(const gfx::Rect& rect) { skregion_.op(gfx::RectToSkIRect(rect), SkRegion::kUnion_Op); } diff --git a/cc/base/region.h b/cc/base/region.h index 3ef32db..d78d4cb 100644 --- a/cc/base/region.h +++ b/cc/base/region.h @@ -7,7 +7,6 @@ #include <string> -#include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "third_party/skia/include/core/SkRegion.h" @@ -22,6 +21,7 @@ class TracedValue; } namespace cc { +class SimpleEnclosedRegion; class CC_EXPORT Region { public: @@ -47,6 +47,7 @@ class CC_EXPORT Region { void Subtract(const gfx::Rect& rect); void Subtract(const Region& region); + void Subtract(const SimpleEnclosedRegion& region); void Union(const gfx::Rect& rect); void Union(const Region& region); void Intersect(const gfx::Rect& rect); diff --git a/cc/base/simple_enclosed_region.cc b/cc/base/simple_enclosed_region.cc new file mode 100644 index 0000000..e2683f3 --- /dev/null +++ b/cc/base/simple_enclosed_region.cc @@ -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 diff --git a/cc/base/simple_enclosed_region.h b/cc/base/simple_enclosed_region.h new file mode 100644 index 0000000..c9625ba --- /dev/null +++ b/cc/base/simple_enclosed_region.h @@ -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_ diff --git a/cc/base/simple_enclosed_region_unittest.cc b/cc/base/simple_enclosed_region_unittest.cc new file mode 100644 index 0000000..869da4e --- /dev/null +++ b/cc/base/simple_enclosed_region_unittest.cc @@ -0,0 +1,637 @@ +// 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 <algorithm> +#include <vector> + +#include "base/logging.h" +#include "cc/base/region.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cc { +namespace { + +bool ExpectRegionEq(const gfx::Rect& rect, const SimpleEnclosedRegion& region) { + std::vector<gfx::Rect> actual_rects; + std::vector<gfx::Rect> expected_rects; + + if (!rect.IsEmpty()) + expected_rects.push_back(rect); + + for (size_t i = 0; i < region.GetRegionComplexity(); ++i) + actual_rects.push_back(region.GetRect(i)); + + if (rect.IsEmpty() != region.IsEmpty()) { + LOG(ERROR) << "Expected: " << rect.IsEmpty() + << " Actual: " << region.IsEmpty(); + return false; + } + + if (expected_rects.size() != actual_rects.size()) { + LOG(ERROR) << "Expected: " << expected_rects.size() + << " Actual: " << actual_rects.size(); + return false; + } + + std::sort(actual_rects.begin(), actual_rects.end()); + std::sort(expected_rects.begin(), expected_rects.end()); + + for (size_t i = 0; i < expected_rects.size(); ++i) { + if (expected_rects[i] != actual_rects[i]) { + LOG(ERROR) << "Expected: " << expected_rects[i].ToString() + << " Actual: " << actual_rects[i].ToString(); + return false; + } + } + + return true; +} + +TEST(SimpleEnclosedRegionTest, Create) { + SimpleEnclosedRegion r1; + EXPECT_TRUE(r1.IsEmpty()); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r1)); + + SimpleEnclosedRegion r2(gfx::Rect(2, 3, 4, 5)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 4, 5), r2)); + + SimpleEnclosedRegion r3(2, 3, 4, 5); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 4, 5), r3)); + + SimpleEnclosedRegion r4(4, 5); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(4, 5), r4)); + + SimpleEnclosedRegion r5(Region(gfx::Rect(2, 3, 4, 5))); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 4, 5), r5)); + + SimpleEnclosedRegion r6(r5); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 4, 5), r6)); +} + +TEST(SimpleEnclosedRegionTest, Assign) { + SimpleEnclosedRegion r; + EXPECT_TRUE(r.IsEmpty()); + + r = gfx::Rect(2, 3, 4, 5); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 4, 5), r)); + + r = SimpleEnclosedRegion(3, 4, 5, 6); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(3, 4, 5, 6), r)); +} + +TEST(SimpleEnclosedRegionTest, Clear) { + SimpleEnclosedRegion r(1, 2, 3, 4); + EXPECT_FALSE(r.IsEmpty()); + r.Clear(); + EXPECT_TRUE(r.IsEmpty()); +} + +TEST(SimpleEnclosedRegionTest, GetRegionComplexity) { + SimpleEnclosedRegion empty; + EXPECT_EQ(0u, empty.GetRegionComplexity()); + + SimpleEnclosedRegion stuff; + stuff.Union(gfx::Rect(1, 2, 3, 4)); + EXPECT_EQ(1u, stuff.GetRegionComplexity()); + + // The SimpleEnclosedRegion only holds up to 1 rect. + stuff.Union(gfx::Rect(5, 6, 7, 8)); + EXPECT_EQ(1u, stuff.GetRegionComplexity()); +} + +TEST(SimpleEnclosedRegionTest, Contains) { + SimpleEnclosedRegion r(1, 2, 5, 6); + + EXPECT_FALSE(r.Contains(gfx::Point(0, 2))); + EXPECT_FALSE(r.Contains(gfx::Point(1, 1))); + EXPECT_TRUE(r.Contains(gfx::Point(1, 2))); + + EXPECT_FALSE(r.Contains(gfx::Point(6, 2))); + EXPECT_FALSE(r.Contains(gfx::Point(5, 1))); + EXPECT_TRUE(r.Contains(gfx::Point(5, 2))); + + EXPECT_FALSE(r.Contains(gfx::Point(0, 7))); + EXPECT_FALSE(r.Contains(gfx::Point(1, 8))); + EXPECT_TRUE(r.Contains(gfx::Point(1, 7))); + + EXPECT_FALSE(r.Contains(gfx::Point(6, 7))); + EXPECT_FALSE(r.Contains(gfx::Point(5, 8))); + EXPECT_TRUE(r.Contains(gfx::Point(5, 7))); + + EXPECT_FALSE(r.Contains(gfx::Rect(0, 2, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(1, 1, 1, 1))); + EXPECT_TRUE(r.Contains(gfx::Rect(1, 2, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(0, 1, 2, 2))); + + EXPECT_FALSE(r.Contains(gfx::Rect(6, 2, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(5, 1, 1, 1))); + EXPECT_TRUE(r.Contains(gfx::Rect(5, 2, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(5, 1, 2, 2))); + + EXPECT_FALSE(r.Contains(gfx::Rect(0, 7, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(1, 8, 1, 1))); + EXPECT_TRUE(r.Contains(gfx::Rect(1, 7, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(0, 7, 2, 2))); + + EXPECT_FALSE(r.Contains(gfx::Rect(6, 7, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(5, 8, 1, 1))); + EXPECT_TRUE(r.Contains(gfx::Rect(5, 7, 1, 1))); + EXPECT_FALSE(r.Contains(gfx::Rect(5, 7, 2, 2))); + + gfx::Rect q(1, 2, 5, 6); + EXPECT_TRUE(r.Contains(q)) << q.ToString(); + q.Inset(-1, 0, 0, 0); + EXPECT_FALSE(r.Contains(q)) << q.ToString(); + q.Inset(1, -1, 0, 0); + EXPECT_FALSE(r.Contains(q)) << q.ToString(); + q.Inset(0, 1, -1, 0); + EXPECT_FALSE(r.Contains(q)) << q.ToString(); + q.Inset(0, 0, 1, -1); + EXPECT_FALSE(r.Contains(q)) << q.ToString(); + + q.Inset(1, 0, 0, 1); + EXPECT_TRUE(r.Contains(q)) << q.ToString(); + q.Inset(-1, 1, 0, 0); + EXPECT_TRUE(r.Contains(q)) << q.ToString(); + q.Inset(0, -1, 1, 0); + EXPECT_TRUE(r.Contains(q)) << q.ToString(); + q.Inset(0, 0, -1, 1); + EXPECT_TRUE(r.Contains(q)) << q.ToString(); + + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(0, 2, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(1, 1, 1, 1))); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(1, 2, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(0, 1, 2, 2))); + + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(6, 2, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(5, 1, 1, 1))); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(5, 2, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(5, 1, 2, 2))); + + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(0, 7, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(1, 8, 1, 1))); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(1, 7, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(0, 7, 2, 2))); + + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(6, 7, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(5, 8, 1, 1))); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(5, 7, 1, 1))); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(5, 7, 2, 2))); + + q = gfx::Rect(1, 2, 5, 6); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(-1, 0, 0, 0); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(1, -1, 0, 0); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 1, -1, 0); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 0, 1, -1); + EXPECT_FALSE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + + q.Inset(1, 0, 0, 1); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(-1, 1, 0, 0); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, -1, 1, 0); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 0, -1, 1); + EXPECT_TRUE(r.Contains(SimpleEnclosedRegion(q))) << q.ToString(); +} + +TEST(SimpleEnclosedRegionTest, Intersects) { + SimpleEnclosedRegion r(1, 2, 5, 6); + + EXPECT_FALSE(r.Intersects(gfx::Rect(0, 2, 1, 1))); + EXPECT_FALSE(r.Intersects(gfx::Rect(1, 1, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(1, 2, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(0, 1, 2, 2))); + + EXPECT_FALSE(r.Intersects(gfx::Rect(6, 2, 1, 1))); + EXPECT_FALSE(r.Intersects(gfx::Rect(5, 1, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(5, 2, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(5, 1, 2, 2))); + + EXPECT_FALSE(r.Intersects(gfx::Rect(0, 7, 1, 1))); + EXPECT_FALSE(r.Intersects(gfx::Rect(1, 8, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(1, 7, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(0, 7, 2, 2))); + + EXPECT_FALSE(r.Intersects(gfx::Rect(6, 7, 1, 1))); + EXPECT_FALSE(r.Intersects(gfx::Rect(5, 8, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(5, 7, 1, 1))); + EXPECT_TRUE(r.Intersects(gfx::Rect(5, 7, 2, 2))); + + gfx::Rect q(1, 2, 5, 6); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(-1, 0, 0, 0); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(1, -1, 0, 0); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(0, 1, -1, 0); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(0, 0, 1, -1); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + + q.Inset(1, 0, 0, 1); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(-1, 1, 0, 0); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(0, -1, 1, 0); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + q.Inset(0, 0, -1, 1); + EXPECT_TRUE(r.Intersects(q)) << q.ToString(); + + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(0, 2, 1, 1))); + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(1, 1, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(1, 2, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(0, 1, 2, 2))); + + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(6, 2, 1, 1))); + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(5, 1, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(5, 2, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(5, 1, 2, 2))); + + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(0, 7, 1, 1))); + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(1, 8, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(1, 7, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(0, 7, 2, 2))); + + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(6, 7, 1, 1))); + EXPECT_FALSE(r.Intersects(SimpleEnclosedRegion(5, 8, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(5, 7, 1, 1))); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(5, 7, 2, 2))); + + q = gfx::Rect(1, 2, 5, 6); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(-1, 0, 0, 0); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(1, -1, 0, 0); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 1, -1, 0); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 0, 1, -1); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + + q.Inset(1, 0, 0, 1); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(-1, 1, 0, 0); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, -1, 1, 0); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); + q.Inset(0, 0, -1, 1); + EXPECT_TRUE(r.Intersects(SimpleEnclosedRegion(q))) << q.ToString(); +} + +TEST(SimpleEnclosedRegionTest, Equals) { + SimpleEnclosedRegion r(1, 2, 3, 4); + EXPECT_TRUE(r.Equals(SimpleEnclosedRegion(1, 2, 3, 4))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(2, 2, 3, 4))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(1, 3, 3, 4))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(1, 2, 4, 4))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(1, 2, 3, 5))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(2, 2, 2, 4))); + EXPECT_FALSE(r.Equals(SimpleEnclosedRegion(1, 3, 3, 3))); +} + +TEST(SimpleEnclosedRegionTest, Bounds) { + SimpleEnclosedRegion r; + EXPECT_EQ(gfx::Rect(), r.bounds()); + r = gfx::Rect(3, 4, 5, 6); + EXPECT_EQ(gfx::Rect(3, 4, 5, 6), r.bounds()); + r.Union(gfx::Rect(1, 2, 12, 13)); + EXPECT_EQ(gfx::Rect(1, 2, 12, 13), r.bounds()); +} + +TEST(SimpleEnclosedRegionTest, GetRect) { + SimpleEnclosedRegion r(3, 4, 5, 6); + EXPECT_EQ(gfx::Rect(3, 4, 5, 6), r.GetRect(0)); + r.Union(gfx::Rect(1, 2, 12, 13)); + EXPECT_EQ(gfx::Rect(1, 2, 12, 13), r.GetRect(0)); +} + +TEST(SimpleEnclosedRegionTest, Union) { + SimpleEnclosedRegion r; + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r)); + + // Empty Union anything = anything. + r.Union(gfx::Rect(4, 5, 6, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(4, 5, 6, 7), r)); + + // Anything Union empty = anything. + r.Union(gfx::Rect()); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(4, 5, 6, 7), r)); + + // Anything Union contained rect = Anything. + r.Union(gfx::Rect(5, 6, 4, 5)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(4, 5, 6, 7), r)); + + // Anything Union containing rect = containing rect. + r.Union(gfx::Rect(2, 3, 8, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 8, 9), r)); + r.Union(gfx::Rect(2, 3, 9, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 9, 10), r)); + + // Union with a smaller disjoint rect is ignored. + r.Union(gfx::Rect(20, 21, 9, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 9, 10), r)); + + // Union with a smaller overlapping rect is ignored. + r.Union(gfx::Rect(3, 4, 9, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(2, 3, 9, 10), r)); + + // Union with an equal sized rect can be either one. + r.Union(gfx::Rect(4, 4, 9, 10)); + EXPECT_EQ(1u, r.GetRegionComplexity()); + EXPECT_TRUE(r.bounds() == gfx::Rect(2, 3, 9, 10) || + r.bounds() == gfx::Rect(4, 4, 9, 10)); + + // Union with a larger disjoint rect is taken. + r.Union(gfx::Rect(20, 21, 12, 13)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(20, 21, 12, 13), r)); + + // Union with a larger overlapping rect is taken. + r.Union(gfx::Rect(19, 19, 12, 14)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(19, 19, 12, 14), r)); + + // True also when the rect covers one edge of the existing region. + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(12, 7, 9, 16)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(12, 7, 9, 16), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(9, 7, 9, 16)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(9, 7, 9, 16), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(7, 12, 16, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(7, 12, 16, 9), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(7, 9, 16, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(7, 9, 16, 9), r)); + + // But if the existing region can be expanded to make a larger rect, then it + // will. Union area is 9*12 = 108. By merging, we make a rect with an area of + // 10*11 = 110. The resulting rect is expanded as far as possible while + // remaining enclosed in the Union. + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(12, 9, 9, 12)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 11, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(9, 9, 9, 12)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(9, 10, 11, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(9, 12, 12, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 11), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Union(gfx::Rect(9, 9, 12, 9)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 9, 10, 11), r)); + + r = gfx::Rect(12, 9, 9, 12); + r.Union(gfx::Rect(10, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 11, 10), r)); + + r = gfx::Rect(9, 9, 9, 12); + r.Union(gfx::Rect(10, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(9, 10, 11, 10), r)); + + r = gfx::Rect(9, 12, 12, 9); + r.Union(gfx::Rect(10, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 11), r)); + + r = gfx::Rect(9, 9, 12, 9); + r.Union(gfx::Rect(10, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 9, 10, 11), r)); +} + +TEST(SimpleEnclosedRegionTest, Subtract) { + SimpleEnclosedRegion r; + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r)); + + // Empty Subtract anything = empty. + r.Subtract(gfx::Rect(4, 5, 6, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r)); + + // Subtracting an enclosing rect = empty. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(9, 9, 12, 12)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(), r)); + + // Subtracting a rect that covers one side of the region will shrink that + // side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(18, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(18, 8, 10, 14)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 18, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(8, 18, 14, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(2, 10, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(12, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(2, 8, 10, 14)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(12, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 2, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 12, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(8, 2, 14, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 12, 10, 8), r)); + + // Subtracting a rect that does not cover a full side will still shrink that + // side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(18, 12, 10, 8)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(18, 12, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 18, 8, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 18, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(2, 12, 10, 8)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(12, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(2, 12, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(12, 10, 8, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 2, 8, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 12, 10, 8), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 2, 10, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 12, 10, 8), r)); + + // Subtracting a rect inside the region will make it choose the larger result. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(11, 11, 7, 8)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(18, 10, 2, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(11, 11, 8, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 18, 10, 2), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 11, 7, 8)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 2, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(11, 12, 8, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 2), r)); + + // Subtracting a rect that cuts the region in two will choose the larger side. + // Here it's the top side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 14, 10, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(0, 14, 30, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 14, 8, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(0, 14, 18, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 14, 18, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + // Here it's the bottom side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 13, 10, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 16, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(0, 13, 30, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 16, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 13, 8, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 16, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(0, 13, 18, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 16, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(12, 13, 18, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 16, 10, 4), r)); + + // Here it's the left side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + // Here it's the right side. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(16, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(16, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(16, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(16, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 10, 3, 10)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(16, 10, 4, 10), r)); + + // Subtracting a rect that leaves three possible choices will choose the + // larger. + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 14, 7, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(10, 14, 5, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(15, 10, 5, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(13, 14, 7, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 4), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(15, 14, 5, 3)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 5, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 10, 3, 5)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 15, 10, 5), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 13, 3, 7)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 4, 10), r)); + + r = gfx::Rect(10, 10, 10, 10); + r.Subtract(gfx::Rect(14, 15, 3, 5)); + EXPECT_TRUE(ExpectRegionEq(gfx::Rect(10, 10, 10, 5), r)); +} + +} // namespace +} // namespace cc @@ -83,6 +83,8 @@ 'base/scoped_ptr_algorithm.h', 'base/scoped_ptr_deque.h', 'base/scoped_ptr_vector.h', + 'base/simple_enclosed_region.cc', + 'base/simple_enclosed_region.h', 'base/swap_promise.h', 'base/swap_promise_monitor.cc', 'base/swap_promise_monitor.h', diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 83ac8ff..8ecb203 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -19,6 +19,7 @@ 'base/region_unittest.cc', 'base/rolling_time_delta_history_unittest.cc', 'base/scoped_ptr_vector_unittest.cc', + 'base/simple_enclosed_region_unittest.cc', 'base/tiling_data_unittest.cc', 'base/unique_notifier_unittest.cc', 'base/util_unittest.cc', diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 57c055b..63b9990 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc @@ -17,6 +17,7 @@ #include "cc/animation/animation_registrar.h" #include "cc/animation/keyframed_animation_curve.h" #include "cc/animation/layer_animation_controller.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/layers/layer_client.h" #include "cc/layers/layer_impl.h" #include "cc/layers/scrollbar_layer_interface.h" @@ -1179,10 +1180,10 @@ void Layer::RemoveLayerAnimationEventObserver( layer_animation_controller_->RemoveEventObserver(animation_observer); } -Region Layer::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion Layer::VisibleContentOpaqueRegion() const { if (contents_opaque()) - return visible_content_rect(); - return Region(); + return SimpleEnclosedRegion(visible_content_rect()); + return SimpleEnclosedRegion(); } ScrollbarLayerInterface* Layer::ToScrollbarLayer() { diff --git a/cc/layers/layer.h b/cc/layers/layer.h index dfbbdf7b..61ef3f8 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h @@ -60,6 +60,7 @@ class PriorityCalculator; class RenderingStatsInstrumentation; class ResourceUpdateQueue; class ScrollbarLayerInterface; +class SimpleEnclosedRegion; struct AnimationEvent; template <typename LayerType> class OcclusionTracker; @@ -417,7 +418,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>, void RemoveLayerAnimationEventObserver( LayerAnimationEventObserver* animation_observer); - virtual Region VisibleContentOpaqueRegion() const; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const; virtual ScrollbarLayerInterface* ToScrollbarLayer(); diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 87cb2f8..affdad9 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc @@ -11,6 +11,7 @@ #include "cc/animation/animation_registrar.h" #include "cc/animation/scrollbar_animation_controller.h" #include "cc/base/math_util.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/debug/debug_colors.h" #include "cc/debug/layer_tree_debug_state.h" #include "cc/debug/micro_benchmark_impl.h" @@ -1147,10 +1148,10 @@ void LayerImpl::SetDoubleSided(bool double_sided) { NoteLayerPropertyChangedForSubtree(); } -Region LayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion LayerImpl::VisibleContentOpaqueRegion() const { if (contents_opaque()) - return visible_content_rect(); - return Region(); + return SimpleEnclosedRegion(visible_content_rect()); + return SimpleEnclosedRegion(); } void LayerImpl::DidBeginTracing() {} diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index b09cb3f..2a86ddd 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h @@ -55,6 +55,7 @@ class OcclusionTracker; class Renderer; class ScrollbarAnimationController; class ScrollbarLayerImplBase; +class SimpleEnclosedRegion; class Tile; struct AppendQuadsData; @@ -492,7 +493,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver, return layer_animation_controller_.get(); } - virtual Region VisibleContentOpaqueRegion() const; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const; virtual void DidBecomeActive(); diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc index 5d386ca..c498bd1 100644 --- a/cc/layers/texture_layer.cc +++ b/cc/layers/texture_layer.cc @@ -8,6 +8,7 @@ #include "base/callback_helpers.h" #include "base/location.h" #include "base/synchronization/lock.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/layers/texture_layer_client.h" #include "cc/layers/texture_layer_impl.h" #include "cc/resources/single_release_callback.h" @@ -254,14 +255,14 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) { } } -Region TextureLayer::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion TextureLayer::VisibleContentOpaqueRegion() const { if (contents_opaque()) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF)) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); - return Region(); + return SimpleEnclosedRegion(); } TextureLayer::TextureMailboxHolder::MainThreadReference::MainThreadReference( diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index fb25da6..2fa8ad9 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h @@ -137,7 +137,7 @@ class CC_EXPORT TextureLayer : public Layer { virtual bool Update(ResourceUpdateQueue* queue, const OcclusionTracker<Layer>* occlusion) OVERRIDE; virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE; - virtual Region VisibleContentOpaqueRegion() const OVERRIDE; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE; protected: explicit TextureLayer(TextureLayerClient* client); diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 594867e..80938ba 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc @@ -180,14 +180,14 @@ void TextureLayerImpl::AppendQuads( flipped_); } -Region TextureLayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion TextureLayerImpl::VisibleContentOpaqueRegion() const { if (contents_opaque()) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); if (blend_background_color_ && (SkColorGetA(background_color()) == 0xFF)) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); - return Region(); + return SimpleEnclosedRegion(); } void TextureLayerImpl::ReleaseResources() { diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h index f27fe48..241fde8 100644 --- a/cc/layers/texture_layer_impl.h +++ b/cc/layers/texture_layer_impl.h @@ -31,7 +31,7 @@ class CC_EXPORT TextureLayerImpl : public LayerImpl { virtual void AppendQuads(RenderPass* render_pass, const OcclusionTracker<LayerImpl>& occlusion_tracker, AppendQuadsData* append_quads_data) OVERRIDE; - virtual Region VisibleContentOpaqueRegion() const OVERRIDE; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE; virtual void ReleaseResources() OVERRIDE; // These setter methods don't cause any implicit damage, so the texture client diff --git a/cc/layers/tiled_layer.cc b/cc/layers/tiled_layer.cc index c1937e4..4a960a8 100644 --- a/cc/layers/tiled_layer.cc +++ b/cc/layers/tiled_layer.cc @@ -10,6 +10,7 @@ #include "base/auto_reset.h" #include "base/basictypes.h" #include "build/build_config.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/layers/layer_impl.h" #include "cc/layers/tiled_layer_impl.h" #include "cc/resources/layer_updater.h" @@ -639,11 +640,11 @@ void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) { } } -Region TiledLayer::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const { if (skips_draw_) - return Region(); + return SimpleEnclosedRegion(); if (contents_opaque()) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); return tiler_->OpaqueRegionInContentRect(visible_content_rect()); } diff --git a/cc/layers/tiled_layer.h b/cc/layers/tiled_layer.h index 4a83e45..9f482c8 100644 --- a/cc/layers/tiled_layer.h +++ b/cc/layers/tiled_layer.h @@ -32,7 +32,7 @@ class CC_EXPORT TiledLayer : public ContentsScalingLayer { virtual void SetLayerTreeHost(LayerTreeHost* layer_tree_host) OVERRIDE; virtual void SetTexturePriorities(const PriorityCalculator& priority_calc) OVERRIDE; - virtual Region VisibleContentOpaqueRegion() const OVERRIDE; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE; virtual bool Update(ResourceUpdateQueue* queue, const OcclusionTracker<Layer>* occlusion) OVERRIDE; virtual void OnOutputSurfaceCreated() OVERRIDE; diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc index 86f90b9..9859882 100644 --- a/cc/layers/tiled_layer_impl.cc +++ b/cc/layers/tiled_layer_impl.cc @@ -8,6 +8,7 @@ #include "base/debug/trace_event_argument.h" #include "base/strings/stringprintf.h" #include "cc/base/math_util.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/debug/debug_colors.h" #include "cc/layers/append_quads_data.h" #include "cc/quads/checkerboard_draw_quad.h" @@ -301,11 +302,11 @@ void TiledLayerImpl::PushInvalidTile(int i, int j) { tile->set_contents_swizzled(false); } -Region TiledLayerImpl::VisibleContentOpaqueRegion() const { +SimpleEnclosedRegion TiledLayerImpl::VisibleContentOpaqueRegion() const { if (skips_draw_) - return Region(); + return SimpleEnclosedRegion(); if (contents_opaque()) - return visible_content_rect(); + return SimpleEnclosedRegion(visible_content_rect()); return tiler_->OpaqueRegionInContentRect(visible_content_rect()); } diff --git a/cc/layers/tiled_layer_impl.h b/cc/layers/tiled_layer_impl.h index e3d38a0..b45b733 100644 --- a/cc/layers/tiled_layer_impl.h +++ b/cc/layers/tiled_layer_impl.h @@ -43,7 +43,7 @@ class CC_EXPORT TiledLayerImpl : public LayerImpl { bool contents_swizzled); void PushInvalidTile(int i, int j); - virtual Region VisibleContentOpaqueRegion() const OVERRIDE; + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE; virtual void ReleaseResources() OVERRIDE; const LayerTilingData* TilingForTesting() const { return tiler_.get(); } diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc index fb6b488..a52a5c7 100644 --- a/cc/layers/tiled_layer_unittest.cc +++ b/cc/layers/tiled_layer_unittest.cc @@ -41,7 +41,7 @@ class TestOcclusionTracker : public OcclusionTracker<Layer> { stack_.back().target = render_target; } - void SetOcclusion(const Region& occlusion) { + void SetOcclusion(const SimpleEnclosedRegion& occlusion) { stack_.back().occlusion_from_inside_target = occlusion; } }; @@ -315,7 +315,7 @@ TEST_F(TiledLayerTest, PushOccludedDirtyTiles) { // Invalidates part of the top tile... layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); // ....but the area is occluded. - occluded.SetOcclusion(gfx::Rect(0, 0, 50, 50)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50))); CalcDrawProps(&render_surface_layer_list); UpdateAndPush(layer, layer_impl); @@ -558,7 +558,7 @@ TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) { // The tile size is 100x100, so this invalidates one occluded tile, culls it // during paint, but prepaints it. - occluded.SetOcclusion(gfx::Rect(0, 0, 100, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100))); layer->SetBounds(gfx::Size(100, 100)); CalcDrawProps(&render_surface_layer_list); @@ -1204,7 +1204,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { layer->SetBounds(gfx::Size(600, 600)); CalcDrawProps(&render_surface_layer_list); - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); layer->draw_properties().drawable_content_rect = gfx::Rect(layer->content_bounds()); layer->draw_properties().visible_content_rect = @@ -1221,7 +1221,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { layer->SetTexturePriorities(priority_calculator_); resource_manager_->PrioritizeTextures(); - occluded.SetOcclusion(gfx::Rect(250, 200, 300, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100))); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); layer->SavePaintProperties(); layer->Update(queue_.get(), &occluded); @@ -1231,7 +1231,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { layer->SetTexturePriorities(priority_calculator_); resource_manager_->PrioritizeTextures(); - occluded.SetOcclusion(gfx::Rect(250, 250, 300, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100))); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); layer->SavePaintProperties(); layer->Update(queue_.get(), &occluded); @@ -1255,7 +1255,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { // The partially occluded tiles (by the 150 occlusion height) are visible // beyond the occlusion, so not culled. - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360); layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); @@ -1270,7 +1270,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { // Now the visible region stops at the edge of the occlusion so the partly // visible tiles become fully occluded. - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350); layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); @@ -1284,7 +1284,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { // Now the visible region is even smaller than the occlusion, it should have // the same result. - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340); layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); @@ -1310,7 +1310,7 @@ TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) { layer->SetBounds(gfx::Size(600, 600)); CalcDrawProps(&render_surface_layer_list); - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600); layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600); layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); @@ -1353,7 +1353,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) { layer->draw_properties().screen_space_transform = screen_transform; layer->draw_properties().target_space_transform = screen_transform; - occluded.SetOcclusion(gfx::Rect(100, 100, 150, 50)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50))); layer->draw_properties().drawable_content_rect = gfx::Rect(layer->content_bounds()); layer->draw_properties().visible_content_rect = @@ -1395,7 +1395,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { layer->content_bounds().ToString()); // No tiles are covered by the 300x50 occlusion. - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 50)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50))); layer->draw_properties().drawable_content_rect = gfx::Rect(layer->bounds()); layer->draw_properties().visible_content_rect = @@ -1411,7 +1411,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { layer->fake_layer_updater()->ClearUpdateCount(); // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still. - occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); layer->draw_properties().drawable_content_rect = gfx::Rect(layer->bounds()); layer->draw_properties().visible_content_rect = @@ -1435,7 +1435,7 @@ TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { layer->draw_properties().target_space_transform = screen_transform; // An occlusion of 150x100 will cover 3*2 = 6 tiles. - occluded.SetOcclusion(gfx::Rect(100, 100, 150, 100)); + occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100))); gfx::Rect layer_bounds_rect(layer->bounds()); layer->draw_properties().drawable_content_rect = @@ -1465,7 +1465,7 @@ TEST_F(TiledLayerTest, VisibleContentOpaqueRegion) { // various ways. gfx::Rect opaque_paint_rect; - Region opaque_contents; + SimpleEnclosedRegion opaque_contents; gfx::Rect content_bounds = gfx::Rect(0, 0, 100, 200); gfx::Rect visible_bounds = gfx::Rect(0, 0, 100, 150); diff --git a/cc/resources/layer_tiling_data.cc b/cc/resources/layer_tiling_data.cc index fe3f4c5..846652a 100644 --- a/cc/resources/layer_tiling_data.cc +++ b/cc/resources/layer_tiling_data.cc @@ -7,6 +7,8 @@ #include <vector> #include "base/logging.h" +#include "cc/base/region.h" +#include "cc/base/simple_enclosed_region.h" namespace cc { @@ -90,10 +92,10 @@ gfx::Rect LayerTilingData::TileRect(const Tile* tile) const { return tile_rect; } -Region LayerTilingData::OpaqueRegionInContentRect( +SimpleEnclosedRegion LayerTilingData::OpaqueRegionInContentRect( const gfx::Rect& content_rect) const { if (content_rect.IsEmpty()) - return Region(); + return SimpleEnclosedRegion(); Region opaque_region; int left, top, right, bottom; @@ -109,7 +111,7 @@ Region LayerTilingData::OpaqueRegionInContentRect( opaque_region.Union(tile_opaque_rect); } } - return opaque_region; + return SimpleEnclosedRegion(opaque_region); } void LayerTilingData::SetTilingSize(const gfx::Size& tiling_size) { diff --git a/cc/resources/layer_tiling_data.h b/cc/resources/layer_tiling_data.h index 32fec4e..dd0d43a 100644 --- a/cc/resources/layer_tiling_data.h +++ b/cc/resources/layer_tiling_data.h @@ -12,7 +12,7 @@ #include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" -#include "cc/base/region.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/base/tiling_data.h" #include "ui/gfx/rect.h" @@ -91,7 +91,7 @@ class CC_EXPORT LayerTilingData { int* bottom) const; gfx::Rect TileRect(const Tile* tile) const; - Region OpaqueRegionInContentRect(const gfx::Rect& rect) const; + SimpleEnclosedRegion OpaqueRegionInContentRect(const gfx::Rect& rect) const; void reset() { tiles_.clear(); } diff --git a/cc/test/test_occlusion_tracker.h b/cc/test/test_occlusion_tracker.h index f244a2d..1f51d67 100644 --- a/cc/test/test_occlusion_tracker.h +++ b/cc/test/test_occlusion_tracker.h @@ -18,35 +18,37 @@ class TestOcclusionTracker : public OcclusionTracker<LayerType> { explicit TestOcclusionTracker(const gfx::Rect& screen_scissor_rect) : OcclusionTracker<LayerType>(screen_scissor_rect) {} - Region occlusion_from_inside_target() const { + SimpleEnclosedRegion occlusion_from_inside_target() const { return OcclusionTracker<LayerType>::stack_.back() .occlusion_from_inside_target; } - Region occlusion_from_outside_target() const { + SimpleEnclosedRegion occlusion_from_outside_target() const { return OcclusionTracker<LayerType>::stack_.back() .occlusion_from_outside_target; } - Region occlusion_on_contributing_surface_from_inside_target() const { + SimpleEnclosedRegion occlusion_on_contributing_surface_from_inside_target() + const { size_t stack_size = OcclusionTracker<LayerType>::stack_.size(); if (stack_size < 2) - return Region(); + return SimpleEnclosedRegion(); return OcclusionTracker<LayerType>::stack_[stack_size - 2] .occlusion_from_inside_target; } - Region occlusion_on_contributing_surface_from_outside_target() const { + SimpleEnclosedRegion occlusion_on_contributing_surface_from_outside_target() + const { size_t stack_size = OcclusionTracker<LayerType>::stack_.size(); if (stack_size < 2) - return Region(); + return SimpleEnclosedRegion(); return OcclusionTracker<LayerType>::stack_[stack_size - 2] .occlusion_from_outside_target; } - void set_occlusion_from_outside_target(const Region& region) { + void set_occlusion_from_outside_target(const SimpleEnclosedRegion& region) { OcclusionTracker<LayerType>::stack_.back().occlusion_from_outside_target = region; } - void set_occlusion_from_inside_target(const Region& region) { + void set_occlusion_from_inside_target(const SimpleEnclosedRegion& region) { OcclusionTracker<LayerType>::stack_.back().occlusion_from_inside_target = region; } diff --git a/cc/trees/layer_tree_host_unittest_occlusion.cc b/cc/trees/layer_tree_host_unittest_occlusion.cc index cb6a5d3..3a572d3 100644 --- a/cc/trees/layer_tree_host_unittest_occlusion.cc +++ b/cc/trees/layer_tree_host_unittest_occlusion.cc @@ -24,19 +24,20 @@ class TestLayer : public Layer { if (!occlusion) return false; - // Gain access to internals of the OcclusionTracker. const TestOcclusionTracker<Layer>* test_occlusion = static_cast<const TestOcclusionTracker<Layer>*>(occlusion); - occlusion_ = UnionRegions( + occlusion_ = UnionSimpleEnclosedRegions( test_occlusion->occlusion_from_inside_target(), test_occlusion->occlusion_from_outside_target()); return false; } - const Region& occlusion() const { return occlusion_; } - const Region& expected_occlusion() const { return expected_occlusion_; } - void set_expected_occlusion(const Region& occlusion) { - expected_occlusion_ = occlusion; + const SimpleEnclosedRegion& occlusion() const { return occlusion_; } + const SimpleEnclosedRegion& expected_occlusion() const { + return expected_occlusion_; + } + void set_expected_occlusion(const gfx::Rect& occlusion) { + expected_occlusion_ = SimpleEnclosedRegion(occlusion); } private: @@ -45,8 +46,8 @@ class TestLayer : public Layer { } virtual ~TestLayer() {} - Region occlusion_; - Region expected_occlusion_; + SimpleEnclosedRegion occlusion_; + SimpleEnclosedRegion expected_occlusion_; }; class LayerTreeHostOcclusionTest : public LayerTreeTest { @@ -415,11 +416,6 @@ class LayerTreeHostOcclusionTestOcclusionOpacityFilter : public LayerTreeHostOcclusionTest { public: virtual void SetupTree() OVERRIDE { - gfx::Transform child_transform; - child_transform.Translate(250.0, 250.0); - child_transform.Rotate(90.0); - child_transform.Translate(-250.0, -250.0); - FilterOperations filters; filters.Append(FilterOperation::CreateOpacityFilter(0.5f)); @@ -429,23 +425,36 @@ class LayerTreeHostOcclusionTestOcclusionOpacityFilter SetLayerPropertiesForTesting( root_.get(), NULL, identity_matrix_, gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true); - SetLayerPropertiesForTesting( - child_.get(), root_.get(), child_transform, - gfx::PointF(30.f, 30.f), gfx::Size(500, 500), true); - SetLayerPropertiesForTesting( - grand_child_.get(), child_.get(), identity_matrix_, - gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true); - SetLayerPropertiesForTesting( - child2_.get(), root_.get(), identity_matrix_, - gfx::PointF(10.f, 70.f), gfx::Size(500, 500), true); + SetLayerPropertiesForTesting(child_.get(), + root_.get(), + identity_matrix_, + gfx::PointF(0.f, 0.f), + gfx::Size(500, 500), + true); + SetLayerPropertiesForTesting(grand_child_.get(), + child_.get(), + identity_matrix_, + gfx::PointF(0.f, 0.f), + gfx::Size(500, 500), + true); + SetLayerPropertiesForTesting(child2_.get(), + root_.get(), + identity_matrix_, + gfx::PointF(10.f, 10.f), + gfx::Size(30, 30), + true); child_->SetMasksToBounds(true); child_->SetFilters(filters); - grand_child_->set_expected_occlusion(gfx::Rect(40, 330, 130, 190)); - child_->set_expected_occlusion(UnionRegions( - gfx::Rect(10, 330, 160, 170), gfx::Rect(40, 500, 130, 20))); - root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130)); + // child2_ occludes grand_child_, showing it does occlude inside child_'s + // subtree. + grand_child_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30)); + // grand_child_ occludes child_, showing there is more occlusion in + // child_'s subtree. + child_->set_expected_occlusion(gfx::Rect(0, 0, 200, 200)); + // child2_'s occlusion reaches the root, but child_'s subtree does not. + root_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30)); layer_tree_host()->SetRootLayer(root_); LayerTreeTest::SetupTree(); diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index b87b93d0..d68633b 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc @@ -7,6 +7,7 @@ #include <algorithm> #include "cc/base/math_util.h" +#include "cc/base/region.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" #include "cc/layers/render_surface.h" @@ -65,13 +66,13 @@ static gfx::Rect ScreenSpaceClipRectInTargetSurface( } template <typename RenderSurfaceType> -static Region TransformSurfaceOpaqueRegion( - const Region& region, +static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( + const SimpleEnclosedRegion& region, bool have_clip_rect, const gfx::Rect& clip_rect_in_new_target, const gfx::Transform& transform) { if (region.IsEmpty()) - return Region(); + return region; // Verify that rects within the |surface| will remain rects in its target // surface after applying |transform|. If this is true, then apply |transform| @@ -79,15 +80,13 @@ static Region TransformSurfaceOpaqueRegion( // TODO(danakj): Find a rect interior to each transformed quad. if (!transform.Preserves2dAxisAlignment()) - return Region(); + return SimpleEnclosedRegion(); - // TODO(danakj): If the Region is too complex, degrade gracefully here by - // skipping rects in it. - Region transformed_region; - for (Region::Iterator rects(region); rects.has_rect(); rects.next()) { + SimpleEnclosedRegion transformed_region; + for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { bool clipped; gfx::QuadF transformed_quad = - MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped); + MathUtil::MapQuad(transform, gfx::QuadF(region.GetRect(i)), &clipped); gfx::Rect transformed_rect = gfx::ToEnclosedRect(transformed_quad.BoundingBox()); DCHECK(!clipped); // We only map if the transform preserves axis alignment. @@ -240,11 +239,12 @@ void OcclusionTracker<LayerType>::FinishedRenderTarget( } template <typename LayerType> -static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, - const gfx::Rect& surface_rect, - const gfx::Transform& surface_transform, - LayerType* render_target, - Region* occlusion_from_inside_target) { +static void ReduceOcclusionBelowSurface( + LayerType* contributing_layer, + const gfx::Rect& surface_rect, + const gfx::Transform& surface_transform, + LayerType* render_target, + SimpleEnclosedRegion* occlusion_from_inside_target) { if (surface_rect.IsEmpty()) return; @@ -265,13 +265,12 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, // to expand outside the clip. affected_area_in_target.Inset( -outset_left, -outset_top, -outset_right, -outset_bottom); - Region affected_occlusion = IntersectRegions(*occlusion_from_inside_target, - affected_area_in_target); - Region::Iterator affected_occlusion_rects(affected_occlusion); + SimpleEnclosedRegion affected_occlusion = *occlusion_from_inside_target; + affected_occlusion.Intersect(affected_area_in_target); occlusion_from_inside_target->Subtract(affected_area_in_target); - for (; affected_occlusion_rects.has_rect(); affected_occlusion_rects.next()) { - gfx::Rect occlusion_rect = affected_occlusion_rects.rect(); + for (size_t i = 0; i < affected_occlusion.GetRegionComplexity(); ++i) { + gfx::Rect occlusion_rect = affected_occlusion.GetRect(i); // Shrink the rect by expanding the non-opaque pixels outside the rect. @@ -309,7 +308,7 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( const typename LayerType::RenderSurfaceType* old_surface = old_target->render_surface(); - Region old_occlusion_from_inside_target_in_new_target = + SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target = TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( stack_[last_index].occlusion_from_inside_target, old_surface->is_clipped(), @@ -324,7 +323,7 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( old_surface->replica_draw_transform())); } - Region old_occlusion_from_outside_target_in_new_target = + SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target = TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( stack_[last_index].occlusion_from_outside_target, false, @@ -400,8 +399,6 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( const LayerType* layer) { DCHECK(!stack_.empty()); DCHECK_EQ(layer->render_target(), stack_.back().target); - if (stack_.empty()) - return; if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1) return; @@ -415,7 +412,7 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( if (!LayerTransformsToTargetKnown(layer)) return; - Region opaque_contents = layer->VisibleContentOpaqueRegion(); + SimpleEnclosedRegion opaque_contents = layer->VisibleContentOpaqueRegion(); if (opaque_contents.IsEmpty()) return; @@ -434,14 +431,12 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( layer->render_target()->render_surface()->content_rect()); } - for (Region::Iterator opaque_content_rects(opaque_contents); - opaque_content_rects.has_rect(); - opaque_content_rects.next()) { + for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { bool clipped; - gfx::QuadF transformed_quad = MathUtil::MapQuad( - layer->draw_transform(), - gfx::QuadF(opaque_content_rects.rect()), - &clipped); + gfx::QuadF transformed_quad = + MathUtil::MapQuad(layer->draw_transform(), + gfx::QuadF(opaque_contents.GetRect(i)), + &clipped); gfx::Rect transformed_rect = gfx::ToEnclosedRect(transformed_quad.BoundingBox()); DCHECK(!clipped); // We only map if the transform preserves axis alignment. @@ -468,8 +463,9 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( if (!non_occluding_screen_space_rects_) return; - Region non_opaque_contents = - SubtractRegions(gfx::Rect(layer->content_bounds()), opaque_contents); + Region non_opaque_contents(gfx::Rect(layer->content_bounds())); + non_opaque_contents.Subtract(opaque_contents); + for (Region::Iterator non_opaque_content_rects(non_opaque_contents); non_opaque_content_rects.has_rect(); non_opaque_content_rects.next()) { @@ -514,24 +510,24 @@ bool OcclusionTracker<LayerType>::Occluded( DCHECK(render_target->render_surface()); DCHECK_EQ(render_target, stack_.back().target); - if (stack_.back().occlusion_from_inside_target.IsEmpty() && - stack_.back().occlusion_from_outside_target.IsEmpty()) { + const StackObject& back = stack_.back(); + if (back.occlusion_from_inside_target.IsEmpty() && + back.occlusion_from_outside_target.IsEmpty()) { return false; } // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = + gfx::Rect unoccluded_rect_in_target_surface = MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); - unoccluded_region_in_target_surface.Subtract( - stack_.back().occlusion_from_inside_target); - gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = - unoccluded_region_in_target_surface.bounds(); - unoccluded_region_in_target_surface.Subtract( - stack_.back().occlusion_from_outside_target); - - gfx::RectF unoccluded_rect_in_target_surface = - unoccluded_region_in_target_surface.bounds(); + DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); + DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); + // These subtract operations are more lossy than if we did both operations at + // once. + unoccluded_rect_in_target_surface.Subtract( + stack_.back().occlusion_from_inside_target.bounds()); + unoccluded_rect_in_target_surface.Subtract( + stack_.back().occlusion_from_outside_target.bounds()); return unoccluded_rect_in_target_surface.IsEmpty(); } @@ -540,13 +536,13 @@ template <typename LayerType> gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( const gfx::Rect& content_rect, const gfx::Transform& draw_transform) const { - if (stack_.empty()) - return content_rect; + DCHECK(!stack_.empty()); if (content_rect.IsEmpty()) return content_rect; - if (stack_.back().occlusion_from_inside_target.IsEmpty() && - stack_.back().occlusion_from_outside_target.IsEmpty()) { + const StackObject& back = stack_.back(); + if (back.occlusion_from_inside_target.IsEmpty() && + back.occlusion_from_outside_target.IsEmpty()) { return content_rect; } @@ -556,18 +552,20 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = + gfx::Rect unoccluded_rect_in_target_surface = MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); - unoccluded_region_in_target_surface.Subtract( - stack_.back().occlusion_from_inside_target); - unoccluded_region_in_target_surface.Subtract( - stack_.back().occlusion_from_outside_target); - - if (unoccluded_region_in_target_surface.IsEmpty()) + DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); + DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); + // These subtract operations are more lossy than if we did both operations at + // once. + unoccluded_rect_in_target_surface.Subtract( + back.occlusion_from_inside_target.bounds()); + unoccluded_rect_in_target_surface.Subtract( + back.occlusion_from_outside_target.bounds()); + + if (unoccluded_rect_in_target_surface.IsEmpty()) return gfx::Rect(); - gfx::Rect unoccluded_rect_in_target_surface = - unoccluded_region_in_target_surface.bounds(); gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( inverse_draw_transform, unoccluded_rect_in_target_surface); unoccluded_rect.Intersect(content_rect); @@ -590,7 +588,6 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( return content_rect; const StackObject& second_last = stack_[stack_.size() - 2]; - if (second_last.occlusion_from_inside_target.IsEmpty() && second_last.occlusion_from_outside_target.IsEmpty()) return content_rect; @@ -601,18 +598,21 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = + gfx::Rect unoccluded_rect_in_target_surface = MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); - unoccluded_region_in_target_surface.Subtract( - second_last.occlusion_from_inside_target); - unoccluded_region_in_target_surface.Subtract( - second_last.occlusion_from_outside_target); - - if (unoccluded_region_in_target_surface.IsEmpty()) + DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u); + DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(), + 1u); + // These subtract operations are more lossy than if we did both operations at + // once. + unoccluded_rect_in_target_surface.Subtract( + second_last.occlusion_from_inside_target.bounds()); + unoccluded_rect_in_target_surface.Subtract( + second_last.occlusion_from_outside_target.bounds()); + + if (unoccluded_rect_in_target_surface.IsEmpty()) return gfx::Rect(); - gfx::Rect unoccluded_rect_in_target_surface = - unoccluded_region_in_target_surface.bounds(); gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( inverse_draw_transform, unoccluded_rect_in_target_surface); unoccluded_rect.Intersect(content_rect); @@ -620,6 +620,17 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( return unoccluded_rect; } +template <typename LayerType> +Region OcclusionTracker<LayerType>::ComputeVisibleRegionInScreen() const { + DCHECK(!stack_.back().target->parent()); + const SimpleEnclosedRegion& occluded = + stack_.back().occlusion_from_inside_target; + Region visible_region(screen_space_clip_rect_); + for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) + visible_region.Subtract(occluded.GetRect(i)); + return visible_region; +} + // Instantiate (and export) templates here for the linker. template class OcclusionTracker<Layer>; template class OcclusionTracker<LayerImpl>; diff --git a/cc/trees/occlusion_tracker.h b/cc/trees/occlusion_tracker.h index 78b992c..8d07f43 100644 --- a/cc/trees/occlusion_tracker.h +++ b/cc/trees/occlusion_tracker.h @@ -9,12 +9,13 @@ #include "base/basictypes.h" #include "cc/base/cc_export.h" -#include "cc/base/region.h" +#include "cc/base/simple_enclosed_region.h" #include "cc/layers/layer_iterator.h" #include "ui/gfx/rect.h" namespace cc { class LayerImpl; +class Region; class RenderSurfaceImpl; class Layer; class RenderSurface; @@ -64,11 +65,7 @@ class CC_EXPORT OcclusionTracker { const gfx::Transform& draw_transform) const; // Gives the region of the screen that is not occluded by something opaque. - Region ComputeVisibleRegionInScreen() const { - DCHECK(!stack_.back().target->parent()); - return SubtractRegions(screen_space_clip_rect_, - stack_.back().occlusion_from_inside_target); - } + Region ComputeVisibleRegionInScreen() const; void set_minimum_tracking_size(const gfx::Size& size) { minimum_tracking_size_ = size; @@ -89,8 +86,8 @@ class CC_EXPORT OcclusionTracker { StackObject() : target(0) {} explicit StackObject(const LayerType* target) : target(target) {} const LayerType* target; - Region occlusion_from_outside_target; - Region occlusion_from_inside_target; + SimpleEnclosedRegion occlusion_from_outside_target; + SimpleEnclosedRegion occlusion_from_inside_target; }; // The stack holds occluded regions for subtrees in the diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc index e6464a2..997d184 100644 --- a/cc/trees/occlusion_tracker_unittest.cc +++ b/cc/trees/occlusion_tracker_unittest.cc @@ -33,9 +33,11 @@ class TestContentLayer : public Layer { SetIsDrawable(true); } - virtual Region VisibleContentOpaqueRegion() const OVERRIDE { - if (override_opaque_contents_rect_) - return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect()); + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE { + if (override_opaque_contents_rect_) { + return SimpleEnclosedRegion( + gfx::IntersectRects(opaque_contents_rect_, visible_content_rect())); + } return Layer::VisibleContentOpaqueRegion(); } void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) { @@ -57,9 +59,11 @@ class TestContentLayerImpl : public LayerImpl { SetDrawsContent(true); } - virtual Region VisibleContentOpaqueRegion() const OVERRIDE { - if (override_opaque_contents_rect_) - return gfx::IntersectRects(opaque_contents_rect_, visible_content_rect()); + virtual SimpleEnclosedRegion VisibleContentOpaqueRegion() const OVERRIDE { + if (override_opaque_contents_rect_) { + return SimpleEnclosedRegion( + gfx::IntersectRects(opaque_contents_rect_, visible_content_rect())); + } return LayerImpl::VisibleContentOpaqueRegion(); } void SetOpaqueContentsRect(const gfx::Rect& opaque_contents_rect) { @@ -179,13 +183,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { virtual void RunMyTest() = 0; - virtual void TearDown() { - Types::DestroyLayer(&root_); - render_surface_layer_list_.reset(); - render_surface_layer_list_impl_.clear(); - replica_layers_.clear(); - mask_layers_.clear(); - } + virtual void TearDown() { DestroyLayers(); } typename Types::HostType* GetHost(); @@ -287,6 +285,14 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { return layer; } + void DestroyLayers() { + Types::DestroyLayer(&root_); + render_surface_layer_list_.reset(); + render_surface_layer_list_impl_.clear(); + replica_layers_.clear(); + mask_layers_.clear(); + ResetLayerIterator(); + } void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {} @@ -336,14 +342,14 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void EnterLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType* occlusion) { - ASSERT_EQ(layer, *layer_iterator_); + ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_itself()); occlusion->EnterLayer(layer_iterator_); } void LeaveLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType* occlusion) { - ASSERT_EQ(layer, *layer_iterator_); + ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_itself()); occlusion->LeaveLayer(layer_iterator_); ++layer_iterator_; @@ -358,7 +364,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void EnterContributingSurface( typename Types::LayerType* layer, typename Types::OcclusionTrackerType* occlusion) { - ASSERT_EQ(layer, *layer_iterator_); + ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_target_render_surface()); occlusion->EnterLayer(layer_iterator_); occlusion->LeaveLayer(layer_iterator_); @@ -370,7 +376,7 @@ template <typename Types> class OcclusionTrackerTest : public testing::Test { void LeaveContributingSurface( typename Types::LayerType* layer, typename Types::OcclusionTrackerType* occlusion) { - ASSERT_EQ(layer, *layer_iterator_); + ASSERT_EQ(*layer_iterator_, layer); ASSERT_TRUE(layer_iterator_.represents_contributing_render_surface()); occlusion->LeaveLayer(layer_iterator_); ++layer_iterator_; @@ -544,38 +550,32 @@ class OcclusionTrackerTestIdentityTransforms EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 30, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 29, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 29, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 29, 69, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 30, 69, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 31, 69, 69))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 31, 70, 69))); - EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 31, 70, 69))); + EXPECT_EQ(gfx::Rect(29, 30, 1, 70), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 30, 70, 70))); + EXPECT_EQ(gfx::Rect(29, 29, 70, 70), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 29, 70, 70))); + EXPECT_EQ(gfx::Rect(30, 29, 70, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 29, 70, 70))); + EXPECT_EQ(gfx::Rect(31, 29, 69, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 29, 69, 70))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 30, 69, 70))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 31, 69, 69))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 31, 70, 69))); + EXPECT_EQ(gfx::Rect(29, 31, 1, 69), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 31, 70, 69))); } }; @@ -619,12 +619,12 @@ class OcclusionTrackerTestQuadsMismatchLayer EXPECT_TRUE(occlusion.UnoccludedContentRect(gfx::Rect(0, 0, 10, 10), quad_transform).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10), - occlusion.UnoccludedContentRect(gfx::Rect(40, 40, 10, 10), - quad_transform)); - EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10), - occlusion.UnoccludedContentRect(gfx::Rect(35, 30, 10, 10), - quad_transform)); + EXPECT_EQ(gfx::Rect(40, 40, 10, 10), + occlusion.UnoccludedContentRect(gfx::Rect(40, 40, 10, 10), + quad_transform)); + EXPECT_EQ(gfx::Rect(40, 30, 5, 10), + occlusion.UnoccludedContentRect(gfx::Rect(35, 30, 10, 10), + quad_transform)); } }; @@ -665,38 +665,32 @@ class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> { EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 70, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 70, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 69, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 70, 69))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 30, 69, 70))); - EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 29, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 29, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(31, 29, 69, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 29, 69, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 30, 69, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 31, 69, 69))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 31, 70, 69))); - EXPECT_RECT_EQ(gfx::Rect(29, 31, 1, 69), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 31, 70, 69))); + EXPECT_EQ(gfx::Rect(29, 30, 1, 70), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 30, 69, 70))); + EXPECT_EQ(gfx::Rect(29, 29, 70, 70), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 29, 70, 70))); + EXPECT_EQ(gfx::Rect(30, 29, 70, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 29, 70, 70))); + EXPECT_EQ(gfx::Rect(31, 29, 69, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 29, 69, 70))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 30, 69, 70))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 31, 69, 69))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 31, 70, 69))); + EXPECT_EQ(gfx::Rect(29, 31, 1, 69), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 31, 70, 69))); } }; @@ -735,35 +729,29 @@ class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> { EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 50, 50, 50))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(49, 50, 50, 50))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(50, 49, 50, 50))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(51, 50, 49, 50))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(50, 51, 50, 49))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(50, 50, 50, 50)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(49, 50, 50, 50))); - EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(49, 49, 50, 50))); - EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(50, 49, 50, 50))); - EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(51, 49, 49, 50))); + EXPECT_EQ(gfx::Rect(49, 50, 1, 50), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(49, 50, 50, 50))); + EXPECT_EQ(gfx::Rect(49, 49, 50, 50), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(49, 49, 50, 50))); + EXPECT_EQ(gfx::Rect(50, 49, 50, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(50, 49, 50, 50))); + EXPECT_EQ(gfx::Rect(51, 49, 49, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(51, 49, 49, 50))); EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(51, 50, 49, 50)).IsEmpty()); EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(51, 51, 49, 49)).IsEmpty()); EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(50, 51, 50, 49)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(49, 51, 50, 49))); + EXPECT_EQ(gfx::Rect(49, 51, 1, 49), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(49, 51, 50, 49))); } }; @@ -814,12 +802,6 @@ class OcclusionTrackerTestChildInRotatedChild EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(31, 40, 69, 60))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 41, 70, 59))); - /* Justification for the above occlusion from |layer|: 100 +---------------------+ @@ -912,15 +894,15 @@ class OcclusionTrackerTestScaledRenderSurface EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_RECT_EQ( + EXPECT_EQ( gfx::Rect(0, 0, 25, 25), occlusion.UnoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25))); - EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25), - occlusion.UnoccludedLayerContentRect( - layer2, gfx::Rect(10, 25, 25, 25))); - EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15), - occlusion.UnoccludedLayerContentRect( - layer2, gfx::Rect(25, 10, 25, 25))); + EXPECT_EQ(gfx::Rect(10, 25, 15, 25), + occlusion.UnoccludedLayerContentRect(layer2, + gfx::Rect(10, 25, 25, 25))); + EXPECT_EQ(gfx::Rect(25, 10, 25, 15), + occlusion.UnoccludedLayerContentRect(layer2, + gfx::Rect(25, 10, 25, 25))); EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty()); } @@ -935,171 +917,60 @@ class OcclusionTrackerTestVisitTargetTwoTimes explicit OcclusionTrackerTestVisitTargetTwoTimes(bool opaque_layers) : OcclusionTrackerTest<Types>(opaque_layers) {} void RunMyTest() { - gfx::Transform child_transform; - child_transform.Translate(250.0, 250.0); - child_transform.Rotate(90.0); - child_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* root = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); - typename Types::ContentLayerType* parent = this->CreateDrawingLayer( - root, this->identity_matrix, gfx::PointF(), gfx::Size(100, 100), true); - parent->SetMasksToBounds(true); - typename Types::LayerType* child = this->CreateSurface( - parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(500, 500)); - child->SetMasksToBounds(true); - typename Types::ContentLayerType* layer = - this->CreateDrawingLayer(child, + typename Types::LayerType* surface = this->CreateSurface( + root, this->identity_matrix, gfx::PointF(30.f, 30.f), gfx::Size()); + typename Types::ContentLayerType* surface_child = + this->CreateDrawingLayer(surface, this->identity_matrix, gfx::PointF(10.f, 10.f), - gfx::Size(500, 500), + gfx::Size(50, 50), true); - // |child2| makes |parent|'s surface get considered by OcclusionTracker - // first, instead of |child|'s. This exercises different code in - // LeaveToRenderTarget, as the target surface has already been seen. - typename Types::ContentLayerType* child2 = - this->CreateDrawingLayer(parent, + // |top_layer| makes |root|'s surface get considered by OcclusionTracker + // first, instead of |surface|'s. This exercises different code in + // LeaveToRenderTarget, as the target surface has already been seen when + // leaving |surface| later. + typename Types::ContentLayerType* top_layer = + this->CreateDrawingLayer(root, this->identity_matrix, - gfx::PointF(30.f, 30.f), - gfx::Size(60, 20), + gfx::PointF(40.f, 90.f), + gfx::Size(50, 20), true); this->CalcDrawEtc(root); TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( gfx::Rect(0, 0, 1000, 1000)); - this->VisitLayer(child2, &occlusion); + this->VisitLayer(top_layer, &occlusion); EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(), + EXPECT_EQ(gfx::Rect(40, 90, 50, 20).ToString(), occlusion.occlusion_from_inside_target().ToString()); - this->VisitLayer(layer, &occlusion); + this->VisitLayer(surface_child, &occlusion); - EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(), + EXPECT_EQ(gfx::Rect(10, 60, 50, 20).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), + EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - this->EnterContributingSurface(child, &occlusion); + this->EnterContributingSurface(surface, &occlusion); - EXPECT_EQ(gfx::Rect(0, 440, 20, 60).ToString(), + EXPECT_EQ(gfx::Rect(10, 60, 50, 20).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), + EXPECT_EQ(gfx::Rect(10, 10, 50, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - // Occlusion in |child2| should get merged with the |child| surface we are - // leaving now. - this->LeaveContributingSurface(child, &occlusion); - this->EnterLayer(parent, &occlusion); + // Occlusion from |top_layer| already in the root target should get merged + // with the occlusion from the |surface| we are leaving now. + this->LeaveContributingSurface(surface, &occlusion); + this->EnterLayer(root, &occlusion); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)) - .ToString(), + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + EXPECT_EQ(gfx::Rect(40, 40, 50, 70).ToString(), occlusion.occlusion_from_inside_target().ToString()); - - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 70, 70))); - EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 30, 70, 70))); - - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 30, 60, 10))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 30, 60, 10))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 29, 60, 10))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(31, 30, 60, 10))); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 31, 60, 10))); - - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); - - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 30, 60, 10)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 30, 60, 10))); - EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 29, 60, 10))); - EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 30, 60, 10))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 31, 60, 10)).IsEmpty()); - - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 40, 70, 60))); - // This rect is mostly occluded by |child2|. - EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 39, 70, 60))); - // This rect extends past top/right ends of |child2|. - EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 29, 70, 70))); - // This rect extends past left/right ends of |child2|. - EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(20, 39, 80, 60))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 40, 69, 60))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 41, 70, 59))); - - /* Justification for the above occlusion from |layer|: - 100 - +---------------------+ - | | - | 30 | rotate(90) - | 30 + ------------+--------------------+ - 100 | | 10 | | | ==> - | |10+----------|----------------------+ - | + ------------+ | | | - | | | | | | - | | | | | | - +----|--|-------------+ | | - | | | | - | | | | - | | | |500 - | | | | - | | | | - | | | | - | | | | - +--|-------------------------------+ | - | | - +---------------------------------+ - 500 - - - +---------------------+ - | |30 Visible region of |layer|: ///// - | 30 60 | |child2|: \\\\\ - | 30 +------------+--------------------+ - | |\\\\\\\\\\\\| |10 | - | +--|\\\\\\\\\\\\|-----------------+ | - | | +------------+//| 420 | | - | | |///////////////|60 | | - | | |///////////////| | | - +--|--|---------------+ | | - 20|10| 70 | | - | | | | - | | | | - | | | | - | | | | - | | | | - | | |10| - | +------------------------------|--+ - | 490 | - +---------------------------------+ - 500 - */ } }; @@ -1153,8 +1024,7 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(75, 55, 1, 1))); - EXPECT_RECT_EQ( + EXPECT_EQ( gfx::Rect(75, 55, 1, 1), occlusion.UnoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1))); } @@ -1213,22 +1083,17 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 430, 60, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(child, gfx::Rect(9, 430, 60, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(11, 430, 59, 70))); - EXPECT_TRUE(occlusion.OccludedLayer(child, gfx::Rect(10, 431, 60, 69))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( child, gfx::Rect(10, 430, 60, 70)).IsEmpty()); - EXPECT_RECT_EQ( + EXPECT_EQ( gfx::Rect(9, 430, 1, 70), occlusion.UnoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - child, gfx::Rect(11, 430, 59, 70))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - child, gfx::Rect(10, 431, 60, 69))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(child, + gfx::Rect(11, 430, 59, 70))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(child, + gfx::Rect(10, 431, 60, 69))); this->LeaveContributingSurface(child, &occlusion); this->EnterLayer(parent, &occlusion); @@ -1238,24 +1103,20 @@ class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 40, 70, 60))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 39, 70, 60))); - EXPECT_TRUE(occlusion.UnoccludedLayerContentRect( parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); - EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(29, 40, 70, 60))); - EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 39, 70, 60))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(31, 40, 69, 60))); - EXPECT_RECT_EQ(gfx::Rect(), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(30, 41, 70, 59))); + EXPECT_EQ(gfx::Rect(29, 40, 1, 60), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(29, 40, 70, 60))); + EXPECT_EQ(gfx::Rect(30, 39, 70, 1), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 39, 70, 60))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(31, 40, 69, 60))); + EXPECT_EQ(gfx::Rect(), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(30, 41, 70, 59))); /* Justification for the above occlusion from |layer1| and |layer2|: @@ -1293,29 +1154,20 @@ class OcclusionTrackerTestOverlappingSurfaceSiblings explicit OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaque_layers) : OcclusionTrackerTest<Types>(opaque_layers) {} void RunMyTest() { - gfx::Transform child_transform; - child_transform.Translate(250.0, 250.0); - child_transform.Rotate(90.0); - child_transform.Translate(-250.0, -250.0); - typename Types::ContentLayerType* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); parent->SetMasksToBounds(true); typename Types::LayerType* child1 = this->CreateSurface( - parent, child_transform, gfx::PointF(30.f, 30.f), gfx::Size(10, 10)); + parent, this->identity_matrix, gfx::PointF(10.f, 0.f), gfx::Size()); typename Types::LayerType* child2 = this->CreateSurface( - parent, child_transform, gfx::PointF(20.f, 40.f), gfx::Size(10, 10)); - typename Types::ContentLayerType* layer1 = - this->CreateDrawingLayer(child1, - this->identity_matrix, - gfx::PointF(-10.f, -10.f), - gfx::Size(510, 510), - true); + parent, this->identity_matrix, gfx::PointF(30.f, 0.f), gfx::Size()); + typename Types::ContentLayerType* layer1 = this->CreateDrawingLayer( + child1, this->identity_matrix, gfx::PointF(), gfx::Size(40, 50), true); typename Types::ContentLayerType* layer2 = this->CreateDrawingLayer(child2, this->identity_matrix, - gfx::PointF(-10.f, -10.f), - gfx::Size(510, 510), + gfx::PointF(10.f, 0.f), + gfx::Size(40, 50), true); this->CalcDrawEtc(parent); @@ -1325,72 +1177,30 @@ class OcclusionTrackerTestOverlappingSurfaceSiblings this->VisitLayer(layer2, &occlusion); this->EnterContributingSurface(child2, &occlusion); + // layer2's occlusion. EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(), + EXPECT_EQ(gfx::Rect(10, 0, 40, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - // There is nothing above child2's surface in the z-order. - EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), - occlusion.UnoccludedSurfaceContentRect( - child2, false, gfx::Rect(-10, 420, 70, 80))); - this->LeaveContributingSurface(child2, &occlusion); this->VisitLayer(layer1, &occlusion); this->EnterContributingSurface(child1, &occlusion); - EXPECT_EQ(gfx::Rect(0, 430, 70, 80).ToString(), + // layer2's occlusion in the target space of layer1. + EXPECT_EQ(gfx::Rect(30, 0, 40, 50).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(), + // layer1's occlusion. + EXPECT_EQ(gfx::Rect(0, 0, 40, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - // child2's contents will occlude child1 below it. - EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70), - occlusion.UnoccludedSurfaceContentRect( - child1, false, gfx::Rect(-10, 430, 80, 70))); - this->LeaveContributingSurface(child1, &occlusion); this->EnterLayer(parent, &occlusion); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70)) - .ToString(), + // The occlusion from from layer1 and layer2 is merged. + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + EXPECT_EQ(gfx::Rect(10, 0, 70, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 20, 80, 80))); - - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(30, 20, 70, 80))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(29, 20, 70, 80))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(30, 19, 70, 80))); - - EXPECT_TRUE(occlusion.OccludedLayer(parent, gfx::Rect(20, 30, 80, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(19, 30, 80, 70))); - EXPECT_FALSE(occlusion.OccludedLayer(parent, gfx::Rect(20, 29, 80, 70))); - - /* Justification for the above occlusion: - 100 - +---------------------+ - | 20 | layer1 - | 30+ ---------------------------------+ - 100 | 30| | layer2 | - |20+----------------------------------+ | - | | | | | | - | | | | | | - | | | | | | - +--|-|----------------+ | | - | | | | 510 - | | | | - | | | | - | | | | - | | | | - | | | | - | | | | - | +--------------------------------|-+ - | | - +----------------------------------+ - 510 - */ } }; @@ -1454,9 +1264,9 @@ class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms this->EnterContributingSurface(child2, &occlusion); // There is nothing above child2's surface in the z-order. - EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), - occlusion.UnoccludedSurfaceContentRect( - child2, false, gfx::Rect(-10, 420, 70, 80))); + EXPECT_EQ(gfx::Rect(-10, 420, 70, 80), + occlusion.UnoccludedSurfaceContentRect( + child2, false, gfx::Rect(-10, 420, 70, 80))); this->LeaveContributingSurface(child2, &occlusion); this->VisitLayer(layer1, &occlusion); @@ -1620,14 +1430,10 @@ class OcclusionTrackerTestReplicaDoesOcclude void RunMyTest() { typename Types::ContentLayerType* parent = this->CreateRoot( this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); - typename Types::LayerType* surface = - this->CreateDrawingSurface(parent, - this->identity_matrix, - gfx::PointF(0.f, 100.f), - gfx::Size(50, 50), - true); + typename Types::LayerType* surface = this->CreateDrawingSurface( + parent, this->identity_matrix, gfx::PointF(), gfx::Size(50, 50), true); this->CreateReplicaLayer( - surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); + surface, this->identity_matrix, gfx::PointF(0.f, 50.f), gfx::Size()); this->CalcDrawEtc(parent); TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( @@ -1642,10 +1448,8 @@ class OcclusionTrackerTestReplicaDoesOcclude this->EnterLayer(parent, &occlusion); // The surface and replica should both be occluding the parent. - EXPECT_EQ( - UnionRegions(gfx::Rect(0, 100, 50, 50), - gfx::Rect(50, 150, 50, 50)).ToString(), - occlusion.occlusion_from_inside_target().ToString()); + EXPECT_EQ(gfx::Rect(50, 100).ToString(), + occlusion.occlusion_from_inside_target().ToString()); } }; @@ -1668,7 +1472,7 @@ class OcclusionTrackerTestReplicaWithClipping gfx::Size(50, 50), true); this->CreateReplicaLayer( - surface, this->identity_matrix, gfx::PointF(50.f, 50.f), gfx::Size()); + surface, this->identity_matrix, gfx::PointF(0.f, 50.f), gfx::Size()); this->CalcDrawEtc(parent); TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( @@ -1676,17 +1480,19 @@ class OcclusionTrackerTestReplicaWithClipping this->VisitLayer(surface, &occlusion); + // The surface layer's occlusion in its own space. EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); this->VisitContributingSurface(surface, &occlusion); this->EnterLayer(parent, &occlusion); - // The surface and replica should both be occluding the parent. - EXPECT_EQ( - UnionRegions(gfx::Rect(0, 100, 50, 50), - gfx::Rect(50, 150, 50, 20)).ToString(), - occlusion.occlusion_from_inside_target().ToString()); + // The surface and replica should both be occluding the parent, the + // replica's occlusion is clipped by the parent. + EXPECT_EQ(gfx::Rect(0, 100, 50, 70).ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); } }; @@ -1752,16 +1558,15 @@ class OcclusionTrackerTestOpaqueContentsRegionEmpty gfx::Rect(0, 0, 1000, 1000)); this->EnterLayer(layer, &occlusion); - EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100))); - EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 0, 100, 100))); - EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 100, 100, 100))); - EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100, 100, 100))); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); this->LeaveLayer(layer, &occlusion); this->VisitContributingSurface(layer, &occlusion); this->EnterLayer(parent, &occlusion); EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); + EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); } }; @@ -1794,13 +1599,6 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(), occlusion.occlusion_from_inside_target().ToString()); - - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); - EXPECT_TRUE( - occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); } { TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( @@ -1813,13 +1611,6 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(), occlusion.occlusion_from_inside_target().ToString()); - - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); - EXPECT_TRUE( - occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); } { TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( @@ -1832,13 +1623,6 @@ class OcclusionTrackerTestOpaqueContentsRegionNonEmpty EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(), occlusion.occlusion_from_inside_target().ToString()); - - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(0, 100, 100, 100))); - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(100, 100, 100, 100))); - EXPECT_FALSE( - occlusion.OccludedLayer(parent, gfx::Rect(200, 200, 100, 100))); } } }; @@ -1872,7 +1656,7 @@ class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> { // The layer is rotated in 3d but without preserving 3d, so it only gets // resized. - EXPECT_RECT_EQ( + EXPECT_EQ( gfx::Rect(0, 0, 200, 200), occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); } @@ -1966,7 +1750,7 @@ class OcclusionTrackerTestPerspectiveTransform gfx::Rect(0, 0, 1000, 1000)); this->EnterLayer(layer, &occlusion); - EXPECT_RECT_EQ( + EXPECT_EQ( gfx::Rect(0, 0, 200, 200), occlusion.UnoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); } @@ -2195,18 +1979,18 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), - occlusion.UnoccludedLayerContentRect( - surface_child, gfx::Rect(0, 0, 200, 300))); + EXPECT_EQ(gfx::Rect(100, 0, 100, 300), + occlusion.UnoccludedLayerContentRect(surface_child, + gfx::Rect(0, 0, 200, 300))); this->LeaveLayer(surface_child, &occlusion); this->EnterLayer(surface, &occlusion); EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), - occlusion.UnoccludedLayerContentRect( - surface, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(200, 0, 50, 300), + occlusion.UnoccludedLayerContentRect(surface, + gfx::Rect(0, 0, 300, 300))); this->LeaveLayer(surface, &occlusion); this->EnterContributingSurface(surface, &occlusion); @@ -2215,9 +1999,9 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(0, 0, 250, 300), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 300, 300))); this->LeaveContributingSurface(surface, &occlusion); // Occlusion from outside the animating surface still exists. @@ -2230,9 +2014,9 @@ class OcclusionTrackerTestAnimationOpacity1OnMainThread this->EnterLayer(parent, &occlusion); // Occlusion is not added for the animating |layer|. - EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(0, 0, 250, 300), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(0, 0, 300, 300))); } }; @@ -2304,9 +2088,9 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(0, 0, 250, 300), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(0, 0, 300, 300))); this->LeaveLayer(parent2, &occlusion); this->VisitLayer(surface_child2, &occlusion); @@ -2315,18 +2099,18 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), - occlusion.UnoccludedLayerContentRect( - surface_child, gfx::Rect(0, 0, 200, 300))); + EXPECT_EQ(gfx::Rect(100, 0, 100, 300), + occlusion.UnoccludedLayerContentRect(surface_child, + gfx::Rect(0, 0, 200, 300))); this->LeaveLayer(surface_child, &occlusion); this->EnterLayer(surface, &occlusion); EXPECT_EQ(gfx::Rect(0, 0, 200, 300).ToString(), occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect(250, 0, 50, 300).ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), - occlusion.UnoccludedLayerContentRect( - surface, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(200, 0, 50, 300), + occlusion.UnoccludedLayerContentRect(surface, + gfx::Rect(0, 0, 300, 300))); this->LeaveLayer(surface, &occlusion); this->EnterContributingSurface(surface, &occlusion); @@ -2335,9 +2119,9 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread occlusion.occlusion_from_inside_target().ToString()); EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(0, 0, 250, 300), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 300, 300))); this->LeaveContributingSurface(surface, &occlusion); // Occlusion from outside the animating surface still exists. @@ -2350,9 +2134,9 @@ class OcclusionTrackerTestAnimationOpacity0OnMainThread this->EnterLayer(parent, &occlusion); // Occlusion is not added for the animating |layer|. - EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), - occlusion.UnoccludedLayerContentRect( - parent, gfx::Rect(0, 0, 300, 300))); + EXPECT_EQ(gfx::Rect(0, 0, 250, 300), + occlusion.UnoccludedLayerContentRect(parent, + gfx::Rect(0, 0, 300, 300))); } }; @@ -2527,8 +2311,8 @@ class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent occlusion.occlusion_from_inside_target().ToString()); // Clear any stored occlusion. - occlusion.set_occlusion_from_outside_target(Region()); - occlusion.set_occlusion_from_inside_target(Region()); + occlusion.set_occlusion_from_outside_target(SimpleEnclosedRegion()); + occlusion.set_occlusion_from_inside_target(SimpleEnclosedRegion()); this->VisitLayer(surface, &occlusion); this->VisitContributingSurface(surface, &occlusion); @@ -2627,9 +2411,9 @@ class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> { this->EnterContributingSurface(surface, &occlusion); // Surface is not occluded so it shouldn't think it is. - EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 100, 100))); } }; @@ -2684,12 +2468,12 @@ class OcclusionTrackerTestSurfaceWithReplicaUnoccluded this->EnterContributingSurface(surface, &occlusion); // Surface is occluded, but only the top 10px of the replica. - EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 100, 100))); - EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90), - occlusion.UnoccludedSurfaceContentRect( - surface, true, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 0, 0, 0), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 10, 100, 90), + occlusion.UnoccludedSurfaceContentRect( + surface, true, gfx::Rect(0, 0, 100, 100))); } }; @@ -2704,7 +2488,7 @@ class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently : OcclusionTrackerTest<Types>(opaque_layers) {} void RunMyTest() { typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(100, 200)); + this->identity_matrix, gfx::PointF(), gfx::Size(200, 100)); typename Types::LayerType* surface = this->CreateDrawingSurface(parent, this->identity_matrix, @@ -2713,14 +2497,18 @@ class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently true); this->CreateReplicaLayer(surface, this->identity_matrix, - gfx::PointF(0.f, 100.f), + gfx::PointF(100.f, 0.f), gfx::Size(100, 100)); - typename Types::LayerType* over_surface = this->CreateDrawingLayer( - parent, this->identity_matrix, gfx::PointF(), gfx::Size(40, 100), true); + typename Types::LayerType* over_surface = + this->CreateDrawingLayer(parent, + this->identity_matrix, + gfx::PointF(60.f, 0.f), + gfx::Size(40, 100), + true); typename Types::LayerType* over_replica = this->CreateDrawingLayer(parent, this->identity_matrix, - gfx::PointF(0.f, 100.f), + gfx::PointF(100.f, 0.f), gfx::Size(50, 100), true); this->CalcDrawEtc(parent); @@ -2735,8 +2523,7 @@ class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100)) - .ToString(), + EXPECT_EQ(gfx::Rect(60, 0, 90, 100).ToString(), occlusion.occlusion_from_inside_target().ToString()); this->VisitLayer(surface, &occlusion); @@ -2750,12 +2537,12 @@ class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently this->EnterContributingSurface(surface, &occlusion); // Surface and replica are occluded different amounts. - EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 100, 100))); - EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100), - occlusion.UnoccludedSurfaceContentRect( - surface, true, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 0, 60, 100), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(50, 0, 50, 100), + occlusion.UnoccludedSurfaceContentRect( + surface, true, gfx::Rect(0, 0, 100, 100))); } }; @@ -2821,9 +2608,9 @@ class OcclusionTrackerTestSurfaceChildOfSurface // The surface_child's parent does not have a clip rect as it owns a render // surface. Make sure the unoccluded rect does not get clipped away // inappropriately. - EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10), - occlusion.UnoccludedSurfaceContentRect( - surface_child, false, gfx::Rect(0, 0, 100, 50))); + EXPECT_EQ(gfx::Rect(0, 40, 100, 10), + occlusion.UnoccludedSurfaceContentRect( + surface_child, false, gfx::Rect(0, 0, 100, 50))); this->LeaveContributingSurface(surface_child, &occlusion); // When the surface_child's occlusion is transformed up to its parent, make @@ -2837,9 +2624,9 @@ class OcclusionTrackerTestSurfaceChildOfSurface this->EnterContributingSurface(surface, &occlusion); // The surface's parent does have a clip rect as it is the root layer. - EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50), - occlusion.UnoccludedSurfaceContentRect( - surface, false, gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 50, 100, 50), + occlusion.UnoccludedSurfaceContentRect( + surface, false, gfx::Rect(0, 0, 100, 100))); } }; @@ -2856,146 +2643,113 @@ class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter gfx::Transform scale_by_half; scale_by_half.Scale(0.5, 0.5); - // Make a 50x50 filtered surface that is completely surrounded by opaque - // layers which are above it in the z-order. The surface is scaled to test - // that the pixel moving is done in the target space, where the background - // filter is applied. - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(200, 150)); - typename Types::LayerType* filtered_surface = - this->CreateDrawingLayer(parent, - scale_by_half, - gfx::PointF(50.f, 50.f), - gfx::Size(100, 100), - false); - typename Types::LayerType* occluding_layer1 = this->CreateDrawingLayer( - parent, this->identity_matrix, gfx::PointF(), gfx::Size(200, 50), true); - typename Types::LayerType* occluding_layer2 = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(0.f, 100.f), - gfx::Size(200, 50), - true); - typename Types::LayerType* occluding_layer3 = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(0.f, 50.f), - gfx::Size(50, 50), - true); - typename Types::LayerType* occluding_layer4 = - this->CreateDrawingLayer(parent, - this->identity_matrix, - gfx::PointF(100.f, 50.f), - gfx::Size(100, 50), - true); - - // Filters make the layer own a surface. FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter(10.f)); - filtered_surface->SetBackgroundFilters(filters); // Save the distance of influence for the blur effect. int outset_top, outset_right, outset_bottom, outset_left; filters.GetOutsets( &outset_top, &outset_right, &outset_bottom, &outset_left); - this->CalcDrawEtc(parent); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - - // These layers occlude pixels directly beside the filtered_surface. Because - // filtered surface blends pixels in a radius, it will need to see some of - // the pixels (up to radius far) underneath the occluding layers. - this->VisitLayer(occluding_layer4, &occlusion); - this->VisitLayer(occluding_layer3, &occlusion); - this->VisitLayer(occluding_layer2, &occlusion); - this->VisitLayer(occluding_layer1, &occlusion); - - Region expected_occlusion; - expected_occlusion.Union(gfx::Rect(0, 0, 200, 50)); - expected_occlusion.Union(gfx::Rect(0, 50, 50, 50)); - expected_occlusion.Union(gfx::Rect(100, 50, 100, 50)); - expected_occlusion.Union(gfx::Rect(0, 100, 200, 50)); - - EXPECT_EQ(expected_occlusion.ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - - this->VisitLayer(filtered_surface, &occlusion); - - // The filtered layer does not occlude. - Region expected_occlusion_outside_surface; - expected_occlusion_outside_surface.Union(gfx::Rect(-50, -50, 200, 50)); - expected_occlusion_outside_surface.Union(gfx::Rect(-50, 0, 50, 50)); - expected_occlusion_outside_surface.Union(gfx::Rect(50, 0, 100, 50)); - expected_occlusion_outside_surface.Union(gfx::Rect(-50, 50, 200, 50)); + enum Direction { + LEFT, + RIGHT, + TOP, + BOTTOM, + LAST_DIRECTION = BOTTOM, + }; + + for (int i = 0; i <= LAST_DIRECTION; ++i) { + SCOPED_TRACE(i); + + // Make a 50x50 filtered surface that is adjacent to occluding layers + // which are above it in the z-order in various configurations. The + // surface is scaled to test that the pixel moving is done in the target + // space, where the background filter is applied. + typename Types::ContentLayerType* parent = this->CreateRoot( + this->identity_matrix, gfx::PointF(), gfx::Size(200, 200)); + typename Types::LayerType* filtered_surface = + this->CreateDrawingLayer(parent, + scale_by_half, + gfx::PointF(50.f, 50.f), + gfx::Size(100, 100), + false); + filtered_surface->SetBackgroundFilters(filters); + + gfx::Rect occlusion_rect; + switch (i) { + case LEFT: + occlusion_rect = gfx::Rect(0, 0, 50, 200); + break; + case RIGHT: + occlusion_rect = gfx::Rect(100, 0, 50, 200); + break; + case TOP: + occlusion_rect = gfx::Rect(0, 0, 200, 50); + break; + case BOTTOM: + occlusion_rect = gfx::Rect(0, 100, 200, 50); + break; + } + + typename Types::LayerType* occluding_layer = + this->CreateDrawingLayer(parent, + this->identity_matrix, + occlusion_rect.origin(), + occlusion_rect.size(), + true); + this->CalcDrawEtc(parent); - EXPECT_EQ(expected_occlusion_outside_surface.ToString(), - occlusion.occlusion_from_outside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_inside_target().ToString()); + TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( + gfx::Rect(0, 0, 200, 200)); - // The surface has a background blur, so it needs pixels that are currently - // considered occluded in order to be drawn. So the pixels it needs should - // be removed some the occluded area so that when we get to the parent they - // are drawn. - this->VisitContributingSurface(filtered_surface, &occlusion); + // This layer occludes pixels directly beside the filtered_surface. + // Because filtered surface blends pixels in a radius, it will need to see + // some of the pixels (up to radius far) underneath the occluding layers. + this->VisitLayer(occluding_layer, &occlusion); - this->EnterLayer(parent, &occlusion); + EXPECT_EQ(occlusion_rect.ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - Region expected_blurred_occlusion; - expected_blurred_occlusion.Union(gfx::Rect(0, 0, 200, 50 - outset_top)); - expected_blurred_occlusion.Union(gfx::Rect( - 0, 50 - outset_top, 50 - outset_left, 50 + outset_top + outset_bottom)); - expected_blurred_occlusion.Union( - gfx::Rect(100 + outset_right, - 50 - outset_top, - 100 - outset_right, - 50 + outset_top + outset_bottom)); - expected_blurred_occlusion.Union( - gfx::Rect(0, 100 + outset_bottom, 200, 50 - outset_bottom)); + this->VisitLayer(filtered_surface, &occlusion); - EXPECT_EQ(expected_blurred_occlusion.ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); + // The occlusion is used fully inside the surface. + gfx::Rect occlusion_inside_surface = + occlusion_rect - gfx::Vector2d(50, 50); + EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty()); + EXPECT_EQ(occlusion_inside_surface.ToString(), + occlusion.occlusion_from_outside_target().ToString()); - gfx::Rect outset_rect; - gfx::Rect test_rect; + // The surface has a background blur, so it needs pixels that are + // currently considered occluded in order to be drawn. So the pixels it + // needs should be removed some the occluded area so that when we get to + // the parent they are drawn. + this->VisitContributingSurface(filtered_surface, &occlusion); + this->EnterLayer(parent, &occlusion); - // Nothing in the blur outsets for the filtered_surface is occluded. - outset_rect = gfx::Rect(50 - outset_left, - 50 - outset_top, - 50 + outset_left + outset_right, - 50 + outset_top + outset_bottom); - test_rect = outset_rect; - EXPECT_EQ( - outset_rect.ToString(), - occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); + gfx::Rect expected_occlusion = occlusion_rect; + switch (i) { + case LEFT: + expected_occlusion.Inset(0, 0, outset_right, 0); + break; + case RIGHT: + expected_occlusion.Inset(outset_right, 0, 0, 0); + break; + case TOP: + expected_occlusion.Inset(0, 0, 0, outset_right); + break; + case BOTTOM: + expected_occlusion.Inset(0, outset_right, 0, 0); + break; + } + + EXPECT_EQ(expected_occlusion.ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - // Stuff outside the blur outsets is still occluded though. - test_rect = outset_rect; - test_rect.Inset(0, 0, -1, 0); - EXPECT_EQ( - outset_rect.ToString(), - occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); - test_rect = outset_rect; - test_rect.Inset(0, 0, 0, -1); - EXPECT_EQ( - outset_rect.ToString(), - occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); - test_rect = outset_rect; - test_rect.Inset(-1, 0, 0, 0); - EXPECT_EQ( - outset_rect.ToString(), - occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); - test_rect = outset_rect; - test_rect.Inset(0, -1, 0, 0); - EXPECT_EQ( - outset_rect.ToString(), - occlusion.UnoccludedLayerContentRect(parent, test_rect).ToString()); + this->DestroyLayers(); + } } }; @@ -3133,21 +2887,28 @@ class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter this->VisitContributingSurface(filtered_surface, &occlusion); this->VisitLayer(behind_replica_layer, &occlusion); - this->VisitLayer(behind_surface_layer, &occlusion); // The layers behind the surface are not blurred, and their occlusion does // not change, until we leave the surface. So it should not be modified by // the filter here. - gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30); gfx::Rect occlusion_behind_replica = gfx::Rect(210, 60, 30, 30); - - Region expected_opaque_bounds = - UnionRegions(occlusion_behind_surface, occlusion_behind_replica); - EXPECT_EQ(expected_opaque_bounds.ToString(), + EXPECT_EQ(occlusion_behind_replica.ToString(), occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); + // Clear the occlusion so the |behind_surface_layer| can add its occlusion + // without existing occlusion interfering. + occlusion.set_occlusion_from_inside_target(SimpleEnclosedRegion()); + + this->VisitLayer(behind_surface_layer, &occlusion); + + // The layers behind the surface are not blurred, and their occlusion does + // not change, until we leave the surface. So it should not be modified by + // the filter here. + gfx::Rect occlusion_behind_surface = gfx::Rect(60, 60, 30, 30); + EXPECT_EQ(occlusion_behind_surface.ToString(), + occlusion.occlusion_from_inside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); } }; @@ -3318,24 +3079,21 @@ class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded gfx::Rect occlusion_beside_surface = gfx::Rect(90, 40, 10, 10); gfx::Rect occlusion_beside_replica = gfx::Rect(200, 40, 10, 10); - Region expected_occlusion; - expected_occlusion.Union(occlusion_above_surface); - expected_occlusion.Union(occlusion_above_replica); - expected_occlusion.Union(occlusion_beside_surface); + SimpleEnclosedRegion expected_occlusion; expected_occlusion.Union(occlusion_beside_replica); + expected_occlusion.Union(occlusion_beside_surface); + expected_occlusion.Union(occlusion_above_replica); + expected_occlusion.Union(occlusion_above_surface); - ASSERT_EQ(expected_occlusion.ToString(), + EXPECT_EQ(expected_occlusion.ToString(), occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); + EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty()); - Region::Iterator expected_rects(expected_occlusion); - Region::Iterator target_surface_rects( - occlusion.occlusion_from_inside_target()); - for (; expected_rects.has_rect(); - expected_rects.next(), target_surface_rects.next()) { - ASSERT_TRUE(target_surface_rects.has_rect()); - EXPECT_EQ(expected_rects.rect(), target_surface_rects.rect()); + const SimpleEnclosedRegion& actual_occlusion = + occlusion.occlusion_from_inside_target(); + for (size_t i = 0; i < expected_occlusion.GetRegionComplexity(); ++i) { + ASSERT_LT(i, actual_occlusion.GetRegionComplexity()); + EXPECT_EQ(expected_occlusion.GetRect(i), actual_occlusion.GetRect(i)); } } }; @@ -3561,5 +3319,95 @@ class OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestHiddenCopyRequestDoesNotOcclude) +template <class Types> +class OcclusionTrackerTestOccludedLayer : public OcclusionTrackerTest<Types> { + protected: + explicit OcclusionTrackerTestOccludedLayer(bool opaque_layers) + : OcclusionTrackerTest<Types>(opaque_layers) {} + void RunMyTest() { + gfx::Transform translate; + translate.Translate(10.0, 20.0); + typename Types::ContentLayerType* root = this->CreateRoot( + this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); + typename Types::LayerType* surface = this->CreateSurface( + root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200)); + typename Types::LayerType* layer = this->CreateDrawingLayer( + surface, translate, gfx::Point(), gfx::Size(200, 200), false); + typename Types::ContentLayerType* outside_layer = this->CreateDrawingLayer( + root, this->identity_matrix, gfx::Point(), gfx::Size(200, 200), false); + this->CalcDrawEtc(root); + + TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( + gfx::Rect(0, 0, 200, 200)); + this->VisitLayer(outside_layer, &occlusion); + this->EnterLayer(layer, &occlusion); + + // No occlusion, is not occluded. + occlusion.set_occlusion_from_outside_target(SimpleEnclosedRegion()); + occlusion.set_occlusion_from_inside_target(SimpleEnclosedRegion()); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(100, 100))); + + // Partial occlusion from outside, is not occluded. + occlusion.set_occlusion_from_outside_target( + SimpleEnclosedRegion(50, 50, 100, 100)); + occlusion.set_occlusion_from_inside_target(SimpleEnclosedRegion()); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 30, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 80, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 0, 100, 100))); + + // Full occlusion from outside, is occluded. + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 100, 100))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(130, 120, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(80, 70, 50, 50))); + + // Partial occlusion from inside, is not occluded. + occlusion.set_occlusion_from_outside_target(SimpleEnclosedRegion()); + occlusion.set_occlusion_from_inside_target( + SimpleEnclosedRegion(50, 50, 100, 100)); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 30, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 80, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 0, 100, 100))); + + // Full occlusion from inside, is occluded. + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 100, 100))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(130, 120, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(80, 70, 50, 50))); + + // Partial occlusion from both, is not occluded. + occlusion.set_occlusion_from_outside_target( + SimpleEnclosedRegion(50, 50, 100, 50)); + occlusion.set_occlusion_from_inside_target( + SimpleEnclosedRegion(50, 100, 100, 50)); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 30, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 0, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(40, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 0, 80, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(0, 80, 100, 100))); + EXPECT_FALSE(occlusion.OccludedLayer(layer, gfx::Rect(90, 0, 100, 100))); + + // Full occlusion from both, is occluded. + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 100, 100))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(40, 30, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(130, 120, 10, 10))); + EXPECT_TRUE(occlusion.OccludedLayer(layer, gfx::Rect(80, 70, 50, 50))); + } +}; + +ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOccludedLayer) + } // namespace } // namespace cc |