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

Side by Side Diff: ui/events/gesture_detection/motion_event_buffer.cc

Issue 2628393003: Remove ScopedVector from ui/events/. (Closed)
Patch Set: chromeos2 Created 3 years, 11 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/events/gesture_detection/motion_event_buffer.h" 5 #include "ui/events/gesture_detection/motion_event_buffer.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm>
10 #include <iterator>
9 #include <utility> 11 #include <utility>
10 12
11 #include "base/trace_event/trace_event.h" 13 #include "base/trace_event/trace_event.h"
12 #include "ui/events/gesture_detection/motion_event_generic.h" 14 #include "ui/events/gesture_detection/motion_event_generic.h"
13 15
14 namespace ui { 16 namespace ui {
15 namespace { 17 namespace {
16 18
17 // Latency added during resampling. A few milliseconds doesn't hurt much but 19 // Latency added during resampling. A few milliseconds doesn't hurt much but
18 // reduces the impact of mispredicted touch positions. 20 // reduces the impact of mispredicted touch positions.
19 const int kResampleLatencyMs = 5; 21 const int kResampleLatencyMs = 5;
20 22
21 // Minimum time difference between consecutive samples before attempting to 23 // Minimum time difference between consecutive samples before attempting to
22 // resample. 24 // resample.
23 const int kResampleMinDeltaMs = 2; 25 const int kResampleMinDeltaMs = 2;
24 26
25 // Maximum time to predict forward from the last known state, to avoid 27 // Maximum time to predict forward from the last known state, to avoid
26 // predicting too far into the future. This time is further bounded by 50% of 28 // predicting too far into the future. This time is further bounded by 50% of
27 // the last time delta. 29 // the last time delta.
28 const int kResampleMaxPredictionMs = 8; 30 const int kResampleMaxPredictionMs = 8;
29 31
30 typedef ScopedVector<MotionEventGeneric> MotionEventVector; 32 using MotionEventVector = std::vector<std::unique_ptr<MotionEventGeneric>>;
31 33
32 float Lerp(float a, float b, float alpha) { 34 float Lerp(float a, float b, float alpha) {
33 return a + alpha * (b - a); 35 return a + alpha * (b - a);
34 } 36 }
35 37
36 bool CanAddSample(const MotionEvent& event0, const MotionEvent& event1) { 38 bool CanAddSample(const MotionEvent& event0, const MotionEvent& event1) {
37 DCHECK_EQ(event0.GetAction(), MotionEvent::ACTION_MOVE); 39 DCHECK_EQ(event0.GetAction(), MotionEvent::ACTION_MOVE);
38 if (event1.GetAction() != MotionEvent::ACTION_MOVE) 40 if (event1.GetAction() != MotionEvent::ACTION_MOVE)
39 return false; 41 return false;
40 42
(...skipping 11 matching lines...) Expand all
52 } 54 }
53 55
54 return true; 56 return true;
55 } 57 }
56 58
57 bool ShouldResampleTool(MotionEvent::ToolType tool) { 59 bool ShouldResampleTool(MotionEvent::ToolType tool) {
58 return tool == MotionEvent::TOOL_TYPE_UNKNOWN || 60 return tool == MotionEvent::TOOL_TYPE_UNKNOWN ||
59 tool == MotionEvent::TOOL_TYPE_FINGER; 61 tool == MotionEvent::TOOL_TYPE_FINGER;
60 } 62 }
61 63
62 size_t CountSamplesNoLaterThan(const MotionEventVector& batch, 64 // Splits a chunk of events from the front of the provided |batch| and returns
63 base::TimeTicks time) { 65 // it. Requires that |batch| is sorted.
64 size_t count = 0;
65 while (count < batch.size() && batch[count]->GetEventTime() <= time)
66 ++count;
67 return count;
68 }
69
70 MotionEventVector ConsumeSamplesNoLaterThan(MotionEventVector* batch, 66 MotionEventVector ConsumeSamplesNoLaterThan(MotionEventVector* batch,
71 base::TimeTicks time) { 67 base::TimeTicks time) {
72 DCHECK(batch); 68 DCHECK(batch);
73 size_t count = CountSamplesNoLaterThan(*batch, time); 69 auto first_kept_event = std::partition_point(
Avi (use Gerrit) 2017/01/14 00:49:42 Note that the queue is sorted by time, which means
74 DCHECK_GE(batch->size(), count); 70 batch->begin(), batch->end(),
75 if (count == 0) 71 [time](const std::unique_ptr<MotionEventGeneric>& event) {
76 return MotionEventVector(); 72 return event->GetEventTime() <= time;
77 73 });
78 if (count == batch->size()) 74 MotionEventVector result(std::make_move_iterator(batch->begin()),
79 return std::move(*batch); 75 std::make_move_iterator(first_kept_event));
80 76 batch->erase(batch->begin(), first_kept_event);
81 // TODO(jdduke): Use a ScopedDeque to work around this mess. 77 return result;
82 MotionEventVector unconsumed_batch;
83 unconsumed_batch.insert(
84 unconsumed_batch.begin(), batch->begin() + count, batch->end());
85 batch->weak_erase(batch->begin() + count, batch->end());
86
87 unconsumed_batch.swap(*batch);
88 DCHECK_GE(unconsumed_batch.size(), 1U);
89 return unconsumed_batch;
90 } 78 }
91 79
92 // Linearly interpolate the pointer position between two MotionEvent samples. 80 // Linearly interpolate the pointer position between two MotionEvent samples.
93 // Only pointers of finger or unknown type will be resampled. 81 // Only pointers of finger or unknown type will be resampled.
94 PointerProperties ResamplePointer(const MotionEvent& event0, 82 PointerProperties ResamplePointer(const MotionEvent& event0,
95 const MotionEvent& event1, 83 const MotionEvent& event1,
96 size_t event0_pointer_index, 84 size_t event0_pointer_index,
97 size_t event1_pointer_index, 85 size_t event1_pointer_index,
98 float alpha) { 86 float alpha) {
99 DCHECK_EQ(event0.GetPointerId(event0_pointer_index), 87 DCHECK_EQ(event0.GetPointerId(event0_pointer_index),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 139
152 DCHECK(event); 140 DCHECK(event);
153 event->set_button_state(event0.GetButtonState()); 141 event->set_button_state(event0.GetButtonState());
154 return event; 142 return event;
155 } 143 }
156 144
157 // Synthesize a compound MotionEventGeneric event from a sequence of events. 145 // Synthesize a compound MotionEventGeneric event from a sequence of events.
158 // Events must be in non-decreasing (time) order. 146 // Events must be in non-decreasing (time) order.
159 std::unique_ptr<MotionEventGeneric> ConsumeSamples(MotionEventVector events) { 147 std::unique_ptr<MotionEventGeneric> ConsumeSamples(MotionEventVector events) {
160 DCHECK(!events.empty()); 148 DCHECK(!events.empty());
161 std::unique_ptr<MotionEventGeneric> event(events.back()); 149 std::unique_ptr<MotionEventGeneric> event = std::move(events.back());
162 for (size_t i = 0; i + 1 < events.size(); ++i) 150 events.pop_back();
163 event->PushHistoricalEvent(std::unique_ptr<MotionEvent>(events[i])); 151 for (auto& historic_event : events)
164 events.weak_clear(); 152 event->PushHistoricalEvent(std::move(historic_event));
165 return event; 153 return event;
166 } 154 }
167 155
168 // Consume a series of event samples, attempting to synthesize a new, synthetic 156 // Consume a series of event samples, attempting to synthesize a new, synthetic
169 // event if the samples and sample time meet certain interpolation/extrapolation 157 // event if the samples and sample time meet certain interpolation/extrapolation
170 // conditions. If such conditions are met, the provided samples will be added 158 // conditions. If such conditions are met, the provided samples will be added
171 // to the synthetic event's history, otherwise, the samples will be used to 159 // to the synthetic event's history, otherwise, the samples will be used to
172 // generate a basic, compound event. 160 // generate a basic, compound event.
173 // TODO(jdduke): Revisit resampling to handle cases where alternating frames 161 // TODO(jdduke): Revisit resampling to handle cases where alternating frames
174 // are resampled or resampling is otherwise inconsistent, e.g., a 90hz input 162 // are resampled or resampling is otherwise inconsistent, e.g., a 90hz input
175 // and 60hz frame signal could phase-align such that even frames yield an 163 // and 60hz frame signal could phase-align such that even frames yield an
176 // extrapolated event and odd frames are not resampled, crbug.com/399381. 164 // extrapolated event and odd frames are not resampled, crbug.com/399381.
177 std::unique_ptr<MotionEventGeneric> ConsumeSamplesAndTryResampling( 165 std::unique_ptr<MotionEventGeneric> ConsumeSamplesAndTryResampling(
178 base::TimeTicks resample_time, 166 base::TimeTicks resample_time,
179 MotionEventVector events, 167 MotionEventVector events,
180 const MotionEvent* next) { 168 const MotionEvent* next) {
181 const ui::MotionEvent* event0 = nullptr; 169 const ui::MotionEvent* event0 = nullptr;
182 const ui::MotionEvent* event1 = nullptr; 170 const ui::MotionEvent* event1 = nullptr;
183 if (next) { 171 if (next) {
184 DCHECK(resample_time < next->GetEventTime()); 172 DCHECK(resample_time < next->GetEventTime());
185 // Interpolate between current sample and future sample. 173 // Interpolate between current sample and future sample.
186 event0 = events.back(); 174 event0 = events.back().get();
187 event1 = next; 175 event1 = next;
188 } else if (events.size() >= 2) { 176 } else if (events.size() >= 2) {
189 // Extrapolate future sample using current sample and past sample. 177 // Extrapolate future sample using current sample and past sample.
190 event0 = events[events.size() - 2]; 178 event0 = events[events.size() - 2].get();
191 event1 = events[events.size() - 1]; 179 event1 = events[events.size() - 1].get();
192 180
193 const base::TimeTicks time1 = event1->GetEventTime(); 181 const base::TimeTicks time1 = event1->GetEventTime();
194 base::TimeTicks max_predict = 182 base::TimeTicks max_predict =
195 time1 + 183 time1 +
196 std::min((event1->GetEventTime() - event0->GetEventTime()) / 2, 184 std::min((event1->GetEventTime() - event0->GetEventTime()) / 2,
197 base::TimeDelta::FromMilliseconds(kResampleMaxPredictionMs)); 185 base::TimeDelta::FromMilliseconds(kResampleMaxPredictionMs));
198 if (resample_time > max_predict) { 186 if (resample_time > max_predict) {
199 TRACE_EVENT_INSTANT2("input", 187 TRACE_EVENT_INSTANT2("input",
200 "MotionEventBuffer::TryResample prediction adjust", 188 "MotionEventBuffer::TryResample prediction adjust",
201 TRACE_EVENT_SCOPE_THREAD, 189 TRACE_EVENT_SCOPE_THREAD,
(...skipping 19 matching lines...) Expand all
221 TRACE_EVENT_INSTANT1("input", 209 TRACE_EVENT_INSTANT1("input",
222 "MotionEventBuffer::TryResample failure", 210 "MotionEventBuffer::TryResample failure",
223 TRACE_EVENT_SCOPE_THREAD, 211 TRACE_EVENT_SCOPE_THREAD,
224 "event_delta_too_small(ms)", 212 "event_delta_too_small(ms)",
225 delta.InMilliseconds()); 213 delta.InMilliseconds());
226 return ConsumeSamples(std::move(events)); 214 return ConsumeSamples(std::move(events));
227 } 215 }
228 216
229 std::unique_ptr<MotionEventGeneric> resampled_event = 217 std::unique_ptr<MotionEventGeneric> resampled_event =
230 ResampleMotionEvent(*event0, *event1, resample_time); 218 ResampleMotionEvent(*event0, *event1, resample_time);
231 for (size_t i = 0; i < events.size(); ++i) 219 for (auto& historic_event : events)
232 resampled_event->PushHistoricalEvent( 220 resampled_event->PushHistoricalEvent(std::move(historic_event));
233 std::unique_ptr<MotionEvent>(events[i]));
234 events.weak_clear();
235 return resampled_event; 221 return resampled_event;
236 } 222 }
237 223
238 } // namespace 224 } // namespace
239 225
240 MotionEventBuffer::MotionEventBuffer(MotionEventBufferClient* client, 226 MotionEventBuffer::MotionEventBuffer(MotionEventBufferClient* client,
241 bool enable_resampling) 227 bool enable_resampling)
242 : client_(client), resample_(enable_resampling) { 228 : client_(client), resample_(enable_resampling) {
243 } 229 }
244 230
(...skipping 21 matching lines...) Expand all
266 252
267 std::unique_ptr<MotionEventGeneric> clone = 253 std::unique_ptr<MotionEventGeneric> clone =
268 MotionEventGeneric::CloneEvent(event); 254 MotionEventGeneric::CloneEvent(event);
269 if (buffered_events_.empty()) { 255 if (buffered_events_.empty()) {
270 buffered_events_.push_back(std::move(clone)); 256 buffered_events_.push_back(std::move(clone));
271 client_->SetNeedsFlush(); 257 client_->SetNeedsFlush();
272 return; 258 return;
273 } 259 }
274 260
275 if (CanAddSample(*buffered_events_.front(), *clone)) { 261 if (CanAddSample(*buffered_events_.front(), *clone)) {
262 // Ensure that buffered_events_ is ordered.
276 DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime()); 263 DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime());
277 } else { 264 } else {
278 FlushWithoutResampling(std::move(buffered_events_)); 265 FlushWithoutResampling(std::move(buffered_events_));
279 } 266 }
280 267
281 buffered_events_.push_back(std::move(clone)); 268 buffered_events_.push_back(std::move(clone));
282 // No need to request another flush as the first event will have requested it. 269 // No need to request another flush as the first event will have requested it.
283 } 270 }
284 271
285 void MotionEventBuffer::Flush(base::TimeTicks frame_time) { 272 void MotionEventBuffer::Flush(base::TimeTicks frame_time) {
286 if (buffered_events_.empty()) 273 if (buffered_events_.empty())
287 return; 274 return;
288 275
289 // Shifting the sample time back slightly minimizes the potential for 276 // Shifting the sample time back slightly minimizes the potential for
290 // misprediction when extrapolating events. 277 // misprediction when extrapolating events.
291 if (resample_) 278 if (resample_)
292 frame_time -= base::TimeDelta::FromMilliseconds(kResampleLatencyMs); 279 frame_time -= base::TimeDelta::FromMilliseconds(kResampleLatencyMs);
293 280
294 // TODO(jdduke): Use a persistent MotionEventVector vector for temporary 281 // TODO(jdduke): Use a persistent MotionEventVector vector for temporary
295 // storage. 282 // storage.
296 MotionEventVector events( 283 MotionEventVector events =
297 ConsumeSamplesNoLaterThan(&buffered_events_, frame_time)); 284 ConsumeSamplesNoLaterThan(&buffered_events_, frame_time);
298 if (events.empty()) { 285 if (events.empty()) {
299 DCHECK(!buffered_events_.empty()); 286 DCHECK(!buffered_events_.empty());
300 client_->SetNeedsFlush(); 287 client_->SetNeedsFlush();
301 return; 288 return;
302 } 289 }
303 290
304 if (!resample_ || (events.size() == 1 && buffered_events_.empty())) { 291 if (!resample_ || (events.size() == 1 && buffered_events_.empty())) {
305 FlushWithoutResampling(std::move(events)); 292 FlushWithoutResampling(std::move(events));
306 if (!buffered_events_.empty()) 293 if (!buffered_events_.empty())
307 client_->SetNeedsFlush(); 294 client_->SetNeedsFlush();
308 return; 295 return;
309 } 296 }
310 297
311 FlushWithResampling(std::move(events), frame_time); 298 FlushWithResampling(std::move(events), frame_time);
312 } 299 }
313 300
314 void MotionEventBuffer::FlushWithResampling(MotionEventVector events, 301 void MotionEventBuffer::FlushWithResampling(MotionEventVector events,
315 base::TimeTicks resample_time) { 302 base::TimeTicks resample_time) {
316 DCHECK(!events.empty()); 303 DCHECK(!events.empty());
317 base::TimeTicks original_event_time = events.back()->GetEventTime(); 304 base::TimeTicks original_event_time = events.back()->GetEventTime();
318 const MotionEvent* next_event = 305 const MotionEvent* next_event =
319 !buffered_events_.empty() ? buffered_events_.front() : nullptr; 306 !buffered_events_.empty() ? buffered_events_.front().get() : nullptr;
320 307
321 std::unique_ptr<MotionEventGeneric> resampled_event = 308 std::unique_ptr<MotionEventGeneric> resampled_event =
322 ConsumeSamplesAndTryResampling(resample_time, std::move(events), 309 ConsumeSamplesAndTryResampling(resample_time, std::move(events),
323 next_event); 310 next_event);
324 DCHECK(resampled_event); 311 DCHECK(resampled_event);
325 312
326 // Log the extrapolated event time, guarding against subsequently queued 313 // Log the extrapolated event time, guarding against subsequently queued
327 // events that might have an earlier timestamp. 314 // events that might have an earlier timestamp.
328 if (!next_event && resampled_event->GetEventTime() > original_event_time) { 315 if (!next_event && resampled_event->GetEventTime() > original_event_time) {
329 last_extrapolated_event_time_ = resampled_event->GetEventTime(); 316 last_extrapolated_event_time_ = resampled_event->GetEventTime();
330 } else { 317 } else {
331 last_extrapolated_event_time_ = base::TimeTicks(); 318 last_extrapolated_event_time_ = base::TimeTicks();
332 } 319 }
333 320
334 client_->ForwardMotionEvent(*resampled_event); 321 client_->ForwardMotionEvent(*resampled_event);
335 if (!buffered_events_.empty()) 322 if (!buffered_events_.empty())
336 client_->SetNeedsFlush(); 323 client_->SetNeedsFlush();
337 } 324 }
338 325
339 void MotionEventBuffer::FlushWithoutResampling(MotionEventVector events) { 326 void MotionEventBuffer::FlushWithoutResampling(MotionEventVector events) {
340 last_extrapolated_event_time_ = base::TimeTicks(); 327 last_extrapolated_event_time_ = base::TimeTicks();
341 if (events.empty()) 328 if (events.empty())
342 return; 329 return;
343 330
344 client_->ForwardMotionEvent(*ConsumeSamples(std::move(events))); 331 client_->ForwardMotionEvent(*ConsumeSamples(std::move(events)));
345 } 332 }
346 333
347 } // namespace ui 334 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698