0

[cc] Add a way to request an "urgent" main frame

When main frame updates are throttled to a lower framerate than impl
frames, some use cases may regress. This is partly intentionnal, for
instance requestAnimationFrame() should run at a lower
framerate. However, some updates (e.g. reacting to an input event) would
benefit from being processed at the next opportunity.

This CL adds the CC-side mechanism for it. It is split from a larger CL,
which adds the blink-side plumbing, as well as use cases.

Bug: 379678455
Change-Id: Idc662418829fb33e8d534063cc888a9572070526
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6163465
Commit-Queue: Benoit Lize <lizeb@chromium.org>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1407060}
This commit is contained in:
Benoît Lizé
2025-01-15 17:31:43 -08:00
committed by Chromium LUCI CQ
parent 10fe5d4663
commit eab48df497
18 changed files with 161 additions and 81 deletions

@ -164,8 +164,8 @@ void Scheduler::NotifyPaintWorkletStateChange(PaintWorkletState state) {
ProcessScheduledActions();
}
void Scheduler::SetNeedsBeginMainFrame() {
state_machine_.SetNeedsBeginMainFrame();
void Scheduler::SetNeedsBeginMainFrame(bool now) {
state_machine_.SetNeedsBeginMainFrame(now);
ProcessScheduledActions();
}

@ -154,7 +154,12 @@ class CC_EXPORT Scheduler : public viz::BeginFrameObserverBase {
// source to be told to send BeginFrames to this client so that this client
// can send a CompositorFrame to the display compositor with appropriate
// timing.
void SetNeedsBeginMainFrame();
//
// Set `now` to true if the BeginMainFrame() should not be throttled, but
// happen as the next opportunity. This is useful when main frame updates are
// running at a lower rate than compositor frames, but we don't want to wait
// (e.g. there is an input event).
void SetNeedsBeginMainFrame(bool now = false);
// Requests a single impl frame (after the current frame if there is one
// active).

@ -1612,8 +1612,12 @@ bool SchedulerStateMachine::ImplLatencyTakesPriority() const {
return false;
}
void SchedulerStateMachine::SetNeedsBeginMainFrame() {
void SchedulerStateMachine::SetNeedsBeginMainFrame(bool now) {
needs_begin_main_frame_ = true;
if (now) {
last_sent_begin_main_frame_time_ = base::TimeTicks();
}
}
void SchedulerStateMachine::SetNeedsOneBeginImplFrame() {
@ -1647,7 +1651,7 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
// the next BeginMainFrame after the deferred commit timeout will cause
// a commit, but it might come later than optimal.
begin_main_frame_state_ = BeginMainFrameState::IDLE;
SetNeedsBeginMainFrame();
SetNeedsBeginMainFrame(/* now = */ false);
break;
case CommitEarlyOutReason::kFinishedNoUpdates:
WillCommit(/*commit_had_no_updates=*/true);
@ -1662,7 +1666,7 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
case CommitEarlyOutReason::kAbortedNotVisible:
case CommitEarlyOutReason::kAbortedDeferredMainFrameUpdate:
case CommitEarlyOutReason::kAbortedDeferredCommit:
SetNeedsBeginMainFrame();
SetNeedsBeginMainFrame(/* now = */ false);
break;
case CommitEarlyOutReason::kFinishedNoUpdates:
commit_count_++;

@ -271,7 +271,13 @@ class CC_EXPORT SchedulerStateMachine {
// Indicates that a new begin main frame flow needs to be performed, either
// to pull updates from the main thread to the impl, or to push deltas from
// the impl thread to main.
void SetNeedsBeginMainFrame();
//
// If `now` is true, then the BeginMainFrame() update is not throttled, and
// the next BeginMainFrame() will be sent at the next opportunity, regardless
// of the interval since the last one. This is to be used in cases where
// `SetThrottleMainFrames()` has been called, and we have an "urgent" update
// that should not wait more than necessary.
void SetNeedsBeginMainFrame(bool now = false);
bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
void SetMainThreadWantsBeginMainFrameNotExpectedMessages(bool new_state);

@ -1,22 +1,24 @@
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/scheduler/scheduler_state_machine.h"
#include <stddef.h>
#include <array>
#include "base/time/time.h"
#include "cc/metrics/begin_main_frame_metrics.h"
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/features.h"
#include "cc/metrics/begin_main_frame_metrics.h"
#include "cc/scheduler/scheduler.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/test/begin_frame_args_test.h"
@ -1153,6 +1155,51 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
EXPECT_FALSE(state.needs_redraw());
}
namespace {
bool RunOneFrameAndReturnWhetherMainFrameIsIssued(StateMachine& state) {
state.IssueNextBeginImplFrame();
// If we send a BeginMainFrame(), simulate the fast path, where main is fast
// enough to catch the next deadline.
bool send_begin_main_frame = state.ShouldSendBeginMainFrame();
if (state.ShouldSendBeginMainFrame()) {
send_begin_main_frame = true;
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
state.NotifyReadyToCommit();
EXPECT_MAIN_FRAME_STATE(
SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
state.NotifyReadyToActivate();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
EXPECT_TRUE(state.active_tree_needs_first_draw());
EXPECT_TRUE(state.needs_redraw());
} else {
// Still need to require a draw, otherwise nothing will happen below.
state.SetNeedsRedraw(true);
}
// Expect to do nothing until BeginImplFrame deadline
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
state.DidSubmitCompositorFrame();
state.DidReceiveCompositorFrameAck();
// Should be synchronized, no draw needed, no action needed.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
EXPECT_FALSE(state.needs_redraw());
return send_begin_main_frame;
}
} // namespace
TEST(SchedulerStateMachineTest, TestMainFrameThrottling) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
@ -1164,50 +1211,55 @@ TEST(SchedulerStateMachineTest, TestMainFrameThrottling) {
int begin_main_frame_count = 0;
for (int i = 0; i < 10; i++) {
state.SetNeedsBeginMainFrame();
state.IssueNextBeginImplFrame();
// If we send a BeginMainFrame(), simulate the fast path, where main is fast
// enough to catch the next deadline.
if (state.ShouldSendBeginMainFrame()) {
begin_main_frame_count += 1;
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::SENT);
EXPECT_FALSE(state.NeedsCommit());
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
state.NotifyReadyToCommit();
EXPECT_MAIN_FRAME_STATE(
SchedulerStateMachine::BeginMainFrameState::READY_TO_COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::POST_COMMIT);
state.NotifyReadyToActivate();
EXPECT_ACTION_UPDATE_STATE(
SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
EXPECT_TRUE(state.active_tree_needs_first_draw());
EXPECT_TRUE(state.needs_redraw());
} else {
// Still need to require a draw, otherwise nothing will happen below.
state.SetNeedsRedraw(true);
}
// Expect to do nothing until BeginImplFrame deadline
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
state.OnBeginImplFrameDeadline();
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::DRAW_IF_POSSIBLE);
state.DidSubmitCompositorFrame();
state.DidReceiveCompositorFrameAck();
// Should be synchronized, no draw needed, no action needed.
EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
EXPECT_MAIN_FRAME_STATE(SchedulerStateMachine::BeginMainFrameState::IDLE);
EXPECT_FALSE(state.needs_redraw());
begin_main_frame_count +=
RunOneFrameAndReturnWhetherMainFrameIsIssued(state) ? 1 : 0;
state.AdvanceTimeBy(base::Hertz(120));
}
EXPECT_EQ(begin_main_frame_count, 5);
}
TEST(SchedulerStateMachineTest, TestMainFrameThrottlingWithUrgentUpdates) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);
SET_UP_STATE(state);
state.SetThrottleMainFrames(base::Hertz(60));
state.AdvanceTimeBy(base::Seconds(1280)); // Start at an arbitrary point.
int begin_main_frame_count = 0;
for (int i = 0; i < 10; i++) {
state.SetNeedsBeginMainFrame(true);
begin_main_frame_count +=
RunOneFrameAndReturnWhetherMainFrameIsIssued(state) ? 1 : 0;
state.AdvanceTimeBy(base::Hertz(120));
}
// All the urgent updates result in main frames.
EXPECT_EQ(begin_main_frame_count, 10);
begin_main_frame_count = 0;
for (int i = 0; i < 10; i++) {
state.SetNeedsBeginMainFrame(false);
state.SetNeedsBeginMainFrame(true);
begin_main_frame_count +=
RunOneFrameAndReturnWhetherMainFrameIsIssued(state) ? 1 : 0;
state.AdvanceTimeBy(base::Hertz(120));
}
// Same when we get multiple requests in a frame, one urgent.
EXPECT_EQ(begin_main_frame_count, 10);
begin_main_frame_count = 0;
for (int i = 0; i < 10; i++) {
bool urgent = i < 3;
state.SetNeedsBeginMainFrame(urgent);
begin_main_frame_count +=
RunOneFrameAndReturnWhetherMainFrameIsIssued(state) ? 1 : 0;
state.AdvanceTimeBy(base::Hertz(120));
}
// One extra main frame, doesn't make all the subsequent ones urgent.
EXPECT_EQ(begin_main_frame_count, 5 + 1);
}
TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) {
SchedulerSettings default_scheduler_settings;
StateMachine state(default_scheduler_settings);

@ -25,7 +25,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
void NotifyReadyToDraw() override;
void SetNeedsRedrawOnImplThread() override {}
void SetNeedsOneBeginImplFrameOnImplThread() override {}
void SetNeedsCommitOnImplThread() override {}
void SetNeedsCommitOnImplThread(bool urgent) override {}
void SetNeedsPrepareTilesOnImplThread() override {}
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}

@ -31,7 +31,7 @@ class FakeProxy : public Proxy {
void ReleaseLayerTreeFrameSink() override {}
void SetShouldWarmUp() override {}
void SetVisible(bool visible) override {}
void SetNeedsAnimate() override {}
void SetNeedsAnimate(bool urgent) override {}
void SetNeedsUpdateLayers() override {}
void SetNeedsCommit() override {}
void SetNeedsRedraw(const gfx::Rect& damage_rect) override {}

@ -130,7 +130,7 @@ class LayerTreeHostImplClient {
// LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsOneBeginImplFrame().
virtual void SetNeedsRedrawOnImplThread() = 0;
virtual void SetNeedsOneBeginImplFrameOnImplThread() = 0;
virtual void SetNeedsCommitOnImplThread() = 0;
virtual void SetNeedsCommitOnImplThread(bool urgent = false) = 0;
virtual void SetNeedsPrepareTilesOnImplThread() = 0;
virtual void SetVideoNeedsBeginFrames(bool needs_begin_frames) = 0;
virtual void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) = 0;

@ -246,7 +246,9 @@ class LayerTreeHostImplTestBase : public testing::Test,
void SetNeedsPrepareTilesOnImplThread() override {
did_request_prepare_tiles_ = true;
}
void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
void SetNeedsCommitOnImplThread(bool urgent) override {
did_request_commit_ = true;
}
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
bool IsInsideDraw() override { return false; }

@ -47,7 +47,7 @@ class CC_EXPORT Proxy {
virtual void SetVisible(bool visible) = 0;
virtual void SetShouldWarmUp() = 0;
virtual void SetNeedsAnimate() = 0;
virtual void SetNeedsAnimate(bool urgent = false) = 0;
virtual void SetNeedsUpdateLayers() = 0;
virtual void SetNeedsCommit() = 0;
virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;

@ -239,8 +239,8 @@ void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
SetNeedsRedrawOnImplThread();
}
void ProxyImpl::SetNeedsCommitOnImpl() {
SetNeedsCommitOnImplThread();
void ProxyImpl::SetNeedsCommitOnImpl(bool urgent) {
SetNeedsCommitOnImplThread(urgent);
}
void ProxyImpl::SetTargetLocalSurfaceIdOnImpl(
@ -413,7 +413,7 @@ void ProxyImpl::NotifyReadyToCommitOnImpl(
// ApplyCompositorChanges. This means we are guaranteed to run another main
// frame after FCP, which is good because there may be hover effects to apply.
if (!scroll_and_viewport_changes_synced)
scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsBeginMainFrame(false);
}
void ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread() {
@ -488,10 +488,10 @@ void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
scheduler_->SetNeedsPrepareTiles();
}
void ProxyImpl::SetNeedsCommitOnImplThread() {
void ProxyImpl::SetNeedsCommitOnImplThread(bool urgent) {
TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
DCHECK(IsImplThread());
scheduler_->SetNeedsBeginMainFrame();
scheduler_->SetNeedsBeginMainFrame(urgent);
}
void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
@ -622,7 +622,7 @@ void ProxyImpl::NotifyImageDecodeRequestFinished(int request_id,
base::BindOnce(&ProxyMain::NotifyImageDecodeRequestFinished,
proxy_main_weak_ptr_, request_id, decode_succeeded));
} else {
SetNeedsCommitOnImplThread();
SetNeedsCommitOnImplThread(/* urgent= */ false);
}
}

@ -61,7 +61,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void SetDeferBeginMainFrameFromMain(bool defer_begin_main_frame);
void SetPauseRendering(bool pause_rendering);
void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
void SetNeedsCommitOnImpl();
void SetNeedsCommitOnImpl(bool urgent);
void SetTargetLocalSurfaceIdOnImpl(
const viz::LocalSurfaceId& target_local_surface_id);
void BeginMainFrameAbortedOnImpl(
@ -115,7 +115,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void SetNeedsRedrawOnImplThread() override;
void SetNeedsOneBeginImplFrameOnImplThread() override;
void SetNeedsPrepareTilesOnImplThread() override;
void SetNeedsCommitOnImplThread() override;
void SetNeedsCommitOnImplThread(bool urgent) override;
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
bool IsInsideDraw() override;

@ -195,6 +195,7 @@ void ProxyMain::BeginMainFrame(
final_pipeline_stage_ = max_requested_pipeline_stage_;
max_requested_pipeline_stage_ = NO_PIPELINE_STAGE;
has_sent_urgent_commit_request_ = false;
// If main frame updates and commits are deferred, skip the entire pipeline.
if (defer_main_frame_update_ || pause_rendering_) {
@ -563,9 +564,9 @@ void ProxyMain::SetShouldWarmUp() {
base::Unretained(proxy_impl_.get())));
}
void ProxyMain::SetNeedsAnimate() {
void ProxyMain::SetNeedsAnimate(bool urgent) {
DCHECK(IsMainThread());
if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE, urgent)) {
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
TRACE_EVENT_SCOPE_THREAD);
}
@ -579,7 +580,8 @@ void ProxyMain::SetNeedsUpdateLayers() {
std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
return;
}
if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE,
/* urgent = */ false)) {
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
TRACE_EVENT_SCOPE_THREAD);
}
@ -595,7 +597,8 @@ void ProxyMain::SetNeedsCommit() {
std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
return;
}
if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE,
/* urgent = */ false)) {
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
TRACE_EVENT_SCOPE_THREAD);
}
@ -864,18 +867,21 @@ void ProxyMain::RequestBeginMainFrameNotExpected(bool new_state) {
}
bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
CommitPipelineStage required_stage) {
CommitPipelineStage required_stage,
bool urgent) {
DCHECK(IsMainThread());
DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
max_requested_pipeline_stage_ =
std::max(max_requested_pipeline_stage_, required_stage);
if (already_posted)
if (already_posted && (!urgent || has_sent_urgent_commit_request_)) {
return false;
}
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&ProxyImpl::SetNeedsCommitOnImpl,
base::Unretained(proxy_impl_.get())));
base::Unretained(proxy_impl_.get()), urgent));
layer_tree_host_->OnCommitRequested();
has_sent_urgent_commit_request_ |= urgent;
return true;
}

