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

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

Issue 2938953002: Implement HitTestAggregator (Closed)
Patch Set: add transform include to resolve build bot failure 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/aggregated_hit_test_region.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 constexpr int kMaxRegionsPerSurface = 1024;
17 constexpr int kMaxSize = 100 * 1024;
18
19 bool ValidateHitTestRegion(
20 const hit_test::mojom::HitTestRegionPtr& hit_test_region) {
21 if (hit_test_region->flags == hit_test::mojom::kHitTestChildSurface) {
22 if (!hit_test_region->surface_id.is_valid())
23 return false;
24 }
25
26 return true;
27 }
28
29 bool ValidateHitTestRegionList(
30 const hit_test::mojom::HitTestRegionListPtr& hit_test_region_list) {
31 if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
32 return false;
33 for (auto& region : hit_test_region_list->regions) {
34 if (!ValidateHitTestRegion(region))
35 return false;
36 }
37 return true;
38 }
39
40 } // namespace
41
42 HitTestAggregator::HitTestAggregator()
43 : active_region_count_(0), weak_ptr_factory_(this) {
danakj 2017/07/13 15:39:38 you can assign the 0 in the .h file where var is d
gklassen 2017/07/13 19:59:14 Done.
44 AllocateHitTestRegionArray();
45 }
46
47 HitTestAggregator::~HitTestAggregator() = default;
48
49 void HitTestAggregator::SubmitHitTestRegionList(
50 hit_test::mojom::HitTestRegionListPtr hit_test_region_list) {
51 DCHECK(ValidateHitTestRegionList(hit_test_region_list));
52 // TODO(gklassen): Runtime validation that hit_test_region_list is valid.
53 // TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
54 // TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
55 pending_[hit_test_region_list->surface_id] = std::move(hit_test_region_list);
56 }
57
58 bool HitTestAggregator::OnSurfaceDamaged(const SurfaceId& surface_id,
59 const cc::BeginFrameAck& ack) {
60 return false;
61 }
62
63 void HitTestAggregator::OnSurfaceDiscarded(const SurfaceId& surface_id) {
64 // Update the region count.
65 auto active_search = active_.find(surface_id);
66 if (active_search != active_.end()) {
67 hit_test::mojom::HitTestRegionList* old_hit_test_data =
68 active_search->second.get();
69 active_region_count_ -= old_hit_test_data->regions.size();
70 }
71 DCHECK_GE(active_region_count_, 0);
72
73 pending_.erase(surface_id);
74 active_.erase(surface_id);
75 }
76
77 void HitTestAggregator::OnSurfaceWillDraw(const SurfaceId& surface_id) {
78 auto pending_search = pending_.find(surface_id);
79 if (pending_search == pending_.end()) {
80 // Have already activated pending hit_test_region_list objects for this
81 // surface.
82 return;
83 }
84 hit_test::mojom::HitTestRegionList* hit_test_region_list =
85 pending_search->second.get();
86
87 // Update the region count.
88 auto active_search = active_.find(surface_id);
89 if (active_search != active_.end()) {
90 hit_test::mojom::HitTestRegionList* old_hit_test_data =
91 active_search->second.get();
92 active_region_count_ -= old_hit_test_data->regions.size();
93 }
94 active_region_count_ += hit_test_region_list->regions.size();
95 DCHECK_GE(active_region_count_, 0);
96
97 active_[surface_id] = std::move(pending_[surface_id]);
98 pending_.erase(surface_id);
99 }
100
101 void HitTestAggregator::AllocateHitTestRegionArray() {
102 AllocateHitTestRegionArray(kInitialSize);
103 Swap();
104 AllocateHitTestRegionArray(kInitialSize);
105 }
106
107 void HitTestAggregator::AllocateHitTestRegionArray(int size) {
108 size_t num_bytes = size * sizeof(AggregatedHitTestRegion);
109 write_handle_ = mojo::SharedBufferHandle::Create(num_bytes);
110 write_size_ = size;
111 write_buffer_ = write_handle_->Map(num_bytes);
112
113 AggregatedHitTestRegion* region =
114 (AggregatedHitTestRegion*)write_buffer_.get();
115 region[0].child_count = kEndOfList;
116 }
117
118 void HitTestAggregator::PostTaskAggregate(SurfaceId display_surface_id) {
119 base::ThreadTaskRunnerHandle::Get()->PostTask(
120 FROM_HERE,
121 base::BindOnce(&HitTestAggregator::Aggregate,
122 weak_ptr_factory_.GetWeakPtr(), display_surface_id));
123 }
124
125 void HitTestAggregator::Aggregate(SurfaceId display_surface_id) {
126 // Check to ensure that enough memory has been allocated.
127 int size = write_size_;
128 int max_size = active_region_count_ + active_.size() + 1;
129 if (max_size > kMaxSize)
130 max_size = kMaxSize;
131
132 if (max_size > size) {
133 size = (1 + max_size / kIncrementalSize) * kIncrementalSize;
134 AllocateHitTestRegionArray(size);
135 }
136
137 AppendRoot(display_surface_id);
138 }
139
140 void HitTestAggregator::AppendRoot(SurfaceId surface_id) {
141 auto search = active_.find(surface_id);
142 CHECK(search != active_.end());
danakj 2017/07/13 15:39:38 do you mean DCHECK? See https://chromium.googleso
gklassen 2017/07/13 19:59:14 The use of CHECK was intentional and based on conv
danakj 2017/07/14 15:27:37 Unless code outside your control is going to somet
gklassen 2017/07/14 16:54:45 Thank you for the explanation and detail - it's ve
143
144 hit_test::mojom::HitTestRegionList* hit_test_region_list =
145 search->second.get();
146
147 AggregatedHitTestRegion* regions =
148 (AggregatedHitTestRegion*)write_buffer_.get();
danakj 2017/07/13 15:39:38 Use c++ casts. https://google.github.io/styleguide
gklassen 2017/07/13 19:59:14 Good call. Thanks. Done.
149
150 regions[0].frame_sink_id = hit_test_region_list->surface_id.frame_sink_id();
151 regions[0].flags = hit_test_region_list->flags;
152 regions[0].rect = hit_test_region_list->bounds;
153 regions[0].transform = hit_test_region_list->transform;
154
155 int index = 1;
156 for (const auto& region : hit_test_region_list->regions) {
157 if (index >= write_size_ - 1)
158 break;
159 index = AppendRegion(regions, region, index);
160 }
161
162 DCHECK_GE(index, 1);
163 regions[0].child_count = index - 1;
164 regions[index].child_count = kEndOfList;
165 }
166
167 int HitTestAggregator::AppendRegion(
168 AggregatedHitTestRegion* regions,
169 const hit_test::mojom::HitTestRegionPtr& region,
170 int index) {
171 AggregatedHitTestRegion* element = &regions[index];
172
173 element->frame_sink_id = region->surface_id.frame_sink_id();
174 element->flags = region->flags;
175 element->rect = region->rect;
176 element->transform = region->transform;
177
178 int parent_index = index++;
179 if (index >= write_size_ - 1) {
180 element->child_count = 0;
181 return index;
182 }
183
184 if (region->flags == hit_test::mojom::kHitTestChildSurface) {
185 auto search = active_.find(region->surface_id);
186 if (search == active_.end()) {
187 // Surface HitTestRegionList not found - it may be late.
188 // Don't include this region so that it doesn't receive events.
189 return parent_index;
190 }
191
192 // Rather than add a node in the tree for this hit_test_region_list element
193 // we can simplify the tree by merging the flags and transform into
194 // the kHitTestChildSurface element.
195 hit_test::mojom::HitTestRegionList* hit_test_region_list =
196 search->second.get();
197 if (!hit_test_region_list->transform.IsIdentity())
198 element->transform.PreconcatTransform(hit_test_region_list->transform);
199
200 element->flags |= hit_test_region_list->flags;
201
202 for (const auto& child_region : hit_test_region_list->regions) {
203 index = AppendRegion(regions, child_region, index);
204 if (index >= write_size_ - 1)
205 break;
206 }
207 }
208 DCHECK_GE(index - parent_index - 1, 0);
209 element->child_count = index - parent_index - 1;
210 return index;
211 }
212
213 void HitTestAggregator::Swap() {
214 std::swap(read_handle_, write_handle_);
danakj 2017/07/13 15:39:38 use ADL lookup for swap, with using std::swap: htt
gklassen 2017/07/13 19:59:14 Done.
215 std::swap(read_size_, write_size_);
216 std::swap(read_buffer_, write_buffer_);
217 }
218
219 } // namespace hit_test
220 } // namespace viz
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698