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

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

Issue 2908783002: WIP Hittest Component.
Patch Set: reviewer comments and handling of memory re-allocation 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/hit_test/hit_test_aggregator.h"
6 #include "base/logging.h"
7 #include "display_hit_test_data.h"
8
9 namespace viz {
10 namespace hit_test {
11
12 namespace {
13 // TODO(gklassen): Review and select appropriate sizes ( based on
14 // telemetry? ).
15 constexpr int kInitialSize = 1024;
16 constexpr int kIncrementalSize = 1024;
rjkroege 2017/06/12 18:13:01 You cannot tear this up and replace it later.
gklassen 2017/06/13 18:54:23 It copies over the portion in-use before switching
17 }
18
19 HitTestAggregator::HitTestAggregator() : weak_ptr_factory_(this) {
20 AllocateDisplayHitTestData();
21 }
22 HitTestAggregator::~HitTestAggregator() {}
23
24 namespace {
25
26 bool ValidateHitTestRegion(
27 const hit_test::mojom::HitTestRegionPtr& hit_test_region) {
28 if (hit_test_region->flags_ ==
29 hit_test::mojom::HitTestRegionFlags::HIT_TEST_CHILD_SURFACE) {
30 if (!hit_test_region->surface_id_.is_valid()) {
31 return false;
32 }
33 }
34 return true;
35 }
36 bool ValidateHitTestData(const hit_test::mojom::HitTestDataPtr& hit_test_data) {
37 for (auto& region : hit_test_data->regions_) {
38 if (!ValidateHitTestRegion(region)) {
39 return false;
40 }
41 }
42 return true;
43 }
44
45 } // namespace
46
47 void HitTestAggregator::SubmitHitTestData(
48 hit_test::mojom::HitTestDataPtr hit_test_data) {
49 DCHECK(ValidateHitTestData(hit_test_data));
rjkroege 2017/06/12 18:13:00 We will need a comprehensive policy to deal with t
gklassen 2017/06/13 18:54:23 Good call and thank you. Done.
50 pending_[hit_test_data->surface_id_] = std::move(hit_test_data);
51 }
52
53 void HitTestAggregator::OnSurfaceDiscarded(const cc::SurfaceId& surface_id) {
54 pending_.erase(surface_id);
55 active_.erase(surface_id);
56 }
57
58 void HitTestAggregator::OnSurfaceWillDraw(const cc::SurfaceId& surface_id) {
59 auto search = pending_.find(surface_id);
60 if (search == pending_.end()) {
61 // Have already activated pending hit_test_data objects for this surface.
62 return;
63 }
64 active_[surface_id] = std::move(pending_[surface_id]);
65 pending_.erase(surface_id);
66 }
67
68 void HitTestAggregator::AllocateDisplayHitTestData() {
69 AllocateDisplayHitTestData(kInitialSize);
70 }
71
72 void HitTestAggregator::AllocateDisplayHitTestData(int length) {
73 size_t byte_count =
74 sizeof(DisplayHitTestData) + length * sizeof(DisplayHitTestRegion);
75 display_hit_test_data_ = (DisplayHitTestData*)malloc(byte_count);
76
77 display_hit_test_data_->length_ = length;
78 display_hit_test_data_->read_offset_ = 0;
79 display_hit_test_data_->regions_[0].child_count_ = kEndOfList;
80 display_hit_test_data_->regions_[length / 2].child_count_ = kEndOfList;
81 }
82
83 void HitTestAggregator::ResizeDisplayHitTestData(int length) {
84 DisplayHitTestData* old_display_hit_test_data = display_hit_test_data_;
85
86 AllocateDisplayHitTestData(length);
87
88 // Copy over the current data and then mark the old structure
rjkroege 2017/06/12 18:13:01 Hm. We need to talk about this.
gklassen 2017/06/13 18:54:23 Based on the discussion yesterday is this ok for n
89 // as invalid so that clients will re-acquire their reference.
90 int old_length = old_display_hit_test_data->length_;
91 int new_length = display_hit_test_data_->length_;
92 DCHECK(new_length > old_length);
93 memcpy(display_hit_test_data_->regions_, old_display_hit_test_data->regions_,
94 old_length * sizeof(DisplayHitTestRegion));
95
96 old_display_hit_test_data->read_offset_ = kOldPleaseReAcquire;
97 }
98
99 void HitTestAggregator::PostTaskAggregate(cc::SurfaceId display_surface_id) {
100 base::ThreadTaskRunnerHandle::Get()->PostTask(
101 FROM_HERE,
102 base::BindOnce(&HitTestAggregator::Aggregate,
103 weak_ptr_factory_.GetWeakPtr(), display_surface_id));
104 }
105
106 namespace {
rjkroege 2017/06/12 18:13:01 one anonymous namespace at the top is conventional
gklassen 2017/06/13 18:54:23 Conventionalized & Done.
107
108 int CountRegions(const HitTestDataMap& map) {
109 int size = 0;
110 for (auto const& it : map) {
111 hit_test::mojom::HitTestData* hit_test_data = it.second.get();
112 size += hit_test_data->regions_.size();
rjkroege 2017/06/12 18:13:01 the regions are the same size? This is O(n). I am
gklassen 2017/06/13 18:54:23 Agreed. I couldn't find a convenient place to tra
113 }
114 return size;
115 }
116
117 } // namespace
118
119 void HitTestAggregator::Aggregate(cc::SurfaceId display_surface_id) {
120 // Size check.
121 int number_of_regions = CountRegions(active_);
122 int length = display_hit_test_data_->length_ / 2;
123 if (number_of_regions + 1 > length) {
124 while (length < number_of_regions) {
125 length += kIncrementalSize;
126 }
127 ResizeDisplayHitTestData(length);
rjkroege 2017/06/12 18:13:00 This means that we can have a large variance in th
gklassen 2017/06/13 18:54:23 Agreed, but I don't know of a better place to do t
128 }
129
130 int index = GetBackIndex();
131 int last_index = Append(display_surface_id, index);
132 display_hit_test_data_->regions_[last_index].child_count_ = kEndOfList;
133 }
134
135 int HitTestAggregator::Append(cc::SurfaceId surface_id, int index) {
136 auto search = active_.find(surface_id);
137 if (search == active_.end()) {
138 // Referenced surface not found ( it may be late ).
139 return index;
140 }
141 hit_test::mojom::HitTestData* hit_test_data = search->second.get();
142
143 for (auto& region : hit_test_data->regions_) {
144 index = Append(region, index);
145 }
146 return index;
147 }
148
149 int HitTestAggregator::Append(const hit_test::mojom::HitTestRegionPtr& region,
150 int index) {
151 DisplayHitTestRegion* element = &display_hit_test_data_->regions_[index];
152
153 element->frame_sink_id_ = region->surface_id_.frame_sink_id();
154 element->flags_ = region->flags_;
155 element->rect_ = region->rect_;
156 element->transform_ = region->transform_;
157
158 int parent_index = index++;
159
160 if (region->flags_ ==
161 hit_test::mojom::HitTestRegionFlags::HIT_TEST_CHILD_SURFACE) {
162 index = Append(region->surface_id_, index);
163 }
164
165 DCHECK((index - parent_index - 1) >= 0);
166 element->child_count_ = index - parent_index - 1;
167 return index;
168 }
169
170 void HitTestAggregator::Swap() {
171 display_hit_test_data_->read_offset_ = GetBackIndex();
172 }
173
174 int HitTestAggregator::GetBackIndex() {
175 if (display_hit_test_data_->read_offset_ == 0)
176 return display_hit_test_data_->length_ / 2;
177 return 0;
178 }
179
180 DisplayHitTestRegion* HitTestAggregator::GetCurrentRegions() {
181 return display_hit_test_data_->regions_ +
182 display_hit_test_data_->read_offset_;
183 }
184
185 } // namespace hit_test
186 } // namespace viz
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698