OLD | NEW |
---|---|
(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 | |
OLD | NEW |