Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Unified Diff: components/viz/service/hit_test/hit_test_aggregator_unittest.cc

Issue 2938953002: Implement HitTestAggregator (Closed)
Patch Set: rebase & improvements based on comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/viz/service/hit_test/hit_test_aggregator_unittest.cc
diff --git a/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d7e0959926c31b80db3a1ff453f40bf3659e2ab0
--- /dev/null
+++ b/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -0,0 +1,940 @@
+// Copyright 2017 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 "hit_test_aggregator.h"
+#include "cc/surfaces/frame_sink_id.h"
+#include "cc/surfaces/local_surface_id.h"
+#include "cc/surfaces/surface_id.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace hit_test {
+namespace test {
+
+namespace {
+
+constexpr cc::FrameSinkId kDisplayFrameSink(2, 0);
+
+cc::SurfaceId MakeSurfaceId(const cc::FrameSinkId& frame_sink_id,
+ uint32_t local_id) {
+ return cc::SurfaceId(
+ frame_sink_id,
+ cc::LocalSurfaceId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
+}
+
+} // namespace
+
+using namespace hit_test::mojom;
+
+class HitTestAggregatorTest : public testing::Test {
+ public:
+ HitTestAggregatorTest() {}
+ ~HitTestAggregatorTest() override {}
+
+ // testing::Test:
+ void SetUp() override {}
+ void TearDown() override { Reset(); }
+
+ HitTestAggregator aggregator_;
+
+ int count() {
+ DisplayHitTestRegion* start =
+ (DisplayHitTestRegion*)aggregator_.read_buffer_.get();
+ DisplayHitTestRegion* end = start;
+ while (end->child_count != kEndOfList)
+ end++;
+
+ int count = end - start;
+ return count;
+ }
+
+ int GetPendingCount() { return aggregator_.pending_.size(); }
+ int GetActiveCount() { return aggregator_.active_.size(); }
+
+ void CallOnSurfaceWillDraw(cc::SurfaceId surface_id) {
+ aggregator_.OnSurfaceWillDraw(surface_id);
+ }
+
+ void Reset() {
+ DisplayHitTestRegion* regions =
+ (DisplayHitTestRegion*)aggregator_.write_buffer_.get();
+ regions[0].child_count = kEndOfList;
+
+ regions = (DisplayHitTestRegion*)aggregator_.read_buffer_.get();
+ regions[0].child_count = kEndOfList;
+
+ aggregator_.pending_.clear();
+ aggregator_.active_.clear();
+ }
+
+ int GetDisplayHitTestRegionListSize() { return aggregator_.read_size_; }
+
+ DisplayHitTestRegion* GetRegions() {
+ return (DisplayHitTestRegion*)aggregator_.read_buffer_.get();
+ }
+
+ // Creates a hit test data element with 8 children recursively to
+ // the specified depth. SurfaceIds are generated in sequential order and
+ // the method returns the next unused id.
+ int CreateAndSubmitHitTestRegionListWith8Children(int id, int depth) {
+ cc::SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, id);
+ id++;
+
+ auto hit_test_region_list = HitTestRegionList::New();
+ hit_test_region_list->surface_id = surface_id;
+ hit_test_region_list->flags = kHitTestMine;
+ hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+
+ for (int i = 0; i < 8; i++) {
+ auto hit_test_region = HitTestRegion::New();
+ hit_test_region->rect.SetRect(100, 100, 100, 100);
+
+ if (depth > 0) {
+ hit_test_region->flags = kHitTestChildSurface;
+ hit_test_region->surface_id = MakeSurfaceId(kDisplayFrameSink, id);
+ id = CreateAndSubmitHitTestRegionListWith8Children(id, depth - 1);
+ } else {
+ hit_test_region->flags = kHitTestMine;
+ }
+ hit_test_region_list->regions.push_back(std::move(hit_test_region));
+ }
+
+ aggregator_.SubmitHitTestRegionList(std::move(hit_test_region_list));
+ return id;
+ }
+};
+
+// TODO(gklassen): Add tests for 3D use cases as suggested by and with
+// input from rjkroege.
+
+// One surface.
+//
+// +----------+
+// | |
+// | |
+// | |
+// +----------+
+//
+TEST_F(HitTestAggregatorTest, OneSurface) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+
+ auto hit_test_region_list = HitTestRegionList::New();
+ hit_test_region_list->surface_id = display_surface_id;
+ hit_test_region_list->flags = kHitTestMine;
+ hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+
+ aggregator_.SubmitHitTestRegionList(std::move(hit_test_region_list));
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetPendingCount(), 1);
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(display_surface_id);
+
+ EXPECT_EQ(GetPendingCount(), 0);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ aggregator_.Aggregate(display_surface_id);
+ aggregator_.Swap();
+
+ // Expect 1 entry routing all events to the one surface (display root).
+ EXPECT_EQ(count(), 1);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, display_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// One opaque embedder with two regions.
+//
+// +e-------------+
+// | +r1-+ +r2--+ |
+// | | | | | |
+// | | | | | |
+// | +---+ +----+ |
+// +--------------+
+//
+TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_r1 = HitTestRegion::New();
+ e_hit_test_region_r1->flags = kHitTestMine;
+ e_hit_test_region_r1->rect.SetRect(100, 100, 200, 400);
+
+ auto e_hit_test_region_r2 = HitTestRegion::New();
+ e_hit_test_region_r2->flags = kHitTestMine;
+ e_hit_test_region_r2->rect.SetRect(400, 100, 300, 400);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r1));
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_r2));
+
+ // Submit HitTestRegionList.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ // Add Surfaces to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+ EXPECT_EQ(count(), 3);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 2);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 400));
+ EXPECT_EQ(region->child_count, 0);
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->rect, gfx::Rect(400, 100, 300, 400));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// One embedder with two children.
+//
+// +e-------------+
+// | +c1-+ +c2--+ |
+// | | | | | |
+// | | | | | |
+// | +---+ +----+ |
+// +--------------+
+//
+
+TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ cc::SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_c1 = HitTestRegion::New();
+ e_hit_test_region_c1->flags = kHitTestChildSurface;
+ e_hit_test_region_c1->surface_id = c1_surface_id;
+ e_hit_test_region_c1->rect.SetRect(100, 100, 200, 300);
+
+ auto e_hit_test_region_c2 = HitTestRegion::New();
+ e_hit_test_region_c2->flags = kHitTestChildSurface;
+ e_hit_test_region_c2->surface_id = c2_surface_id;
+ e_hit_test_region_c2->rect.SetRect(400, 100, 400, 300);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1));
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c2));
+
+ auto c1_hit_test_data = HitTestRegionList::New();
+ c1_hit_test_data->surface_id = c1_surface_id;
+
+ auto c2_hit_test_data = HitTestRegionList::New();
+ c2_hit_test_data->surface_id = c2_surface_id;
+
+ // Submit in unexpected order.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c1_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 2);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c2_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 3);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(c2_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ CallOnSurfaceWillDraw(c1_surface_id);
+ EXPECT_EQ(GetActiveCount(), 2);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 3);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 3);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 2);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestChildSurface);
+ EXPECT_EQ(region->frame_sink_id, c1_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 300));
+ EXPECT_EQ(region->child_count, 0);
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestChildSurface);
+ EXPECT_EQ(region->frame_sink_id, c2_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(400, 100, 400, 300));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// Occluded child frame (OOPIF).
+//
+// +e-----------+
+// | +c--+ |
+// | | +div-+ |
+// | | | | |
+// | | +----+ |
+// | +---+ |
+// +------------+
+//
+
+TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_div = HitTestRegion::New();
+ e_hit_test_region_div->flags = kHitTestMine;
+ e_hit_test_region_div->surface_id = e_surface_id;
+ e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+
+ auto e_hit_test_region_c = HitTestRegion::New();
+ e_hit_test_region_c->flags = kHitTestChildSurface;
+ e_hit_test_region_c->surface_id = c_surface_id;
+ e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div));
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c));
+
+ auto c_hit_test_data = HitTestRegionList::New();
+ c_hit_test_data->surface_id = c_surface_id;
+ c_hit_test_data->flags = kHitTestMine;
+ c_hit_test_data->bounds.SetRect(0, 0, 200, 500);
+
+ // Submit in unexpected order.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 2);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ CallOnSurfaceWillDraw(c_surface_id);
+ EXPECT_EQ(GetActiveCount(), 2);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 3);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 2);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region->child_count, 0);
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 500));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// Foreground child frame (OOPIF).
+// Same as the previous test except the child is foreground.
+//
+// +e-----------+
+// | +c--+ |
+// | | |div-+ |
+// | | | | |
+// | | |----+ |
+// | +---+ |
+// +------------+
+//
+
+TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_div = HitTestRegion::New();
+ e_hit_test_region_div->flags = kHitTestMine;
+ e_hit_test_region_div->surface_id = e_surface_id;
+ e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+
+ auto e_hit_test_region_c = HitTestRegion::New();
+ e_hit_test_region_c->flags = kHitTestChildSurface;
+ e_hit_test_region_c->surface_id = c_surface_id;
+ e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div));
+
+ auto c_hit_test_data = HitTestRegionList::New();
+ c_hit_test_data->surface_id = c_surface_id;
+ c_hit_test_data->flags = kHitTestMine;
+ c_hit_test_data->bounds.SetRect(0, 0, 200, 500);
+
+ // Submit in unexpected order.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 2);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ CallOnSurfaceWillDraw(c_surface_id);
+ EXPECT_EQ(GetActiveCount(), 2);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 3);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 2);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 500));
+ EXPECT_EQ(region->child_count, 0);
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// One embedder with a clipped child with a tab and transparent background.
+//
+// +e-------------+
+// | +c---------| Point maps to
+// | 1 |+a--+ | ----- -------
+// | || 2 | 3 | 1 e
+// | |+b--------| 2 a
+// | || | 3 e (transparent area in c)
+// | || 4 | 4 b
+// +--------------+
+//
+
+TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ cc::SurfaceId a_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
+ cc::SurfaceId b_surface_id = MakeSurfaceId(kDisplayFrameSink, 4);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_c = HitTestRegion::New();
+ e_hit_test_region_c->flags = kHitTestChildSurface;
+ e_hit_test_region_c->surface_id = c_surface_id;
+ e_hit_test_region_c->rect.SetRect(200, 100, 1600, 800);
+ e_hit_test_region_c->transform.Translate(200, 100);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c));
+
+ auto c_hit_test_data = HitTestRegionList::New();
+ c_hit_test_data->surface_id = c_surface_id;
+ c_hit_test_data->flags = kHitTestIgnore;
+ c_hit_test_data->bounds.SetRect(0, 0, 1600, 800);
+
+ auto c_hit_test_region_a = HitTestRegion::New();
+ c_hit_test_region_a->flags = kHitTestChildSurface;
+ c_hit_test_region_a->surface_id = a_surface_id;
+ c_hit_test_region_a->rect.SetRect(0, 0, 200, 100);
+
+ auto c_hit_test_region_b = HitTestRegion::New();
+ c_hit_test_region_b->flags = kHitTestChildSurface;
+ c_hit_test_region_b->surface_id = b_surface_id;
+ c_hit_test_region_b->rect.SetRect(0, 100, 800, 600);
+
+ c_hit_test_data->regions.push_back(std::move(c_hit_test_region_a));
+ c_hit_test_data->regions.push_back(std::move(c_hit_test_region_b));
+
+ auto a_hit_test_data = HitTestRegionList::New();
+ a_hit_test_data->surface_id = a_surface_id;
+ a_hit_test_data->flags = kHitTestMine;
+ a_hit_test_data->bounds.SetRect(0, 0, 200, 100);
+
+ auto b_hit_test_data = HitTestRegionList::New();
+ b_hit_test_data->surface_id = b_surface_id;
+ b_hit_test_data->flags = kHitTestMine;
+ b_hit_test_data->bounds.SetRect(0, 100, 800, 600);
+
+ // Submit in unexpected order.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ aggregator_.SubmitHitTestRegionList(std::move(a_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 2);
+
+ aggregator_.SubmitHitTestRegionList(std::move(b_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 3);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 4);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(c_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 2);
+
+ CallOnSurfaceWillDraw(b_surface_id);
+ EXPECT_EQ(GetActiveCount(), 3);
+
+ CallOnSurfaceWillDraw(a_surface_id);
+ EXPECT_EQ(GetActiveCount(), 4);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 4);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 3);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestIgnore);
+ EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(200, 100, 1600, 800));
+ EXPECT_EQ(region->child_count, 2);
+
+ gfx::Point point(300, 300);
+ region->transform.TransformPointReverse(&point);
+ EXPECT_TRUE(point == gfx::Point(100, 200));
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, a_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 200, 100));
+ EXPECT_EQ(region->child_count, 0);
+
+ region = &regions[3];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, b_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 100, 800, 600));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// Three children deep.
+//
+// +e------------+
+// | +c1-------+ |
+// | | +c2---+ | |
+// | | | +c3-| | |
+// | | | | | | |
+// | | | +---| | |
+// | | +-----+ | |
+// | +---------+ |
+// +-------------+
+//
+
+TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c1_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+ cc::SurfaceId c2_surface_id = MakeSurfaceId(kDisplayFrameSink, 3);
+ cc::SurfaceId c3_surface_id = MakeSurfaceId(kDisplayFrameSink, 4);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_c1 = HitTestRegion::New();
+ e_hit_test_region_c1->flags = kHitTestChildSurface;
+ e_hit_test_region_c1->surface_id = c1_surface_id;
+ e_hit_test_region_c1->rect.SetRect(100, 100, 700, 700);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c1));
+
+ auto c1_hit_test_data = HitTestRegionList::New();
+ c1_hit_test_data->surface_id = c1_surface_id;
+ c1_hit_test_data->flags = kHitTestMine;
+ c1_hit_test_data->bounds.SetRect(0, 0, 600, 600);
+
+ auto c1_hit_test_region_c2 = HitTestRegion::New();
+ c1_hit_test_region_c2->flags = kHitTestChildSurface;
+ c1_hit_test_region_c2->surface_id = c2_surface_id;
+ c1_hit_test_region_c2->rect.SetRect(100, 100, 500, 500);
+
+ c1_hit_test_data->regions.push_back(std::move(c1_hit_test_region_c2));
+
+ auto c2_hit_test_data = HitTestRegionList::New();
+ c2_hit_test_data->surface_id = c2_surface_id;
+ c2_hit_test_data->flags = kHitTestMine;
+ c2_hit_test_data->bounds.SetRect(0, 0, 400, 400);
+
+ auto c2_hit_test_region_c3 = HitTestRegion::New();
+ c2_hit_test_region_c3->flags = kHitTestChildSurface;
+ c2_hit_test_region_c3->surface_id = c3_surface_id;
+ c2_hit_test_region_c3->rect.SetRect(100, 100, 300, 300);
+
+ c2_hit_test_data->regions.push_back(std::move(c2_hit_test_region_c3));
+
+ auto c3_hit_test_data = HitTestRegionList::New();
+ c3_hit_test_data->surface_id = c3_surface_id;
+ c3_hit_test_data->flags = kHitTestMine;
+ c3_hit_test_data->bounds.SetRect(0, 0, 200, 200);
+
+ // Submit in unexpected order.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c1_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c3_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 2);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 3);
+
+ aggregator_.SubmitHitTestRegionList(std::move(c2_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 4);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(c2_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ CallOnSurfaceWillDraw(c1_surface_id);
+ EXPECT_EQ(GetActiveCount(), 2);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 3);
+
+ CallOnSurfaceWillDraw(c3_surface_id);
+ EXPECT_EQ(GetActiveCount(), 4);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 4);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 3);
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, c1_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 700, 700));
+ EXPECT_EQ(region->child_count, 2);
+
+ region = &regions[2];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, c2_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 500, 500));
+ EXPECT_EQ(region->child_count, 1);
+
+ region = &regions[3];
+ EXPECT_EQ(region->flags, kHitTestChildSurface | kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, c3_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(100, 100, 300, 300));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// Missing / late child.
+//
+// +e-----------+
+// | +c--+ |
+// | | |div-+ |
+// | | | | |
+// | | |----+ |
+// | +---+ |
+// +------------+
+//
+
+TEST_F(HitTestAggregatorTest, MissingChildFrame) {
+ EXPECT_EQ(count(), 0);
+
+ cc::SurfaceId e_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+ cc::SurfaceId c_surface_id = MakeSurfaceId(kDisplayFrameSink, 2);
+
+ auto e_hit_test_data = HitTestRegionList::New();
+ e_hit_test_data->surface_id = e_surface_id;
+ e_hit_test_data->flags = kHitTestMine;
+ e_hit_test_data->bounds.SetRect(0, 0, 1024, 768);
+
+ auto e_hit_test_region_div = HitTestRegion::New();
+ e_hit_test_region_div->flags = kHitTestMine;
+ e_hit_test_region_div->surface_id = e_surface_id;
+ e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+
+ auto e_hit_test_region_c = HitTestRegion::New();
+ e_hit_test_region_c->flags = kHitTestChildSurface;
+ e_hit_test_region_c->surface_id = c_surface_id;
+ e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_data->regions.push_back(std::move(e_hit_test_region_div));
+
+ auto c_hit_test_data = HitTestRegionList::New();
+ c_hit_test_data->surface_id = c_surface_id;
+ c_hit_test_data->flags = kHitTestMine;
+ c_hit_test_data->bounds.SetRect(0, 0, 200, 500);
+
+ // Submit in unexpected order, but not the child.
+
+ EXPECT_EQ(GetPendingCount(), 0);
+
+ aggregator_.SubmitHitTestRegionList(std::move(e_hit_test_data));
+ EXPECT_EQ(GetPendingCount(), 1);
+
+ // Surfaces added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ CallOnSurfaceWillDraw(e_surface_id);
+ EXPECT_EQ(GetActiveCount(), 1);
+
+ // Aggregate and swap.
+
+ aggregator_.Aggregate(e_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ EXPECT_EQ(count(), 2);
+
+ DisplayHitTestRegion* regions = GetRegions();
+
+ DisplayHitTestRegion* region = nullptr;
+
+ region = &regions[0];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region->child_count, 1);
+
+ // Child would exist here but it was not included in the Display Frame.
+
+ region = &regions[1];
+ EXPECT_EQ(region->flags, kHitTestMine);
+ EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region->child_count, 0);
+}
+
+// Exceed limits to ensure that bounds and resize work.
+//
+// A tree of embedders each with 8 children and 4 levels deep = 4096 regions.
+// This will exceed initial allocation and force a resize.
+//
+// +e--------------------------------------------------------+
+// | +c1----------++c2----------++c3----------++c4----------+|
+// | | +c1--------|| +c1--------|| +c1--------|| +c1--------||
+// | | | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-||
+// | | | | || || | | || || | | || || | | || ||
+// | | | +---++---|| | +---++---|| | +---++---|| | +---++---||
+// | +------------++------------++------------++------------+|
+// | +c5----------++c6----------++c7----------++c8----------+|
+// | | +c1--------|| +c1--------|| +c1--------|| +c1--------||
+// | | | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-|| | +c1-++c2-||
+// | | | | || || | | || || | | || || | | || ||
+// | | | +---++---|| | +---++---|| | +---++---|| | +---++---||
+// | +------------++------------++------------++------------+|
+// +---------------------------------------------------------+
+//
+
+TEST_F(HitTestAggregatorTest, ExceedLimits) {
+ EXPECT_EQ(count(), 0);
+
+ EXPECT_LT(GetDisplayHitTestRegionListSize(), 4096);
+
+ cc::SurfaceId display_surface_id = MakeSurfaceId(kDisplayFrameSink, 1);
+
+ int next_surface_id = CreateAndSubmitHitTestRegionListWith8Children(1, 3);
+ int surface_count = next_surface_id - 1;
+
+ EXPECT_EQ(GetPendingCount(), surface_count);
+
+ // Mark Surfaces as added to DisplayFrame in unexpected order.
+
+ EXPECT_EQ(count(), 0);
+ EXPECT_EQ(GetActiveCount(), 0);
+
+ for (int i = 1; i <= surface_count; i++) {
+ cc::SurfaceId surface_id = MakeSurfaceId(kDisplayFrameSink, i);
+ CallOnSurfaceWillDraw(surface_id);
+ }
+
+ EXPECT_EQ(GetActiveCount(), surface_count);
+
+ // Aggregate and swap.
+ aggregator_.Aggregate(display_surface_id);
+ EXPECT_EQ(count(), 0);
+
+ aggregator_.Swap();
+
+ // Expect 4680 regions:
+ // 8 children 4 levels deep 8*8*8*8 is 4096
+ // 1 region for each embedder/surface + 584
+ // 1 root + 1
+ // -----
+ // 4681.
+ EXPECT_EQ(count(), 4681);
+
+ EXPECT_GE(GetDisplayHitTestRegionListSize(), 4681);
+}
+
+} // namespace test
+} // namespace hit_test
+} // namespace viz

Powered by Google App Engine
This is Rietveld 408576698