Index: content/browser/renderer_host/render_widget_host_view_android.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc |
index 60078386bb068c281f82bf56a7bf23718125a432..0e0e5539d4ee68e5308e3d104eba5546c689de01 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_android.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc |
@@ -76,7 +76,6 @@ |
#include "third_party/khronos/GLES2/gl2.h" |
#include "third_party/khronos/GLES2/gl2ext.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
-#include "ui/android/delegated_frame_host_android.h" |
#include "ui/android/window_android.h" |
#include "ui/android/window_android_compositor.h" |
#include "ui/base/layout.h" |
@@ -438,7 +437,8 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( |
RenderWidgetHostImpl* widget_host, |
ContentViewCoreImpl* content_view_core) |
: host_(widget_host), |
- outstanding_vsync_requests_(0), |
+ begin_frame_source_(nullptr), |
+ outstanding_begin_frame_requests_(0), |
is_showing_(!widget_host->is_hidden()), |
is_window_visible_(true), |
is_window_activity_started_(true), |
@@ -462,9 +462,7 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( |
view_.SetLayer(cc::Layer::Create()); |
if (using_browser_compositor_) { |
delegated_frame_host_.reset(new ui::DelegatedFrameHostAndroid( |
- &view_, cached_background_color_, |
- base::Bind(&RenderWidgetHostViewAndroid::ReturnResources, |
- weak_ptr_factory_.GetWeakPtr()))); |
+ &view_, cached_background_color_, this)); |
} |
host_->SetView(this); |
@@ -802,9 +800,9 @@ void RenderWidgetHostViewAndroid::SetNeedsBeginFrames(bool needs_begin_frames) { |
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SetNeedsBeginFrames", |
"needs_begin_frames", needs_begin_frames); |
if (needs_begin_frames) |
- RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME); |
+ AddBeginFrameRequest(PERSISTENT_BEGIN_FRAME); |
else |
- outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME; |
+ ClearBeginFrameRequest(PERSISTENT_BEGIN_FRAME); |
} |
void RenderWidgetHostViewAndroid::OnStartContentIntent( |
@@ -854,11 +852,11 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent( |
host_->ForwardTouchEventWithLatencyInfo(web_event, latency_info); |
// Send a proactive BeginFrame for this vsync to reduce scroll latency for |
- // scroll-inducing touch events. Note that Android's Choreographer ensures |
- // that BeginFrame requests made during ACTION_MOVE dispatch will be honored |
- // in the same vsync phase. |
+ // scroll-inducing touch events. Note that even if we weren't observing the |
+ // BeginFrameSource prior to this, we will receive a (missed) BeginFrame for |
+ // the current vsync phase. |
if (observing_root_window_ && result.moved_beyond_slop_region) |
- RequestVSyncUpdate(BEGIN_FRAME); |
+ AddBeginFrameRequest(BEGIN_FRAME); |
return true; |
} |
@@ -1155,7 +1153,24 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() { |
void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( |
uint32_t compositor_frame_sink_id, |
cc::CompositorFrame frame) { |
+ uint64_t begin_frame_source_id = frame.metadata.begin_frame_source_id; |
+ uint64_t begin_frame_number = frame.metadata.begin_frame_number; |
+ uint64_t latest_confirmed_frame = frame.metadata.latest_confirmed_frame; |
+ |
InternalSwapCompositorFrame(compositor_frame_sink_id, std::move(frame)); |
+ |
+ // DelegatedFrameHostAndroid always submits a frame. |
+ bool has_damage = true; |
+ cc::BeginFrameAck ack(begin_frame_source_id, begin_frame_number, |
+ latest_confirmed_frame, 0, has_damage); |
+ if (begin_frame_source_) |
+ begin_frame_source_->DidFinishFrame(this, ack); |
+} |
+ |
+void RenderWidgetHostViewAndroid::OnBeginFrameDidNotDraw( |
+ const cc::BeginFrameAck& ack) { |
+ if (begin_frame_source_) |
+ begin_frame_source_->DidFinishFrame(this, ack); |
} |
void RenderWidgetHostViewAndroid::ClearCompositorFrame() { |
@@ -1384,9 +1399,9 @@ void RenderWidgetHostViewAndroid::ShowInternal() { |
host_->WasShown(ui::LatencyInfo()); |
- if (content_view_core_) { |
+ if (content_view_core_ && view_.GetWindowAndroid()) { |
StartObservingRootWindow(); |
- RequestVSyncUpdate(BEGIN_FRAME); |
+ AddBeginFrameRequest(BEGIN_FRAME); |
} |
} |
@@ -1429,29 +1444,52 @@ void RenderWidgetHostViewAndroid::HideInternal() { |
host_->WasHidden(); |
} |
-void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32_t requests) { |
- bool should_request_vsync = !outstanding_vsync_requests_ && requests; |
- outstanding_vsync_requests_ |= requests; |
+void RenderWidgetHostViewAndroid::SetBeginFrameSource( |
+ cc::BeginFrameSource* begin_frame_source) { |
+ if (begin_frame_source_ == begin_frame_source) |
+ return; |
+ |
+ if (begin_frame_source_ && outstanding_begin_frame_requests_) |
+ begin_frame_source_->RemoveObserver(this); |
+ begin_frame_source_ = begin_frame_source; |
+ if (begin_frame_source_ && outstanding_begin_frame_requests_) |
+ begin_frame_source_->AddObserver(this); |
+} |
+ |
+void RenderWidgetHostViewAndroid::AddBeginFrameRequest( |
+ BeginFrameRequestType request) { |
+ DCHECK(this); |
+ uint32_t requests = outstanding_begin_frame_requests_ | request; |
- // 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) { |
+ // Note that if we don't currently have a BeginFrameSource, outstanding begin |
+ // frame requests will be pushed if/when we get one during |
+ // |StartObservingRootWindow()| or when the DelegatedFrameHostAndroid sets it. |
+ cc::BeginFrameSource* source = begin_frame_source_; |
+ if (source && requests && !outstanding_begin_frame_requests_) { |
ui::WindowAndroid* windowAndroid = view_.GetWindowAndroid(); |
DCHECK(windowAndroid); |
- // TODO(boliu): This check should be redundant with |
- // |observing_root_window_| check above. However we are receiving trickle |
- // of crash reports (crbug.com/639868) with no root cause. Should |
- // investigate more when time allows what corner case is missed. |
+ // TODO(boliu): This check should be redundant with |source| check above. |
+ // However, there seem to be cases where we are not notified of window |
+ // destruction, which invalidates the BeginFrameSource. See also related |
+ // crash reports in crbug.com/639868. |
if (windowAndroid) |
- windowAndroid->RequestVSyncUpdate(); |
+ source->AddObserver(this); |
} |
+ outstanding_begin_frame_requests_ = requests; |
+} |
+ |
+void RenderWidgetHostViewAndroid::ClearBeginFrameRequest( |
+ BeginFrameRequestType request) { |
+ uint32_t requests = outstanding_begin_frame_requests_ & ~request; |
+ |
+ cc::BeginFrameSource* source = begin_frame_source_; |
+ if (source && !requests && outstanding_begin_frame_requests_) |
+ source->RemoveObserver(this); |
+ outstanding_begin_frame_requests_ = requests; |
} |
void RenderWidgetHostViewAndroid::StartObservingRootWindow() { |
DCHECK(content_view_core_); |
- // TODO(yusufo): This will need to have a better fallback for cases where |
- // setContentViewCore is called with a valid ContentViewCore without a window. |
DCHECK(view_.GetWindowAndroid()); |
DCHECK(is_showing_); |
if (observing_root_window_) |
@@ -1461,11 +1499,9 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() { |
if (host_) |
host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), false)); |
view_.GetWindowAndroid()->AddObserver(this); |
- |
- // Clear existing vsync requests to allow a request to the new window. |
- uint32_t outstanding_vsync_requests = outstanding_vsync_requests_; |
- outstanding_vsync_requests_ = 0; |
- RequestVSyncUpdate(outstanding_vsync_requests); |
+ // When using browser compositor, DelegatedFrameHostAndroid provides the BFS. |
+ if (!using_browser_compositor_) |
+ SetBeginFrameSource(view_.GetWindowAndroid()->GetBeginFrameSource()); |
ui::WindowAndroidCompositor* compositor = |
view_.GetWindowAndroid()->GetCompositor(); |
@@ -1491,26 +1527,26 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() { |
if (host_) |
host_->Send(new ViewMsg_SetBeginFramePaused(host_->GetRoutingID(), true)); |
view_.GetWindowAndroid()->RemoveObserver(this); |
+ if (!using_browser_compositor_) |
+ SetBeginFrameSource(nullptr); |
// If the DFH has already been destroyed, it will have cleaned itself up. |
// This happens in some WebView cases. |
if (delegated_frame_host_) |
delegated_frame_host_->UnregisterFrameSinkHierarchy(); |
+ DCHECK_EQ(nullptr, begin_frame_source_); |
} |
-void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time, |
- base::TimeDelta vsync_period) { |
- TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame", |
- "frame_time_us", frame_time.ToInternalValue()); |
+void RenderWidgetHostViewAndroid::SendBeginFrame(cc::BeginFrameArgs args) { |
+ TRACE_EVENT2("cc", "RenderWidgetHostViewAndroid::SendBeginFrame", |
+ "frame_number", args.sequence_number, |
+ "frame_time_us", args.frame_time.ToInternalValue()); |
// Synchronous compositor does not use deadline-based scheduling. |
// TODO(brianderson): Replace this hardcoded deadline after Android |
- // switches to Surfaces and the Browser's commit isn't in the critcal path. |
- base::TimeTicks deadline = |
- sync_compositor_ ? base::TimeTicks() : frame_time + (vsync_period * 0.6); |
- host_->Send(new ViewMsg_BeginFrame( |
- host_->GetRoutingID(), |
- cc::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline, |
- vsync_period, cc::BeginFrameArgs::NORMAL))); |
+ // switches to Surfaces and the Browser's commit isn't in the critical path. |
+ args.deadline = sync_compositor_ ? base::TimeTicks() |
+ : args.frame_time + (args.interval * 0.6); |
+ host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args)); |
if (sync_compositor_) |
sync_compositor_->DidSendBeginFrame(view_.GetWindowAndroid()); |
} |
@@ -1624,7 +1660,7 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent( |
void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() { |
TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput"); |
- RequestVSyncUpdate(FLUSH_INPUT); |
+ AddBeginFrameRequest(FLUSH_INPUT); |
} |
BrowserAccessibilityManager* |
@@ -1807,7 +1843,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore( |
return; |
} |
- if (is_showing_) |
+ if (is_showing_ && view_.GetWindowAndroid()) |
StartObservingRootWindow(); |
if (resize) |
@@ -1888,10 +1924,12 @@ void RenderWidgetHostViewAndroid::OnAttachCompositor() { |
if (!overscroll_controller_) |
overscroll_controller_ = CreateOverscrollController( |
content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView())); |
- ui::WindowAndroidCompositor* compositor = |
- view_.GetWindowAndroid()->GetCompositor(); |
- delegated_frame_host_->RegisterFrameSinkHierarchy( |
- compositor->GetFrameSinkId()); |
+ if (observing_root_window_) { |
+ ui::WindowAndroidCompositor* compositor = |
+ view_.GetWindowAndroid()->GetCompositor(); |
+ delegated_frame_host_->RegisterFrameSinkHierarchy( |
+ compositor->GetFrameSinkId()); |
+ } |
} |
void RenderWidgetHostViewAndroid::OnDetachCompositor() { |
@@ -1902,28 +1940,41 @@ void RenderWidgetHostViewAndroid::OnDetachCompositor() { |
delegated_frame_host_->UnregisterFrameSinkHierarchy(); |
} |
-void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, |
- base::TimeDelta vsync_period) { |
- TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync"); |
+void RenderWidgetHostViewAndroid::OnBeginFrame(const cc::BeginFrameArgs& args) { |
+ TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnBeginFrame"); |
if (!host_) |
return; |
- if (outstanding_vsync_requests_ & FLUSH_INPUT) { |
- outstanding_vsync_requests_ &= ~FLUSH_INPUT; |
+ // In sync mode, we disregard missed frame args to ensure that |
+ // SynchronousCompositorBrowserFilter::SyncStateAfterVSync will be called |
+ // during an OnVSync() observer iteration. |
+ if (sync_compositor_ && args.type == cc::BeginFrameArgs::MISSED) |
+ return; |
+ |
+ if (outstanding_begin_frame_requests_ & FLUSH_INPUT) { |
+ ClearBeginFrameRequest(FLUSH_INPUT); |
host_->FlushInput(); |
} |
- if (outstanding_vsync_requests_ & BEGIN_FRAME || |
- outstanding_vsync_requests_ & PERSISTENT_BEGIN_FRAME) { |
- outstanding_vsync_requests_ &= ~BEGIN_FRAME; |
- SendBeginFrame(frame_time, vsync_period); |
+ if ((outstanding_begin_frame_requests_ & BEGIN_FRAME) || |
+ (outstanding_begin_frame_requests_ & PERSISTENT_BEGIN_FRAME)) { |
+ ClearBeginFrameRequest(BEGIN_FRAME); |
+ SendBeginFrame(args); |
} |
- // This allows for SendBeginFrame and FlushInput to modify |
- // outstanding_vsync_requests. |
- uint32_t outstanding_vsync_requests = outstanding_vsync_requests_; |
- outstanding_vsync_requests_ = 0; |
- RequestVSyncUpdate(outstanding_vsync_requests); |
+ last_begin_frame_args_ = args; |
+} |
+ |
+const cc::BeginFrameArgs& RenderWidgetHostViewAndroid::LastUsedBeginFrameArgs() |
+ const { |
+ return last_begin_frame_args_; |
+} |
+ |
+void RenderWidgetHostViewAndroid::OnBeginFrameSourcePausedChanged(bool paused) { |
+ // The BeginFrameSources we listen to don't use this. For WebView, we signal |
+ // the "paused" state to the RenderWidget when our window attaches/detaches, |
+ // see |StartObservingRootWindow()| and |StopObservingRootWindow()|. |
+ DCHECK(!paused); |
} |
void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) { |