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

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

Issue 2938953002: Implement HitTestAggregator (Closed)
Patch Set: improvements based on reviewer 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 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)) {
varkha 2017/06/20 19:56:59 nit: no need for {}
gklassen 2017/06/26 21:55:19 Done.
28 return false;
29 }
30 }
31 return true;
32 }
33
34 } // namespace
35
36 HitTestAggregator::HitTestAggregator(
37 std::unique_ptr<DisplayHitTestDataFactory> display_hit_test_data_factory)
38 : active_region_count_(0),
39 display_hit_test_data_factory_(std::move(display_hit_test_data_factory)),
40 weak_ptr_factory_(this) {
41 AllocateDisplayHitTestData();
42 }
43 HitTestAggregator::~HitTestAggregator() {}
44
45 void HitTestAggregator::SubmitHitTestData(
46 hit_test::mojom::HitTestDataPtr hit_test_data) {
47 DCHECK(ValidateHitTestData(hit_test_data));
48 // TODO(gklassen): Runtime validation that hit_test_data is valid.
49 // TODO(gklassen): Inform FrameSink that the hit_test_data is invalid.
50 // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
51 pending_[hit_test_data->surface_id] = std::move(hit_test_data);
52 }
53
54 bool HitTestAggregator::OnSurfaceDamaged(const cc::SurfaceId& surface_id,
55 const cc::BeginFrameAck& ack) {
56 return false;
57 }
58
59 void HitTestAggregator::OnSurfaceDiscarded(const cc::SurfaceId& surface_id) {
60 pending_.erase(surface_id);
61 active_.erase(surface_id);
62 }
63
64 void HitTestAggregator::OnSurfaceWillDraw(const cc::SurfaceId& surface_id) {
65 auto pending_search = pending_.find(surface_id);
66 if (pending_search == pending_.end()) {
67 // Have already activated pending hit_test_data objects for this surface.
68 return;
69 }
70 hit_test::mojom::HitTestData* hit_test_data = pending_search->second.get();
71
72 // Update the region count.
73 auto active_search = active_.find(surface_id);
74 if (active_search != active_.end()) {
75 hit_test::mojom::HitTestData* old_hit_test_data =
76 active_search->second.get();
77 active_region_count_ -= old_hit_test_data->regions.size();
78 }
79 active_region_count_ += hit_test_data->regions.size();
80 DCHECK_GE(active_region_count_, 0);
81
82 active_[surface_id] = std::move(pending_[surface_id]);
83 pending_.erase(surface_id);
84 }
85
86 void HitTestAggregator::AllocateDisplayHitTestData() {
87 AllocateDisplayHitTestData(kInitialSize);
88 }
89
90 void HitTestAggregator::AllocateDisplayHitTestData(int length) {
91 size_t byte_count =
92 sizeof(DisplayHitTestData) + length * sizeof(DisplayHitTestRegion);
93 display_hit_test_data_ = (DisplayHitTestData*)malloc(byte_count);
94
95 display_hit_test_data_->length = length;
96 display_hit_test_data_->read_offset = 0;
97 display_hit_test_data_->regions[0].child_count = kEndOfList;
98 display_hit_test_data_->regions[length / 2].child_count = kEndOfList;
99 }
100
101 void HitTestAggregator::ResizeDisplayHitTestData(int length) {
102 DisplayHitTestData* old_display_hit_test_data = display_hit_test_data_;
103
104 AllocateDisplayHitTestData(length);
105
106 // Copy over the current data and then mark the old structure
107 // as invalid so that clients will re-acquire their reference.
108 int old_length = old_display_hit_test_data->length;
109 int new_length = display_hit_test_data_->length;
110 DCHECK(new_length > old_length);
111 memcpy(display_hit_test_data_->regions, old_display_hit_test_data->regions,
112 old_length * sizeof(DisplayHitTestRegion));
113
114 old_display_hit_test_data->read_offset = kOldPleaseReAcquire;
115 }
116
117 void HitTestAggregator::PostTaskAggregate(cc::SurfaceId display_surface_id) {
118 base::ThreadTaskRunnerHandle::Get()->PostTask(
119 FROM_HERE,
120 base::BindOnce(&HitTestAggregator::Aggregate,
121 weak_ptr_factory_.GetWeakPtr(), display_surface_id));
122 }
123
124 void HitTestAggregator::Aggregate(cc::SurfaceId display_surface_id) {
125 // Size check.
126 int length = display_hit_test_data_->length / 2;
127 // TODO(gklassen): sharpen this estimate
128 int max_size = active_region_count_ * 2;
129 if (max_size > length) {
130 while (length < max_size) {
varkha 2017/06/20 19:56:59 nit: no need for {}
gklassen 2017/06/26 21:55:19 Done.
131 length += kIncrementalSize;
132 }
133
134 ResizeDisplayHitTestData(length);
135 }
136
137 int index = GetBackIndex();
138 int last_index = AppendRoot(display_surface_id, index);
139 display_hit_test_data_->regions[last_index].child_count = kEndOfList;
140 }
141
142 int HitTestAggregator::AppendRoot(cc::SurfaceId surface_id, int index) {
143 auto search = active_.find(surface_id);
144 if (search == active_.end()) {
145 // Referenced surface not found ( it may be late ).
146 return index;
147 }
148 hit_test::mojom::HitTestData* hit_test_data = search->second.get();
149
150 DisplayHitTestRegion* element = &display_hit_test_data_->regions[index];
151
152 element->frame_sink_id = hit_test_data->surface_id.frame_sink_id();
153 element->flags = hit_test_data->flags;
154 element->rect = hit_test_data->bounds;
155 element->transform = hit_test_data->transform;
156
157 int parent_index = index++;
158
159 for (auto& region : hit_test_data->regions) {
varkha 2017/06/20 19:56:59 nit ditto.
gklassen 2017/06/26 21:55:19 Done.
160 index = AppendRegion(region, index);
161 }
162 DCHECK_GE(index - parent_index - 1, 0);
163 element->child_count = index - parent_index - 1;
164 return index;
165 }
166
167 int HitTestAggregator::AppendRegion(
168 const hit_test::mojom::HitTestRegionPtr& region,
169 int index) {
170 DisplayHitTestRegion* element = &display_hit_test_data_->regions[index];
171
172 element->frame_sink_id = region->surface_id.frame_sink_id();
173 element->flags = region->flags;
174 element->rect = region->rect;
175 element->transform = region->transform;
176
177 int parent_index = index++;
178
179 if (region->flags == hit_test::mojom::kHitTestChildSurface) {
180 auto search = active_.find(region->surface_id);
181 if (search == active_.end()) {
182 // Surface HitTestData not found - it may be late.
183 // Don't include this region so that it doesn't receive events.
184 // TODO(gklassen): create test case for this case.
185 return parent_index;
186 }
187
188 // Rather than add a node in the tree for this hit_test_data element
189 // we can simplify the tree by merging the flags and transform into
190 // the kHitTestChildSurface element.
191 hit_test::mojom::HitTestData* hit_test_data = search->second.get();
192 if (!hit_test_data->transform.IsIdentity()) {
193 // TODO(gklassen): Add test case to validate this.
194 element->transform.PreconcatTransform(hit_test_data->transform);
195 }
196 element->flags |= hit_test_data->flags;
197
198 for (auto& child_region : hit_test_data->regions) {
varkha 2017/06/20 19:56:59 nit: ditto.
gklassen 2017/06/26 21:55:19 Done.
199 index = AppendRegion(child_region, index);
200 }
201 }
202 DCHECK_GE(index - parent_index - 1, 0);
203 element->child_count = index - parent_index - 1;
204 return index;
205 }
206
207 void HitTestAggregator::Swap() {
208 display_hit_test_data_->read_offset = GetBackIndex();
209 }
210
211 int HitTestAggregator::GetBackIndex() {
212 if (display_hit_test_data_->read_offset == 0)
213 return display_hit_test_data_->length / 2;
214 return 0;
215 }
216
217 DisplayHitTestRegion* HitTestAggregator::GetCurrentRegions() {
218 return display_hit_test_data_->regions + display_hit_test_data_->read_offset;
219 }
220
221 } // namespace hit_test
222 } // namespace viz
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698