summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-18 05:06:11 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-18 05:06:11 +0000
commitc1490266036958df7d1f2959542b872fe21b8601 (patch)
treefb84f4e62c1d51ba87a4a7b20f66e02c8475bf2b
parent5e09494c74fbadcd1bf83aedae31b0db86525e46 (diff)
downloadchromium_src-c1490266036958df7d1f2959542b872fe21b8601.zip
chromium_src-c1490266036958df7d1f2959542b872fe21b8601.tar.gz
chromium_src-c1490266036958df7d1f2959542b872fe21b8601.tar.bz2
cc: Throttle swaps in Scheduler instead of OutputSurface
This doesn't represent a functional change and only moves the swap throttling logic from the OutputSurface to the Scheduler. BUG=311213 Review URL: https://codereview.chromium.org/199523002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264732 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/layers/texture_layer_unittest.cc2
-rw-r--r--cc/output/output_surface.cc96
-rw-r--r--cc/output/output_surface.h14
-rw-r--r--cc/output/output_surface_client.h2
-rw-r--r--cc/output/output_surface_unittest.cc61
-rw-r--r--cc/scheduler/draw_swap_readback_result.h10
-rw-r--r--cc/scheduler/frame_rate_controller.cc126
-rw-r--r--cc/scheduler/frame_rate_controller.h41
-rw-r--r--cc/scheduler/frame_rate_controller_unittest.cc153
-rw-r--r--cc/scheduler/scheduler.cc20
-rw-r--r--cc/scheduler/scheduler.h3
-rw-r--r--cc/scheduler/scheduler_state_machine.cc47
-rw-r--r--cc/scheduler/scheduler_state_machine.h15
-rw-r--r--cc/scheduler/scheduler_unittest.cc130
-rw-r--r--cc/scheduler/time_source.h2
-rw-r--r--cc/test/fake_layer_tree_host_impl_client.h3
-rw-r--r--cc/test/fake_output_surface_client.h2
-rw-r--r--cc/test/layer_tree_test.cc4
-rw-r--r--cc/test/scheduler_test_common.h2
-rw-r--r--cc/trees/layer_tree_host_impl.cc14
-rw-r--r--cc/trees/layer_tree_host_impl.h5
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc7
-rw-r--r--cc/trees/layer_tree_host_unittest_delegated.cc2
-rw-r--r--cc/trees/single_thread_proxy.cc4
-rw-r--r--cc/trees/single_thread_proxy.h3
-rw-r--r--cc/trees/thread_proxy.cc17
-rw-r--r--cc/trees/thread_proxy.h5
27 files changed, 312 insertions, 478 deletions
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index dd67086..97b52f4 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -1183,7 +1183,6 @@ class TextureLayerNoExtraCommitForMailboxTest
for (size_t i = 0; i < resources_to_return.size(); ++i)
output_surface()->ReturnResource(resources_to_return[i].id, &ack);
host_impl->ReclaimResources(&ack);
- host_impl->OnSwapBuffersComplete();
}
virtual void AfterTest() OVERRIDE {}
@@ -1323,7 +1322,6 @@ class TextureLayerChangeInvisibleMailboxTest
for (size_t i = 0; i < resources_to_return.size(); ++i)
output_surface()->ReturnResource(resources_to_return[i].id, &ack);
host_impl->ReclaimResources(&ack);
- host_impl->OnSwapBuffersComplete();
}
virtual void AfterTest() OVERRIDE {}
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 3aaa1a1..7818849 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -46,8 +46,8 @@ namespace cc {
OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider)
: context_provider_(context_provider),
device_scale_factor_(-1),
- max_frames_pending_(0),
- pending_swap_buffers_(0),
+ begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
+ throttle_frame_production_(true),
needs_begin_frame_(false),
client_ready_for_begin_frame_(true),
client_(NULL),
@@ -59,8 +59,8 @@ OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider)
OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
: software_device_(software_device.Pass()),
device_scale_factor_(-1),
- max_frames_pending_(0),
- pending_swap_buffers_(0),
+ begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
+ throttle_frame_production_(true),
needs_begin_frame_(false),
client_ready_for_begin_frame_(true),
client_(NULL),
@@ -74,8 +74,8 @@ OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider,
: context_provider_(context_provider),
software_device_(software_device.Pass()),
device_scale_factor_(-1),
- max_frames_pending_(0),
- pending_swap_buffers_(0),
+ begin_frame_interval_(BeginFrameArgs::DefaultInterval()),
+ throttle_frame_production_(true),
needs_begin_frame_(false),
client_ready_for_begin_frame_(true),
client_(NULL),
@@ -84,37 +84,26 @@ OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider,
weak_ptr_factory_(this),
gpu_latency_history_(kGpuLatencyHistorySize) {}
+void OutputSurface::SetThrottleFrameProduction(bool enable) {
+ DCHECK(!frame_rate_controller_);
+ throttle_frame_production_ = enable;
+}
+
void OutputSurface::InitializeBeginFrameEmulation(
base::SingleThreadTaskRunner* task_runner,
- bool throttle_frame_production,
base::TimeDelta interval) {
- if (throttle_frame_production) {
- scoped_refptr<DelayBasedTimeSource> time_source;
- if (gfx::FrameTime::TimestampsAreHighRes())
- time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner);
- else
- time_source = DelayBasedTimeSource::Create(interval, task_runner);
- frame_rate_controller_.reset(new FrameRateController(time_source));
- } else {
- frame_rate_controller_.reset(new FrameRateController(task_runner));
- }
+ DCHECK(throttle_frame_production_);
+ scoped_refptr<DelayBasedTimeSource> time_source;
+ if (gfx::FrameTime::TimestampsAreHighRes())
+ time_source = DelayBasedTimeSourceHighRes::Create(interval, task_runner);
+ else
+ time_source = DelayBasedTimeSource::Create(interval, task_runner);
+ frame_rate_controller_.reset(new FrameRateController(time_source));
frame_rate_controller_->SetClient(this);
- frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
frame_rate_controller_->SetDeadlineAdjustment(
capabilities_.adjust_deadline_for_parent ?
BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta());
-
- // The new frame rate controller will consume the swap acks of the old
- // frame rate controller, so we set that expectation up here.
- for (int i = 0; i < pending_swap_buffers_; i++)
- frame_rate_controller_->DidSwapBuffers();
-}
-
-void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
- if (frame_rate_controller_)
- frame_rate_controller_->SetMaxSwapsPending(max_frames_pending);
- max_frames_pending_ = max_frames_pending;
}
void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
@@ -125,17 +114,14 @@ void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
(timebase - base::TimeTicks()).InSecondsF(),
"interval",
interval.InSecondsF());
+ begin_frame_interval_ = interval;
if (frame_rate_controller_)
frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
}
-void OutputSurface::FrameRateControllerTick(bool throttled,
- const BeginFrameArgs& args) {
+void OutputSurface::FrameRateControllerTick(const BeginFrameArgs& args) {
DCHECK(frame_rate_controller_);
- if (throttled)
- skipped_begin_frame_args_ = args;
- else
- BeginFrame(args);
+ BeginFrame(args);
}
// Forwarded to OutputSurfaceClient
@@ -148,25 +134,29 @@ void OutputSurface::SetNeedsBeginFrame(bool enable) {
TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
needs_begin_frame_ = enable;
client_ready_for_begin_frame_ = true;
- if (frame_rate_controller_) {
+ if (!throttle_frame_production_) {
+ if (enable) {
+ base::TimeTicks frame_time = gfx::FrameTime::Now();
+ base::TimeTicks deadline = frame_time + begin_frame_interval_;
+ skipped_begin_frame_args_ =
+ BeginFrameArgs::Create(frame_time, deadline, begin_frame_interval_);
+ }
+ } else if (frame_rate_controller_) {
BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable);
if (skipped.IsValid())
skipped_begin_frame_args_ = skipped;
}
+
if (needs_begin_frame_)
PostCheckForRetroactiveBeginFrame();
}
void OutputSurface::BeginFrame(const BeginFrameArgs& args) {
- TRACE_EVENT2("cc",
+ TRACE_EVENT1("cc",
"OutputSurface::BeginFrame",
"client_ready_for_begin_frame_",
- client_ready_for_begin_frame_,
- "pending_swap_buffers_",
- pending_swap_buffers_);
- if (!needs_begin_frame_ || !client_ready_for_begin_frame_ ||
- (pending_swap_buffers_ >= max_frames_pending_ &&
- max_frames_pending_ > 0)) {
+ client_ready_for_begin_frame_);
+ if (!needs_begin_frame_ || !client_ready_for_begin_frame_) {
skipped_begin_frame_args_ = args;
} else {
client_ready_for_begin_frame_ = false;
@@ -201,28 +191,19 @@ void OutputSurface::PostCheckForRetroactiveBeginFrame() {
void OutputSurface::CheckForRetroactiveBeginFrame() {
TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame");
check_for_retroactive_begin_frame_pending_ = false;
- if (gfx::FrameTime::Now() < RetroactiveBeginFrameDeadline())
+ if (!throttle_frame_production_ ||
+ gfx::FrameTime::Now() < RetroactiveBeginFrameDeadline())
BeginFrame(skipped_begin_frame_args_);
}
void OutputSurface::DidSwapBuffers() {
- pending_swap_buffers_++;
- TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers",
- "pending_swap_buffers_", pending_swap_buffers_);
+ TRACE_EVENT0("cc", "OutputSurface::DidSwapBuffers");
client_->DidSwapBuffers();
- if (frame_rate_controller_)
- frame_rate_controller_->DidSwapBuffers();
- PostCheckForRetroactiveBeginFrame();
}
void OutputSurface::OnSwapBuffersComplete() {
- pending_swap_buffers_--;
- TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete",
- "pending_swap_buffers_", pending_swap_buffers_);
- client_->OnSwapBuffersComplete();
- if (frame_rate_controller_)
- frame_rate_controller_->DidSwapBuffersComplete();
- PostCheckForRetroactiveBeginFrame();
+ TRACE_EVENT0("cc", "OutputSurface::OnSwapBuffersComplete");
+ client_->DidSwapBuffersComplete();
}
void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
@@ -232,7 +213,6 @@ void OutputSurface::ReclaimResources(const CompositorFrameAck* ack) {
void OutputSurface::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
client_ready_for_begin_frame_ = true;
- pending_swap_buffers_ = 0;
skipped_begin_frame_args_ = BeginFrameArgs();
if (frame_rate_controller_)
frame_rate_controller_->SetActive(false);
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index a5d4d7b..471170a 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -105,12 +105,12 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// thread.
virtual bool BindToClient(OutputSurfaceClient* client);
+ // Enable or disable vsync.
+ void SetThrottleFrameProduction(bool enable);
+
void InitializeBeginFrameEmulation(base::SingleThreadTaskRunner* task_runner,
- bool throttle_frame_production,
base::TimeDelta interval);
- void SetMaxFramesPending(int max_frames_pending);
-
virtual void EnsureBackbuffer();
virtual void DiscardBackbuffer();
@@ -162,16 +162,16 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
scoped_ptr<OverlayCandidateValidator> overlay_candidate_validator_;
gfx::Size surface_size_;
float device_scale_factor_;
+ base::TimeDelta begin_frame_interval_;
// The FrameRateController is deprecated.
// Platforms should move to native BeginFrames instead.
void CommitVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
- virtual void FrameRateControllerTick(bool throttled,
- const BeginFrameArgs& args) OVERRIDE;
+ virtual void FrameRateControllerTick(const BeginFrameArgs& args) OVERRIDE;
scoped_ptr<FrameRateController> frame_rate_controller_;
- int max_frames_pending_;
- int pending_swap_buffers_;
+
+ bool throttle_frame_production_;
bool needs_begin_frame_;
bool client_ready_for_begin_frame_;
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h
index 08d9b62..141e01a 100644
--- a/cc/output/output_surface_client.h
+++ b/cc/output/output_surface_client.h
@@ -33,7 +33,7 @@ class CC_EXPORT OutputSurfaceClient {
virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0;
virtual void BeginFrame(const BeginFrameArgs& args) = 0;
virtual void DidSwapBuffers() = 0;
- virtual void OnSwapBuffersComplete() = 0;
+ virtual void DidSwapBuffersComplete() = 0;
virtual void ReclaimResources(const CompositorFrameAck* ack) = 0;
virtual void DidLoseOutputSurface() = 0;
virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index d40feb1..637ba05 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -59,10 +59,6 @@ class TestOutputSurface : public OutputSurface {
DidSwapBuffers();
}
- int pending_swap_buffers() {
- return pending_swap_buffers_;
- }
-
void OnSwapBuffersCompleteForTesting() {
OnSwapBuffersComplete();
}
@@ -232,20 +228,17 @@ TEST(OutputSurfaceTest, BeginFrameEmulation) {
// Initialize BeginFrame emulation
scoped_refptr<base::TestSimpleTaskRunner> task_runner =
new base::TestSimpleTaskRunner;
- bool throttle_frame_production = true;
const base::TimeDelta display_refresh_interval =
BeginFrameArgs::DefaultInterval();
- output_surface.InitializeBeginFrameEmulation(
- task_runner.get(), throttle_frame_production, display_refresh_interval);
+ output_surface.InitializeBeginFrameEmulation(task_runner.get(),
+ display_refresh_interval);
- output_surface.SetMaxFramesPending(2);
output_surface.EnableRetroactiveBeginFrameDeadline(
false, false, base::TimeDelta());
// We should start off with 0 BeginFrames
EXPECT_EQ(client.begin_frame_count(), 0);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
// We should not have a pending task until a BeginFrame has been
// requested.
@@ -256,54 +249,29 @@ TEST(OutputSurfaceTest, BeginFrameEmulation) {
// BeginFrame should be called on the first tick.
task_runner->RunPendingTasks();
EXPECT_EQ(client.begin_frame_count(), 1);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
// BeginFrame should not be called when there is a pending BeginFrame.
task_runner->RunPendingTasks();
EXPECT_EQ(client.begin_frame_count(), 1);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
-
// SetNeedsBeginFrame should clear the pending BeginFrame after
// a SwapBuffers.
output_surface.DidSwapBuffersForTesting();
output_surface.SetNeedsBeginFrame(true);
EXPECT_EQ(client.begin_frame_count(), 1);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
task_runner->RunPendingTasks();
EXPECT_EQ(client.begin_frame_count(), 2);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
-
- // BeginFrame should be throttled by pending swap buffers.
- output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 2);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
- task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 2);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
-
- // SwapAck should decrement pending swap buffers and unblock BeginFrame
- // again.
- output_surface.OnSwapBuffersCompleteForTesting();
- EXPECT_EQ(client.begin_frame_count(), 2);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
- task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 3);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
// Calling SetNeedsBeginFrame again indicates a swap did not occur but
// the client still wants another BeginFrame.
output_surface.SetNeedsBeginFrame(true);
task_runner->RunPendingTasks();
- EXPECT_EQ(client.begin_frame_count(), 4);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+ EXPECT_EQ(client.begin_frame_count(), 3);
// Disabling SetNeedsBeginFrame should prevent further BeginFrames.
output_surface.SetNeedsBeginFrame(false);
task_runner->RunPendingTasks();
EXPECT_FALSE(task_runner->HasPendingTask());
- EXPECT_EQ(client.begin_frame_count(), 4);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+ EXPECT_EQ(client.begin_frame_count(), 3);
}
TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
@@ -315,7 +283,6 @@ TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
EXPECT_TRUE(output_surface.HasClient());
EXPECT_FALSE(client.deferred_initialize_called());
- output_surface.SetMaxFramesPending(2);
output_surface.EnableRetroactiveBeginFrameDeadline(
true, false, base::TimeDelta());
@@ -341,19 +308,6 @@ TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
output_surface.DidSwapBuffersForTesting();
output_surface.SetNeedsBeginFrame(true);
EXPECT_EQ(client.begin_frame_count(), 3);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
-
- // Optimistically injected BeginFrames should be by throttled by pending
- // swap buffers...
- output_surface.DidSwapBuffersForTesting();
- output_surface.SetNeedsBeginFrame(true);
- EXPECT_EQ(client.begin_frame_count(), 3);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
- output_surface.BeginFrameForTesting();
- EXPECT_EQ(client.begin_frame_count(), 3);
- // ...and retroactively triggered by OnSwapBuffersComplete
- output_surface.OnSwapBuffersCompleteForTesting();
- EXPECT_EQ(client.begin_frame_count(), 4);
}
TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
@@ -373,23 +327,20 @@ TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
// Initialize BeginFrame emulation
scoped_refptr<base::TestSimpleTaskRunner> task_runner =
new base::TestSimpleTaskRunner;
- bool throttle_frame_production = true;
const base::TimeDelta display_refresh_interval = big_interval;
- output_surface.InitializeBeginFrameEmulation(
- task_runner.get(), throttle_frame_production, display_refresh_interval);
+ output_surface.InitializeBeginFrameEmulation(task_runner.get(),
+ display_refresh_interval);
// We need to subtract an epsilon from Now() because some platforms have
// a slow clock.
output_surface.CommitVSyncParametersForTesting(
gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval);
- output_surface.SetMaxFramesPending(2);
output_surface.EnableRetroactiveBeginFrameDeadline(true, true, big_interval);
// We should start off with 0 BeginFrames
EXPECT_EQ(client.begin_frame_count(), 0);
- EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
// The first SetNeedsBeginFrame(true) should start a retroactive
// BeginFrame.
diff --git a/cc/scheduler/draw_swap_readback_result.h b/cc/scheduler/draw_swap_readback_result.h
index a87a08b..852b897 100644
--- a/cc/scheduler/draw_swap_readback_result.h
+++ b/cc/scheduler/draw_swap_readback_result.h
@@ -19,15 +19,17 @@ struct DrawSwapReadbackResult {
};
DrawSwapReadbackResult()
- : draw_result(INVALID_RESULT), did_swap(false), did_readback(false) {}
+ : draw_result(INVALID_RESULT),
+ did_request_swap(false),
+ did_readback(false) {}
DrawSwapReadbackResult(DrawResult draw_result,
- bool did_swap,
+ bool did_request_swap,
bool did_readback)
: draw_result(draw_result),
- did_swap(did_swap),
+ did_request_swap(did_request_swap),
did_readback(did_readback) {}
DrawResult draw_result;
- bool did_swap;
+ bool did_request_swap;
bool did_readback;
};
diff --git a/cc/scheduler/frame_rate_controller.cc b/cc/scheduler/frame_rate_controller.cc
index 243ef6b..beaa1e1 100644
--- a/cc/scheduler/frame_rate_controller.cc
+++ b/cc/scheduler/frame_rate_controller.cc
@@ -15,59 +15,15 @@
namespace cc {
-class FrameRateControllerTimeSourceAdapter : public TimeSourceClient {
- public:
- static scoped_ptr<FrameRateControllerTimeSourceAdapter> Create(
- FrameRateController* frame_rate_controller) {
- return make_scoped_ptr(
- new FrameRateControllerTimeSourceAdapter(frame_rate_controller));
- }
- virtual ~FrameRateControllerTimeSourceAdapter() {}
-
- virtual void OnTimerTick() OVERRIDE {
- frame_rate_controller_->OnTimerTick();
- }
-
- private:
- explicit FrameRateControllerTimeSourceAdapter(
- FrameRateController* frame_rate_controller)
- : frame_rate_controller_(frame_rate_controller) {}
-
- FrameRateController* frame_rate_controller_;
-};
-
FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
: client_(NULL),
- num_frames_pending_(0),
- max_swaps_pending_(0),
interval_(BeginFrameArgs::DefaultInterval()),
time_source_(timer),
- active_(false),
- is_time_source_throttling_(true),
- manual_tick_pending_(false),
- task_runner_(NULL),
- weak_factory_(this) {
- time_source_client_adapter_ =
- FrameRateControllerTimeSourceAdapter::Create(this);
- time_source_->SetClient(time_source_client_adapter_.get());
+ active_(false) {
+ time_source_->SetClient(this);
}
-FrameRateController::FrameRateController(
- base::SingleThreadTaskRunner* task_runner)
- : client_(NULL),
- num_frames_pending_(0),
- max_swaps_pending_(0),
- interval_(BeginFrameArgs::DefaultInterval()),
- active_(false),
- is_time_source_throttling_(false),
- manual_tick_pending_(false),
- task_runner_(task_runner),
- weak_factory_(this) {}
-
-FrameRateController::~FrameRateController() {
- if (is_time_source_throttling_)
- time_source_->SetActive(false);
-}
+FrameRateController::~FrameRateController() { time_source_->SetActive(false); }
BeginFrameArgs FrameRateController::SetActive(bool active) {
if (active_ == active)
@@ -75,35 +31,20 @@ BeginFrameArgs FrameRateController::SetActive(bool active) {
TRACE_EVENT1("cc", "FrameRateController::SetActive", "active", active);
active_ = active;
- if (is_time_source_throttling_) {
- base::TimeTicks missed_tick_time = time_source_->SetActive(active);
- if (!missed_tick_time.is_null()) {
- base::TimeTicks deadline = NextTickTime();
- return BeginFrameArgs::Create(
- missed_tick_time, deadline + deadline_adjustment_, interval_);
- }
- } else {
- if (active) {
- PostManualTick();
- } else {
- weak_factory_.InvalidateWeakPtrs();
- manual_tick_pending_ = false;
- }
+ base::TimeTicks missed_tick_time = time_source_->SetActive(active);
+ if (!missed_tick_time.is_null()) {
+ base::TimeTicks deadline = NextTickTime();
+ return BeginFrameArgs::Create(
+ missed_tick_time, deadline + deadline_adjustment_, interval_);
}
return BeginFrameArgs();
}
-void FrameRateController::SetMaxSwapsPending(int max_swaps_pending) {
- DCHECK_GE(max_swaps_pending, 0);
- max_swaps_pending_ = max_swaps_pending;
-}
-
void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase,
base::TimeDelta interval) {
interval_ = interval;
- if (is_time_source_throttling_)
- time_source_->SetTimebaseAndInterval(timebase, interval);
+ time_source_->SetTimebaseAndInterval(timebase, interval);
}
void FrameRateController::SetDeadlineAdjustment(base::TimeDelta delta) {
@@ -114,65 +55,22 @@ void FrameRateController::OnTimerTick() {
TRACE_EVENT0("cc", "FrameRateController::OnTimerTick");
DCHECK(active_);
- // Check if we have too many frames in flight.
- bool throttled =
- max_swaps_pending_ && num_frames_pending_ >= max_swaps_pending_;
- TRACE_COUNTER_ID1("cc", "ThrottledCompositor", task_runner_, throttled);
-
if (client_) {
// TODO(brianderson): Use an adaptive parent compositor deadline.
base::TimeTicks frame_time = LastTickTime();
base::TimeTicks deadline = NextTickTime();
BeginFrameArgs args = BeginFrameArgs::Create(
frame_time, deadline + deadline_adjustment_, interval_);
- client_->FrameRateControllerTick(throttled, args);
+ client_->FrameRateControllerTick(args);
}
-
- if (!is_time_source_throttling_ && !throttled)
- PostManualTick();
-}
-
-void FrameRateController::PostManualTick() {
- if (active_ && !manual_tick_pending_) {
- manual_tick_pending_ = true;
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&FrameRateController::ManualTick,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-void FrameRateController::ManualTick() {
- manual_tick_pending_ = false;
- OnTimerTick();
-}
-
-void FrameRateController::DidSwapBuffers() {
- num_frames_pending_++;
-}
-
-void FrameRateController::DidSwapBuffersComplete() {
- DCHECK_GT(num_frames_pending_, 0);
- num_frames_pending_--;
- if (!is_time_source_throttling_)
- PostManualTick();
-}
-
-void FrameRateController::DidAbortAllPendingFrames() {
- num_frames_pending_ = 0;
}
base::TimeTicks FrameRateController::NextTickTime() {
- if (is_time_source_throttling_)
- return time_source_->NextTickTime();
-
- return base::TimeTicks();
+ return time_source_->NextTickTime();
}
base::TimeTicks FrameRateController::LastTickTime() {
- if (is_time_source_throttling_)
- return time_source_->LastTickTime();
-
- return gfx::FrameTime::Now();
+ return time_source_->LastTickTime();
}
} // namespace cc
diff --git a/cc/scheduler/frame_rate_controller.h b/cc/scheduler/frame_rate_controller.h
index 6d86d97..2ec62ac 100644
--- a/cc/scheduler/frame_rate_controller.h
+++ b/cc/scheduler/frame_rate_controller.h
@@ -11,6 +11,7 @@
#include "base/time/time.h"
#include "cc/base/cc_export.h"
#include "cc/output/begin_frame_args.h"
+#include "cc/scheduler/time_source.h"
namespace base { class SingleThreadTaskRunner; }
@@ -24,20 +25,14 @@ class CC_EXPORT FrameRateControllerClient {
virtual ~FrameRateControllerClient() {}
public:
- // Throttled is true when we have a maximum number of frames pending.
- virtual void FrameRateControllerTick(bool throttled,
- const BeginFrameArgs& args) = 0;
+ virtual void FrameRateControllerTick(const BeginFrameArgs& args) = 0;
};
-class FrameRateControllerTimeSourceAdapter;
-
// The FrameRateController is used in cases where we self-tick (i.e. BeginFrame
// is not sent by a parent compositor.
-class CC_EXPORT FrameRateController {
+class CC_EXPORT FrameRateController : TimeSourceClient {
public:
explicit FrameRateController(scoped_refptr<TimeSource> timer);
- // Alternate form of FrameRateController with unthrottled frame-rate.
- explicit FrameRateController(base::SingleThreadTaskRunner* task_runner);
virtual ~FrameRateController();
void SetClient(FrameRateControllerClient* client) { client_ = client; }
@@ -48,50 +43,24 @@ class CC_EXPORT FrameRateController {
bool IsActive() { return active_; }
- // Use the following methods to adjust target frame rate.
- //
- // Multiple frames can be in-progress, but for every DidSwapBuffers, a
- // DidFinishFrame should be posted.
- //
- // If the rendering pipeline crashes, call DidAbortAllPendingFrames.
- void DidSwapBuffers();
- void DidSwapBuffersComplete();
- void DidAbortAllPendingFrames();
- void SetMaxSwapsPending(int max_swaps_pending); // 0 for unlimited.
- int MaxSwapsPending() const { return max_swaps_pending_; }
- int NumSwapsPendingForTesting() const { return num_frames_pending_; }
-
void SetTimebaseAndInterval(base::TimeTicks timebase,
base::TimeDelta interval);
void SetDeadlineAdjustment(base::TimeDelta delta);
- protected:
- friend class FrameRateControllerTimeSourceAdapter;
- void OnTimerTick();
-
- void PostManualTick();
- void ManualTick();
+ virtual void OnTimerTick() OVERRIDE;
+ protected:
// This returns null for unthrottled frame-rate.
base::TimeTicks NextTickTime();
// This returns now for unthrottled frame-rate.
base::TimeTicks LastTickTime();
FrameRateControllerClient* client_;
- int num_frames_pending_;
- int max_swaps_pending_;
base::TimeDelta interval_;
base::TimeDelta deadline_adjustment_;
scoped_refptr<TimeSource> time_source_;
- scoped_ptr<FrameRateControllerTimeSourceAdapter> time_source_client_adapter_;
bool active_;
- // Members for unthrottled frame-rate.
- bool is_time_source_throttling_;
- bool manual_tick_pending_;
- base::SingleThreadTaskRunner* task_runner_;
- base::WeakPtrFactory<FrameRateController> weak_factory_;
-
private:
DISALLOW_COPY_AND_ASSIGN(FrameRateController);
};
diff --git a/cc/scheduler/frame_rate_controller_unittest.cc b/cc/scheduler/frame_rate_controller_unittest.cc
index e7d7580..ed7de67 100644
--- a/cc/scheduler/frame_rate_controller_unittest.cc
+++ b/cc/scheduler/frame_rate_controller_unittest.cc
@@ -19,9 +19,8 @@ class FakeFrameRateControllerClient : public FrameRateControllerClient {
bool BeganFrame() const { return frame_count_ > 0; }
int frame_count() const { return frame_count_; }
- virtual void FrameRateControllerTick(
- bool throttled, const BeginFrameArgs& args) OVERRIDE {
- frame_count_ += throttled ? 0 : 1;
+ virtual void FrameRateControllerTick(const BeginFrameArgs& args) OVERRIDE {
+ frame_count_ += 1;
}
protected:
@@ -50,14 +49,6 @@ TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) {
EXPECT_TRUE(client.BeganFrame());
client.Reset();
- // Tell the controller we drew
- controller.DidSwapBuffers();
-
- // Tell the controller the frame ended 5ms later
- time_source->SetNow(time_source->Now() +
- base::TimeDelta::FromMilliseconds(5));
- controller.DidSwapBuffersComplete();
-
// Trigger another frame, make sure BeginFrame runs again
elapsed += task_runner->NextPendingTaskDelay();
// Sanity check that previous code didn't move time backward.
@@ -67,145 +58,5 @@ TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) {
EXPECT_TRUE(client.BeganFrame());
}
-TEST(FrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight) {
- scoped_refptr<base::TestSimpleTaskRunner> task_runner =
- new base::TestSimpleTaskRunner;
- FakeFrameRateControllerClient client;
- base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
- base::Time::kMicrosecondsPerSecond / 60);
- scoped_refptr<FakeDelayBasedTimeSource> time_source =
- FakeDelayBasedTimeSource::Create(interval, task_runner.get());
- FrameRateController controller(time_source);
-
- controller.SetClient(&client);
- controller.SetActive(true);
- controller.SetMaxSwapsPending(2);
-
- base::TimeTicks elapsed; // Muck around with time a bit
-
- // Trigger one frame, make sure the BeginFrame callback is called
- elapsed += task_runner->NextPendingTaskDelay();
- time_source->SetNow(elapsed);
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- // Tell the controller we drew
- controller.DidSwapBuffers();
-
- // Trigger another frame, make sure BeginFrame callback runs again
- elapsed += task_runner->NextPendingTaskDelay();
- // Sanity check that previous code didn't move time backward.
- EXPECT_GE(elapsed, time_source->Now());
- time_source->SetNow(elapsed);
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- // Tell the controller we drew, again.
- controller.DidSwapBuffers();
-
- // Trigger another frame. Since two frames are pending, we should not draw.
- elapsed += task_runner->NextPendingTaskDelay();
- // Sanity check that previous code didn't move time backward.
- EXPECT_GE(elapsed, time_source->Now());
- time_source->SetNow(elapsed);
- task_runner->RunPendingTasks();
- EXPECT_FALSE(client.BeganFrame());
-
- // Tell the controller the first frame ended 5ms later
- time_source->SetNow(time_source->Now() +
- base::TimeDelta::FromMilliseconds(5));
- controller.DidSwapBuffersComplete();
-
- // Tick should not have been called
- EXPECT_FALSE(client.BeganFrame());
-
- // Trigger yet another frame. Since one frames is pending, another
- // BeginFrame callback should run.
- elapsed += task_runner->NextPendingTaskDelay();
- // Sanity check that previous code didn't move time backward.
- EXPECT_GE(elapsed, time_source->Now());
- time_source->SetNow(elapsed);
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
-}
-
-TEST(FrameRateControllerTest, TestFrameThrottling_Unthrottled) {
- scoped_refptr<base::TestSimpleTaskRunner> task_runner =
- new base::TestSimpleTaskRunner;
- FakeFrameRateControllerClient client;
- FrameRateController controller(task_runner.get());
-
- controller.SetClient(&client);
- controller.SetMaxSwapsPending(2);
-
- // SetActive triggers 1st frame, make sure the BeginFrame callback
- // is called
- controller.SetActive(true);
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- // Even if we don't call DidSwapBuffers, FrameRateController should
- // still attempt to tick multiple times until it does result in
- // a DidSwapBuffers.
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is
- // called
- controller.DidSwapBuffers();
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
-
- // DidSwapBuffers triggers 3rd frame (> max_frames_pending),
- // make sure the BeginFrame callback is NOT called
- controller.DidSwapBuffers();
- task_runner->RunPendingTasks();
- EXPECT_FALSE(client.BeganFrame());
- client.Reset();
-
- // Make sure there is no pending task since we can't do anything until we
- // receive a DidSwapBuffersComplete anyway.
- EXPECT_FALSE(task_runner->HasPendingTask());
-
- // DidSwapBuffersComplete triggers a frame, make sure the BeginFrame
- // callback is called
- controller.DidSwapBuffersComplete();
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
-}
-
-TEST(FrameRateControllerTest, TestFrameThrottling_NoDoubleTicking) {
- scoped_refptr<base::TestSimpleTaskRunner> task_runner =
- new base::TestSimpleTaskRunner;
- FakeFrameRateControllerClient client;
- FrameRateController controller(task_runner.get());
- controller.SetClient(&client);
-
- // SetActive triggers 1st frame and queues another tick task since the time
- // source isn't throttling.
- controller.SetActive(true);
- task_runner->RunPendingTasks();
- EXPECT_TRUE(client.BeganFrame());
- client.Reset();
- EXPECT_TRUE(task_runner->HasPendingTask());
-
- // Simulate a frame swap. This shouldn't queue a second tick task.
- controller.DidSwapBuffers();
- controller.DidSwapBuffersComplete();
-
- // The client should only be ticked once.
- task_runner->RunPendingTasks();
- EXPECT_EQ(1, client.frame_count());
-}
-
} // namespace
} // namespace cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 5d70010..592cbf1 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -92,11 +92,29 @@ void Scheduler::SetNeedsManageTiles() {
ProcessScheduledActions();
}
+void Scheduler::SetMaxSwapsPending(int max) {
+ state_machine_.SetMaxSwapsPending(max);
+}
+
+void Scheduler::DidSwapBuffers() {
+ state_machine_.DidSwapBuffers();
+ // There is no need to call ProcessScheduledActions here because
+ // swapping should not trigger any new actions.
+ if (!inside_process_scheduled_actions_) {
+ DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE);
+ }
+}
+
void Scheduler::SetSwapUsedIncompleteTile(bool used_incomplete_tile) {
state_machine_.SetSwapUsedIncompleteTile(used_incomplete_tile);
ProcessScheduledActions();
}
+void Scheduler::DidSwapBuffersComplete() {
+ state_machine_.DidSwapBuffersComplete();
+ ProcessScheduledActions();
+}
+
void Scheduler::SetSmoothnessTakesPriority(bool smoothness_takes_priority) {
state_machine_.SetSmoothnessTakesPriority(smoothness_takes_priority);
ProcessScheduledActions();
@@ -433,7 +451,7 @@ void Scheduler::DrawAndSwapForced() {
void Scheduler::DrawAndReadback() {
DrawSwapReadbackResult result = client_->ScheduledActionDrawAndReadback();
- DCHECK(!result.did_swap);
+ DCHECK(!result.did_request_swap);
}
void Scheduler::ProcessScheduledActions() {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 18ecb50..7dd531b 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -75,7 +75,10 @@ class CC_EXPORT Scheduler {
void SetNeedsManageTiles();
+ void SetMaxSwapsPending(int max);
+ void DidSwapBuffers();
void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
+ void DidSwapBuffersComplete();
void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 9a08819..7b2bb43 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -27,6 +27,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
last_frame_number_update_visible_tiles_was_called_(-1),
manage_tiles_funnel_(0),
consecutive_checkerboard_animations_(0),
+ max_pending_swaps_(1),
+ pending_swaps_(0),
needs_redraw_(false),
needs_manage_tiles_(false),
swap_used_incomplete_tile_(false),
@@ -226,6 +228,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const {
minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
minor_state->SetInteger("consecutive_checkerboard_animations",
consecutive_checkerboard_animations_);
+ minor_state->SetInteger("max_pending_swaps_", max_pending_swaps_);
+ minor_state->SetInteger("pending_swaps_", pending_swaps_);
minor_state->SetBoolean("needs_redraw", needs_redraw_);
minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
minor_state->SetBoolean("swap_used_incomplete_tile",
@@ -364,6 +368,10 @@ bool SchedulerStateMachine::ShouldDraw() const {
if (HasSwappedThisFrame())
return false;
+ // Do not queue too many swaps.
+ if (pending_swaps_ >= max_pending_swaps_)
+ return false;
+
// Except for the cases above, do not draw outside of the BeginImplFrame
// deadline.
if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
@@ -472,6 +480,11 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
if (!HasInitializedOutputSurface())
return false;
+ // SwapAck throttle the BeginMainFrames
+ // TODO(brianderson): Remove this restriction to improve throughput.
+ if (pending_swaps_ >= max_pending_swaps_)
+ return false;
+
if (skip_begin_main_frame_to_reduce_latency_)
return false;
@@ -581,15 +594,15 @@ void SchedulerStateMachine::UpdateState(Action action) {
case ACTION_DRAW_AND_SWAP_FORCED:
case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
- bool did_swap = true;
- UpdateStateOnDraw(did_swap);
+ bool did_request_swap = true;
+ UpdateStateOnDraw(did_request_swap);
return;
}
case ACTION_DRAW_AND_SWAP_ABORT:
case ACTION_DRAW_AND_READBACK: {
- bool did_swap = false;
- UpdateStateOnDraw(did_swap);
+ bool did_request_swap = false;
+ UpdateStateOnDraw(did_request_swap);
return;
}
@@ -726,7 +739,7 @@ void SchedulerStateMachine::UpdateStateOnActivation() {
needs_redraw_ = true;
}
-void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
+void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
DCHECK(readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT &&
readback_state_ != READBACK_STATE_WAITING_FOR_REPLACEMENT_ACTIVATION)
<< *AsValue();
@@ -751,7 +764,7 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
draw_if_possible_failed_ = false;
active_tree_needs_first_draw_ = false;
- if (did_swap)
+ if (did_request_swap)
last_frame_number_swap_performed_ = current_frame_number_;
}
@@ -792,8 +805,7 @@ bool SchedulerStateMachine::SupportsProactiveBeginFrame() const {
// Both the synchronous compositor and disabled vsync settings
// make it undesirable to proactively request BeginImplFrames.
// If this is true, the scheduler should poll.
- return !settings_.using_synchronous_renderer_compositor &&
- settings_.throttle_frame_production;
+ return !settings_.using_synchronous_renderer_compositor;
}
// These are the cases where we definitely (or almost definitely) have a
@@ -908,6 +920,10 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const {
if (output_surface_state_ == OUTPUT_SURFACE_LOST)
return true;
+ // SwapAck throttle the deadline since we wont draw and swap anyway.
+ if (pending_swaps_ >= max_pending_swaps_)
+ return false;
+
if (active_tree_needs_first_draw_)
return true;
@@ -996,11 +1012,25 @@ void SchedulerStateMachine::SetNeedsManageTiles() {
}
}
+void SchedulerStateMachine::SetMaxSwapsPending(int max) {
+ max_pending_swaps_ = max;
+}
+
+void SchedulerStateMachine::DidSwapBuffers() {
+ pending_swaps_++;
+ DCHECK_LE(pending_swaps_, max_pending_swaps_);
+}
+
void SchedulerStateMachine::SetSwapUsedIncompleteTile(
bool used_incomplete_tile) {
swap_used_incomplete_tile_ = used_incomplete_tile;
}
+void SchedulerStateMachine::DidSwapBuffersComplete() {
+ DCHECK_GT(pending_swaps_, 0);
+ pending_swaps_--;
+}
+
void SchedulerStateMachine::SetSmoothnessTakesPriority(
bool smoothness_takes_priority) {
smoothness_takes_priority_ = smoothness_takes_priority;
@@ -1132,6 +1162,7 @@ void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
needs_commit_ = true;
}
did_create_and_initialize_first_output_surface_ = true;
+ pending_swaps_ = 0;
}
void SchedulerStateMachine::NotifyBeginMainFrameStarted() {
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index c8d68fc..2779264 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -168,10 +168,21 @@ class CC_EXPORT SchedulerStateMachine {
// ManageTiles will occur shortly (even if no redraw is required).
void SetNeedsManageTiles();
+ // Sets how many swaps can be pending to the OutputSurface.
+ void SetMaxSwapsPending(int max);
+
+ // If the scheduler attempted to draw and swap, this provides feedback
+ // regarding whether or not the swap actually occured. We might skip the
+ // swap when there is not damage, for example.
+ void DidSwapBuffers();
+
// Indicates whether a redraw is required because we are currently rendering
// with a low resolution or checkerboarded tile.
void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
+ // Notification from the OutputSurface that a swap has been consumed.
+ void DidSwapBuffersComplete();
+
// Indicates whether to prioritize animation smoothness over new content
// activation.
void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
@@ -260,7 +271,7 @@ class CC_EXPORT SchedulerStateMachine {
void UpdateStateOnCommit(bool commit_was_aborted);
void UpdateStateOnActivation();
- void UpdateStateOnDraw(bool did_swap);
+ void UpdateStateOnDraw(bool did_request_swap);
void UpdateStateOnManageTiles();
const SchedulerSettings settings_;
@@ -285,6 +296,8 @@ class CC_EXPORT SchedulerStateMachine {
// ManageTile per BeginImplFrame.
int manage_tiles_funnel_;
int consecutive_checkerboard_animations_;
+ int max_pending_swaps_;
+ int pending_swaps_;
bool needs_redraw_;
bool needs_manage_tiles_;
bool swap_used_incomplete_tile_;
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 68dc0d1..21e20ea 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -40,7 +40,7 @@ void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler,
class FakeSchedulerClient : public SchedulerClient {
public:
FakeSchedulerClient()
- : needs_begin_impl_frame_(false) {
+ : needs_begin_impl_frame_(false), automatic_swap_ack_(true) {
Reset();
}
@@ -92,6 +92,9 @@ class FakeSchedulerClient : public SchedulerClient {
void SetSwapWillHappenIfDrawHappens(bool swap_will_happen_if_draw_happens) {
swap_will_happen_if_draw_happens_ = swap_will_happen_if_draw_happens;
}
+ void SetAutomaticSwapAck(bool automatic_swap_ack) {
+ automatic_swap_ack_ = automatic_swap_ack;
+ }
// SchedulerClient implementation.
virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
@@ -117,6 +120,13 @@ class FakeSchedulerClient : public SchedulerClient {
draw_will_happen_
? DrawSwapReadbackResult::DRAW_SUCCESS
: DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
+ bool swap_will_happen =
+ draw_will_happen_ && swap_will_happen_if_draw_happens_;
+ if (swap_will_happen) {
+ scheduler_->DidSwapBuffers();
+ if (automatic_swap_ack_)
+ scheduler_->DidSwapBuffersComplete();
+ }
return DrawSwapReadbackResult(
result,
draw_will_happen_ && swap_will_happen_if_draw_happens_,
@@ -125,18 +135,18 @@ class FakeSchedulerClient : public SchedulerClient {
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndSwapForced");
states_.push_back(scheduler_->StateAsValue().release());
- bool did_swap = swap_will_happen_if_draw_happens_;
+ bool did_request_swap = swap_will_happen_if_draw_happens_;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE {
actions_.push_back("ScheduledActionDrawAndReadback");
states_.push_back(scheduler_->StateAsValue().release());
- bool did_swap = false;
+ bool did_request_swap = false;
bool did_readback = true;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {
actions_.push_back("ScheduledActionCommit");
@@ -178,6 +188,7 @@ class FakeSchedulerClient : public SchedulerClient {
bool needs_begin_impl_frame_;
bool draw_will_happen_;
bool swap_will_happen_if_draw_happens_;
+ bool automatic_swap_ack_;
int num_draws_;
bool log_anticipated_draw_time_change_;
base::TimeTicks posted_begin_impl_frame_deadline_;
@@ -381,10 +392,10 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_swap = true;
+ bool did_request_swap = true;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {}
@@ -497,10 +508,10 @@ class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient {
virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE {
NOTREACHED();
- bool did_swap = false;
+ bool did_request_swap = false;
bool did_readback = false;
return DrawSwapReadbackResult(
- DrawSwapReadbackResult::DRAW_SUCCESS, did_swap, did_readback);
+ DrawSwapReadbackResult::DRAW_SUCCESS, did_request_swap, did_readback);
}
virtual void ScheduledActionCommit() OVERRIDE {}
@@ -1058,6 +1069,9 @@ TEST(SchedulerTest, PollForCommitCompletion) {
client.task_runner().RunPendingTasks(); // Run posted deadline.
EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ scheduler->DidSwapBuffers();
+ scheduler->DidSwapBuffersComplete();
+
// At this point, we've drawn a frame. Start another commit, but hold off on
// the NotifyReadyToCommit for now.
EXPECT_FALSE(scheduler->CommitPending());
@@ -1065,6 +1079,13 @@ TEST(SchedulerTest, PollForCommitCompletion) {
scheduler->BeginFrame(frame_args);
EXPECT_TRUE(scheduler->CommitPending());
+ // Draw and swap the frame, but don't ack the swap to simulate the Browser
+ // blocking on the renderer.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ scheduler->DidSwapBuffers();
+
// Spin the event loop a few times and make sure we get more
// DidAnticipateDrawTimeChange calls every time.
int actions_so_far = client.num_actions_();
@@ -1095,7 +1116,7 @@ TEST(SchedulerTest, PollForCommitCompletion) {
}
}
-TEST(SchedulerTest, BeginRetroFrame) {
+TEST(SchedulerTest, BeginRetroFrameBasic) {
FakeSchedulerClient client;
SchedulerSettings scheduler_settings;
Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
@@ -1116,7 +1137,6 @@ TEST(SchedulerTest, BeginRetroFrame) {
BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
args.deadline += base::TimeDelta::FromHours(1);
scheduler->BeginFrame(args);
-
EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
@@ -1172,5 +1192,93 @@ TEST(SchedulerTest, BeginRetroFrame) {
client.Reset();
}
+TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) {
+ FakeSchedulerClient client;
+ SchedulerSettings scheduler_settings;
+ Scheduler* scheduler = client.CreateScheduler(scheduler_settings);
+ scheduler->SetCanStart();
+ scheduler->SetVisible(true);
+ scheduler->SetCanDraw(true);
+ InitializeOutputSurfaceAndFirstCommit(scheduler, &client);
+
+ // To test swap ack throttling, this test disables automatic swap acks.
+ scheduler->SetMaxSwapsPending(1);
+ client.SetAutomaticSwapAck(false);
+
+ // SetNeedsCommit should begin the frame on the next BeginImplFrame.
+ client.Reset();
+ scheduler->SetNeedsCommit();
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrame", client);
+ client.Reset();
+
+ // Create a BeginFrame with a long deadline to avoid race conditions.
+ // This is the first BeginFrame, which will be handled immediately.
+ BeginFrameArgs args = BeginFrameArgs::CreateForTesting();
+ args.deadline += base::TimeDelta::FromHours(1);
+ scheduler->BeginFrame(args);
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // Queue BeginFrame while we are still handling the previous BeginFrame.
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ EXPECT_EQ(0, client.num_actions_());
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ client.Reset();
+
+ // NotifyReadyToCommit should trigger the pending commit and draw.
+ scheduler->NotifyBeginMainFrameStarted();
+ scheduler->NotifyReadyToCommit();
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // Swapping will put us into a swap throttled state.
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // While swap throttled, BeginRetroFrames should trigger BeginImplFrames
+ // but not a BeginMainFrame or draw.
+ scheduler->SetNeedsCommit();
+ client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame.
+ EXPECT_ACTION("WillBeginImplFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // Queue BeginFrame while we are still handling the previous BeginFrame.
+ args.frame_time += base::TimeDelta::FromSeconds(1);
+ scheduler->BeginFrame(args);
+ EXPECT_EQ(0, client.num_actions_());
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // Take us out of a swap throttled state.
+ scheduler->DidSwapBuffersComplete();
+ EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 0, 1);
+ EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+
+ // BeginImplFrame deadline should draw.
+ scheduler->SetNeedsRedraw();
+ client.task_runner().RunPendingTasks(); // Run posted deadline.
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrame", client, 1, 2);
+ EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending());
+ EXPECT_TRUE(client.needs_begin_impl_frame());
+ client.Reset();
+}
+
} // namespace
} // namespace cc
diff --git a/cc/scheduler/time_source.h b/cc/scheduler/time_source.h
index e45ffbb..3b8d048 100644
--- a/cc/scheduler/time_source.h
+++ b/cc/scheduler/time_source.h
@@ -11,7 +11,7 @@
namespace cc {
-class TimeSourceClient {
+class CC_EXPORT TimeSourceClient {
public:
virtual void OnTimerTick() = 0;
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h
index 975992d..bdbea22 100644
--- a/cc/test/fake_layer_tree_host_impl_client.h
+++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -15,8 +15,9 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
// LayerTreeHostImplClient implementation.
virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
+ virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
+ virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {}
virtual void NotifyReadyToActivate() OVERRIDE {}
diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h
index d64e063..b572c5e 100644
--- a/cc/test/fake_output_surface_client.h
+++ b/cc/test/fake_output_surface_client.h
@@ -25,7 +25,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) OVERRIDE {}
virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE;
virtual void DidSwapBuffers() OVERRIDE {}
- virtual void OnSwapBuffersComplete() OVERRIDE {}
+ virtual void DidSwapBuffersComplete() OVERRIDE {}
virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE {}
virtual void DidLoseOutputSurface() OVERRIDE;
virtual void SetExternalDrawConstraints(
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index ed8de34..5c85d16 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -128,8 +128,8 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
return result;
}
- virtual void OnSwapBuffersComplete() OVERRIDE {
- LayerTreeHostImpl::OnSwapBuffersComplete();
+ virtual void DidSwapBuffersComplete() OVERRIDE {
+ LayerTreeHostImpl::DidSwapBuffersComplete();
test_hooks_->SwapBuffersCompleteOnThread(this);
}
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 46e6012..071332d 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -51,8 +51,6 @@ class FakeFrameRateController : public FrameRateController {
public:
explicit FakeFrameRateController(scoped_refptr<TimeSource> timer)
: FrameRateController(timer) {}
-
- int NumFramesPending() const { return num_frames_pending_; }
};
} // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 84cf31d..9fac004 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1300,8 +1300,8 @@ void LayerTreeHostImpl::DidSwapBuffers() {
client_->DidSwapBuffersOnImplThread();
}
-void LayerTreeHostImpl::OnSwapBuffersComplete() {
- client_->OnSwapBuffersCompleteOnImplThread();
+void LayerTreeHostImpl::DidSwapBuffersComplete() {
+ client_->DidSwapBuffersCompleteOnImplThread();
}
void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) {
@@ -1900,8 +1900,11 @@ bool LayerTreeHostImpl::InitializeRenderer(
GetRendererCapabilities().allow_rasterize_on_demand);
}
- // Setup BeginFrameEmulation if it's not supported natively
- if (!settings_.begin_impl_frame_scheduling_enabled) {
+ if (!settings_.throttle_frame_production) {
+ // Disable VSync
+ output_surface->SetThrottleFrameProduction(false);
+ } else if (!settings_.begin_impl_frame_scheduling_enabled) {
+ // Setup BeginFrameEmulation if it's not supported natively
const base::TimeDelta display_refresh_interval =
base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond /
@@ -1909,7 +1912,6 @@ bool LayerTreeHostImpl::InitializeRenderer(
output_surface->InitializeBeginFrameEmulation(
proxy_->ImplThreadTaskRunner(),
- settings_.throttle_frame_production,
display_refresh_interval);
}
@@ -1917,7 +1919,7 @@ bool LayerTreeHostImpl::InitializeRenderer(
output_surface->capabilities().max_frames_pending;
if (max_frames_pending <= 0)
max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING;
- output_surface->SetMaxFramesPending(max_frames_pending);
+ client_->SetMaxSwapsPendingOnImplThread(max_frames_pending);
resource_provider_ = resource_provider.Pass();
output_surface_ = output_surface.Pass();
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 7f0aab6..a1f4fae 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -63,8 +63,9 @@ class LayerTreeHostImplClient {
public:
virtual void UpdateRendererCapabilitiesOnImplThread() = 0;
virtual void DidLoseOutputSurfaceOnImplThread() = 0;
+ virtual void SetMaxSwapsPendingOnImplThread(int max) = 0;
virtual void DidSwapBuffersOnImplThread() = 0;
- virtual void OnSwapBuffersCompleteOnImplThread() = 0;
+ virtual void DidSwapBuffersCompleteOnImplThread() = 0;
virtual void BeginFrame(const BeginFrameArgs& args) = 0;
virtual void OnCanDrawStateChanged(bool can_draw) = 0;
virtual void NotifyReadyToActivate() = 0;
@@ -233,7 +234,7 @@ class CC_EXPORT LayerTreeHostImpl
bool valid_for_tile_management) OVERRIDE;
virtual void DidLoseOutputSurface() OVERRIDE;
virtual void DidSwapBuffers() OVERRIDE;
- virtual void OnSwapBuffersComplete() OVERRIDE;
+ virtual void DidSwapBuffersComplete() OVERRIDE;
virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE;
virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
virtual void SetTreeActivationCallback(const base::Closure& callback)
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 04d377e..35cd1fa 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -108,8 +108,9 @@ class LayerTreeHostImplTest : public testing::Test,
virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE {}
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
+ virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
+ virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {}
virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
on_can_draw_state_changed_called_ = true;
@@ -5354,7 +5355,7 @@ class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
CompositorFrameMetadataTest()
: swap_buffers_complete_(0) {}
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
+ virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE {
swap_buffers_complete_++;
}
@@ -5372,7 +5373,7 @@ TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
}
CompositorFrameAck ack;
host_impl_->ReclaimResources(&ack);
- host_impl_->OnSwapBuffersComplete();
+ host_impl_->DidSwapBuffersComplete();
EXPECT_EQ(swap_buffers_complete_, 1);
}
diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc
index 7cf8e69..ab5e4c2 100644
--- a/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -240,7 +240,6 @@ class LayerTreeHostDelegatedTest : public LayerTreeTest {
for (size_t i = 0; i < resources_to_return.size(); ++i)
output_surface()->ReturnResource(resources_to_return[i], &ack);
host_impl->ReclaimResources(&ack);
- host_impl->OnSwapBuffersComplete();
}
};
@@ -1648,7 +1647,6 @@ class LayerTreeHostDelegatedTestResourceSentToParent
CompositorFrameAck ack;
output_surface()->ReturnResource(map.find(999)->second, &ack);
host_impl->ReclaimResources(&ack);
- host_impl->OnSwapBuffersComplete();
}
virtual void UnusedResourcesAreAvailable() OVERRIDE {
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 5ccef20..72f16dc 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -382,8 +382,8 @@ void SingleThreadProxy::DidSwapBuffersOnImplThread() {
client_->DidPostSwapBuffers();
}
-void SingleThreadProxy::OnSwapBuffersCompleteOnImplThread() {
- TRACE_EVENT0("cc", "SingleThreadProxy::OnSwapBuffersCompleteOnImplThread");
+void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
+ TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
client_->DidCompleteSwapBuffers();
}
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index a52a6f5..0f86673 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -55,8 +55,9 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
// LayerTreeHostImplClient implementation
virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE;
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
+ virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE {}
virtual void DidSwapBuffersOnImplThread() OVERRIDE;
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
+ virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE;
virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void NotifyReadyToActivate() OVERRIDE;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index e84937b..cac9bc6 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -433,9 +433,18 @@ void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
impl().scheduler->DidLoseOutputSurface();
}
-void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
- TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
+void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
+ impl().scheduler->SetMaxSwapsPending(max);
+}
+
+void ThreadProxy::DidSwapBuffersOnImplThread() {
+ impl().scheduler->DidSwapBuffers();
+}
+
+void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
+ TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
DCHECK(IsImplThread());
+ impl().scheduler->DidSwapBuffersComplete();
Proxy::MainThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
@@ -1237,10 +1246,10 @@ DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal(
impl().readback_request = NULL;
} else if (draw_frame) {
DCHECK(swap_requested);
- result.did_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
+ result.did_request_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
// We don't know if we have incomplete tiles if we didn't actually swap.
- if (result.did_swap) {
+ if (result.did_request_swap) {
DCHECK(!frame.has_no_damage);
SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile);
}
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index b105c93..e2a8f21 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -73,8 +73,9 @@ class ThreadProxy : public Proxy,
// LayerTreeHostImplClient implementation
virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE;
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
- virtual void DidSwapBuffersOnImplThread() OVERRIDE {}
- virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
+ virtual void SetMaxSwapsPendingOnImplThread(int max) OVERRIDE;
+ virtual void DidSwapBuffersOnImplThread() OVERRIDE;
+ virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE;
virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE;
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void NotifyReadyToActivate() OVERRIDE;