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

Side by Side Diff: ui/events/blink/input_handler_proxy.cc

Issue 2429953002: Implement compositor thread VSync aligned event queue (Closed)
Patch Set: tdresser's review: Move CanCoalesce/Coalesce; Test queueing time Created 4 years, 1 month 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/blink/input_handler_proxy.h" 5 #include "ui/events/blink/input_handler_proxy.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "base/auto_reset.h" 11 #include "base/auto_reset.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
15 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
16 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
17 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
18 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
19 #include "cc/input/main_thread_scrolling_reason.h" 20 #include "cc/input/main_thread_scrolling_reason.h"
20 #include "third_party/WebKit/public/platform/WebInputEvent.h" 21 #include "third_party/WebKit/public/platform/WebInputEvent.h"
22 #include "ui/events/blink/blink_event_util.h"
23 #include "ui/events/blink/compositor_thread_event_queue.h"
21 #include "ui/events/blink/did_overscroll_params.h" 24 #include "ui/events/blink/did_overscroll_params.h"
25 #include "ui/events/blink/event_with_callback.h"
22 #include "ui/events/blink/input_handler_proxy_client.h" 26 #include "ui/events/blink/input_handler_proxy_client.h"
23 #include "ui/events/blink/input_scroll_elasticity_controller.h" 27 #include "ui/events/blink/input_scroll_elasticity_controller.h"
24 #include "ui/events/blink/web_input_event_traits.h" 28 #include "ui/events/blink/web_input_event_traits.h"
25 #include "ui/events/latency_info.h" 29 #include "ui/events/latency_info.h"
26 #include "ui/gfx/geometry/point_conversions.h" 30 #include "ui/gfx/geometry/point_conversions.h"
27 31
28 using blink::WebFloatPoint; 32 using blink::WebFloatPoint;
29 using blink::WebFloatSize; 33 using blink::WebFloatSize;
30 using blink::WebGestureEvent; 34 using blink::WebGestureEvent;
31 using blink::WebInputEvent; 35 using blink::WebInputEvent;
(...skipping 23 matching lines...) Expand all
55 // Minimum velocity for the active touch scroll to preserve (boost) an active 59 // Minimum velocity for the active touch scroll to preserve (boost) an active
56 // fling for which cancellation has been deferred. 60 // fling for which cancellation has been deferred.
57 const double kMinBoostTouchScrollSpeedSquare = 150 * 150.; 61 const double kMinBoostTouchScrollSpeedSquare = 150 * 150.;
58 62
59 // Timeout window after which the active fling will be cancelled if no animation 63 // Timeout window after which the active fling will be cancelled if no animation
60 // ticks, scrolls or flings of sufficient velocity relative to the current fling 64 // ticks, scrolls or flings of sufficient velocity relative to the current fling
61 // are received. The default value on Android native views is 40ms, but we use a 65 // are received. The default value on Android native views is 40ms, but we use a
62 // slightly increased value to accomodate small IPC message delays. 66 // slightly increased value to accomodate small IPC message delays.
63 const double kFlingBoostTimeoutDelaySeconds = 0.05; 67 const double kFlingBoostTimeoutDelaySeconds = 0.05;
64 68
69 const size_t kTenSeconds = 10 * 1000 * 1000;
70
65 gfx::Vector2dF ToClientScrollIncrement(const WebFloatSize& increment) { 71 gfx::Vector2dF ToClientScrollIncrement(const WebFloatSize& increment) {
66 return gfx::Vector2dF(-increment.width, -increment.height); 72 return gfx::Vector2dF(-increment.width, -increment.height);
67 } 73 }
68 74
69 double InSecondsF(const base::TimeTicks& time) { 75 double InSecondsF(const base::TimeTicks& time) {
70 return (time - base::TimeTicks()).InSecondsF(); 76 return (time - base::TimeTicks()).InSecondsF();
71 } 77 }
72 78
73 bool ShouldSuppressScrollForFlingBoosting( 79 bool ShouldSuppressScrollForFlingBoosting(
74 const gfx::Vector2dF& current_fling_velocity, 80 const gfx::Vector2dF& current_fling_velocity,
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 blink::WebGestureDevice device) { 222 blink::WebGestureDevice device) {
217 return device == blink::WebGestureDeviceTouchpad 223 return device == blink::WebGestureDeviceTouchpad
218 ? cc::InputHandler::WHEEL 224 ? cc::InputHandler::WHEEL
219 : cc::InputHandler::TOUCHSCREEN; 225 : cc::InputHandler::TOUCHSCREEN;
220 } 226 }
221 227
222 } // namespace 228 } // namespace
223 229
224 namespace ui { 230 namespace ui {
225 231
232 std::unique_ptr<base::TimeTicks> InputHandlerProxy::testing_timestamp_now_ =
233 nullptr;
234
226 InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler, 235 InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
227 InputHandlerProxyClient* client) 236 InputHandlerProxyClient* client)
228 : client_(client), 237 : client_(client),
229 input_handler_(input_handler), 238 input_handler_(input_handler),
230 deferred_fling_cancel_time_seconds_(0), 239 deferred_fling_cancel_time_seconds_(0),
231 synchronous_input_handler_(nullptr), 240 synchronous_input_handler_(nullptr),
232 allow_root_animate_(true), 241 allow_root_animate_(true),
233 #ifndef NDEBUG 242 #ifndef NDEBUG
234 expect_scroll_update_end_(false), 243 expect_scroll_update_end_(false),
235 #endif 244 #endif
236 gesture_scroll_on_impl_thread_(false), 245 gesture_scroll_on_impl_thread_(false),
237 gesture_pinch_on_impl_thread_(false), 246 gesture_pinch_on_impl_thread_(false),
238 fling_may_be_active_on_main_thread_(false), 247 fling_may_be_active_on_main_thread_(false),
239 disallow_horizontal_fling_scroll_(false), 248 disallow_horizontal_fling_scroll_(false),
240 disallow_vertical_fling_scroll_(false), 249 disallow_vertical_fling_scroll_(false),
241 has_fling_animation_started_(false), 250 has_fling_animation_started_(false),
242 smooth_scroll_enabled_(false), 251 smooth_scroll_enabled_(false),
243 uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()), 252 uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()),
244 touch_start_result_(kEventDispositionUndefined), 253 touch_start_result_(kEventDispositionUndefined),
245 current_overscroll_params_(nullptr) { 254 current_overscroll_params_(nullptr),
255 has_ongoing_compositor_scroll_pinch_(false),
256 compositor_event_queue_enabled_(
257 base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)) {
246 DCHECK(client); 258 DCHECK(client);
247 input_handler_->BindToClient(this); 259 input_handler_->BindToClient(this);
248 cc::ScrollElasticityHelper* scroll_elasticity_helper = 260 cc::ScrollElasticityHelper* scroll_elasticity_helper =
249 input_handler_->CreateScrollElasticityHelper(); 261 input_handler_->CreateScrollElasticityHelper();
250 if (scroll_elasticity_helper) { 262 if (scroll_elasticity_helper) {
251 scroll_elasticity_controller_.reset( 263 scroll_elasticity_controller_.reset(
252 new InputScrollElasticityController(scroll_elasticity_helper)); 264 new InputScrollElasticityController(scroll_elasticity_helper));
253 } 265 }
266 if (compositor_event_queue_enabled_) {
267 event_queue_ = base::MakeUnique<CompositorThreadEventQueue>();
dtapuska 2016/11/09 21:28:05 no scope brackets
chongz 2016/11/11 21:52:04 Done.
268 }
254 } 269 }
255 270
256 InputHandlerProxy::~InputHandlerProxy() {} 271 InputHandlerProxy::~InputHandlerProxy() {}
257 272
258 void InputHandlerProxy::WillShutdown() { 273 void InputHandlerProxy::WillShutdown() {
259 scroll_elasticity_controller_.reset(); 274 scroll_elasticity_controller_.reset();
260 input_handler_ = NULL; 275 input_handler_ = NULL;
261 client_->WillShutdown(); 276 client_->WillShutdown();
262 } 277 }
263 278
264 void InputHandlerProxy::HandleInputEventWithLatencyInfo( 279 void InputHandlerProxy::HandleInputEventWithLatencyInfo(
265 ScopedWebInputEvent event, 280 ScopedWebInputEvent event,
266 const LatencyInfo& latency_info, 281 const LatencyInfo& latency_info,
267 const EventDispositionCallback& callback) { 282 const EventDispositionCallback& callback) {
268 DCHECK(input_handler_); 283 DCHECK(input_handler_);
269 284
270 if (uma_latency_reporting_enabled_) 285 if (uma_latency_reporting_enabled_)
271 ReportInputEventLatencyUma(*event, latency_info); 286 ReportInputEventLatencyUma(*event, latency_info);
272 287
273 TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow", 288 TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
274 TRACE_ID_DONT_MANGLE(latency_info.trace_id()), 289 TRACE_ID_DONT_MANGLE(latency_info.trace_id()),
275 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, 290 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
276 "step", "HandleInputEventImpl"); 291 "step", "HandleInputEventImpl");
277 292
278 ui::LatencyInfo monitored_latency_info = latency_info; 293 std::unique_ptr<EventWithCallback> event_with_callback =
294 base::MakeUnique<EventWithCallback>(std::move(event), latency_info,
295 callback);
296
297 if (!compositor_event_queue_enabled_ ||
298 !IsGestureScollOrPinch(event_with_callback->event().type)) {
299 DispatchSingleInputEvent(std::move(event_with_callback));
300 return;
301 }
302
303 if (has_ongoing_compositor_scroll_pinch_) {
304 bool needs_animate_input = event_queue_->empty();
305 event_queue_->Queue(std::move(event_with_callback));
306 if (needs_animate_input)
307 input_handler_->SetNeedsAnimateInput();
308 return;
309 }
310
311 // We have to dispatch the event to know whether the gesture sequence will be
312 // handled by the compositor or not.
313 DispatchSingleInputEvent(std::move(event_with_callback));
314 }
315
316 void InputHandlerProxy::DispatchSingleInputEvent(
317 std::unique_ptr<EventWithCallback> event_with_callback) {
318 if (compositor_event_queue_enabled_ &&
319 IsGestureScollOrPinch(event_with_callback->event().type)) {
320 // Report the coalesced count only for continuous events to avoid the noise
321 // from non-continuous events.
322 base::TimeTicks now = testing_timestamp_now_ ? *testing_timestamp_now_
323 : base::TimeTicks::Now();
324 if (IsContinuousGestureEvent(event_with_callback->event().type)) {
325 UMA_HISTOGRAM_CUSTOM_COUNTS(
326 "Event.CompositorThreadEventQueue.Continuous.HeadQueueingTime",
327 (now - event_with_callback->creationTimestamp()).InMicroseconds(), 1,
328 kTenSeconds, 50);
329
330 UMA_HISTOGRAM_CUSTOM_COUNTS(
331 "Event.CompositorThreadEventQueue.Continuous.TailQueueingTime",
332 (now - event_with_callback->lastCoalescedTimestamp())
333 .InMicroseconds(),
334 1, kTenSeconds, 50);
335
336 UMA_HISTOGRAM_COUNTS_1000(
337 "Event.CompositorThreadEventQueue.CoalescedCount",
338 static_cast<int>(event_with_callback->coalescedCount()));
339 } else {
340 UMA_HISTOGRAM_CUSTOM_COUNTS(
341 "Event.CompositorThreadEventQueue.NonContinuous.QueueingTime",
342 (now - event_with_callback->creationTimestamp()).InMicroseconds(), 1,
343 kTenSeconds, 50);
344 }
345 }
346
347 ui::LatencyInfo monitored_latency_info = event_with_callback->latencyInfo();
279 std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = 348 std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
280 input_handler_->CreateLatencyInfoSwapPromiseMonitor( 349 input_handler_->CreateLatencyInfoSwapPromiseMonitor(
281 &monitored_latency_info); 350 &monitored_latency_info);
282 351
283 current_overscroll_params_.reset(); 352 current_overscroll_params_.reset();
284 InputHandlerProxy::EventDisposition disposition = HandleInputEvent(*event); 353 InputHandlerProxy::EventDisposition disposition =
285 callback.Run(disposition, std::move(event), monitored_latency_info, 354 HandleInputEvent(event_with_callback->event());
286 std::move(current_overscroll_params_)); 355
356 switch (event_with_callback->event().type) {
357 case blink::WebGestureEvent::GestureScrollBegin:
358 case blink::WebGestureEvent::GesturePinchBegin:
359 has_ongoing_compositor_scroll_pinch_ = disposition == DID_HANDLE;
360 break;
361
362 case blink::WebGestureEvent::GestureScrollUpdate:
dtapuska 2016/11/09 21:28:05 Can this be combined with the above cases?
chongz 2016/11/11 21:52:04 Done.
363 case blink::WebGestureEvent::GesturePinchUpdate:
364 has_ongoing_compositor_scroll_pinch_ = disposition == DID_HANDLE;
365 break;
366
367 case blink::WebGestureEvent::GestureScrollEnd:
368 case blink::WebGestureEvent::GesturePinchEnd:
369 has_ongoing_compositor_scroll_pinch_ = false;
370 break;
371 default:
372 break;
373 }
374
375 // Will run callback for every original events.
376 event_with_callback->RunCallbacks(disposition, monitored_latency_info,
377 std::move(current_overscroll_params_));
378 }
379
380 void InputHandlerProxy::DispatchQueuedInputEvents() {
381 if (!compositor_event_queue_enabled_)
382 return;
383
384 while (!event_queue_->empty())
385 DispatchSingleInputEvent(event_queue_->Pop());
287 } 386 }
288 387
289 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( 388 InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
290 const WebInputEvent& event) { 389 const WebInputEvent& event) {
291 DCHECK(input_handler_); 390 DCHECK(input_handler_);
292 391
293 if (FilterInputEventForFlingBoosting(event)) 392 if (FilterInputEventForFlingBoosting(event))
294 return DID_HANDLE; 393 return DID_HANDLE;
295 394
296 switch (event.type) { 395 switch (event.type) {
(...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 float page_scale_factor, 1230 float page_scale_factor,
1132 float min_page_scale_factor, 1231 float min_page_scale_factor,
1133 float max_page_scale_factor) { 1232 float max_page_scale_factor) {
1134 if (synchronous_input_handler_) { 1233 if (synchronous_input_handler_) {
1135 synchronous_input_handler_->UpdateRootLayerState( 1234 synchronous_input_handler_->UpdateRootLayerState(
1136 total_scroll_offset, max_scroll_offset, scrollable_size, 1235 total_scroll_offset, max_scroll_offset, scrollable_size,
1137 page_scale_factor, min_page_scale_factor, max_page_scale_factor); 1236 page_scale_factor, min_page_scale_factor, max_page_scale_factor);
1138 } 1237 }
1139 } 1238 }
1140 1239
1240 void InputHandlerProxy::DeliverInputForBeginFrame() {
1241 DispatchQueuedInputEvents();
1242 }
1243
1141 void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings( 1244 void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings(
1142 SynchronousInputHandler* synchronous_input_handler) { 1245 SynchronousInputHandler* synchronous_input_handler) {
1143 allow_root_animate_ = !synchronous_input_handler; 1246 allow_root_animate_ = !synchronous_input_handler;
1144 synchronous_input_handler_ = synchronous_input_handler; 1247 synchronous_input_handler_ = synchronous_input_handler;
1145 if (synchronous_input_handler_) 1248 if (synchronous_input_handler_)
1146 input_handler_->RequestUpdateForSynchronousInputHandler(); 1249 input_handler_->RequestUpdateForSynchronousInputHandler();
1147 } 1250 }
1148 1251
1149 void InputHandlerProxy::SynchronouslyAnimate(base::TimeTicks time) { 1252 void InputHandlerProxy::SynchronouslyAnimate(base::TimeTicks time) {
1150 // When this function is used, SetOnlySynchronouslyAnimate() should have been 1253 // When this function is used, SetOnlySynchronouslyAnimate() should have been
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 // is made asynchronously, to minimize divergence between main thread and 1519 // is made asynchronously, to minimize divergence between main thread and
1417 // impl thread event handling paths. 1520 // impl thread event handling paths.
1418 base::ThreadTaskRunnerHandle::Get()->PostTask( 1521 base::ThreadTaskRunnerHandle::Get()->PostTask(
1419 FROM_HERE, 1522 FROM_HERE,
1420 base::Bind(&InputScrollElasticityController::ObserveGestureEventAndResult, 1523 base::Bind(&InputScrollElasticityController::ObserveGestureEventAndResult,
1421 scroll_elasticity_controller_->GetWeakPtr(), gesture_event, 1524 scroll_elasticity_controller_->GetWeakPtr(), gesture_event,
1422 scroll_result)); 1525 scroll_result));
1423 } 1526 }
1424 1527
1425 } // namespace ui 1528 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698