[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:

committed by
Chromium LUCI CQ

parent
10fe5d4663
commit
eab48df497
cc
scheduler
scheduler.ccscheduler.hscheduler_state_machine.ccscheduler_state_machine.hscheduler_state_machine_unittest.cc
test
trees
components/viz/service/layers
@@ -164,8 +164,8 @@ void Scheduler::NotifyPaintWorkletStateChange(PaintWorkletState state) {
|
|||||||
ProcessScheduledActions();
|
ProcessScheduledActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::SetNeedsBeginMainFrame() {
|
void Scheduler::SetNeedsBeginMainFrame(bool now) {
|
||||||
state_machine_.SetNeedsBeginMainFrame();
|
state_machine_.SetNeedsBeginMainFrame(now);
|
||||||
ProcessScheduledActions();
|
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
|
// source to be told to send BeginFrames to this client so that this client
|
||||||
// can send a CompositorFrame to the display compositor with appropriate
|
// can send a CompositorFrame to the display compositor with appropriate
|
||||||
// timing.
|
// 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
|
// Requests a single impl frame (after the current frame if there is one
|
||||||
// active).
|
// active).
|
||||||
|
@@ -1612,8 +1612,12 @@ bool SchedulerStateMachine::ImplLatencyTakesPriority() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SchedulerStateMachine::SetNeedsBeginMainFrame() {
|
void SchedulerStateMachine::SetNeedsBeginMainFrame(bool now) {
|
||||||
needs_begin_main_frame_ = true;
|
needs_begin_main_frame_ = true;
|
||||||
|
|
||||||
|
if (now) {
|
||||||
|
last_sent_begin_main_frame_time_ = base::TimeTicks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SchedulerStateMachine::SetNeedsOneBeginImplFrame() {
|
void SchedulerStateMachine::SetNeedsOneBeginImplFrame() {
|
||||||
@@ -1647,7 +1651,7 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
|
|||||||
// the next BeginMainFrame after the deferred commit timeout will cause
|
// the next BeginMainFrame after the deferred commit timeout will cause
|
||||||
// a commit, but it might come later than optimal.
|
// a commit, but it might come later than optimal.
|
||||||
begin_main_frame_state_ = BeginMainFrameState::IDLE;
|
begin_main_frame_state_ = BeginMainFrameState::IDLE;
|
||||||
SetNeedsBeginMainFrame();
|
SetNeedsBeginMainFrame(/* now = */ false);
|
||||||
break;
|
break;
|
||||||
case CommitEarlyOutReason::kFinishedNoUpdates:
|
case CommitEarlyOutReason::kFinishedNoUpdates:
|
||||||
WillCommit(/*commit_had_no_updates=*/true);
|
WillCommit(/*commit_had_no_updates=*/true);
|
||||||
@@ -1662,7 +1666,7 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
|
|||||||
case CommitEarlyOutReason::kAbortedNotVisible:
|
case CommitEarlyOutReason::kAbortedNotVisible:
|
||||||
case CommitEarlyOutReason::kAbortedDeferredMainFrameUpdate:
|
case CommitEarlyOutReason::kAbortedDeferredMainFrameUpdate:
|
||||||
case CommitEarlyOutReason::kAbortedDeferredCommit:
|
case CommitEarlyOutReason::kAbortedDeferredCommit:
|
||||||
SetNeedsBeginMainFrame();
|
SetNeedsBeginMainFrame(/* now = */ false);
|
||||||
break;
|
break;
|
||||||
case CommitEarlyOutReason::kFinishedNoUpdates:
|
case CommitEarlyOutReason::kFinishedNoUpdates:
|
||||||
commit_count_++;
|
commit_count_++;
|
||||||
|
@@ -271,7 +271,13 @@ class CC_EXPORT SchedulerStateMachine {
|
|||||||
// Indicates that a new begin main frame flow needs to be performed, either
|
// 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
|
// to pull updates from the main thread to the impl, or to push deltas from
|
||||||
// the impl thread to main.
|
// 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_; }
|
bool needs_begin_main_frame() const { return needs_begin_main_frame_; }
|
||||||
|
|
||||||
void SetMainThreadWantsBeginMainFrameNotExpectedMessages(bool new_state);
|
void SetMainThreadWantsBeginMainFrameNotExpectedMessages(bool new_state);
|
||||||
|
@@ -1,22 +1,24 @@
|
|||||||
// Copyright 2011 The Chromium Authors
|
// Copyright 2011 The Chromium Authors
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "cc/scheduler/scheduler_state_machine.h"
|
#include "cc/scheduler/scheduler_state_machine.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "base/time/time.h"
|
|
||||||
#include "cc/metrics/begin_main_frame_metrics.h"
|
|
||||||
#ifdef UNSAFE_BUFFERS_BUILD
|
#ifdef UNSAFE_BUFFERS_BUILD
|
||||||
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
|
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
|
||||||
#pragma allow_unsafe_buffers
|
#pragma allow_unsafe_buffers
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/test/gtest_util.h"
|
#include "base/test/gtest_util.h"
|
||||||
#include "base/test/scoped_feature_list.h"
|
#include "base/test/scoped_feature_list.h"
|
||||||
|
#include "base/time/time.h"
|
||||||
#include "base/trace_event/trace_event.h"
|
#include "base/trace_event/trace_event.h"
|
||||||
#include "cc/base/features.h"
|
#include "cc/base/features.h"
|
||||||
|
#include "cc/metrics/begin_main_frame_metrics.h"
|
||||||
#include "cc/scheduler/scheduler.h"
|
#include "cc/scheduler/scheduler.h"
|
||||||
#include "components/viz/common/frame_sinks/begin_frame_args.h"
|
#include "components/viz/common/frame_sinks/begin_frame_args.h"
|
||||||
#include "components/viz/test/begin_frame_args_test.h"
|
#include "components/viz/test/begin_frame_args_test.h"
|
||||||
@@ -1153,6 +1155,51 @@ TEST(SchedulerStateMachineTest, TestFullCycle) {
|
|||||||
EXPECT_FALSE(state.needs_redraw());
|
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) {
|
TEST(SchedulerStateMachineTest, TestMainFrameThrottling) {
|
||||||
SchedulerSettings default_scheduler_settings;
|
SchedulerSettings default_scheduler_settings;
|
||||||
StateMachine state(default_scheduler_settings);
|
StateMachine state(default_scheduler_settings);
|
||||||
@@ -1164,50 +1211,55 @@ TEST(SchedulerStateMachineTest, TestMainFrameThrottling) {
|
|||||||
int begin_main_frame_count = 0;
|
int begin_main_frame_count = 0;
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
state.SetNeedsBeginMainFrame();
|
state.SetNeedsBeginMainFrame();
|
||||||
state.IssueNextBeginImplFrame();
|
begin_main_frame_count +=
|
||||||
|
RunOneFrameAndReturnWhetherMainFrameIsIssued(state) ? 1 : 0;
|
||||||
// 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());
|
|
||||||
|
|
||||||
state.AdvanceTimeBy(base::Hertz(120));
|
state.AdvanceTimeBy(base::Hertz(120));
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(begin_main_frame_count, 5);
|
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) {
|
TEST(SchedulerStateMachineTest, CommitWithoutDrawWithPendingTree) {
|
||||||
SchedulerSettings default_scheduler_settings;
|
SchedulerSettings default_scheduler_settings;
|
||||||
StateMachine state(default_scheduler_settings);
|
StateMachine state(default_scheduler_settings);
|
||||||
|
@@ -25,7 +25,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
|
|||||||
void NotifyReadyToDraw() override;
|
void NotifyReadyToDraw() override;
|
||||||
void SetNeedsRedrawOnImplThread() override {}
|
void SetNeedsRedrawOnImplThread() override {}
|
||||||
void SetNeedsOneBeginImplFrameOnImplThread() override {}
|
void SetNeedsOneBeginImplFrameOnImplThread() override {}
|
||||||
void SetNeedsCommitOnImplThread() override {}
|
void SetNeedsCommitOnImplThread(bool urgent) override {}
|
||||||
void SetNeedsPrepareTilesOnImplThread() override {}
|
void SetNeedsPrepareTilesOnImplThread() override {}
|
||||||
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
|
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
|
||||||
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
||||||
|
@@ -31,7 +31,7 @@ class FakeProxy : public Proxy {
|
|||||||
void ReleaseLayerTreeFrameSink() override {}
|
void ReleaseLayerTreeFrameSink() override {}
|
||||||
void SetShouldWarmUp() override {}
|
void SetShouldWarmUp() override {}
|
||||||
void SetVisible(bool visible) override {}
|
void SetVisible(bool visible) override {}
|
||||||
void SetNeedsAnimate() override {}
|
void SetNeedsAnimate(bool urgent) override {}
|
||||||
void SetNeedsUpdateLayers() override {}
|
void SetNeedsUpdateLayers() override {}
|
||||||
void SetNeedsCommit() override {}
|
void SetNeedsCommit() override {}
|
||||||
void SetNeedsRedraw(const gfx::Rect& damage_rect) override {}
|
void SetNeedsRedraw(const gfx::Rect& damage_rect) override {}
|
||||||
|
@@ -130,7 +130,7 @@ class LayerTreeHostImplClient {
|
|||||||
// LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsOneBeginImplFrame().
|
// LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsOneBeginImplFrame().
|
||||||
virtual void SetNeedsRedrawOnImplThread() = 0;
|
virtual void SetNeedsRedrawOnImplThread() = 0;
|
||||||
virtual void SetNeedsOneBeginImplFrameOnImplThread() = 0;
|
virtual void SetNeedsOneBeginImplFrameOnImplThread() = 0;
|
||||||
virtual void SetNeedsCommitOnImplThread() = 0;
|
virtual void SetNeedsCommitOnImplThread(bool urgent = false) = 0;
|
||||||
virtual void SetNeedsPrepareTilesOnImplThread() = 0;
|
virtual void SetNeedsPrepareTilesOnImplThread() = 0;
|
||||||
virtual void SetVideoNeedsBeginFrames(bool needs_begin_frames) = 0;
|
virtual void SetVideoNeedsBeginFrames(bool needs_begin_frames) = 0;
|
||||||
virtual void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) = 0;
|
virtual void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) = 0;
|
||||||
|
@@ -246,7 +246,9 @@ class LayerTreeHostImplTestBase : public testing::Test,
|
|||||||
void SetNeedsPrepareTilesOnImplThread() override {
|
void SetNeedsPrepareTilesOnImplThread() override {
|
||||||
did_request_prepare_tiles_ = true;
|
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 SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
|
||||||
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
||||||
bool IsInsideDraw() override { return false; }
|
bool IsInsideDraw() override { return false; }
|
||||||
|
@@ -47,7 +47,7 @@ class CC_EXPORT Proxy {
|
|||||||
virtual void SetVisible(bool visible) = 0;
|
virtual void SetVisible(bool visible) = 0;
|
||||||
virtual void SetShouldWarmUp() = 0;
|
virtual void SetShouldWarmUp() = 0;
|
||||||
|
|
||||||
virtual void SetNeedsAnimate() = 0;
|
virtual void SetNeedsAnimate(bool urgent = false) = 0;
|
||||||
virtual void SetNeedsUpdateLayers() = 0;
|
virtual void SetNeedsUpdateLayers() = 0;
|
||||||
virtual void SetNeedsCommit() = 0;
|
virtual void SetNeedsCommit() = 0;
|
||||||
virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
|
virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
|
||||||
|
@@ -239,8 +239,8 @@ void ProxyImpl::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
|
|||||||
SetNeedsRedrawOnImplThread();
|
SetNeedsRedrawOnImplThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyImpl::SetNeedsCommitOnImpl() {
|
void ProxyImpl::SetNeedsCommitOnImpl(bool urgent) {
|
||||||
SetNeedsCommitOnImplThread();
|
SetNeedsCommitOnImplThread(urgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyImpl::SetTargetLocalSurfaceIdOnImpl(
|
void ProxyImpl::SetTargetLocalSurfaceIdOnImpl(
|
||||||
@@ -413,7 +413,7 @@ void ProxyImpl::NotifyReadyToCommitOnImpl(
|
|||||||
// ApplyCompositorChanges. This means we are guaranteed to run another main
|
// ApplyCompositorChanges. This means we are guaranteed to run another main
|
||||||
// frame after FCP, which is good because there may be hover effects to apply.
|
// frame after FCP, which is good because there may be hover effects to apply.
|
||||||
if (!scroll_and_viewport_changes_synced)
|
if (!scroll_and_viewport_changes_synced)
|
||||||
scheduler_->SetNeedsBeginMainFrame();
|
scheduler_->SetNeedsBeginMainFrame(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread() {
|
void ProxyImpl::DidLoseLayerTreeFrameSinkOnImplThread() {
|
||||||
@@ -488,10 +488,10 @@ void ProxyImpl::SetNeedsPrepareTilesOnImplThread() {
|
|||||||
scheduler_->SetNeedsPrepareTiles();
|
scheduler_->SetNeedsPrepareTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyImpl::SetNeedsCommitOnImplThread() {
|
void ProxyImpl::SetNeedsCommitOnImplThread(bool urgent) {
|
||||||
TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
|
TRACE_EVENT0("cc", "ProxyImpl::SetNeedsCommitOnImplThread");
|
||||||
DCHECK(IsImplThread());
|
DCHECK(IsImplThread());
|
||||||
scheduler_->SetNeedsBeginMainFrame();
|
scheduler_->SetNeedsBeginMainFrame(urgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
|
void ProxyImpl::SetVideoNeedsBeginFrames(bool needs_begin_frames) {
|
||||||
@@ -622,7 +622,7 @@ void ProxyImpl::NotifyImageDecodeRequestFinished(int request_id,
|
|||||||
base::BindOnce(&ProxyMain::NotifyImageDecodeRequestFinished,
|
base::BindOnce(&ProxyMain::NotifyImageDecodeRequestFinished,
|
||||||
proxy_main_weak_ptr_, request_id, decode_succeeded));
|
proxy_main_weak_ptr_, request_id, decode_succeeded));
|
||||||
} else {
|
} else {
|
||||||
SetNeedsCommitOnImplThread();
|
SetNeedsCommitOnImplThread(/* urgent= */ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -61,7 +61,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
|
|||||||
void SetDeferBeginMainFrameFromMain(bool defer_begin_main_frame);
|
void SetDeferBeginMainFrameFromMain(bool defer_begin_main_frame);
|
||||||
void SetPauseRendering(bool pause_rendering);
|
void SetPauseRendering(bool pause_rendering);
|
||||||
void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
|
void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
|
||||||
void SetNeedsCommitOnImpl();
|
void SetNeedsCommitOnImpl(bool urgent);
|
||||||
void SetTargetLocalSurfaceIdOnImpl(
|
void SetTargetLocalSurfaceIdOnImpl(
|
||||||
const viz::LocalSurfaceId& target_local_surface_id);
|
const viz::LocalSurfaceId& target_local_surface_id);
|
||||||
void BeginMainFrameAbortedOnImpl(
|
void BeginMainFrameAbortedOnImpl(
|
||||||
@@ -115,7 +115,7 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
|
|||||||
void SetNeedsRedrawOnImplThread() override;
|
void SetNeedsRedrawOnImplThread() override;
|
||||||
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
||||||
void SetNeedsPrepareTilesOnImplThread() override;
|
void SetNeedsPrepareTilesOnImplThread() override;
|
||||||
void SetNeedsCommitOnImplThread() override;
|
void SetNeedsCommitOnImplThread(bool urgent) override;
|
||||||
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
||||||
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
|
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
|
||||||
bool IsInsideDraw() override;
|
bool IsInsideDraw() override;
|
||||||
|
@@ -195,6 +195,7 @@ void ProxyMain::BeginMainFrame(
|
|||||||
|
|
||||||
final_pipeline_stage_ = max_requested_pipeline_stage_;
|
final_pipeline_stage_ = max_requested_pipeline_stage_;
|
||||||
max_requested_pipeline_stage_ = NO_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 main frame updates and commits are deferred, skip the entire pipeline.
|
||||||
if (defer_main_frame_update_ || pause_rendering_) {
|
if (defer_main_frame_update_ || pause_rendering_) {
|
||||||
@@ -563,9 +564,9 @@ void ProxyMain::SetShouldWarmUp() {
|
|||||||
base::Unretained(proxy_impl_.get())));
|
base::Unretained(proxy_impl_.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyMain::SetNeedsAnimate() {
|
void ProxyMain::SetNeedsAnimate(bool urgent) {
|
||||||
DCHECK(IsMainThread());
|
DCHECK(IsMainThread());
|
||||||
if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE)) {
|
if (SendCommitRequestToImplThreadIfNeeded(ANIMATE_PIPELINE_STAGE, urgent)) {
|
||||||
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
|
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsAnimate",
|
||||||
TRACE_EVENT_SCOPE_THREAD);
|
TRACE_EVENT_SCOPE_THREAD);
|
||||||
}
|
}
|
||||||
@@ -579,7 +580,8 @@ void ProxyMain::SetNeedsUpdateLayers() {
|
|||||||
std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
|
std::max(final_pipeline_stage_, UPDATE_LAYERS_PIPELINE_STAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE)) {
|
if (SendCommitRequestToImplThreadIfNeeded(UPDATE_LAYERS_PIPELINE_STAGE,
|
||||||
|
/* urgent = */ false)) {
|
||||||
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
|
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsUpdateLayers",
|
||||||
TRACE_EVENT_SCOPE_THREAD);
|
TRACE_EVENT_SCOPE_THREAD);
|
||||||
}
|
}
|
||||||
@@ -595,7 +597,8 @@ void ProxyMain::SetNeedsCommit() {
|
|||||||
std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
|
std::max(final_pipeline_stage_, COMMIT_PIPELINE_STAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE)) {
|
if (SendCommitRequestToImplThreadIfNeeded(COMMIT_PIPELINE_STAGE,
|
||||||
|
/* urgent = */ false)) {
|
||||||
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
|
TRACE_EVENT_INSTANT0("cc", "ProxyMain::SetNeedsCommit",
|
||||||
TRACE_EVENT_SCOPE_THREAD);
|
TRACE_EVENT_SCOPE_THREAD);
|
||||||
}
|
}
|
||||||
@@ -864,18 +867,21 @@ void ProxyMain::RequestBeginMainFrameNotExpected(bool new_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
|
bool ProxyMain::SendCommitRequestToImplThreadIfNeeded(
|
||||||
CommitPipelineStage required_stage) {
|
CommitPipelineStage required_stage,
|
||||||
|
bool urgent) {
|
||||||
DCHECK(IsMainThread());
|
DCHECK(IsMainThread());
|
||||||
DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
|
DCHECK_NE(NO_PIPELINE_STAGE, required_stage);
|
||||||
bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
|
bool already_posted = max_requested_pipeline_stage_ != NO_PIPELINE_STAGE;
|
||||||
max_requested_pipeline_stage_ =
|
max_requested_pipeline_stage_ =
|
||||||
std::max(max_requested_pipeline_stage_, required_stage);
|
std::max(max_requested_pipeline_stage_, required_stage);
|
||||||
if (already_posted)
|
if (already_posted && (!urgent || has_sent_urgent_commit_request_)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
ImplThreadTaskRunner()->PostTask(
|
ImplThreadTaskRunner()->PostTask(
|
||||||
FROM_HERE, base::BindOnce(&ProxyImpl::SetNeedsCommitOnImpl,
|
FROM_HERE, base::BindOnce(&ProxyImpl::SetNeedsCommitOnImpl,
|
||||||
base::Unretained(proxy_impl_.get())));
|
base::Unretained(proxy_impl_.get()), urgent));
|
||||||
layer_tree_host_->OnCommitRequested();
|
layer_tree_host_->OnCommitRequested();
|
||||||
|
has_sent_urgent_commit_request_ |= urgent;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -95,7 +95,7 @@ class CC_EXPORT ProxyMain : public Proxy {
|
|||||||
LayerTreeFrameSink* layer_tree_frame_sink) override;
|
LayerTreeFrameSink* layer_tree_frame_sink) override;
|
||||||
void SetVisible(bool visible) override;
|
void SetVisible(bool visible) override;
|
||||||
void SetShouldWarmUp() override;
|
void SetShouldWarmUp() override;
|
||||||
void SetNeedsAnimate() override;
|
void SetNeedsAnimate(bool urgent) override;
|
||||||
void SetNeedsUpdateLayers() override;
|
void SetNeedsUpdateLayers() override;
|
||||||
void SetNeedsCommit() override;
|
void SetNeedsCommit() override;
|
||||||
void SetNeedsRedraw(const gfx::Rect& damage_rect) 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
|
// Returns |true| if the request was actually sent, |false| if one was
|
||||||
// already outstanding.
|
// already outstanding.
|
||||||
bool SendCommitRequestToImplThreadIfNeeded(
|
bool SendCommitRequestToImplThreadIfNeeded(CommitPipelineStage required_stage,
|
||||||
CommitPipelineStage required_stage);
|
bool urgent);
|
||||||
bool IsMainThread() const;
|
bool IsMainThread() const;
|
||||||
bool IsImplThread() const;
|
bool IsImplThread() const;
|
||||||
base::SingleThreadTaskRunner* ImplThreadTaskRunner();
|
base::SingleThreadTaskRunner* ImplThreadTaskRunner();
|
||||||
@@ -170,6 +170,11 @@ class CC_EXPORT ProxyMain : public Proxy {
|
|||||||
// deferred.
|
// deferred.
|
||||||
CommitPipelineStage deferred_final_pipeline_stage_;
|
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
|
// Set when the Proxy is started using Proxy::Start() and reset when it is
|
||||||
// stopped using Proxy::Stop().
|
// stopped using Proxy::Stop().
|
||||||
bool started_;
|
bool started_;
|
||||||
|
@@ -192,7 +192,7 @@ void SingleThreadProxy::SetLayerTreeFrameSink(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleThreadProxy::SetNeedsAnimate() {
|
void SingleThreadProxy::SetNeedsAnimate(bool urgent) {
|
||||||
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
|
TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
|
||||||
DCHECK(task_runner_provider_->IsMainThread());
|
DCHECK(task_runner_provider_->IsMainThread());
|
||||||
if (animate_requested_)
|
if (animate_requested_)
|
||||||
@@ -200,7 +200,7 @@ void SingleThreadProxy::SetNeedsAnimate() {
|
|||||||
animate_requested_ = true;
|
animate_requested_ = true;
|
||||||
DebugScopedSetImplThread impl(task_runner_provider_);
|
DebugScopedSetImplThread impl(task_runner_provider_);
|
||||||
if (scheduler_on_impl_thread_)
|
if (scheduler_on_impl_thread_)
|
||||||
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
|
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(urgent);
|
||||||
layer_tree_host_->OnCommitRequested();
|
layer_tree_host_->OnCommitRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ void SingleThreadProxy::SetNeedsUpdateLayers() {
|
|||||||
if (!RequestedAnimatePending()) {
|
if (!RequestedAnimatePending()) {
|
||||||
DebugScopedSetImplThread impl(task_runner_provider_);
|
DebugScopedSetImplThread impl(task_runner_provider_);
|
||||||
if (scheduler_on_impl_thread_)
|
if (scheduler_on_impl_thread_)
|
||||||
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
|
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(/* urgent = */ false);
|
||||||
}
|
}
|
||||||
update_layers_requested_ = true;
|
update_layers_requested_ = true;
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ void SingleThreadProxy::SetNeedsCommit() {
|
|||||||
commit_requested_ = true;
|
commit_requested_ = true;
|
||||||
DebugScopedSetImplThread impl(task_runner_provider_);
|
DebugScopedSetImplThread impl(task_runner_provider_);
|
||||||
if (scheduler_on_impl_thread_)
|
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) {
|
void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
|
||||||
@@ -537,12 +537,12 @@ void SingleThreadProxy::SetNeedsPrepareTilesOnImplThread() {
|
|||||||
scheduler_on_impl_thread_->SetNeedsPrepareTiles();
|
scheduler_on_impl_thread_->SetNeedsPrepareTiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleThreadProxy::SetNeedsCommitOnImplThread() {
|
void SingleThreadProxy::SetNeedsCommitOnImplThread(bool urgent) {
|
||||||
DCHECK(!task_runner_provider_->HasImplThread() ||
|
DCHECK(!task_runner_provider_->HasImplThread() ||
|
||||||
task_runner_provider_->IsImplThread());
|
task_runner_provider_->IsImplThread());
|
||||||
single_thread_client_->ScheduleAnimationForWebTests();
|
single_thread_client_->ScheduleAnimationForWebTests();
|
||||||
if (scheduler_on_impl_thread_)
|
if (scheduler_on_impl_thread_)
|
||||||
scheduler_on_impl_thread_->SetNeedsBeginMainFrame();
|
scheduler_on_impl_thread_->SetNeedsBeginMainFrame(urgent);
|
||||||
commit_requested_ = true;
|
commit_requested_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +667,7 @@ void SingleThreadProxy::NotifyImageDecodeRequestFinished(
|
|||||||
DebugScopedSetMainThread main_thread(task_runner_provider_);
|
DebugScopedSetMainThread main_thread(task_runner_provider_);
|
||||||
IssueImageDecodeFinishedCallbacks();
|
IssueImageDecodeFinishedCallbacks();
|
||||||
} else {
|
} else {
|
||||||
SetNeedsCommitOnImplThread();
|
SetNeedsCommitOnImplThread(/* urgent = */ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,7 +55,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
|
|||||||
void ReleaseLayerTreeFrameSink() override;
|
void ReleaseLayerTreeFrameSink() override;
|
||||||
void SetVisible(bool visible) override;
|
void SetVisible(bool visible) override;
|
||||||
void SetShouldWarmUp() override;
|
void SetShouldWarmUp() override;
|
||||||
void SetNeedsAnimate() override;
|
void SetNeedsAnimate(bool urgent) override;
|
||||||
void SetNeedsUpdateLayers() override;
|
void SetNeedsUpdateLayers() override;
|
||||||
void SetNeedsCommit() override;
|
void SetNeedsCommit() override;
|
||||||
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
|
void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
|
||||||
@@ -131,7 +131,7 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
|
|||||||
void SetNeedsRedrawOnImplThread() override;
|
void SetNeedsRedrawOnImplThread() override;
|
||||||
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
||||||
void SetNeedsPrepareTilesOnImplThread() override;
|
void SetNeedsPrepareTilesOnImplThread() override;
|
||||||
void SetNeedsCommitOnImplThread() override;
|
void SetNeedsCommitOnImplThread(bool urgent) override;
|
||||||
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
||||||
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override {}
|
||||||
bool IsInsideDraw() override;
|
bool IsInsideDraw() override;
|
||||||
|
@@ -894,7 +894,7 @@ void LayerContextImpl::SetNeedsPrepareTilesOnImplThread() {
|
|||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayerContextImpl::SetNeedsCommitOnImplThread() {
|
void LayerContextImpl::SetNeedsCommitOnImplThread(bool urgent) {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ class LayerContextImpl : public cc::LayerTreeHostImplClient,
|
|||||||
void SetNeedsRedrawOnImplThread() override;
|
void SetNeedsRedrawOnImplThread() override;
|
||||||
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
void SetNeedsOneBeginImplFrameOnImplThread() override;
|
||||||
void SetNeedsPrepareTilesOnImplThread() override;
|
void SetNeedsPrepareTilesOnImplThread() override;
|
||||||
void SetNeedsCommitOnImplThread() override;
|
void SetNeedsCommitOnImplThread(bool urgent) override;
|
||||||
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override;
|
||||||
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
|
void SetDeferBeginMainFrameFromImpl(bool defer_begin_main_frame) override;
|
||||||
bool IsInsideDraw() override;
|
bool IsInsideDraw() override;
|
||||||
|
Reference in New Issue
Block a user