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

Unified Diff: content/browser/renderer_host/render_widget_host_view_android.cc

Issue 2527283003: cc: Introduce BeginFrame sequence numbers and acknowledgements.
Patch Set: Address Brian's comments. Created 4 years 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 side-by-side diff with in-line comments
Download patch
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) {

Powered by Google App Engine
This is Rietveld 408576698