Commit 03cc3218 authored by jdduke@chromium.org's avatar jdduke@chromium.org

[Android] Consolidate vsync request logic in RWHVAndroid

The current vsync subscription scheme in RWHVAndroid is rather ad-hoc. Formalize
the request logic by creating explicit request types, avoiding redundant vsync
requests (and the associated JNI call) while also enforcing the validity of
such requests (for WebView).

BUG=394604

Review URL: https://codereview.chromium.org/492923002

Cr-Commit-Position: refs/heads/master@{#291296}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291296 0039d316-1c4b-4281-b951-d872f2087c98
parent cf43d43f
...@@ -245,7 +245,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( ...@@ -245,7 +245,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
RenderWidgetHostImpl* widget_host, RenderWidgetHostImpl* widget_host,
ContentViewCoreImpl* content_view_core) ContentViewCoreImpl* content_view_core)
: host_(widget_host), : host_(widget_host),
needs_begin_frame_(false), outstanding_vsync_requests_(0),
is_showing_(!widget_host->is_hidden()), is_showing_(!widget_host->is_hidden()),
content_view_core_(NULL), content_view_core_(NULL),
ime_adapter_android_(this), ime_adapter_android_(this),
...@@ -259,7 +259,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( ...@@ -259,7 +259,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
gesture_text_selector_(this), gesture_text_selector_(this),
touch_scrolling_(false), touch_scrolling_(false),
potentially_active_fling_count_(0), potentially_active_fling_count_(0),
flush_input_requested_(false),
accelerated_surface_route_id_(0), accelerated_surface_route_id_(0),
using_synchronous_compositor_(SynchronousCompositorImpl::FromID( using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
widget_host->GetProcess()->GetID(), widget_host->GetProcess()->GetID(),
...@@ -323,10 +322,9 @@ void RenderWidgetHostViewAndroid::WasShown() { ...@@ -323,10 +322,9 @@ void RenderWidgetHostViewAndroid::WasShown() {
host_->WasShown(ui::LatencyInfo()); host_->WasShown(ui::LatencyInfo());
if (content_view_core_ && !using_synchronous_compositor_) { if (content_view_core_) {
content_view_core_->GetWindowAndroid()->AddObserver(this); StartObservingRootWindow();
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); RequestVSyncUpdate(BEGIN_FRAME);
observing_root_window_ = true;
} }
} }
...@@ -340,10 +338,7 @@ void RenderWidgetHostViewAndroid::WasHidden() { ...@@ -340,10 +338,7 @@ void RenderWidgetHostViewAndroid::WasHidden() {
// utilization. // utilization.
host_->WasHidden(); host_->WasHidden();
if (content_view_core_ && !using_synchronous_compositor_) { StopObservingRootWindow();
content_view_core_->GetWindowAndroid()->RemoveObserver(this);
observing_root_window_ = false;
}
} }
void RenderWidgetHostViewAndroid::WasResized() { void RenderWidgetHostViewAndroid::WasResized() {
...@@ -628,15 +623,13 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor( ...@@ -628,15 +623,13 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
} }
void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) { void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
if (enabled == needs_begin_frame_) DCHECK(!using_synchronous_compositor_);
return;
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame", TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
"enabled", enabled); "enabled", enabled);
if (content_view_core_ && enabled) if (enabled)
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
else
needs_begin_frame_ = enabled; outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
} }
void RenderWidgetHostViewAndroid::OnStartContentIntent( void RenderWidgetHostViewAndroid::OnStartContentIntent(
...@@ -1257,6 +1250,62 @@ void RenderWidgetHostViewAndroid::RemoveLayers() { ...@@ -1257,6 +1250,62 @@ void RenderWidgetHostViewAndroid::RemoveLayers() {
overscroll_effect_->Disable(); overscroll_effect_->Disable();
} }
void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
// The synchronous compositor does not requre BeginFrame messages.
if (using_synchronous_compositor_)
requests &= FLUSH_INPUT;
bool should_request_vsync = !outstanding_vsync_requests_ && requests;
outstanding_vsync_requests_ |= requests;
// Note that if we're not currently observing the root window, outstanding
// vsync requests will be pushed if/when we resume observing in
// |StartObservingRootWindow()|.
if (observing_root_window_ && should_request_vsync)
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
}
void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
DCHECK(content_view_core_);
DCHECK(!observing_root_window_);
observing_root_window_ = true;
content_view_core_->GetWindowAndroid()->AddObserver(this);
// Clear existing vsync requests to allow a request to the new window.
uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
outstanding_vsync_requests_ = 0;
RequestVSyncUpdate(outstanding_vsync_requests);
}
void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
if (!content_view_core_) {
DCHECK(!observing_root_window_);
return;
}
if (!observing_root_window_)
return;
observing_root_window_ = false;
content_view_core_->GetWindowAndroid()->RemoveObserver(this);
}
void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
base::TimeDelta vsync_period) {
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
base::TimeTicks display_time = frame_time + vsync_period;
// TODO(brianderson): Use adaptive draw-time estimation.
base::TimeDelta estimated_browser_composite_time =
base::TimeDelta::FromMicroseconds(
(1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
base::TimeTicks deadline = display_time - estimated_browser_composite_time;
host_->Send(new ViewMsg_BeginFrame(
host_->GetRoutingID(),
cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
}
bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) { bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
bool needs_animate = bool needs_animate =
overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false; overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
...@@ -1405,11 +1454,8 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent( ...@@ -1405,11 +1454,8 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
} }
void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() { void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
if (flush_input_requested_ || !content_view_core_)
return;
TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput"); TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
flush_input_requested_ = true; RequestVSyncUpdate(FLUSH_INPUT);
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
} }
BrowserAccessibilityManager* BrowserAccessibilityManager*
...@@ -1450,9 +1496,8 @@ void RenderWidgetHostViewAndroid::SendTouchEvent( ...@@ -1450,9 +1496,8 @@ void RenderWidgetHostViewAndroid::SendTouchEvent(
// This is good enough as long as the first touch event has Begin semantics // This is good enough as long as the first touch event has Begin semantics
// and the actual scroll happens on the next vsync. // and the actual scroll happens on the next vsync.
// TODO: Is this actually still needed? // TODO: Is this actually still needed?
if (content_view_core_ && observing_root_window_) { if (observing_root_window_)
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); RequestVSyncUpdate(BEGIN_FRAME);
}
} }
void RenderWidgetHostViewAndroid::SendMouseEvent( void RenderWidgetHostViewAndroid::SendMouseEvent(
...@@ -1548,10 +1593,7 @@ void RenderWidgetHostViewAndroid::DidStopFlinging() { ...@@ -1548,10 +1593,7 @@ void RenderWidgetHostViewAndroid::DidStopFlinging() {
void RenderWidgetHostViewAndroid::SetContentViewCore( void RenderWidgetHostViewAndroid::SetContentViewCore(
ContentViewCoreImpl* content_view_core) { ContentViewCoreImpl* content_view_core) {
RemoveLayers(); RemoveLayers();
if (observing_root_window_ && content_view_core_) { StopObservingRootWindow();
content_view_core_->GetWindowAndroid()->RemoveObserver(this);
observing_root_window_ = false;
}
bool resize = false; bool resize = false;
if (content_view_core != content_view_core_) { if (content_view_core != content_view_core_) {
...@@ -1577,12 +1619,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore( ...@@ -1577,12 +1619,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
if (!content_view_core_) if (!content_view_core_)
return; return;
if (!using_synchronous_compositor_) { StartObservingRootWindow();
content_view_core_->GetWindowAndroid()->AddObserver(this);
observing_root_window_ = true;
if (needs_begin_frame_)
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
}
if (resize) if (resize)
WasResized(); WasResized();
...@@ -1627,27 +1664,19 @@ void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, ...@@ -1627,27 +1664,19 @@ void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
if (!host_) if (!host_)
return; return;
if (flush_input_requested_) { const uint32 current_vsync_requests = outstanding_vsync_requests_;
flush_input_requested_ = false; outstanding_vsync_requests_ = 0;
host_->FlushInput();
}
TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
base::TimeTicks display_time = frame_time + vsync_period;
// TODO(brianderson): Use adaptive draw-time estimation.
base::TimeDelta estimated_browser_composite_time =
base::TimeDelta::FromMicroseconds(
(1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
base::TimeTicks deadline = display_time - estimated_browser_composite_time; if (current_vsync_requests & FLUSH_INPUT)
host_->FlushInput();
host_->Send(new ViewMsg_BeginFrame( if (current_vsync_requests & BEGIN_FRAME ||
host_->GetRoutingID(), current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period))); SendBeginFrame(frame_time, vsync_period);
}
if (needs_begin_frame_) if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
content_view_core_->GetWindowAndroid()->RequestVSyncUpdate(); RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
} }
void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) { void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
......
...@@ -332,6 +332,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -332,6 +332,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void InternalSwapCompositorFrame(uint32 output_surface_id, void InternalSwapCompositorFrame(uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame); scoped_ptr<cc::CompositorFrame> frame);
enum VSyncRequestType {
FLUSH_INPUT = 1 << 0,
BEGIN_FRAME = 1 << 1,
PERSISTENT_BEGIN_FRAME = 1 << 2
};
void RequestVSyncUpdate(uint32 requests);
void StartObservingRootWindow();
void StopObservingRootWindow();
void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period);
bool Animate(base::TimeTicks frame_time); bool Animate(base::TimeTicks frame_time);
void OnContentScrollingChange(); void OnContentScrollingChange();
...@@ -345,8 +354,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -345,8 +354,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// The model object. // The model object.
RenderWidgetHostImpl* host_; RenderWidgetHostImpl* host_;
// Used to track whether this render widget needs a BeginFrame. // Used to control action dispatch at the next |OnVSync()| call.
bool needs_begin_frame_; uint32 outstanding_vsync_requests_;
bool is_showing_; bool is_showing_;
...@@ -392,8 +401,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -392,8 +401,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
bool touch_scrolling_; bool touch_scrolling_;
size_t potentially_active_fling_count_; size_t potentially_active_fling_count_;
bool flush_input_requested_;
int accelerated_surface_route_id_; int accelerated_surface_route_id_;
// Size to use if we have no backing ContentViewCore // Size to use if we have no backing ContentViewCore
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment