Chromium Code Reviews| 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 |