summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-22 01:16:43 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-08-22 01:21:15 +0000
commitd5467eb7835eccd7b1e1a65096c9b1f37c70fcb2 (patch)
treedb295fcc90bc936cf52818bffd73d7560c80f0f3 /cc
parent903cf847d2d66f33e1f2cdab5f45a1b07558fa7a (diff)
downloadchromium_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')
-rw-r--r--cc/BUILD.gn3
-rw-r--r--cc/base/region.cc9
-rw-r--r--cc/base/region.h3
-rw-r--r--cc/base/simple_enclosed_region.cc136
-rw-r--r--cc/base/simple_enclosed_region.h122
-rw-r--r--cc/base/simple_enclosed_region_unittest.cc637
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/layers/layer.cc7
-rw-r--r--cc/layers/layer.h3
-rw-r--r--cc/layers/layer_impl.cc7
-rw-r--r--cc/layers/layer_impl.h3
-rw-r--r--cc/layers/texture_layer.cc9
-rw-r--r--cc/layers/texture_layer.h2
-rw-r--r--cc/layers/texture_layer_impl.cc8
-rw-r--r--cc/layers/texture_layer_impl.h2
-rw-r--r--cc/layers/tiled_layer.cc7
-rw-r--r--cc/layers/tiled_layer.h2
-rw-r--r--cc/layers/tiled_layer_impl.cc7
-rw-r--r--cc/layers/tiled_layer_impl.h2
-rw-r--r--cc/layers/tiled_layer_unittest.cc30
-rw-r--r--cc/resources/layer_tiling_data.cc8
-rw-r--r--cc/resources/layer_tiling_data.h4
-rw-r--r--cc/test/test_occlusion_tracker.h18
-rw-r--r--cc/trees/layer_tree_host_unittest_occlusion.cc61
-rw-r--r--cc/trees/occlusion_tracker.cc147
-rw-r--r--cc/trees/occlusion_tracker.h13
-rw-r--r--cc/trees/occlusion_tracker_unittest.cc1050
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
diff --git a/cc/cc.gyp b/cc/cc.gyp
index f63d58a..04f8a91 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -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