| 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 9959a73d73a619d001f4ce9db679d67bf30a27a0..cc1d26880258674da88c599cf8d750fa1455077d 100644
|
| --- a/content/browser/renderer_host/render_widget_host_view_android.cc
|
| +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
|
| @@ -77,7 +77,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"
|
| @@ -432,7 +431,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),
|
| @@ -457,9 +457,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);
|
| @@ -799,9 +797,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::OnPhysicalBackingSizeChanged(int width,
|
| @@ -860,7 +858,7 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
|
| // that BeginFrame requests made during ACTION_MOVE dispatch will be honored
|
| // in the same vsync phase.
|
| if (observing_root_window_ && result.moved_beyond_slop_region)
|
| - RequestVSyncUpdate(BEGIN_FRAME);
|
| + AddBeginFrameRequest(BEGIN_FRAME);
|
|
|
| return true;
|
| }
|
| @@ -1391,9 +1389,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);
|
| }
|
| }
|
|
|
| @@ -1436,29 +1434,43 @@ void RenderWidgetHostViewAndroid::HideInternal() {
|
| host_->WasHidden();
|
| }
|
|
|
| -void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32_t requests) {
|
| - 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) {
|
| - 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.
|
| - if (windowAndroid)
|
| - windowAndroid->RequestVSyncUpdate();
|
| - }
|
| +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) {
|
| + uint32_t prior_requests = outstanding_begin_frame_requests_;
|
| + outstanding_begin_frame_requests_ = prior_requests | request;
|
| +
|
| + // 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 && outstanding_begin_frame_requests_ && !prior_requests)
|
| + source->AddObserver(this);
|
| +}
|
| +
|
| +void RenderWidgetHostViewAndroid::ClearBeginFrameRequest(
|
| + BeginFrameRequestType request) {
|
| + uint32_t prior_requests = outstanding_begin_frame_requests_;
|
| + outstanding_begin_frame_requests_ = prior_requests & ~request;
|
| +
|
| + cc::BeginFrameSource* source = begin_frame_source_;
|
| + if (source && !outstanding_begin_frame_requests_ && prior_requests)
|
| + source->RemoveObserver(this);
|
| }
|
|
|
| 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_)
|
| @@ -1468,11 +1480,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();
|
| @@ -1498,26 +1508,25 @@ 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(!begin_frame_source_);
|
| }
|
|
|
| -void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
|
| - base::TimeDelta vsync_period) {
|
| +void RenderWidgetHostViewAndroid::SendBeginFrame(cc::BeginFrameArgs args) {
|
| TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
|
| - "frame_time_us", frame_time.ToInternalValue());
|
| + "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());
|
| }
|
| @@ -1631,7 +1640,7 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
|
|
|
| void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
|
| TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
|
| - RequestVSyncUpdate(FLUSH_INPUT);
|
| + AddBeginFrameRequest(FLUSH_INPUT);
|
| }
|
|
|
| BrowserAccessibilityManager*
|
| @@ -1813,7 +1822,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
|
| return;
|
| }
|
|
|
| - if (is_showing_)
|
| + if (is_showing_ && view_.GetWindowAndroid())
|
| StartObservingRootWindow();
|
|
|
| if (resize)
|
| @@ -1889,10 +1898,12 @@ void RenderWidgetHostViewAndroid::OnDetachedFromWindow() {
|
| void RenderWidgetHostViewAndroid::OnAttachCompositor() {
|
| DCHECK(content_view_core_);
|
| CreateOverscrollControllerIfPossible();
|
| - 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() {
|
| @@ -1903,28 +1914,48 @@ 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 WindowAndroid::WindowBeginFrameSource::OnVSync() observer iteration.
|
| + if (sync_compositor_ && args.type == cc::BeginFrameArgs::MISSED)
|
| + return;
|
| +
|
| + // Update |last_begin_frame_args_| before handling
|
| + // |outstanding_begin_frame_requests_| to prevent the BeginFrameSource from
|
| + // sending the same MISSED args in infinite recursion. This may otherwise
|
| + // happen if |host_->FlushInput()| causes a synchronous OnSetNeedsFlushInput()
|
| + // which can lead to |begin_frame_source_->AddObserver()| and OnBeginFrame().
|
| + // By setting |last_begin_frame_args_|, we indicate to the source not to send
|
| + // the same args during |AddObserver()| again.
|
| + last_begin_frame_args_ = args;
|
| +
|
| + 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);
|
| }
|
| +}
|
| +
|
| +const cc::BeginFrameArgs& RenderWidgetHostViewAndroid::LastUsedBeginFrameArgs()
|
| + const {
|
| + return last_begin_frame_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);
|
| +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) {
|
|
|