summaryrefslogtreecommitdiffstats
path: root/content/renderer
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-23 17:22:40 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-23 17:22:40 +0000
commit5a992e9cc29dabab761193bbbec07c8c40a80acc (patch)
tree333906ffc4700187adccd1613c45f66a398112e8 /content/renderer
parent1847ce79a71a755e276070553eddd08f969d0e43 (diff)
downloadchromium_src-5a992e9cc29dabab761193bbbec07c8c40a80acc.zip
chromium_src-5a992e9cc29dabab761193bbbec07c8c40a80acc.tar.gz
chromium_src-5a992e9cc29dabab761193bbbec07c8c40a80acc.tar.bz2
Only throttle input to the render widget for heavy input handlers
This tracks the total time spent handling input on the main thread for the current frame and only throttles input events once the total time has reached a threshold. If a cheap and reliable HighResNow is not available, the handlers are assumed to be heavy. TEST=Manually run MapsGL in a small window so it hits 60fps. Verified panning tracks pointer more closely when using a 120Hz mouse. Also tested with http://thj.no/personal/latency_test_case.html. This patch produces visibly lower latency and allows the app to receive more mouse move events to produce smoother curves. BUG=305210 Review URL: https://codereview.chromium.org/25687004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230458 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-rw-r--r--content/renderer/render_widget.cc45
-rw-r--r--content/renderer/render_widget.h4
2 files changed, 40 insertions, 9 deletions
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 742557e..76b3fe9 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -141,6 +141,13 @@ ui::TextInputMode ConvertInputMode(
return it->second;
}
+// TODO(brianderson): Replace the hard-coded threshold with a fraction of
+// the BeginMainFrame interval.
+// 4166us will allow 1/4 of a 60Hz interval or 1/2 of a 120Hz interval to
+// be spent in input hanlders before input starts getting throttled.
+static const base::TimeDelta kInputHandlingTimeThrottlingThreshold =
+ base::TimeDelta::FromMicroseconds(4166);
+
} // namespace
namespace content {
@@ -1051,6 +1058,10 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
return;
}
+ base::TimeTicks start_time;
+ if (base::TimeTicks::IsHighResNowFastAndReliable())
+ start_time = base::TimeTicks::HighResNow();
+
const char* const event_name =
WebInputEventTraits::GetName(input_event->type);
TRACE_EVENT1("renderer", "RenderWidget::OnHandleInputEvent",
@@ -1130,7 +1141,7 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
input_event->type,
ack_result,
latency_info);
- bool event_type_gets_rate_limited =
+ bool event_type_can_be_rate_limited =
input_event->type == WebInputEvent::MouseMove ||
input_event->type == WebInputEvent::MouseWheel ||
input_event->type == WebInputEvent::TouchMove;
@@ -1141,9 +1152,23 @@ void RenderWidget::OnHandleInputEvent(const WebKit::WebInputEvent* input_event,
compositor_->commitRequested();
}
- if (event_type_gets_rate_limited && frame_pending && !is_hidden_) {
+ // If we don't have a fast and accurate HighResNow, we assume the input
+ // handlers are heavy and rate limit them.
+ bool rate_limiting_wanted = true;
+ if (base::TimeTicks::IsHighResNowFastAndReliable()) {
+ base::TimeTicks end_time = base::TimeTicks::HighResNow();
+ total_input_handling_time_this_frame_ += (end_time - start_time);
+ rate_limiting_wanted = (total_input_handling_time_this_frame_ >
+ kInputHandlingTimeThrottlingThreshold);
+ }
+
+ if (rate_limiting_wanted && event_type_can_be_rate_limited &&
+ frame_pending && !is_hidden_) {
// We want to rate limit the input events in this case, so we'll wait for
// painting to finish before ACKing this message.
+ TRACE_EVENT_INSTANT0("renderer",
+ "RenderWidget::OnHandleInputEvent ack throttled",
+ TRACE_EVENT_SCOPE_THREAD);
if (pending_input_event_ack_) {
// As two different kinds of events could cause us to postpone an ack
// we send it now, if we have one pending. The Browser should never
@@ -1399,11 +1424,15 @@ void RenderWidget::InvalidationCallback() {
DoDeferredUpdateAndSendInputAck();
}
-void RenderWidget::DoDeferredUpdateAndSendInputAck() {
- DoDeferredUpdate();
-
+void RenderWidget::FlushPendingInputEventAck() {
if (pending_input_event_ack_)
Send(pending_input_event_ack_.release());
+ total_input_handling_time_this_frame_ = base::TimeDelta();
+}
+
+void RenderWidget::DoDeferredUpdateAndSendInputAck() {
+ DoDeferredUpdate();
+ FlushPendingInputEventAck();
}
void RenderWidget::DoDeferredUpdate() {
@@ -1625,8 +1654,7 @@ void RenderWidget::DoDeferredUpdate() {
// UpdateReply message so we can receive another input event before the
// UpdateRect_ACK on platforms where the UpdateRect_ACK is sent from within
// the UpdateRect IPC message handler.
- if (pending_input_event_ack_)
- Send(pending_input_event_ack_.release());
+ FlushPendingInputEventAck();
// If Composite() called SwapBuffers, pending_update_params_ will be reset (in
// OnSwapBuffersPosted), meaning a message has been added to the
@@ -1845,8 +1873,7 @@ void RenderWidget::willBeginCompositorFrame() {
void RenderWidget::didBecomeReadyForAdditionalInput() {
TRACE_EVENT0("renderer", "RenderWidget::didBecomeReadyForAdditionalInput");
- if (pending_input_event_ack_)
- Send(pending_input_event_ack_.release());
+ FlushPendingInputEventAck();
}
void RenderWidget::DidCommitCompositorFrame() {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 1299613..1a14d2c 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -293,6 +293,7 @@ class CONTENT_EXPORT RenderWidget
void AnimationCallback();
void AnimateIfNeeded();
void InvalidationCallback();
+ void FlushPendingInputEventAck();
void DoDeferredUpdateAndSendInputAck();
void DoDeferredUpdate();
void DoDeferredClose();
@@ -712,6 +713,9 @@ class CONTENT_EXPORT RenderWidget
scoped_ptr<IPC::Message> pending_input_event_ack_;
+ // The time spent in input handlers this frame. Used to throttle input acks.
+ base::TimeDelta total_input_handling_time_this_frame_;
+
// Indicates if the next sequence of Char events should be suppressed or not.
bool suppress_next_char_events_;