Commit 0e58f2ca authored by Sahel Sharify's avatar Sahel Sharify Committed by Commit Bot

Register fling scheduler on GSB instead of GFS.

Registering the FlingScheduler after processing a GFS causes a frame of
jank at the beginning of the fling. This is because the first OnAnimationStep
call after observer's registration might be missing and/or incorrectly have
the timestamp of the last begin frame before the observer's registration
rather than the first begin frame after the registration.

To avoid this issue, in this cl we register the observer on GSB instead of GFS
so that the potential missing/incorrect OnAnimationStep call passes by the time
that the GFS is processed. We unregister the observer on GSE instead of when
the fling stops since not all GSBs are followed by GFS events.

Bug: 882907
Test: GestureEventQueueWithCompositorEventQueueTest.FlingSchedulerOpbserverRegisteredOnGSB
Change-Id: I149469fce31c9146c7282bee5cba7152ee65b1ea
Reviewed-on: https://chromium-review.googlesource.com/c/1313270Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Commit-Queue: Sahel Sharify <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604707}
parent b25a21ec
...@@ -197,7 +197,7 @@ void FlingController::ProcessGestureFlingStart( ...@@ -197,7 +197,7 @@ void FlingController::ProcessGestureFlingStart(
} }
void FlingController::ScheduleFlingProgress() { void FlingController::ScheduleFlingProgress() {
scheduler_client_->ScheduleFlingProgress(weak_ptr_factory_.GetWeakPtr()); scheduler_client_->ScheduleFlingProgress();
} }
void FlingController::ProcessGestureFlingCancel( void FlingController::ProcessGestureFlingCancel(
...@@ -417,7 +417,7 @@ void FlingController::CancelCurrentFling() { ...@@ -417,7 +417,7 @@ void FlingController::CancelCurrentFling() {
} }
if (had_active_fling) { if (had_active_fling) {
scheduler_client_->DidStopFlingingOnBrowser(weak_ptr_factory_.GetWeakPtr()); scheduler_client_->DidStopFlingingOnBrowser();
TRACE_EVENT_ASYNC_END0("input", kFlingTraceName, this); TRACE_EVENT_ASYNC_END0("input", kFlingTraceName, this);
} }
} }
...@@ -449,6 +449,15 @@ bool FlingController::UpdateCurrentFlingState( ...@@ -449,6 +449,15 @@ bool FlingController::UpdateCurrentFlingState(
return true; return true;
} }
void FlingController::RegisterFlingSchedulerObserver() {
scheduler_client_->RegisterFlingSchedulerObserver(
weak_ptr_factory_.GetWeakPtr());
}
void FlingController::UnregisterFlingSchedulerObserver() {
scheduler_client_->UnregisterFlingSchedulerObserver();
}
bool FlingController::FlingCancellationIsDeferred() const { bool FlingController::FlingCancellationIsDeferred() const {
return fling_booster_ && fling_booster_->fling_cancellation_is_deferred(); return fling_booster_ && fling_booster_->fling_cancellation_is_deferred();
} }
......
...@@ -39,12 +39,15 @@ class CONTENT_EXPORT FlingControllerSchedulerClient { ...@@ -39,12 +39,15 @@ class CONTENT_EXPORT FlingControllerSchedulerClient {
public: public:
virtual ~FlingControllerSchedulerClient() {} virtual ~FlingControllerSchedulerClient() {}
virtual void ScheduleFlingProgress( virtual void ScheduleFlingProgress() = 0;
base::WeakPtr<FlingController> fling_controller) = 0;
virtual void DidStopFlingingOnBrowser( virtual void RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) = 0; base::WeakPtr<FlingController> fling_controller) = 0;
virtual void UnregisterFlingSchedulerObserver() = 0;
virtual void DidStopFlingingOnBrowser() = 0;
virtual bool NeedsBeginFrameForFlingProgress() = 0; virtual bool NeedsBeginFrameForFlingProgress() = 0;
}; };
...@@ -100,6 +103,19 @@ class CONTENT_EXPORT FlingController { ...@@ -100,6 +103,19 @@ class CONTENT_EXPORT FlingController {
gfx::Vector2dF CurrentFlingVelocity() const; gfx::Vector2dF CurrentFlingVelocity() const;
// Registering the FlingScheduler after processing a GFS causes a frame of
// jank at the beginning of the fling (see https://crbug.com/882907). This is
// because the first OnAnimationStep call after observer's registration might
// be missing and/or incorrectly have the timestamp of the last begin frame
// before the observer's registration rather than the first begin frame after
// the registration (https://crbug.com/848796). To avoid this issue we
// register the observer on GSB instead of GFS so that the potential
// missing/incorrect OnAnimationStep call passes by the time that the GFS is
// processed. We unregister the observer on GSE instead of when the fling
// stops since not all GSBs are followed by GFS events.
void RegisterFlingSchedulerObserver();
void UnregisterFlingSchedulerObserver();
// Returns the |TouchpadTapSuppressionController| instance. // Returns the |TouchpadTapSuppressionController| instance.
TouchpadTapSuppressionController* GetTouchpadTapSuppressionController(); TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
......
...@@ -69,15 +69,16 @@ class FlingControllerTest : public FlingControllerEventSenderClient, ...@@ -69,15 +69,16 @@ class FlingControllerTest : public FlingControllerEventSenderClient,
} }
// FlingControllerSchedulerClient // FlingControllerSchedulerClient
void ScheduleFlingProgress( void ScheduleFlingProgress() override {
base::WeakPtr<FlingController> fling_controller) override {
DCHECK(!scheduled_next_fling_progress_); DCHECK(!scheduled_next_fling_progress_);
scheduled_next_fling_progress_ = true; scheduled_next_fling_progress_ = true;
} }
void DidStopFlingingOnBrowser( void DidStopFlingingOnBrowser() override {
base::WeakPtr<FlingController> fling_controller) override {
notified_client_after_fling_stop_ = true; notified_client_after_fling_stop_ = true;
} }
void RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) override {}
void UnregisterFlingSchedulerObserver() override {}
bool NeedsBeginFrameForFlingProgress() override { bool NeedsBeginFrameForFlingProgress() override {
return needs_begin_frame_for_fling_progress_; return needs_begin_frame_for_fling_progress_;
} }
......
...@@ -24,31 +24,39 @@ FlingScheduler::~FlingScheduler() { ...@@ -24,31 +24,39 @@ FlingScheduler::~FlingScheduler() {
observed_compositor_->RemoveAnimationObserver(this); observed_compositor_->RemoveAnimationObserver(this);
} }
void FlingScheduler::ScheduleFlingProgress( void FlingScheduler::ScheduleFlingProgress() {
base::WeakPtr<FlingController> fling_controller) {
DCHECK(fling_controller);
fling_controller_ = fling_controller;
// Don't do anything if a ui::Compositor is already being observed. // Don't do anything if a ui::Compositor is already being observed.
if (observed_compositor_) if (observed_compositor_)
return; return;
host_->SetNeedsBeginFrameForFlingProgress();
}
void FlingScheduler::RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) {
DCHECK(fling_controller);
fling_controller_ = fling_controller;
DCHECK(!observed_compositor_);
ui::Compositor* compositor = GetCompositor(); ui::Compositor* compositor = GetCompositor();
// If a ui::Compositor can't be obtained, ask the host for BeginFrames. // If a ui::Compositor can't be obtained, ask the host for BeginFrames.
if (!compositor) { if (!compositor)
host_->SetNeedsBeginFrameForFlingProgress();
return; return;
}
compositor->AddAnimationObserver(this); compositor->AddAnimationObserver(this);
observed_compositor_ = compositor; observed_compositor_ = compositor;
} }
void FlingScheduler::DidStopFlingingOnBrowser( void FlingScheduler::UnregisterFlingSchedulerObserver() {
base::WeakPtr<FlingController> fling_controller) {
DCHECK(fling_controller);
if (observed_compositor_) { if (observed_compositor_) {
observed_compositor_->RemoveAnimationObserver(this); observed_compositor_->RemoveAnimationObserver(this);
observed_compositor_ = nullptr; observed_compositor_ = nullptr;
} }
fling_controller_ = nullptr; fling_controller_ = nullptr;
}
void FlingScheduler::DidStopFlingingOnBrowser() {
UnregisterFlingSchedulerObserver();
host_->DidStopFlinging(); host_->DidStopFlinging();
} }
......
...@@ -24,10 +24,11 @@ class CONTENT_EXPORT FlingScheduler : public FlingSchedulerBase, ...@@ -24,10 +24,11 @@ class CONTENT_EXPORT FlingScheduler : public FlingSchedulerBase,
~FlingScheduler() override; ~FlingScheduler() override;
// FlingControllerSchedulerClient // FlingControllerSchedulerClient
void ScheduleFlingProgress( void ScheduleFlingProgress() override;
base::WeakPtr<FlingController> fling_controller) override; void RegisterFlingSchedulerObserver(
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override; base::WeakPtr<FlingController> fling_controller) override;
void UnregisterFlingSchedulerObserver() override;
void DidStopFlingingOnBrowser() override;
bool NeedsBeginFrameForFlingProgress() override; bool NeedsBeginFrameForFlingProgress() override;
// FlingSchedulerBase // FlingSchedulerBase
......
...@@ -20,33 +20,41 @@ FlingSchedulerAndroid::~FlingSchedulerAndroid() { ...@@ -20,33 +20,41 @@ FlingSchedulerAndroid::~FlingSchedulerAndroid() {
observed_window_->RemoveObserver(this); observed_window_->RemoveObserver(this);
} }
void FlingSchedulerAndroid::ScheduleFlingProgress( void FlingSchedulerAndroid::ScheduleFlingProgress() {
base::WeakPtr<FlingController> fling_controller) {
DCHECK(fling_controller);
fling_controller_ = fling_controller;
if (!observed_window_) { if (!observed_window_) {
ui::WindowAndroid* window = GetRootWindow();
// If the root window does not have a Compositor (happens on Android // If the root window does not have a Compositor (happens on Android
// WebView), we'll never receive an OnAnimate call. In this case fall back // WebView), we'll never receive an OnAnimate call. In this case fall back
// to BeginFrames coming from the host. // to BeginFrames coming from the host.
if (!window || !window->GetCompositor()) { host_->SetNeedsBeginFrameForFlingProgress();
host_->SetNeedsBeginFrameForFlingProgress(); return;
return;
}
window->AddObserver(this);
observed_window_ = window;
} }
observed_window_->SetNeedsAnimate(); observed_window_->SetNeedsAnimate();
} }
void FlingSchedulerAndroid::DidStopFlingingOnBrowser( void FlingSchedulerAndroid::RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) { base::WeakPtr<FlingController> fling_controller) {
DCHECK(fling_controller); DCHECK(fling_controller);
fling_controller_ = fling_controller;
DCHECK(!observed_window_);
ui::WindowAndroid* window = GetRootWindow();
if (!window || !window->GetCompositor())
return;
window->AddObserver(this);
observed_window_ = window;
}
void FlingSchedulerAndroid::UnregisterFlingSchedulerObserver() {
if (observed_window_) { if (observed_window_) {
observed_window_->RemoveObserver(this); observed_window_->RemoveObserver(this);
observed_window_ = nullptr; observed_window_ = nullptr;
} }
fling_controller_ = nullptr; fling_controller_ = nullptr;
}
void FlingSchedulerAndroid::DidStopFlingingOnBrowser() {
UnregisterFlingSchedulerObserver();
host_->DidStopFlinging(); host_->DidStopFlinging();
} }
......
...@@ -21,10 +21,11 @@ class CONTENT_EXPORT FlingSchedulerAndroid : public FlingSchedulerBase, ...@@ -21,10 +21,11 @@ class CONTENT_EXPORT FlingSchedulerAndroid : public FlingSchedulerBase,
~FlingSchedulerAndroid() override; ~FlingSchedulerAndroid() override;
// FlingControllerSchedulerClient // FlingControllerSchedulerClient
void ScheduleFlingProgress( void ScheduleFlingProgress() override;
base::WeakPtr<FlingController> fling_controller) override; void RegisterFlingSchedulerObserver(
void DidStopFlingingOnBrowser(
base::WeakPtr<FlingController> fling_controller) override; base::WeakPtr<FlingController> fling_controller) override;
void UnregisterFlingSchedulerObserver() override;
void DidStopFlingingOnBrowser() override;
bool NeedsBeginFrameForFlingProgress() override; bool NeedsBeginFrameForFlingProgress() override;
// FlingSchedulerBase // FlingSchedulerBase
......
...@@ -18,15 +18,13 @@ class FakeFlingScheduler : public FlingScheduler { ...@@ -18,15 +18,13 @@ class FakeFlingScheduler : public FlingScheduler {
public: public:
FakeFlingScheduler(RenderWidgetHostImpl* host) : FlingScheduler(host) {} FakeFlingScheduler(RenderWidgetHostImpl* host) : FlingScheduler(host) {}
void ScheduleFlingProgress( void ScheduleFlingProgress() override {
base::WeakPtr<FlingController> fling_controller) override { FlingScheduler::ScheduleFlingProgress();
FlingScheduler::ScheduleFlingProgress(fling_controller);
fling_in_progress_ = true; fling_in_progress_ = true;
} }
void DidStopFlingingOnBrowser( void DidStopFlingingOnBrowser() override {
base::WeakPtr<FlingController> fling_controller) override { FlingScheduler::DidStopFlingingOnBrowser();
FlingScheduler::DidStopFlingingOnBrowser(fling_controller);
fling_in_progress_ = false; fling_in_progress_ = false;
} }
...@@ -56,6 +54,7 @@ class FlingSchedulerTest : public testing::Test, ...@@ -56,6 +54,7 @@ class FlingSchedulerTest : public testing::Test,
fling_scheduler_ = std::make_unique<FakeFlingScheduler>(widget_host_); fling_scheduler_ = std::make_unique<FakeFlingScheduler>(widget_host_);
fling_controller_ = std::make_unique<FlingController>( fling_controller_ = std::make_unique<FlingController>(
this, fling_scheduler_.get(), FlingController::Config()); this, fling_scheduler_.get(), FlingController::Config());
fling_controller_->RegisterFlingSchedulerObserver();
} }
void TearDown() override { void TearDown() override {
......
...@@ -148,6 +148,12 @@ void GestureEventQueue::QueueAndForwardIfNecessary( ...@@ -148,6 +148,12 @@ void GestureEventQueue::QueueAndForwardIfNecessary(
DCHECK_NE(gesture_event.event.GetType(), DCHECK_NE(gesture_event.event.GetType(),
WebInputEvent::kGestureFlingCancel); WebInputEvent::kGestureFlingCancel);
coalesced_gesture_events_.push_back(gesture_event); coalesced_gesture_events_.push_back(gesture_event);
if (gesture_event.event.GetType() == WebInputEvent::kGestureScrollBegin) {
fling_controller_.RegisterFlingSchedulerObserver();
} else if (gesture_event.event.GetType() ==
WebInputEvent::kGestureScrollEnd) {
fling_controller_.UnregisterFlingSchedulerObserver();
}
client_->SendGestureEventImmediately(gesture_event); client_->SendGestureEventImmediately(gesture_event);
return; return;
} }
...@@ -160,6 +166,10 @@ void GestureEventQueue::QueueAndForwardIfNecessary( ...@@ -160,6 +166,10 @@ void GestureEventQueue::QueueAndForwardIfNecessary(
case WebInputEvent::kGestureScrollBegin: case WebInputEvent::kGestureScrollBegin:
if (OnScrollBegin(gesture_event)) if (OnScrollBegin(gesture_event))
return; return;
fling_controller_.RegisterFlingSchedulerObserver();
break;
case WebGestureEvent::kGestureScrollEnd:
fling_controller_.UnregisterFlingSchedulerObserver();
break; break;
default: default:
break; break;
......
...@@ -103,10 +103,15 @@ class GestureEventQueueTest : public testing::Test, ...@@ -103,10 +103,15 @@ class GestureEventQueueTest : public testing::Test,
const GestureEventWithLatencyInfo& gesture_event) override {} const GestureEventWithLatencyInfo& gesture_event) override {}
// FlingControllerSchedulerClient // FlingControllerSchedulerClient
void ScheduleFlingProgress( void ScheduleFlingProgress() override {}
base::WeakPtr<FlingController> fling_controller) override {} void DidStopFlingingOnBrowser() override {}
void DidStopFlingingOnBrowser( void RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) override {} base::WeakPtr<FlingController> fling_controller) override {
fling_scheduler_observer_registered_ = true;
}
void UnregisterFlingSchedulerObserver() override {
fling_scheduler_observer_registered_ = false;
}
bool NeedsBeginFrameForFlingProgress() override { return false; } bool NeedsBeginFrameForFlingProgress() override { return false; }
protected: protected:
...@@ -188,6 +193,10 @@ class GestureEventQueueTest : public testing::Test, ...@@ -188,6 +193,10 @@ class GestureEventQueueTest : public testing::Test,
SyntheticWebGestureEventBuilder::Build(type, sourceDevice))); SyntheticWebGestureEventBuilder::Build(type, sourceDevice)));
} }
bool fling_scheduler_observer_registered() const {
return fling_scheduler_observer_registered_;
}
unsigned GestureEventQueueSize() { unsigned GestureEventQueueSize() {
return queue()->coalesced_gesture_events_.size(); return queue()->coalesced_gesture_events_.size();
} }
...@@ -234,6 +243,7 @@ class GestureEventQueueTest : public testing::Test, ...@@ -234,6 +243,7 @@ class GestureEventQueueTest : public testing::Test,
WebGestureEvent last_acked_event_; WebGestureEvent last_acked_event_;
std::unique_ptr<InputEventAckState> sync_ack_result_; std::unique_ptr<InputEventAckState> sync_ack_result_;
std::unique_ptr<WebGestureEvent> sync_followup_event_; std::unique_ptr<WebGestureEvent> sync_followup_event_;
bool fling_scheduler_observer_registered_ = false;
base::test::ScopedFeatureList feature_list_; base::test::ScopedFeatureList feature_list_;
}; };
...@@ -1243,4 +1253,17 @@ TEST_F(GestureEventQueueWithCompositorEventQueueTest, ...@@ -1243,4 +1253,17 @@ TEST_F(GestureEventQueueWithCompositorEventQueueTest,
EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
} }
// Checks that the fling scheduler observer is regsitered/unregistered on
// GSB/GSE respectively.
TEST_F(GestureEventQueueWithCompositorEventQueueTest,
FlingSchedulerOpbserverRegisteredOnGSB) {
EXPECT_FALSE(fling_scheduler_observer_registered());
SimulateGestureEvent(WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchscreen);
EXPECT_TRUE(fling_scheduler_observer_registered());
SimulateGestureEvent(WebInputEvent::kGestureScrollEnd,
blink::kWebGestureDeviceTouchscreen);
EXPECT_FALSE(fling_scheduler_observer_registered());
}
} // namespace content } // namespace content
...@@ -67,10 +67,11 @@ class MockInputRouterClient : public InputRouterClient, ...@@ -67,10 +67,11 @@ class MockInputRouterClient : public InputRouterClient,
} }
// FlingControllerSchedulerClient // FlingControllerSchedulerClient
void ScheduleFlingProgress( void ScheduleFlingProgress() override {}
base::WeakPtr<FlingController> fling_controller) override {} void DidStopFlingingOnBrowser() override {}
void DidStopFlingingOnBrowser( void RegisterFlingSchedulerObserver(
base::WeakPtr<FlingController> fling_controller) override {} base::WeakPtr<FlingController> fling_controller) override {}
void UnregisterFlingSchedulerObserver() override {}
bool NeedsBeginFrameForFlingProgress() override; bool NeedsBeginFrameForFlingProgress() override;
private: private:
......
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