@ -95,7 +95,7 @@ class CC_EXPORT ProxyMain : public Proxy {
LayerTreeFrameSink* layer_tree_frame_sink) override;
void SetVisible(bool visible) override;
void SetShouldWarmUp() override;
void SetNeedsAnimate() override;
void SetNeedsAnimate(bool urgent) override;
void SetNeedsUpdateLayers() override;
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
@ -138,8 +138,8 @@ class CC_EXPORT ProxyMain : public Proxy {
// Returns |true| if the request was actually sent, |false| if one was
// already outstanding.
bool SendCommitRequestToImplThreadIfNeeded(
CommitPipelineStage required_stage);
bool SendCommitRequestToImplThreadIfNeeded(CommitPipelineStage required_stage,
bool urgent);
bool IsMainThread() const;
bool IsImplThread() const;
base::SingleThreadTaskRunner* ImplThreadTaskRunner();
@ -170,6 +170,11 @@ class CC_EXPORT ProxyMain : public Proxy {
// deferred.
CommitPipelineStage deferred_final_pipeline_stage_;
// Commit requests are deduplicated, however if we requested a regular commit
// request, then get an "urgent" request later, we should inform impl that the
// request became urgent.
bool has_sent_urgent_commit_request_ = false;
// Set when the Proxy is started using Proxy::Start() and reset when it is
// stopped using Proxy::Stop().
bool started_;

@ -192,7 +192,7 @@ void SingleThreadProxy::SetLayerTreeFrameSink(
}
}
void SingleThreadProxy::SetNeedsAnimate() {
void SingleThreadProxy::SetNeedsAnimate(bool urgent) {
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
DCHECK(task_runner_provider_->IsMainThread());
if (animate_requested_)
@ -200,7 +200,7 @@ void SingleThreadProxy::SetNeedsAnimate() {
animate_requested_ = true;
DebugScopedSetImplThread impl(task_runner_provider_);
if (scheduler_on_impl_thread_)
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(urgent);
layer_tree_host_->OnCommitRequested();
}
@ -210,7 +210,7 @@ void SingleThreadProxy::SetNeedsUpdateLayers() {
if (!RequestedAnimatePending()) {
DebugScopedSetImplThread impl(task_runner_provider_);
if (scheduler_on_impl_thread_)
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(/* urgent = */ false);
}
update_layers_requested_ = true;
}
@ -305,7 +305,7 @@ void SingleThreadProxy::SetNeedsCommit() {
commit_requested_ = true;
DebugScopedSetImplThread impl(task_runner_provider_);
if (scheduler_on_impl_thread_)
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(/* urgent = */ false);
}
void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
@ -537,12 +537,12 @@ void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
scheduler_on_impl_thread_->SetNeedsPrepareTiles();
}
void SingleThreadProxy::SetNeedsCommitOnImplThread() {
void SingleThreadProxy::SetNeedsCommitOnImplThread(bool urgent) {
DCHECK(!task_runner_provider_->HasImplThread() ||
task_runner_provider_->IsImplThread());
single_thread_client_->ScheduleAnimationForWebTests();
if (scheduler_on_impl_thread_)
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(urgent);
commit_requested_ = true;
}
@ -667,7 +667,7 @@ void SingleThreadProxy::NotifyImageDecodeRequestFinished(
DebugScopedSetMainThread main_thread(task_runner_provider_);
IssueImageDecodeFinishedCallbacks();
} else {
SetNeedsCommitOnImplThread();
SetNeedsCommitOnImplThread(/* urgent = */ false);
}
}
}

@ -55,7 +55,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void ReleaseLayerTreeFrameSink() override;
void SetVisible(bool visible) override;
void SetShouldWarmUp() override;
void SetNeedsAnimate() override;
void SetNeedsAnimate(bool urgent) override;
void SetNeedsUpdateLayers() override;
void SetNeedsCommit() override;
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
@ -131,7 +131,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void SetNeedsRedrawOnImplThread() override;
void SetNeedsOneBeginImplFrameOnImplThread() override;
void SetNeedsPrepareTilesOnImplThread() override;
void SetNeedsCommitOnImplThread() override;
void SetNeedsCommitOnImplThread(bool urgent) override;
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
bool IsInsideDraw() override;

@ -894,7 +894,7 @@ void LayerContextImpl::SetNeedsPrepareTilesOnImplThread() {
NOTREACHED();
}
void LayerContextImpl::SetNeedsCommitOnImplThread() {
void LayerContextImpl::SetNeedsCommitOnImplThread(bool urgent) {
NOTIMPLEMENTED();
}

@ -59,7 +59,7 @@ class LayerContextImpl : public cc::LayerTreeHostImplClient,
void SetNeedsRedrawOnImplThread() override;
void SetNeedsOneBeginImplFrameOnImplThread() override;
void SetNeedsPrepareTilesOnImplThread() override;
void SetNeedsCommitOnImplThread() override;
void SetNeedsCommitOnImplThread(bool urgent) override;
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
bool IsInsideDraw() override;