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

Side by Side Diff: components/viz/service/hit_test/hit_test_aggregator.cc

Issue 2938953002: Implement HitTestAggregator (Closed)
Patch Set: Use Shared Memory handles and mappings to manage buffers & other improvements based on reviewer com… Created 3 years, 5 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/viz/service/hit_test/hit_test_aggregator.h"
6 #include "components/viz/common/hit_test/display_hit_test_data.h"
7
8 namespace viz {
9 namespace hit_test {
10
11 namespace {
12 // TODO(gklassen): Review and select appropriate sizes ( based on
13 // telemetry / UMA? ).
14 constexpr int kInitialSize = 1024;
15 constexpr int kIncrementalSize = 1024;
16
17 bool ValidateHitTestRegion(
18 const hit_test::mojom::HitTestRegionPtr& hit_test_region) {
19 if (hit_test_region->flags == hit_test::mojom::kHitTestChildSurface) {
20 if (!hit_test_region->surface_id.is_valid())
21 return false;
22 }
23 return true;
24 }
25 bool ValidateHitTestData(const hit_test::mojom::HitTestDataPtr& hit_test_data) {
26 for (auto& region : hit_test_data->regions) {
27 if (!ValidateHitTestRegion(region))
28 return false;
29 }
30 return true;
31 }
32
33 } // namespace
34
35 HitTestAggregator::HitTestAggregator()
36 : active_region_count_(0), weak_ptr_factory_(this) {
37 AllocateDisplayHitTestData();
38 }
39 HitTestAggregator::~HitTestAggregator() {}
40
41 void HitTestAggregator::SubmitHitTestData(
42 hit_test::mojom::HitTestDataPtr hit_test_data) {
43 DCHECK(ValidateHitTestData(hit_test_data));
44 // TODO(gklassen): Runtime validation that hit_test_data is valid.
45 // TODO(gklassen): Inform FrameSink that the hit_test_data is invalid.
46 // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
47 pending_[hit_test_data->surface_id] = std::move(hit_test_data);
48 }
49
50 bool HitTestAggregator::OnSurfaceDamaged(const cc::SurfaceId& surface_id,
51 const cc::BeginFrameAck& ack) {
52 return false;
53 }
54
55 void HitTestAggregator::OnSurfaceDiscarded(const cc::SurfaceId& surface_id) {
56 pending_.erase(surface_id);
57 active_.erase(surface_id);
58 }
59
60 void HitTestAggregator::OnSurfaceWillDraw(const cc::SurfaceId& surface_id) {
61 auto pending_search = pending_.find(surface_id);
62 if (pending_search == pending_.end()) {
63 // Have already activated pending hit_test_data objects for this surface.
64 return;
65 }
66 hit_test::mojom::HitTestData* hit_test_data = pending_search->second.get();
67
68 // Update the region count.
69 auto active_search = active_.find(surface_id);
70 if (active_search != active_.end()) {
71 hit_test::mojom::HitTestData* old_hit_test_data =
72 active_search->second.get();
73 active_region_count_ -= old_hit_test_data->regions.size();
74 }
75 active_region_count_ += hit_test_data->regions.size();
76 DCHECK_GE(active_region_count_, 0);
77
78 active_[surface_id] = std::move(pending_[surface_id]);
79 pending_.erase(surface_id);
80 }
81
82 void HitTestAggregator::AllocateDisplayHitTestData() {
83 AllocateDisplayHitTestData(kInitialSize);
84 Swap();
85 AllocateDisplayHitTestData(kInitialSize);
86 }
87
88 void HitTestAggregator::AllocateDisplayHitTestData(int size) {
89 size_t num_bytes = size * sizeof(DisplayHitTestRegion);
sadrul 2017/06/27 04:23:35 Since |size| here depends on the input coming in f
gklassen 2017/06/27 21:46:33 Good call. A check has been added in the code tha
90 write_handle_ = mojo::SharedBufferHandle::Create(num_bytes);
91 write_size_ = size;
92
93 mojo::ScopedSharedBufferMapping mapping = write_handle_->Map(num_bytes);
94 DisplayHitTestRegion* region = (DisplayHitTestRegion*)mapping.get();
95 region[0].child_count = kEndOfList;
96 }
97
98 void HitTestAggregator::PostTaskAggregate(cc::SurfaceId display_surface_id) {
99 base::ThreadTaskRunnerHandle::Get()->PostTask(
100 FROM_HERE,
101 base::BindOnce(&HitTestAggregator::Aggregate,
102 weak_ptr_factory_.GetWeakPtr(), display_surface_id));
103 }
104
105 void HitTestAggregator::Aggregate(cc::SurfaceId display_surface_id) {
106 // Size check.
107 int size = write_size_;
108 int max_size = active_region_count_ + active_.size() + 1;
109 if (max_size > size) {
110 while (size < max_size)
111 size += kIncrementalSize;
sadrul 2017/06/27 04:23:35 We probably don't need the while loop?
gklassen 2017/06/27 21:46:33 Done.
112 AllocateDisplayHitTestData(size);
113 }
114
115 AppendRoot(display_surface_id);
116 }
117
118 void HitTestAggregator::AppendRoot(cc::SurfaceId surface_id) {
119 auto search = active_.find(surface_id);
120 if (search == active_.end()) {
121 // Referenced surface not found ( it may be late ).
122 return;
123 }
124 hit_test::mojom::HitTestData* hit_test_data = search->second.get();
125
126 mojo::ScopedSharedBufferMapping mapping = MapWriteBuffer();
sadrul 2017/06/27 04:23:34 Is there a reason we need to map/unmap? Can we jus
gklassen 2017/06/27 21:46:33 It needs to be mapped here to initialize the list.
gklassen 2017/06/27 21:52:38 On second thought this is a good suggestion. Do
127 DisplayHitTestRegion* regions = (DisplayHitTestRegion*)mapping.get();
128
129 regions[0].frame_sink_id = hit_test_data->surface_id.frame_sink_id();
130 regions[0].flags = hit_test_data->flags;
131 regions[0].rect = hit_test_data->bounds;
132 regions[0].transform = hit_test_data->transform;
133
134 int index = 1;
135 for (auto& region : hit_test_data->regions)
136 index = AppendRegion(regions, region, index);
sadrul 2017/06/27 04:23:35 Can we DCHECK/CHECK that |index| remains within bo
gklassen 2017/06/27 21:46:33 Done.
137
138 DCHECK_GE(index, 1);
139 regions[0].child_count = index - 1;
140 regions[index].child_count = kEndOfList;
141 }
142
143 int HitTestAggregator::AppendRegion(
144 DisplayHitTestRegion* regions,
145 const hit_test::mojom::HitTestRegionPtr& region,
146 int index) {
147 DisplayHitTestRegion* element = &regions[index];
148
149 element->frame_sink_id = region->surface_id.frame_sink_id();
150 element->flags = region->flags;
151 element->rect = region->rect;
152 element->transform = region->transform;
153
154 int parent_index = index++;
155
156 if (region->flags == hit_test::mojom::kHitTestChildSurface) {
157 auto search = active_.find(region->surface_id);
158 if (search == active_.end()) {
159 // Surface HitTestData not found - it may be late.
160 // Don't include this region so that it doesn't receive events.
161 // TODO(gklassen): create test case for this case.
162 return parent_index;
163 }
164
165 // Rather than add a node in the tree for this hit_test_data element
166 // we can simplify the tree by merging the flags and transform into
167 // the kHitTestChildSurface element.
168 hit_test::mojom::HitTestData* hit_test_data = search->second.get();
169 // TODO(gklassen): Add test case to validate this.
170 if (!hit_test_data->transform.IsIdentity())
171 element->transform.PreconcatTransform(hit_test_data->transform);
172
173 element->flags |= hit_test_data->flags;
174
175 for (auto& child_region : hit_test_data->regions)
176 index = AppendRegion(regions, child_region, index);
177 }
178 DCHECK_GE(index - parent_index - 1, 0);
179 element->child_count = index - parent_index - 1;
180 return index;
181 }
182
183 void HitTestAggregator::Swap() {
184 std::swap(read_handle_, write_handle_);
185 std::swap(read_size_, write_size_);
186 }
187
188 mojo::ScopedSharedBufferMapping HitTestAggregator::MapReadBuffer() {
189 return read_handle_->Map(read_size_ * sizeof(DisplayHitTestRegion));
190 }
191 mojo::ScopedSharedBufferMapping HitTestAggregator::MapWriteBuffer() {
192 return write_handle_->Map(write_size_ * sizeof(DisplayHitTestRegion));
193 }
194
195 } // namespace hit_test
196 } // namespace viz
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698