summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc')
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/output/output_surface.cc149
-rw-r--r--cc/output/output_surface.h44
-rw-r--r--cc/output/output_surface_client.h2
-rw-r--r--cc/output/output_surface_unittest.cc159
-rw-r--r--cc/scheduler/frame_rate_controller.cc26
-rw-r--r--cc/scheduler/frame_rate_controller.h21
-rw-r--r--cc/scheduler/frame_rate_controller_unittest.cc6
-rw-r--r--cc/scheduler/scheduler.cc125
-rw-r--r--cc/scheduler/scheduler.h32
-rw-r--r--cc/scheduler/scheduler_settings.cc3
-rw-r--r--cc/scheduler/scheduler_settings.h1
-rw-r--r--cc/scheduler/scheduler_state_machine.cc15
-rw-r--r--cc/scheduler/scheduler_state_machine.h6
-rw-r--r--cc/scheduler/scheduler_state_machine_unittest.cc2
-rw-r--r--cc/scheduler/scheduler_unittest.cc283
-rw-r--r--cc/scheduler/vsync_time_source.cc76
-rw-r--r--cc/scheduler/vsync_time_source.h78
-rw-r--r--cc/scheduler/vsync_time_source_unittest.cc124
-rw-r--r--cc/test/fake_layer_tree_host_impl_client.h3
-rw-r--r--cc/test/fake_output_surface.cc26
-rw-r--r--cc/test/fake_output_surface.h4
-rw-r--r--cc/test/layer_tree_test.cc8
-rw-r--r--cc/test/layer_tree_test.h2
-rw-r--r--cc/test/scheduler_test_common.cc10
-rw-r--r--cc/test/scheduler_test_common.h30
-rw-r--r--cc/trees/layer_tree_host_impl.cc24
-rw-r--r--cc/trees/layer_tree_host_impl.h8
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc2
-rw-r--r--cc/trees/layer_tree_host_unittest.cc62
-rw-r--r--cc/trees/layer_tree_host_unittest_animation.cc4
-rw-r--r--cc/trees/proxy.cc4
-rw-r--r--cc/trees/proxy.h3
-rw-r--r--cc/trees/single_thread_proxy.h2
-rw-r--r--cc/trees/thread_proxy.cc109
-rw-r--r--cc/trees/thread_proxy.h41
37 files changed, 692 insertions, 805 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index d08ade1..dcc8b23 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -321,8 +321,6 @@
'scheduler/texture_uploader.cc',
'scheduler/texture_uploader.h',
'scheduler/time_source.h',
- 'scheduler/vsync_time_source.cc',
- 'scheduler/vsync_time_source.h',
'trees/damage_tracker.cc',
'trees/damage_tracker.h',
'trees/layer_sorter.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 07cecc0..f214015 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -68,7 +68,6 @@
'scheduler/scheduler_state_machine_unittest.cc',
'scheduler/scheduler_unittest.cc',
'scheduler/texture_uploader_unittest.cc',
- 'scheduler/vsync_time_source_unittest.cc',
'test/fake_web_graphics_context_3d_unittest.cc',
'trees/damage_tracker_unittest.cc',
'trees/layer_sorter_unittest.cc',
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 0889b96..6efa083 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -9,12 +9,14 @@
#include <vector>
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/output_surface_client.h"
+#include "cc/scheduler/delay_based_time_source.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -32,7 +34,7 @@ class OutputSurfaceCallbacks
WebGraphicsSwapBuffersCompleteCallbackCHROMIUM,
public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
- explicit OutputSurfaceCallbacks(OutputSurfaceClient* client)
+ explicit OutputSurfaceCallbacks(OutputSurface* client)
: client_(client) {
DCHECK(client_);
}
@@ -44,50 +46,155 @@ class OutputSurfaceCallbacks
virtual void onContextLost() { client_->DidLoseOutputSurface(); }
private:
- OutputSurfaceClient* client_;
+ OutputSurface* client_;
};
OutputSurface::OutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : client_(NULL),
- context3d_(context3d.Pass()),
+ : context3d_(context3d.Pass()),
has_gl_discard_backbuffer_(false),
has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this) {
+ weak_ptr_factory_(this),
+ max_frames_pending_(0),
+ pending_swap_buffers_(0),
+ begin_frame_pending_(false),
+ client_(NULL) {
}
OutputSurface::OutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device)
- : client_(NULL),
- software_device_(software_device.Pass()),
+ : software_device_(software_device.Pass()),
has_gl_discard_backbuffer_(false),
has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this) {
+ weak_ptr_factory_(this),
+ max_frames_pending_(0),
+ pending_swap_buffers_(0),
+ begin_frame_pending_(false),
+ client_(NULL) {
}
OutputSurface::OutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
scoped_ptr<cc::SoftwareOutputDevice> software_device)
- : client_(NULL),
- context3d_(context3d.Pass()),
+ : context3d_(context3d.Pass()),
software_device_(software_device.Pass()),
has_gl_discard_backbuffer_(false),
has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this) {
+ weak_ptr_factory_(this),
+ max_frames_pending_(0),
+ pending_swap_buffers_(0),
+ begin_frame_pending_(false),
+ client_(NULL) {
+}
+
+void OutputSurface::InitializeBeginFrameEmulation(
+ Thread* thread,
+ bool throttle_frame_production,
+ base::TimeDelta interval) {
+ if (throttle_frame_production){
+ frame_rate_controller_.reset(
+ new FrameRateController(
+ DelayBasedTimeSource::Create(interval, thread)));
+ } else {
+ frame_rate_controller_.reset(new FrameRateController(thread));
+ }
+
+ frame_rate_controller_->SetClient(this);
+ frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
+
+ // 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::OnVSyncParametersChanged(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged",
+ "timebase", (timebase - base::TimeTicks()).InSecondsF(),
+ "interval", interval.InSecondsF());
+ if (frame_rate_controller_)
+ frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
+}
+
+void OutputSurface::FrameRateControllerTick(bool throttled) {
+ DCHECK(frame_rate_controller_);
+ if (!throttled)
+ BeginFrame(frame_rate_controller_->LastTickTime());
+}
+
+// Forwarded to OutputSurfaceClient
+void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) {
+ TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
+ client_->SetNeedsRedrawRect(damage_rect);
+}
+
+void OutputSurface::SetNeedsBeginFrame(bool enable) {
+ TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
+ begin_frame_pending_ = false;
+ if (frame_rate_controller_)
+ frame_rate_controller_->SetActive(enable);
+}
+
+void OutputSurface::BeginFrame(base::TimeTicks frame_time) {
+ if (begin_frame_pending_ ||
+ (pending_swap_buffers_ >= max_frames_pending_ && max_frames_pending_ > 0))
+ return;
+ TRACE_EVENT1("cc", "OutputSurface::BeginFrame",
+ "pending_swap_buffers_", pending_swap_buffers_);
+ begin_frame_pending_ = true;
+ client_->BeginFrame(frame_time);
+}
+
+void OutputSurface::DidSwapBuffers() {
+ begin_frame_pending_ = false;
+ pending_swap_buffers_++;
+ TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers",
+ "pending_swap_buffers_", pending_swap_buffers_);
+ if (frame_rate_controller_)
+ frame_rate_controller_->DidSwapBuffers();
+}
+
+void OutputSurface::OnSwapBuffersComplete(const CompositorFrameAck* ack) {
+ pending_swap_buffers_--;
+ TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete",
+ "pending_swap_buffers_", pending_swap_buffers_);
+ client_->OnSwapBuffersComplete(ack);
+ if (frame_rate_controller_)
+ frame_rate_controller_->DidSwapBuffersComplete();
+}
+
+void OutputSurface::DidLoseOutputSurface() {
+ TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
+ begin_frame_pending_ = false;
+ pending_swap_buffers_ = 0;
+ client_->DidLoseOutputSurface();
+}
+
+void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform,
+ gfx::Rect viewport) {
+ client_->SetExternalDrawConstraints(transform, viewport);
}
OutputSurface::~OutputSurface() {
+ if (frame_rate_controller_)
+ frame_rate_controller_->SetActive(false);
}
bool OutputSurface::ForcedDrawToSoftwareDevice() const {
return false;
}
-bool OutputSurface::BindToClient(
- cc::OutputSurfaceClient* client) {
+bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
DCHECK(client);
client_ = client;
bool success = true;
@@ -143,7 +250,7 @@ void OutputSurface::SetContext3D(
context3d_ = context3d.Pass();
- callbacks_.reset(new OutputSurfaceCallbacks(client_));
+ callbacks_.reset(new OutputSurfaceCallbacks(this));
context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get());
context3d_->setContextLostCallback(callbacks_.get());
}
@@ -206,20 +313,16 @@ void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
if (!has_swap_buffers_complete_callback_)
PostSwapBuffersComplete();
+
+ DidSwapBuffers();
}
void OutputSurface::PostSwapBuffersComplete() {
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&OutputSurface::SwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void OutputSurface::SwapBuffersComplete() {
- if (!client_)
- return;
-
- client_->OnSwapBuffersComplete(NULL);
+ base::Bind(&OutputSurface::OnSwapBuffersComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ static_cast<CompositorFrameAck*>(NULL)));
}
} // namespace cc
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index d263d3a..8f782d7 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -12,6 +12,7 @@
#include "cc/base/cc_export.h"
#include "cc/output/context_provider.h"
#include "cc/output/software_output_device.h"
+#include "cc/scheduler/frame_rate_controller.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
namespace ui { struct LatencyInfo; }
@@ -19,13 +20,16 @@ namespace ui { struct LatencyInfo; }
namespace gfx {
class Rect;
class Size;
+class Transform;
}
namespace cc {
class CompositorFrame;
+class CompositorFrameAck;
class OutputSurfaceClient;
class OutputSurfaceCallbacks;
+class Thread;
// Represents the output surface for a compositor. The compositor owns
// and manages its destruction. Its lifetime is:
@@ -34,7 +38,7 @@ class OutputSurfaceCallbacks;
// From here on, it will only be used on the compositor thread.
// 3. If the 3D context is lost, then the compositor will delete the output
// surface (on the compositor thread) and go back to step 1.
-class CC_EXPORT OutputSurface {
+class CC_EXPORT OutputSurface : public FrameRateControllerClient {
public:
explicit OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
@@ -83,6 +87,13 @@ class CC_EXPORT OutputSurface {
// thread.
virtual bool BindToClient(OutputSurfaceClient* client);
+ void InitializeBeginFrameEmulation(
+ Thread* thread,
+ bool throttle_frame_production,
+ base::TimeDelta interval);
+
+ void SetMaxFramesPending(int max_frames_pending);
+
virtual void EnsureBackbuffer();
virtual void DiscardBackbuffer();
@@ -103,7 +114,7 @@ class CC_EXPORT OutputSurface {
// Requests a BeginFrame notification from the output surface. The
// notification will be delivered by calling
// OutputSurfaceClient::BeginFrame until the callback is disabled.
- virtual void SetNeedsBeginFrame(bool enable) {}
+ virtual void SetNeedsBeginFrame(bool enable);
protected:
// Synchronously initialize context3d and enter hardware mode.
@@ -116,7 +127,6 @@ class CC_EXPORT OutputSurface {
void PostSwapBuffersComplete();
- OutputSurfaceClient* client_;
struct cc::OutputSurface::Capabilities capabilities_;
scoped_ptr<OutputSurfaceCallbacks> callbacks_;
scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
@@ -125,12 +135,34 @@ class CC_EXPORT OutputSurface {
bool has_swap_buffers_complete_callback_;
gfx::Size surface_size_;
float device_scale_factor_;
+ base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
+
+ // The FrameRateController is deprecated.
+ // Platforms should move to native BeginFrames instead.
+ void OnVSyncParametersChanged(base::TimeTicks timebase,
+ base::TimeDelta interval);
+ virtual void FrameRateControllerTick(bool throttled) OVERRIDE;
+ scoped_ptr<FrameRateController> frame_rate_controller_;
+ int max_frames_pending_;
+ int pending_swap_buffers_;
+ bool begin_frame_pending_;
+
+ // Forwarded to OutputSurfaceClient but threaded through OutputSurface
+ // first so OutputSurface has a chance to update the FrameRateController
+ bool HasClient() { return !!client_; }
+ void SetNeedsRedrawRect(gfx::Rect damage_rect);
+ void BeginFrame(base::TimeTicks frame_time);
+ void DidSwapBuffers();
+ void OnSwapBuffersComplete(const CompositorFrameAck* ack);
+ void DidLoseOutputSurface();
+ void SetExternalDrawConstraints(const gfx::Transform& transform,
+ gfx::Rect viewport);
private:
- void SetContext3D(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
- void SwapBuffersComplete();
+ OutputSurfaceClient* client_;
+ friend class OutputSurfaceCallbacks;
- base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
+ void SetContext3D(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
DISALLOW_COPY_AND_ASSIGN(OutputSurface);
};
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h
index f5999c3..d727629 100644
--- a/cc/output/output_surface_client.h
+++ b/cc/output/output_surface_client.h
@@ -27,8 +27,6 @@ class CC_EXPORT OutputSurfaceClient {
virtual bool DeferredInitialize(
scoped_refptr<ContextProvider> offscreen_context_provider) = 0;
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) = 0;
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) = 0;
virtual void BeginFrame(base::TimeTicks frame_time) = 0;
virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) = 0;
virtual void DidLoseOutputSurface() = 0;
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index ebc018f..7dcb1cc 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -5,6 +5,7 @@
#include "cc/output/output_surface.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
+#include "cc/test/scheduler_test_common.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,19 +26,43 @@ class TestOutputSurface : public OutputSurface {
scoped_ptr<cc::SoftwareOutputDevice> software_device)
: OutputSurface(context3d.Pass(), software_device.Pass()) {}
- OutputSurfaceClient* client() { return client_; }
-
bool InitializeNewContext3D(
scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) {
return InitializeAndSetContext3D(new_context3d.Pass(),
scoped_refptr<ContextProvider>());
}
+
+ bool HasClientForTesting() {
+ return HasClient();
+ }
+
+ void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ OnVSyncParametersChanged(timebase, interval);
+ }
+
+ void BeginFrameForTesting(base::TimeTicks frame_time) {
+ BeginFrame(frame_time);
+ }
+
+ void DidSwapBuffersForTesting() {
+ DidSwapBuffers();
+ }
+
+ int pending_swap_buffers() {
+ return pending_swap_buffers_;
+ }
+
+ void OnSwapBuffersCompleteForTesting() {
+ OnSwapBuffersComplete(NULL);
+ }
};
class FakeOutputSurfaceClient : public OutputSurfaceClient {
public:
FakeOutputSurfaceClient()
- : deferred_initialize_result_(true),
+ : begin_frame_count_(0),
+ deferred_initialize_result_(true),
deferred_initialize_called_(false),
did_lose_output_surface_called_(false) {}
@@ -47,9 +72,9 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
return deferred_initialize_result_;
}
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
- virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {}
+ virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {
+ begin_frame_count_++;
+ }
virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {}
virtual void DidLoseOutputSurface() OVERRIDE {
did_lose_output_surface_called_ = true;
@@ -57,6 +82,10 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
gfx::Rect viewport) OVERRIDE {}
+ int begin_frame_count() {
+ return begin_frame_count_;
+ }
+
void set_deferred_initialize_result(bool result) {
deferred_initialize_result_ = result;
}
@@ -70,6 +99,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
}
private:
+ int begin_frame_count_;
bool deferred_initialize_result_;
bool deferred_initialize_called_;
bool did_lose_output_surface_called_;
@@ -81,11 +111,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
FakeOutputSurfaceClient client;
EXPECT_TRUE(output_surface.BindToClient(&client));
- EXPECT_EQ(&client, output_surface.client());
+ EXPECT_TRUE(output_surface.HasClientForTesting());
EXPECT_FALSE(client.deferred_initialize_called());
// Verify DidLoseOutputSurface callback is hooked up correctly.
@@ -104,11 +134,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
FakeOutputSurfaceClient client;
EXPECT_FALSE(output_surface.BindToClient(&client));
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
}
class InitializeNewContext3D : public ::testing::Test {
@@ -121,13 +151,13 @@ class InitializeNewContext3D : public ::testing::Test {
protected:
void BindOutputSurface() {
EXPECT_TRUE(output_surface_.BindToClient(&client_));
- EXPECT_EQ(&client_, output_surface_.client());
+ EXPECT_TRUE(output_surface_.HasClientForTesting());
}
void InitializeNewContextExpectFail() {
EXPECT_FALSE(output_surface_.InitializeNewContext3D(
context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
- EXPECT_EQ(&client_, output_surface_.client());
+ EXPECT_TRUE(output_surface_.HasClientForTesting());
EXPECT_FALSE(output_surface_.context3d());
EXPECT_TRUE(output_surface_.software_device());
@@ -164,5 +194,110 @@ TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) {
InitializeNewContextExpectFail();
}
+TEST(OutputSurfaceTest, BeginFrameEmulation) {
+ scoped_ptr<TestWebGraphicsContext3D> context3d =
+ TestWebGraphicsContext3D::Create();
+
+ TestOutputSurface output_surface(
+ context3d.PassAs<WebKit::WebGraphicsContext3D>());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
+
+ FakeOutputSurfaceClient client;
+ EXPECT_TRUE(output_surface.BindToClient(&client));
+ EXPECT_TRUE(output_surface.HasClientForTesting());
+ EXPECT_FALSE(client.deferred_initialize_called());
+
+ // Initialize BeginFrame emulation
+ FakeThread impl_thread;
+ bool throttle_frame_production = true;
+ const base::TimeDelta display_refresh_interval =
+ base::TimeDelta::FromMicroseconds(16666);
+
+ output_surface.InitializeBeginFrameEmulation(
+ &impl_thread,
+ throttle_frame_production,
+ display_refresh_interval);
+
+ output_surface.SetMaxFramesPending(2);
+
+ // 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.
+ EXPECT_FALSE(impl_thread.HasPendingTask());
+ output_surface.SetNeedsBeginFrame(true);
+ EXPECT_TRUE(impl_thread.HasPendingTask());
+
+ // BeginFrame should be called on the first tick.
+ impl_thread.RunPendingTask();
+ 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.
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
+
+ // DidSwapBuffers should clear the pending BeginFrame.
+ output_surface.DidSwapBuffersForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+ impl_thread.RunPendingTask();
+ 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();
+ EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+ impl_thread.RunPendingTask();
+ 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);
+ impl_thread.RunPendingTask();
+ 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);
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
+ output_surface.SetNeedsBeginFrame(false);
+ impl_thread.RunPendingTask();
+ EXPECT_FALSE(impl_thread.HasPendingTask());
+ EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should be
+ // allowed.
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
+ // still be throttled by pending begin frames however.
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
+ // also be throttled by pending swap buffers.
+ output_surface.DidSwapBuffersForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+}
+
} // namespace
} // namespace cc
diff --git a/cc/scheduler/frame_rate_controller.cc b/cc/scheduler/frame_rate_controller.cc
index b4f1272..90cf0d7 100644
--- a/cc/scheduler/frame_rate_controller.cc
+++ b/cc/scheduler/frame_rate_controller.cc
@@ -21,7 +21,9 @@ class FrameRateControllerTimeSourceAdapter : public TimeSourceClient {
}
virtual ~FrameRateControllerTimeSourceAdapter() {}
- virtual void OnTimerTick() OVERRIDE { frame_rate_controller_->OnTimerTick(); }
+ virtual void OnTimerTick() OVERRIDE {
+ frame_rate_controller_->OnTimerTick();
+ }
private:
explicit FrameRateControllerTimeSourceAdapter(
@@ -34,7 +36,7 @@ class FrameRateControllerTimeSourceAdapter : public TimeSourceClient {
FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
: client_(NULL),
num_frames_pending_(0),
- max_frames_pending_(0),
+ max_swaps_pending_(0),
time_source_(timer),
active_(false),
is_time_source_throttling_(true),
@@ -48,7 +50,7 @@ FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
FrameRateController::FrameRateController(Thread* thread)
: client_(NULL),
num_frames_pending_(0),
- max_frames_pending_(0),
+ max_swaps_pending_(0),
active_(false),
is_time_source_throttling_(false),
weak_factory_(this),
@@ -75,9 +77,9 @@ void FrameRateController::SetActive(bool active) {
}
}
-void FrameRateController::SetMaxFramesPending(int max_frames_pending) {
- DCHECK_GE(max_frames_pending, 0);
- max_frames_pending_ = max_frames_pending;
+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,
@@ -87,15 +89,17 @@ void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase,
}
void FrameRateController::OnTimerTick() {
+ TRACE_EVENT0("cc", "FrameRateController::OnTimerTick");
DCHECK(active_);
// Check if we have too many frames in flight.
bool throttled =
- max_frames_pending_ && num_frames_pending_ >= max_frames_pending_;
+ max_swaps_pending_ && num_frames_pending_ >= max_swaps_pending_;
TRACE_COUNTER_ID1("cc", "ThrottledCompositor", thread_, throttled);
- if (client_)
- client_->BeginFrame(throttled);
+ if (client_) {
+ client_->FrameRateControllerTick(throttled);
+ }
if (!is_time_source_throttling_ && !throttled)
PostManualTick();
@@ -108,7 +112,9 @@ void FrameRateController::PostManualTick() {
}
}
-void FrameRateController::ManualTick() { OnTimerTick(); }
+void FrameRateController::ManualTick() {
+ OnTimerTick();
+}
void FrameRateController::DidSwapBuffers() {
num_frames_pending_++;
diff --git a/cc/scheduler/frame_rate_controller.h b/cc/scheduler/frame_rate_controller.h
index 070c26a..70964e2 100644
--- a/cc/scheduler/frame_rate_controller.h
+++ b/cc/scheduler/frame_rate_controller.h
@@ -15,18 +15,21 @@ namespace cc {
class Thread;
class TimeSource;
+class FrameRateController;
class CC_EXPORT FrameRateControllerClient {
- public:
- // Throttled is true when we have a maximum number of frames pending.
- virtual void BeginFrame(bool throttled) = 0;
-
protected:
virtual ~FrameRateControllerClient() {}
+
+ public:
+ // Throttled is true when we have a maximum number of frames pending.
+ virtual void FrameRateControllerTick(bool throttled) = 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 {
public:
enum {
@@ -41,6 +44,7 @@ class CC_EXPORT FrameRateController {
void SetClient(FrameRateControllerClient* client) { client_ = client; }
void SetActive(bool active);
+ bool IsActive() { return active_; }
// Use the following methods to adjust target frame rate.
//
@@ -51,9 +55,9 @@ class CC_EXPORT FrameRateController {
void DidSwapBuffers();
void DidSwapBuffersComplete();
void DidAbortAllPendingFrames();
- void SetMaxFramesPending(int max_frames_pending); // 0 for unlimited.
- int MaxFramesPending() const { return max_frames_pending_; }
- int NumFramesPendingForTesting() const { return num_frames_pending_; }
+ void SetMaxSwapsPending(int max_swaps_pending); // 0 for unlimited.
+ int MaxSwapsPending() const { return max_swaps_pending_; }
+ int NumSwapsPendingForTesting() const { return num_frames_pending_; }
// This returns null for unthrottled frame-rate.
base::TimeTicks NextTickTime();
@@ -73,7 +77,7 @@ class CC_EXPORT FrameRateController {
FrameRateControllerClient* client_;
int num_frames_pending_;
- int max_frames_pending_;
+ int max_swaps_pending_;
scoped_refptr<TimeSource> time_source_;
scoped_ptr<FrameRateControllerTimeSourceAdapter> time_source_client_adapter_;
bool active_;
@@ -83,6 +87,7 @@ class CC_EXPORT FrameRateController {
base::WeakPtrFactory<FrameRateController> weak_factory_;
Thread* thread_;
+ 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 183f576..3fcf4a7 100644
--- a/cc/scheduler/frame_rate_controller_unittest.cc
+++ b/cc/scheduler/frame_rate_controller_unittest.cc
@@ -17,7 +17,7 @@ class FakeFrameRateControllerClient : public cc::FrameRateControllerClient {
void Reset() { began_frame_ = false; }
bool BeganFrame() const { return began_frame_; }
- virtual void BeginFrame(bool throttled) OVERRIDE {
+ virtual void FrameRateControllerTick(bool throttled) OVERRIDE {
began_frame_ = !throttled;
}
@@ -74,7 +74,7 @@ TEST(FrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight) {
controller.SetClient(&client);
controller.SetActive(true);
- controller.SetMaxFramesPending(2);
+ controller.SetMaxSwapsPending(2);
base::TimeTicks elapsed; // Muck around with time a bit
@@ -132,7 +132,7 @@ TEST(FrameRateControllerTest, TestFrameThrottling_Unthrottled) {
FrameRateController controller(&thread);
controller.SetClient(&client);
- controller.SetMaxFramesPending(2);
+ controller.SetMaxSwapsPending(2);
// SetActive triggers 1st frame, make sure the BeginFrame callback
// is called
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index d308b0d..7110bff 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -7,23 +7,29 @@
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "cc/base/thread.h"
namespace cc {
Scheduler::Scheduler(SchedulerClient* client,
- scoped_ptr<FrameRateController> frame_rate_controller,
const SchedulerSettings& scheduler_settings)
: settings_(scheduler_settings),
client_(client),
- frame_rate_controller_(frame_rate_controller.Pass()),
+ weak_factory_(this),
+ last_set_needs_begin_frame_(false),
+ has_pending_begin_frame_(false),
+ last_begin_frame_time_(base::TimeTicks()),
+ // TODO(brianderson): Pass with BeginFrame in the near future.
+ interval_(base::TimeDelta::FromMicroseconds(16666)),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false) {
DCHECK(client_);
- frame_rate_controller_->SetClient(this);
DCHECK(!state_machine_.BeginFrameNeededByImplThread());
}
-Scheduler::~Scheduler() { frame_rate_controller_->SetActive(false); }
+Scheduler::~Scheduler() {
+ client_->SetNeedsBeginFrameOnImplThread(false);
+}
void Scheduler::SetCanStart() {
state_machine_.SetCanStart();
@@ -88,23 +94,6 @@ void Scheduler::BeginFrameAbortedByMainThread() {
ProcessScheduledActions();
}
-void Scheduler::SetMaxFramesPending(int max_frames_pending) {
- frame_rate_controller_->SetMaxFramesPending(max_frames_pending);
-}
-
-int Scheduler::MaxFramesPending() const {
- return frame_rate_controller_->MaxFramesPending();
-}
-
-int Scheduler::NumFramesPendingForTesting() const {
- return frame_rate_controller_->NumFramesPendingForTesting();
-}
-
-void Scheduler::DidSwapBuffersComplete() {
- TRACE_EVENT0("cc", "Scheduler::DidSwapBuffersComplete");
- frame_rate_controller_->DidSwapBuffersComplete();
-}
-
void Scheduler::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
state_machine_.DidLoseOutputSurface();
@@ -113,31 +102,69 @@ void Scheduler::DidLoseOutputSurface() {
void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
- frame_rate_controller_->DidAbortAllPendingFrames();
state_machine_.DidCreateAndInitializeOutputSurface();
+ has_pending_begin_frame_ = false;
+ last_set_needs_begin_frame_ = false;
ProcessScheduledActions();
}
-void Scheduler::SetTimebaseAndInterval(base::TimeTicks timebase,
- base::TimeDelta interval) {
- frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
-}
-
base::TimeTicks Scheduler::AnticipatedDrawTime() {
- return frame_rate_controller_->NextTickTime();
+ TRACE_EVENT0("cc", "Scheduler::AnticipatedDrawTime");
+ base::TimeTicks now = base::TimeTicks::Now();
+ int64 intervals = ((now - last_begin_frame_time_) / interval_) + 1;
+ return last_begin_frame_time_ + (interval_ * intervals);
}
base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
- return frame_rate_controller_->LastTickTime();
+ return last_begin_frame_time_;
+}
+
+void Scheduler::SetupNextBeginFrameIfNeeded() {
+ // Determine if we need BeginFrame notifications.
+ // If we do, always request the BeginFrame immediately.
+ // If not, only disable on the next BeginFrame to avoid unnecessary toggles.
+ // The synchronous renderer compositor requires immediate disables though.
+ bool needs_begin_frame = state_machine_.BeginFrameNeededByImplThread();
+ if ((needs_begin_frame ||
+ state_machine_.inside_begin_frame() ||
+ settings_.using_synchronous_renderer_compositor) &&
+ (needs_begin_frame != last_set_needs_begin_frame_)) {
+ client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
+ last_set_needs_begin_frame_ = needs_begin_frame;
+ }
+
+ // Request another BeginFrame if we haven't drawn for now until we have
+ // deadlines implemented.
+ if (state_machine_.inside_begin_frame() && has_pending_begin_frame_) {
+ has_pending_begin_frame_ = false;
+ client_->SetNeedsBeginFrameOnImplThread(true);
+ }
}
-void Scheduler::BeginFrame(bool throttled) {
- TRACE_EVENT1("cc", "Scheduler::BeginFrame", "throttled", throttled);
- if (!throttled)
- state_machine_.DidEnterBeginFrame();
+void Scheduler::BeginFrame(base::TimeTicks frame_time) {
+ TRACE_EVENT0("cc", "Scheduler::BeginFrame");
+ DCHECK(!has_pending_begin_frame_);
+ has_pending_begin_frame_ = true;
+ last_begin_frame_time_ = frame_time;
+ state_machine_.DidEnterBeginFrame();
+ state_machine_.SetFrameTime(frame_time);
ProcessScheduledActions();
- if (!throttled)
- state_machine_.DidLeaveBeginFrame();
+ state_machine_.DidLeaveBeginFrame();
+}
+
+void Scheduler::DrawAndSwapIfPossible() {
+ ScheduledActionDrawAndSwapResult result =
+ client_->ScheduledActionDrawAndSwapIfPossible();
+ state_machine_.DidDrawIfPossibleCompleted(result.did_draw);
+ if (result.did_swap)
+ has_pending_begin_frame_ = false;
+}
+
+void Scheduler::DrawAndSwapForced() {
+ ScheduledActionDrawAndSwapResult result =
+ client_->ScheduledActionDrawAndSwapForced();
+ if (result.did_swap)
+ has_pending_begin_frame_ = false;
}
void Scheduler::ProcessScheduledActions() {
@@ -151,9 +178,6 @@ void Scheduler::ProcessScheduledActions() {
SchedulerStateMachine::Action action = state_machine_.NextAction();
while (action != SchedulerStateMachine::ACTION_NONE) {
state_machine_.UpdateState(action);
- TRACE_EVENT1(
- "cc", "Scheduler::ProcessScheduledActions()", "action", action);
-
switch (action) {
case SchedulerStateMachine::ACTION_NONE:
break;
@@ -169,23 +193,12 @@ void Scheduler::ProcessScheduledActions() {
case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED:
client_->ScheduledActionActivatePendingTreeIfNeeded();
break;
- case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: {
- frame_rate_controller_->DidSwapBuffers();
- ScheduledActionDrawAndSwapResult result =
- client_->ScheduledActionDrawAndSwapIfPossible();
- state_machine_.DidDrawIfPossibleCompleted(result.did_draw);
- if (!result.did_swap)
- frame_rate_controller_->DidSwapBuffersComplete();
+ case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE:
+ DrawAndSwapIfPossible();
break;
- }
- case SchedulerStateMachine::ACTION_DRAW_FORCED: {
- frame_rate_controller_->DidSwapBuffers();
- ScheduledActionDrawAndSwapResult result =
- client_->ScheduledActionDrawAndSwapForced();
- if (!result.did_swap)
- frame_rate_controller_->DidSwapBuffersComplete();
+ case SchedulerStateMachine::ACTION_DRAW_FORCED:
+ DrawAndSwapForced();
break;
- }
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
client_->ScheduledActionBeginOutputSurfaceCreation();
break;
@@ -196,10 +209,8 @@ void Scheduler::ProcessScheduledActions() {
action = state_machine_.NextAction();
}
- // Activate or deactivate the frame rate controller.
- frame_rate_controller_->SetActive(
- state_machine_.BeginFrameNeededByImplThread());
- client_->DidAnticipatedDrawTimeChange(frame_rate_controller_->NextTickTime());
+ SetupNextBeginFrameIfNeeded();
+ client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
}
bool Scheduler::WillDrawIfNeeded() const {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 6ecd889..d8151fa 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -11,7 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "cc/base/cc_export.h"
-#include "cc/scheduler/frame_rate_controller.h"
#include "cc/scheduler/scheduler_settings.h"
#include "cc/scheduler/scheduler_state_machine.h"
#include "cc/trees/layer_tree_host.h"
@@ -33,6 +32,7 @@ struct ScheduledActionDrawAndSwapResult {
class SchedulerClient {
public:
+ virtual void SetNeedsBeginFrameOnImplThread(bool enable) = 0;
virtual void ScheduledActionSendBeginFrameToMainThread() = 0;
virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapIfPossible() = 0;
@@ -49,14 +49,12 @@ class SchedulerClient {
virtual ~SchedulerClient() {}
};
-class CC_EXPORT Scheduler : FrameRateControllerClient {
+class CC_EXPORT Scheduler {
public:
static scoped_ptr<Scheduler> Create(
SchedulerClient* client,
- scoped_ptr<FrameRateController> frame_rate_controller,
const SchedulerSettings& scheduler_settings) {
- return make_scoped_ptr(new Scheduler(
- client, frame_rate_controller.Pass(), scheduler_settings));
+ return make_scoped_ptr(new Scheduler(client, scheduler_settings));
}
virtual ~Scheduler();
@@ -86,12 +84,6 @@ class CC_EXPORT Scheduler : FrameRateControllerClient {
void FinishCommit();
void BeginFrameAbortedByMainThread();
- void SetMaxFramesPending(int max);
- int MaxFramesPending() const;
- int NumFramesPendingForTesting() const;
-
- void DidSwapBuffersComplete();
-
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
bool HasInitializedOutputSurface() const {
@@ -103,28 +95,32 @@ class CC_EXPORT Scheduler : FrameRateControllerClient {
bool WillDrawIfNeeded() const;
- void SetTimebaseAndInterval(base::TimeTicks timebase,
- base::TimeDelta interval);
-
base::TimeTicks AnticipatedDrawTime();
base::TimeTicks LastBeginFrameOnImplThreadTime();
- // FrameRateControllerClient implementation
- virtual void BeginFrame(bool throttled) OVERRIDE;
+ void BeginFrame(base::TimeTicks frame_time);
std::string StateAsStringForTesting() { return state_machine_.ToString(); }
private:
Scheduler(SchedulerClient* client,
- scoped_ptr<FrameRateController> frame_rate_controller,
const SchedulerSettings& scheduler_settings);
+ void SetupNextBeginFrameIfNeeded();
+ void DrawAndSwapIfPossible();
+ void DrawAndSwapForced();
void ProcessScheduledActions();
const SchedulerSettings settings_;
SchedulerClient* client_;
- scoped_ptr<FrameRateController> frame_rate_controller_;
+
+ base::WeakPtrFactory<Scheduler> weak_factory_;
+ bool last_set_needs_begin_frame_;
+ bool has_pending_begin_frame_;
+ base::TimeTicks last_begin_frame_time_;
+ base::TimeDelta interval_;
+
SchedulerStateMachine state_machine_;
bool inside_process_scheduled_actions_;
diff --git a/cc/scheduler/scheduler_settings.cc b/cc/scheduler/scheduler_settings.cc
index 29c525b..4850a108 100644
--- a/cc/scheduler/scheduler_settings.cc
+++ b/cc/scheduler/scheduler_settings.cc
@@ -8,7 +8,8 @@ namespace cc {
SchedulerSettings::SchedulerSettings()
: impl_side_painting(false),
- timeout_and_draw_when_animation_checkerboards(true) {}
+ timeout_and_draw_when_animation_checkerboards(true),
+ using_synchronous_renderer_compositor(false) {}
SchedulerSettings::~SchedulerSettings() {}
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index ebcfc6a..c06e28f 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -16,6 +16,7 @@ class CC_EXPORT SchedulerSettings {
bool impl_side_painting;
bool timeout_and_draw_when_animation_checkerboards;
+ bool using_synchronous_renderer_compositor;
};
} // namespace cc
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 76f7bb1..fda6e6b 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -4,6 +4,7 @@
#include "cc/scheduler/scheduler_state_machine.h"
+#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
@@ -12,6 +13,7 @@ namespace cc {
SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
: settings_(settings),
commit_state_(COMMIT_STATE_IDLE),
+ commit_count_(0),
current_frame_number_(0),
last_frame_number_where_draw_was_called_(-1),
last_frame_number_where_tree_activation_attempted_(-1),
@@ -42,6 +44,7 @@ std::string SchedulerStateMachine::ToString() {
"settings_.impl_side_painting = %d; ",
settings_.impl_side_painting);
base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_);
+ base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_);
base::StringAppendF(
&str, "current_frame_number_ = %d; ", current_frame_number_);
base::StringAppendF(&str,
@@ -80,6 +83,8 @@ std::string SchedulerStateMachine::ToString() {
main_thread_needs_layer_textures_);
base::StringAppendF(&str, "inside_begin_frame_ = %d; ",
inside_begin_frame_);
+ base::StringAppendF(&str, "last_frame_time_ = %"PRId64"; ",
+ (last_frame_time_ - base::TimeTicks()).InMilliseconds());
base::StringAppendF(&str, "visible_ = %d; ", visible_);
base::StringAppendF(&str, "can_start_ = %d; ", can_start_);
base::StringAppendF(&str, "can_draw_ = %d; ", can_draw_);
@@ -273,6 +278,7 @@ void SchedulerStateMachine::UpdateState(Action action) {
return;
case ACTION_COMMIT:
+ commit_count_++;
if (expect_immediate_begin_frame_for_main_thread_)
commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
else
@@ -332,6 +338,11 @@ void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() {
}
bool SchedulerStateMachine::BeginFrameNeededByImplThread() const {
+ // We should proactively request a BeginFrame if a commit is pending.
+ if (needs_commit_ || needs_forced_commit_ ||
+ commit_state_ != COMMIT_STATE_IDLE)
+ return true;
+
// If we have a pending tree, need to keep getting notifications until
// the tree is ready to be swapped.
if (has_pending_tree_)
@@ -355,6 +366,10 @@ void SchedulerStateMachine::DidEnterBeginFrame() {
inside_begin_frame_ = true;
}
+void SchedulerStateMachine::SetFrameTime(base::TimeTicks frame_time) {
+ last_frame_time_ = frame_time;
+}
+
void SchedulerStateMachine::DidLeaveBeginFrame() {
current_frame_number_++;
inside_begin_frame_ = false;
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index 1be0749..59e940c 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/time.h"
#include "cc/base/cc_export.h"
#include "cc/scheduler/scheduler_settings.h"
@@ -78,7 +79,9 @@ class CC_EXPORT SchedulerStateMachine {
// The scheduler will not draw more than once in a given BeginFrame
// callback.
void DidEnterBeginFrame();
+ void SetFrameTime(base::TimeTicks frame_time);
void DidLeaveBeginFrame();
+ bool inside_begin_frame() const { return inside_begin_frame_; }
// Indicates whether the LayerTreeHostImpl is visible.
void SetVisible(bool visible);
@@ -168,6 +171,7 @@ class CC_EXPORT SchedulerStateMachine {
const SchedulerSettings settings_;
CommitState commit_state_;
+ int commit_count_;
int current_frame_number_;
int last_frame_number_where_draw_was_called_;
@@ -184,6 +188,7 @@ class CC_EXPORT SchedulerStateMachine {
bool expect_immediate_begin_frame_for_main_thread_;
bool main_thread_needs_layer_textures_;
bool inside_begin_frame_;
+ base::TimeTicks last_frame_time_;
bool visible_;
bool can_start_;
bool can_draw_;
@@ -193,6 +198,7 @@ class CC_EXPORT SchedulerStateMachine {
OutputSurfaceState output_surface_state_;
bool did_create_and_initialize_first_output_surface_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SchedulerStateMachine);
};
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 001a229..c535212 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -98,7 +98,7 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) {
EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_FRAME_IN_PROGRESS,
state.CommitState());
EXPECT_FALSE(state.NeedsCommit());
- EXPECT_FALSE(state.BeginFrameNeededByImplThread());
+ EXPECT_TRUE(state.BeginFrameNeededByImplThread());
}
}
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 68aecaf..bc7d575 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -30,7 +30,11 @@ namespace {
class FakeSchedulerClient : public SchedulerClient {
public:
- FakeSchedulerClient() { Reset(); }
+ FakeSchedulerClient()
+ : needs_begin_frame_(false) {
+ Reset();
+ }
+
void Reset() {
actions_.clear();
states_.clear();
@@ -39,15 +43,12 @@ class FakeSchedulerClient : public SchedulerClient {
num_draws_ = 0;
}
- Scheduler* CreateScheduler(
- scoped_ptr<FrameRateController> frame_rate_controller,
- const SchedulerSettings& settings) {
- scheduler_ =
- Scheduler::Create(this, frame_rate_controller.Pass(), settings);
+ Scheduler* CreateScheduler(const SchedulerSettings& settings) {
+ scheduler_ = Scheduler::Create(this, settings);
return scheduler_.get();
}
-
+ bool needs_begin_frame() { return needs_begin_frame_; }
int num_draws() const { return num_draws_; }
int num_actions_() const { return static_cast<int>(actions_.size()); }
const char* Action(int i) const { return actions_[i]; }
@@ -68,6 +69,11 @@ class FakeSchedulerClient : public SchedulerClient {
}
// Scheduler Implementation.
+ virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE {
+ actions_.push_back("SetNeedsBeginFrameOnImplThread");
+ states_.push_back(scheduler_->StateAsStringForTesting());
+ needs_begin_frame_ = enable;
+ }
virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {
actions_.push_back("ScheduledActionSendBeginFrameToMainThread");
states_.push_back(scheduler_->StateAsStringForTesting());
@@ -111,6 +117,7 @@ class FakeSchedulerClient : public SchedulerClient {
virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {}
protected:
+ bool needs_begin_frame_;
bool draw_will_happen_;
bool swap_will_happen_if_draw_happens_;
int num_draws_;
@@ -121,11 +128,8 @@ class FakeSchedulerClient : public SchedulerClient {
TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -138,11 +142,8 @@ TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
TEST(SchedulerTest, RequestCommit) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -153,33 +154,29 @@ TEST(SchedulerTest, RequestCommit) {
// SetNeedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginFrameToMainThread", client);
- EXPECT_FALSE(time_source->Active());
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// FinishCommit should commit
scheduler->FinishCommit();
EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
- // Tick should draw.
- time_source->Tick();
- EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client);
- EXPECT_FALSE(time_source->Active());
+ // BeginFrame should draw.
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_FALSE(client.needs_begin_frame());
client.Reset();
-
- // Timer should be off.
- EXPECT_FALSE(time_source->Active());
}
TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -190,7 +187,8 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
// SetNedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- EXPECT_SINGLE_ACTION("ScheduledActionSendBeginFrameToMainThread", client);
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
client.Reset();
// Now SetNeedsCommit again. Calling here means we need a second frame.
@@ -203,78 +201,85 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
client.Reset();
// Tick should draw but then begin another frame.
- time_source->Tick();
- EXPECT_FALSE(time_source->Active());
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2);
client.Reset();
+
+ // Go back to quiescent state and verify we no longer request BeginFrames.
+ scheduler->FinishCommit();
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_FALSE(client.needs_begin_frame());
}
TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
-
EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+
client.Reset();
scheduler->DidCreateAndInitializeOutputSurface();
-
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ EXPECT_TRUE(client.needs_begin_frame());
- time_source->Tick();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
- EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(time_source->Active());
client.Reset();
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(client.needs_begin_frame());
+ client.Reset();
scheduler->SetMainThreadNeedsLayerTextures();
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
0,
- 2);
+ 3);
// A commit was started by SetMainThreadNeedsLayerTextures().
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2);
- client.Reset();
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 3);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 2, 3);
+ // We should request a BeginFrame in anticipation of a draw.
+ client.Reset();
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// No draw happens since the textures are acquired by the main thread.
- time_source->Tick();
- EXPECT_EQ(0, client.num_actions_());
+ client.Reset();
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
+ // Commit will release the texture.
+ client.Reset();
scheduler->FinishCommit();
- EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
+ EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
- client.Reset();
+ EXPECT_TRUE(client.needs_begin_frame());
// Now we can draw again after the commit happens.
- time_source->Tick();
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
+ client.Reset();
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(time_source->Active());
+ EXPECT_FALSE(client.needs_begin_frame());
client.Reset();
}
TEST(SchedulerTest, TextureAcquisitionCollision) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -285,19 +290,22 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
scheduler->SetNeedsCommit();
scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 3);
+ EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 3);
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
- 1,
- 2);
+ 2,
+ 3);
client.Reset();
- // Compositor not scheduled to draw because textures are locked by main thread
- EXPECT_FALSE(time_source->Active());
+ // Although the compositor cannot draw because textures are locked by main
+ // thread, we continue requesting SetNeedsBeginFrame in anticipation of the
+ // unlock.
+ EXPECT_TRUE(client.needs_begin_frame());
// Trigger the commit
scheduler->FinishCommit();
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
client.Reset();
// Between commit and draw, texture acquisition for main thread delayed,
@@ -307,7 +315,7 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
client.Reset();
// Once compositor draw complete, the delayed texture acquisition fires.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
@@ -319,11 +327,8 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
FakeSchedulerClient client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -379,11 +384,8 @@ class SchedulerClientThatsetNeedsDrawInsideDraw : public FakeSchedulerClient {
// 2. the scheduler drawing twice inside a single tick
TEST(SchedulerTest, RequestRedrawInsideDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -391,28 +393,25 @@ TEST(SchedulerTest, RequestRedrawInsideDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(time_source->Active());
+ EXPECT_FALSE(client.needs_begin_frame());
}
// Test that requesting redraw inside a failed draw doesn't lose the request.
TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -422,33 +421,33 @@ TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the redraw
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail the draw again.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
}
class SchedulerClientThatsetNeedsCommitInsideDraw : public FakeSchedulerClient {
@@ -477,11 +476,8 @@ class SchedulerClientThatsetNeedsCommitInsideDraw : public FakeSchedulerClient {
// happen inside a ScheduledActionDrawAndSwap
TEST(SchedulerTest, RequestCommitInsideDraw) {
SchedulerClientThatsetNeedsCommitInsideDraw client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -490,28 +486,26 @@ TEST(SchedulerTest, RequestCommitInsideDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_EQ(0, client.num_draws());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
- time_source->Tick();
- EXPECT_FALSE(time_source->Active());
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
+ EXPECT_TRUE(client.needs_begin_frame());
scheduler->FinishCommit();
- time_source->Tick();
- EXPECT_EQ(2, client.num_draws());
- EXPECT_FALSE(time_source->Active());
+ scheduler->BeginFrame(base::TimeTicks::Now());
+ EXPECT_EQ(2, client.num_draws());;
EXPECT_FALSE(scheduler->RedrawPending());
+ EXPECT_FALSE(scheduler->CommitPending());
+ EXPECT_FALSE(client.needs_begin_frame());
}
// Tests that when a draw fails then the pending commit should not be dropped.
TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
SchedulerClientThatsetNeedsDrawInsideDraw client;
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- make_scoped_ptr(new FrameRateController(time_source)),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -521,128 +515,77 @@ TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(1, client.num_draws());
// We have a commit pending and the draw failed, and we didn't lose the commit
// request.
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail the draw again.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// Draw successfully.
client.SetDrawWillHappen(true);
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
}
TEST(SchedulerTest, NoSwapWhenDrawFails) {
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerClientThatsetNeedsCommitInsideDraw client;
- scoped_ptr<FakeFrameRateController> controller(
- new FakeFrameRateController(time_source));
- FakeFrameRateController* controller_ptr = controller.get();
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- controller.PassAs<FrameRateController>(),
- default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
scheduler->DidCreateAndInitializeOutputSurface();
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
-
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
EXPECT_EQ(0, client.num_draws());
// Draw successfully, this starts a new frame.
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(1, client.num_draws());
- EXPECT_EQ(1, controller_ptr->NumFramesPending());
- scheduler->DidSwapBuffersComplete();
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(time_source->Active());
+ EXPECT_TRUE(client.needs_begin_frame());
// Fail to draw, this should not start a frame.
client.SetDrawWillHappen(false);
- time_source->Tick();
+ scheduler->BeginFrame(base::TimeTicks::Now());
EXPECT_EQ(2, client.num_draws());
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
}
TEST(SchedulerTest, NoSwapWhenSwapFailsDuringForcedCommit) {
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
FakeSchedulerClient client;
- scoped_ptr<FakeFrameRateController> controller(
- new FakeFrameRateController(time_source));
- FakeFrameRateController* controller_ptr = controller.get();
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- controller.PassAs<FrameRateController>(),
- default_scheduler_settings);
-
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
+ Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
// Tell the client that it will fail to swap.
client.SetDrawWillHappen(true);
client.SetSwapWillHappenIfDrawHappens(false);
// Get the compositor to do a ScheduledActionDrawAndSwapForced.
+ scheduler->SetCanDraw(true);
scheduler->SetNeedsRedraw();
scheduler->SetNeedsForcedRedraw();
EXPECT_TRUE(client.HasAction("ScheduledActionDrawAndSwapForced"));
-
- // We should not have told the frame rate controller that we began a frame.
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
-}
-
-TEST(SchedulerTest, RecreateOutputSurfaceClearsPendingDrawCount) {
- scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
- FakeSchedulerClient client;
- scoped_ptr<FakeFrameRateController> controller(
- new FakeFrameRateController(time_source));
- FakeFrameRateController* controller_ptr = controller.get();
- SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(
- controller.PassAs<FrameRateController>(),
- default_scheduler_settings);
-
- scheduler->SetCanStart();
- scheduler->SetVisible(true);
- scheduler->SetCanDraw(true);
- scheduler->DidCreateAndInitializeOutputSurface();
-
- // Draw successfully, this starts a new frame.
- scheduler->SetNeedsRedraw();
- time_source->Tick();
- EXPECT_EQ(1, controller_ptr->NumFramesPending());
-
- scheduler->DidLoseOutputSurface();
- // Verifying that it's 1 so that we know that it's reset on recreate.
- EXPECT_EQ(1, controller_ptr->NumFramesPending());
-
- scheduler->DidCreateAndInitializeOutputSurface();
- EXPECT_EQ(0, controller_ptr->NumFramesPending());
}
} // namespace
diff --git a/cc/scheduler/vsync_time_source.cc b/cc/scheduler/vsync_time_source.cc
deleted file mode 100644
index 206e2376..0000000
--- a/cc/scheduler/vsync_time_source.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/scheduler/vsync_time_source.h"
-
-#include "base/logging.h"
-
-namespace cc {
-
-scoped_refptr<VSyncTimeSource> VSyncTimeSource::Create(
- VSyncProvider* vsync_provider, NotificationDisableOption option) {
- return make_scoped_refptr(new VSyncTimeSource(vsync_provider, option));
-}
-
-VSyncTimeSource::VSyncTimeSource(
- VSyncProvider* vsync_provider, NotificationDisableOption option)
- : active_(false),
- notification_requested_(false),
- vsync_provider_(vsync_provider),
- client_(NULL),
- disable_option_(option) {}
-
-VSyncTimeSource::~VSyncTimeSource() {}
-
-void VSyncTimeSource::SetClient(TimeSourceClient* client) {
- client_ = client;
-}
-
-void VSyncTimeSource::SetActive(bool active) {
- if (active_ == active)
- return;
- active_ = active;
- if (active_ && !notification_requested_) {
- notification_requested_ = true;
- vsync_provider_->RequestVSyncNotification(this);
- }
- if (!active_ && disable_option_ == DISABLE_SYNCHRONOUSLY) {
- notification_requested_ = false;
- vsync_provider_->RequestVSyncNotification(NULL);
- }
-}
-
-bool VSyncTimeSource::Active() const {
- return active_;
-}
-
-base::TimeTicks VSyncTimeSource::LastTickTime() {
- return last_tick_time_;
-}
-
-base::TimeTicks VSyncTimeSource::NextTickTime() {
- return Active() ? last_tick_time_ + interval_ : base::TimeTicks();
-}
-
-void VSyncTimeSource::SetTimebaseAndInterval(base::TimeTicks,
- base::TimeDelta interval) {
- interval_ = interval;
-}
-
-void VSyncTimeSource::DidVSync(base::TimeTicks frame_time) {
- last_tick_time_ = frame_time;
- if (disable_option_ == DISABLE_SYNCHRONOUSLY) {
- DCHECK(active_);
- } else if (!active_) {
- if (notification_requested_) {
- notification_requested_ = false;
- vsync_provider_->RequestVSyncNotification(NULL);
- }
- return;
- }
- if (client_)
- client_->OnTimerTick();
-}
-
-} // namespace cc
diff --git a/cc/scheduler/vsync_time_source.h b/cc/scheduler/vsync_time_source.h
deleted file mode 100644
index 4cd0441..0000000
--- a/cc/scheduler/vsync_time_source.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_SCHEDULER_VSYNC_TIME_SOURCE_H_
-#define CC_SCHEDULER_VSYNC_TIME_SOURCE_H_
-
-#include "cc/base/cc_export.h"
-#include "cc/scheduler/time_source.h"
-
-namespace cc {
-
-class CC_EXPORT VSyncClient {
- public:
- virtual void DidVSync(base::TimeTicks frame_time) = 0;
-
- protected:
- virtual ~VSyncClient() {}
-};
-
-class VSyncProvider {
- public:
- // Request to be notified of future vsync events. The notifications will be
- // delivered until they are disabled by calling this function with a null
- // client.
- virtual void RequestVSyncNotification(VSyncClient* client) = 0;
-
- protected:
- virtual ~VSyncProvider() {}
-};
-
-// This timer implements a time source that is explicitly triggered by an
-// external vsync signal.
-class CC_EXPORT VSyncTimeSource : public TimeSource, public VSyncClient {
- public:
- enum NotificationDisableOption {
- // The notification will be lazily disabled in the callback to ensure
- // we get notified of the frame immediately following a quick on-off-on
- // transition.
- DISABLE_ON_NEXT_TICK,
- DISABLE_SYNCHRONOUSLY
- };
-
- static scoped_refptr<VSyncTimeSource> Create(
- VSyncProvider* vsync_provider, NotificationDisableOption option);
-
- // TimeSource implementation
- virtual void SetClient(TimeSourceClient* client) OVERRIDE;
- virtual void SetTimebaseAndInterval(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
- virtual void SetActive(bool active) OVERRIDE;
- virtual bool Active() const OVERRIDE;
- virtual base::TimeTicks LastTickTime() OVERRIDE;
- virtual base::TimeTicks NextTickTime() OVERRIDE;
-
- // VSyncClient implementation
- virtual void DidVSync(base::TimeTicks frame_time) OVERRIDE;
-
- protected:
- explicit VSyncTimeSource(VSyncProvider* vsync_provider,
- NotificationDisableOption option);
- virtual ~VSyncTimeSource();
-
- base::TimeTicks last_tick_time_;
- base::TimeDelta interval_;
- bool active_;
- bool notification_requested_;
-
- VSyncProvider* vsync_provider_;
- TimeSourceClient* client_;
- NotificationDisableOption disable_option_;
-
- DISALLOW_COPY_AND_ASSIGN(VSyncTimeSource);
-};
-
-} // namespace cc
-
-#endif // CC_SCHEDULER_VSYNC_TIME_SOURCE_H_
diff --git a/cc/scheduler/vsync_time_source_unittest.cc b/cc/scheduler/vsync_time_source_unittest.cc
deleted file mode 100644
index 4834630..0000000
--- a/cc/scheduler/vsync_time_source_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/scheduler/vsync_time_source.h"
-
-#include "cc/test/scheduler_test_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace cc {
-namespace {
-
-class FakeVSyncProvider : public VSyncProvider {
- public:
- FakeVSyncProvider() : client_(NULL) {}
-
- // VSyncProvider implementation.
- virtual void RequestVSyncNotification(VSyncClient* client) OVERRIDE {
- client_ = client;
- }
-
- bool IsVSyncNotificationEnabled() const { return client_ != NULL; }
-
- void Trigger(base::TimeTicks frame_time) {
- if (client_)
- client_->DidVSync(frame_time);
- }
-
- private:
- VSyncClient* client_;
-};
-
-class VSyncTimeSourceTest : public testing::Test {
- public:
- VSyncTimeSourceTest()
- : timer_(VSyncTimeSource::Create(
- &provider_, VSyncTimeSource::DISABLE_ON_NEXT_TICK)) {
- timer_->SetClient(&client_);
- }
-
- protected:
- FakeTimeSourceClient client_;
- FakeVSyncProvider provider_;
- scoped_refptr<VSyncTimeSource> timer_;
-};
-
-TEST_F(VSyncTimeSourceTest, TaskPostedAndTickCalled) {
- EXPECT_FALSE(provider_.IsVSyncNotificationEnabled());
-
- timer_->SetActive(true);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
-
- base::TimeTicks frame_time = base::TimeTicks::Now();
- provider_.Trigger(frame_time);
- EXPECT_TRUE(client_.TickCalled());
- EXPECT_EQ(timer_->LastTickTime(), frame_time);
-}
-
-TEST_F(VSyncTimeSourceTest, NotificationDisabledLazily) {
- base::TimeTicks frame_time = base::TimeTicks::Now();
-
- // Enable timer and trigger sync once.
- timer_->SetActive(true);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
- provider_.Trigger(frame_time);
- EXPECT_TRUE(client_.TickCalled());
-
- // Disabling the timer should not disable vsync notification immediately.
- client_.Reset();
- timer_->SetActive(false);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
-
- // At the next vsync the notification is disabled, but the timer isn't ticked.
- provider_.Trigger(frame_time);
- EXPECT_FALSE(provider_.IsVSyncNotificationEnabled());
- EXPECT_FALSE(client_.TickCalled());
-
- // The notification should not be disabled multiple times.
- provider_.RequestVSyncNotification(timer_.get());
- provider_.Trigger(frame_time);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
- EXPECT_FALSE(client_.TickCalled());
-}
-
-TEST_F(VSyncTimeSourceTest, NotificationDisabledImmediatelyForSetting) {
- timer_ = VSyncTimeSource::Create(&provider_,
- VSyncTimeSource::DISABLE_SYNCHRONOUSLY);
- timer_->SetClient(&client_);
- base::TimeTicks frame_time = base::TimeTicks::Now();
-
- // Enable timer and trigger sync once.
- timer_->SetActive(true);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
- provider_.Trigger(frame_time);
- EXPECT_TRUE(client_.TickCalled());
-
- // Disable timer should disable vsync notification immediately.
- timer_->SetActive(false);
- EXPECT_FALSE(provider_.IsVSyncNotificationEnabled());
-
- // Enable again and timer can be ticked again.
- client_.Reset();
- timer_->SetActive(true);
- EXPECT_TRUE(provider_.IsVSyncNotificationEnabled());
- provider_.Trigger(frame_time);
- EXPECT_TRUE(client_.TickCalled());
-}
-
-TEST_F(VSyncTimeSourceTest, ValidNextTickTime) {
- base::TimeTicks frame_time = base::TimeTicks::Now();
- base::TimeDelta interval = base::TimeDelta::FromSeconds(1);
-
- ASSERT_EQ(timer_->NextTickTime(), base::TimeTicks());
-
- timer_->SetActive(true);
- provider_.Trigger(frame_time);
- ASSERT_EQ(timer_->NextTickTime(), frame_time);
-
- timer_->SetTimebaseAndInterval(frame_time, interval);
- ASSERT_EQ(timer_->NextTickTime(), frame_time + interval);
-}
-
-} // namespace
-} // namespace cc
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h
index dad4014..58816cc 100644
--- a/cc/test/fake_layer_tree_host_impl_client.h
+++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -17,9 +17,6 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {}
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
- virtual void OnVSyncParametersChanged(
- base::TimeTicks,
- base::TimeDelta) OVERRIDE {}
virtual void BeginFrameOnImplThread(base::TimeTicks frame_time)
OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {}
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc
index c3f3e1a..9ceadda 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -8,6 +8,7 @@
#include "base/message_loop.h"
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/output_surface_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
@@ -17,7 +18,8 @@ FakeOutputSurface::FakeOutputSurface(
: OutputSurface(context3d.Pass()),
num_sent_frames_(0),
needs_begin_frame_(false),
- forced_draw_to_software_device_(false) {
+ forced_draw_to_software_device_(false),
+ fake_weak_ptr_factory_(this) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -28,7 +30,8 @@ FakeOutputSurface::FakeOutputSurface(
scoped_ptr<SoftwareOutputDevice> software_device, bool delegated_rendering)
: OutputSurface(software_device.Pass()),
num_sent_frames_(0),
- forced_draw_to_software_device_(false) {
+ forced_draw_to_software_device_(false),
+ fake_weak_ptr_factory_(this) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -41,7 +44,8 @@ FakeOutputSurface::FakeOutputSurface(
bool delegated_rendering)
: OutputSurface(context3d.Pass(), software_device.Pass()),
num_sent_frames_(0),
- forced_draw_to_software_device_(false) {
+ forced_draw_to_software_device_(false),
+ fake_weak_ptr_factory_(this) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -56,6 +60,7 @@ void FakeOutputSurface::SwapBuffers(CompositorFrame* frame) {
frame->AssignTo(&last_sent_frame_);
++num_sent_frames_;
PostSwapBuffersComplete();
+ DidSwapBuffers();
} else {
OutputSurface::SwapBuffers(frame);
frame->AssignTo(&last_sent_frame_);
@@ -65,12 +70,23 @@ void FakeOutputSurface::SwapBuffers(CompositorFrame* frame) {
void FakeOutputSurface::SetNeedsBeginFrame(bool enable) {
needs_begin_frame_ = enable;
+ OutputSurface::SetNeedsBeginFrame(enable);
+
+ // If there is not BeginFrame emulation from the FrameRateController,
+ // then we just post a BeginFrame to emulate it as part of the test.
+ if (enable && !frame_rate_controller_) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, base::Bind(&FakeOutputSurface::OnBeginFrame,
+ fake_weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(16));
+ }
}
-void FakeOutputSurface::BeginFrame(base::TimeTicks frame_time) {
- client_->BeginFrame(frame_time);
+void FakeOutputSurface::OnBeginFrame() {
+ OutputSurface::BeginFrame(base::TimeTicks::Now());
}
+
bool FakeOutputSurface::ForcedDrawToSoftwareDevice() const {
return forced_draw_to_software_device_;
}
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index d54ffd3..7bc1a4f 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -74,7 +74,6 @@ class FakeOutputSurface : public OutputSurface {
bool needs_begin_frame() const {
return needs_begin_frame_;
}
- void BeginFrame(base::TimeTicks frame_time);
void set_forced_draw_to_software_device(bool forced) {
forced_draw_to_software_device_ = forced;
@@ -95,10 +94,13 @@ class FakeOutputSurface : public OutputSurface {
scoped_ptr<SoftwareOutputDevice> software_device,
bool delegated_rendering);
+ void OnBeginFrame();
+
CompositorFrame last_sent_frame_;
size_t num_sent_frames_;
bool needs_begin_frame_;
bool forced_draw_to_software_device_;
+ base::WeakPtrFactory<FakeOutputSurface> fake_weak_ptr_factory_;
};
static inline scoped_ptr<cc::OutputSurface> CreateFakeOutputSurface() {
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 0bb17f346..9f046d9e 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -590,9 +590,13 @@ void LayerTreeTest::RunTest(bool threaded,
}
scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface() {
+ scoped_ptr<FakeOutputSurface> output_surface;
if (delegating_renderer_)
- return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
- return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
+ output_surface = FakeOutputSurface::CreateDelegating3d();
+ else
+ output_surface = FakeOutputSurface::Create3d();
+ output_surface_ = output_surface.get();
+ return output_surface.PassAs<OutputSurface>();
}
scoped_refptr<cc::ContextProvider> LayerTreeTest::
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 856caaa..2d67a44 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -24,6 +24,7 @@ class LayerImpl;
class LayerTreeHost;
class LayerTreeHostClient;
class LayerTreeHostImpl;
+class FakeOutputSurface;
// Used by test stubs to notify the test when something interesting happens.
class TestHooks : public WebKit::WebAnimationDelegate {
@@ -160,6 +161,7 @@ class LayerTreeTest : public testing::Test, public TestHooks {
LayerTreeSettings settings_;
scoped_ptr<LayerTreeHostClientForTesting> client_;
scoped_ptr<LayerTreeHost> layer_tree_host_;
+ FakeOutputSurface* output_surface_;
bool beginning_;
bool end_when_begin_returns_;
diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc
index c1aa200..8ccf47e 100644
--- a/cc/test/scheduler_test_common.cc
+++ b/cc/test/scheduler_test_common.cc
@@ -35,16 +35,6 @@ void FakeThread::PostDelayedTask(base::Closure cb, base::TimeDelta delay) {
bool FakeThread::BelongsToCurrentThread() const { return true; }
-void FakeTimeSource::SetClient(TimeSourceClient* client) { client_ = client; }
-
-void FakeTimeSource::SetActive(bool b) { active_ = b; }
-
-bool FakeTimeSource::Active() const { return active_; }
-
-base::TimeTicks FakeTimeSource::LastTickTime() { return base::TimeTicks(); }
-
-base::TimeTicks FakeTimeSource::NextTickTime() { return base::TimeTicks(); }
-
base::TimeTicks FakeDelayBasedTimeSource::Now() const { return now_; }
} // namespace cc
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index b3b2c2d..8834e62 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -62,36 +62,6 @@ class FakeThread : public cc::Thread {
bool run_pending_task_on_overwrite_;
};
-class FakeTimeSource : public cc::TimeSource {
- public:
- FakeTimeSource() : active_(false), client_(0) {}
-
- virtual void SetClient(cc::TimeSourceClient* client) OVERRIDE;
- virtual void SetActive(bool b) OVERRIDE;
- virtual bool Active() const OVERRIDE;
- virtual void SetTimebaseAndInterval(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
- virtual base::TimeTicks LastTickTime() OVERRIDE;
- virtual base::TimeTicks NextTickTime() OVERRIDE;
-
- void Tick() {
- ASSERT_TRUE(active_);
- if (client_)
- client_->OnTimerTick();
- }
-
- void SetNextTickTime(base::TimeTicks next_tick_time) {
- next_tick_time_ = next_tick_time;
- }
-
- protected:
- virtual ~FakeTimeSource() {}
-
- bool active_;
- base::TimeTicks next_tick_time_;
- cc::TimeSourceClient* client_;
-};
-
class FakeDelayBasedTimeSource : public cc::DelayBasedTimeSource {
public:
static scoped_refptr<FakeDelayBasedTimeSource> Create(
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index a497421..2670bf8 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1071,11 +1071,6 @@ void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) {
client_->SetNeedsRedrawRectOnImplThread(damage_rect);
}
-void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) {
- client_->OnVSyncParametersChanged(timebase, interval);
-}
-
void LayerTreeHostImpl::BeginFrame(base::TimeTicks frame_time) {
client_->BeginFrameOnImplThread(frame_time);
}
@@ -1514,6 +1509,25 @@ bool LayerTreeHostImpl::DoInitializeRenderer(
resource_provider_ = resource_provider.Pass();
}
+ // Setup BeginFrameEmulation if it's not supported natively
+ if (!settings_.begin_frame_scheduling_enabled) {
+ const base::TimeDelta display_refresh_interval =
+ base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond /
+ settings_.refresh_rate);
+
+ output_surface->InitializeBeginFrameEmulation(
+ proxy_->ImplThread(),
+ settings_.throttle_frame_production,
+ display_refresh_interval);
+ }
+
+ int max_frames_pending =
+ output_surface->capabilities().max_frames_pending;
+ if (max_frames_pending <= 0)
+ max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING;
+ output_surface->SetMaxFramesPending(max_frames_pending);
+
output_surface_ = output_surface.Pass();
if (!visible_)
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 72c542d..e2a303e 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -54,8 +54,6 @@ class LayerTreeHostImplClient {
scoped_refptr<ContextProvider> offscreen_context_provider) = 0;
virtual void DidLoseOutputSurfaceOnImplThread() = 0;
virtual void OnSwapBuffersCompleteOnImplThread() = 0;
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) = 0;
virtual void BeginFrameOnImplThread(base::TimeTicks frame_time) = 0;
virtual void OnCanDrawStateChanged(bool can_draw) = 0;
virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) = 0;
@@ -183,8 +181,6 @@ class CC_EXPORT LayerTreeHostImpl
virtual float DeviceScaleFactor() const OVERRIDE;
virtual const LayerTreeSettings& Settings() const OVERRIDE;
public:
- virtual void DidLoseOutputSurface() OVERRIDE;
- virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE;
virtual void SetFullRootLayerDamage() OVERRIDE;
virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
OVERRIDE;
@@ -205,12 +201,12 @@ class CC_EXPORT LayerTreeHostImpl
virtual bool DeferredInitialize(
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE;
virtual void SetNeedsRedrawRect(gfx::Rect rect) OVERRIDE;
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
virtual void BeginFrame(base::TimeTicks frame_time)
OVERRIDE;
virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
gfx::Rect viewport) OVERRIDE;
+ virtual void DidLoseOutputSurface() OVERRIDE;
+ virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE;
// Called from LayerTreeImpl.
void OnCanDrawStateChangedForTree();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 8ceb6bd..78e5a6d 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -95,8 +95,6 @@ class LayerTreeHostImplTest : public testing::Test,
}
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
virtual void BeginFrameOnImplThread(base::TimeTicks frame_time)
OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index b8a2e9c..e4d192e 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2049,36 +2049,6 @@ class LayerTreeHostTestCapturePicture : public LayerTreeHostTest {
MULTI_THREAD_TEST_F(LayerTreeHostTestCapturePicture);
-class LayerTreeHostTestMaxPendingFrames : public LayerTreeHostTest {
- public:
- LayerTreeHostTestMaxPendingFrames() : LayerTreeHostTest() {}
-
- virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
-
- virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- DCHECK(host_impl->proxy()->HasImplThread());
-
- const ThreadProxy* proxy = static_cast<ThreadProxy*>(host_impl->proxy());
- if (delegating_renderer()) {
- EXPECT_EQ(1, proxy->MaxFramesPendingForTesting());
- } else {
- EXPECT_EQ(FrameRateController::DEFAULT_MAX_FRAMES_PENDING,
- proxy->MaxFramesPendingForTesting());
- }
- EndTest();
- }
-
- virtual void AfterTest() OVERRIDE {}
-};
-
-TEST_F(LayerTreeHostTestMaxPendingFrames, DelegatingRenderer) {
- RunTest(true, true, true);
-}
-
-TEST_F(LayerTreeHostTestMaxPendingFrames, GLRenderer) {
- RunTest(true, false, true);
-}
-
class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
: public LayerTreeHostTest {
public:
@@ -2253,32 +2223,10 @@ class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest {
}
virtual void BeginTest() OVERRIDE {
+ // This will trigger a SetNeedsBeginFrame which will trigger a BeginFrame.
PostSetNeedsCommitToMainThread();
}
- virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- FakeOutputSurface* fake_output_surface =
- reinterpret_cast<FakeOutputSurface*>(host_impl->output_surface());
-
- // The BeginFrame notification is turned off now but will get
- // enabled once we return, so post a task to trigger it.
- ASSERT_FALSE(fake_output_surface->needs_begin_frame());
- PostBeginFrameOnImplThread(fake_output_surface);
- }
-
- void PostBeginFrameOnImplThread(FakeOutputSurface* fake_output_surface) {
- DCHECK(ImplThread());
- ImplThread()->PostTask(
- base::Bind(&LayerTreeHostTestBeginFrameNotification::BeginFrame,
- base::Unretained(this),
- base::Unretained(fake_output_surface)));
- }
-
- void BeginFrame(FakeOutputSurface* fake_output_surface) {
- ASSERT_TRUE(fake_output_surface->needs_begin_frame());
- fake_output_surface->BeginFrame(frame_time_);
- }
-
virtual bool PrepareToDrawOnThread(
LayerTreeHostImpl* host_impl,
LayerTreeHostImpl::FrameData* frame,
@@ -2824,11 +2772,6 @@ class LayerTreeHostTestNumFramesPending : public LayerTreeHostTest {
}
}
- virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
- const ThreadProxy* proxy = static_cast<ThreadProxy*>(impl->proxy());
- EXPECT_EQ(0, proxy->NumFramesPendingForTesting());
- }
-
virtual void AfterTest() OVERRIDE {}
protected:
@@ -2895,6 +2838,9 @@ class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest {
// Force redraw again.
host_impl->SetNeedsRedrawRect(gfx::Rect(1, 1));
+
+ // If we didn't swap this begin frame, we need to request another one.
+ host_impl->SetNeedsBeginFrame(true);
}
virtual void AfterTest() OVERRIDE {
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index c448002..29cc4f4 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -193,7 +193,7 @@ class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
started_animating_ = true;
}
- virtual void DrawLayersOnThread(LayerTreeHostImpl* tree_impl) OVERRIDE {
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
if (started_animating_)
EndTest();
}
@@ -205,7 +205,7 @@ class LayerTreeHostAnimationTestCheckerboardDoesNotStarveDraws
return false;
}
- virtual void AfterTest() OVERRIDE {}
+ virtual void AfterTest() OVERRIDE { }
private:
bool started_animating_;
diff --git a/cc/trees/proxy.cc b/cc/trees/proxy.cc
index 8d2d2b7..fd39ed0 100644
--- a/cc/trees/proxy.cc
+++ b/cc/trees/proxy.cc
@@ -78,4 +78,8 @@ Proxy::~Proxy() {
DCHECK(IsMainThread());
}
+std::string Proxy::SchedulerStateAsStringForTesting() {
+ return "";
+}
+
} // namespace cc
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index aaab780..4e6171c 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_PROXY_H_
#define CC_TREES_PROXY_H_
+#include <string>
+
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -98,6 +100,7 @@ class CC_EXPORT Proxy {
// Testing hooks
virtual bool CommitPendingForTesting() = 0;
+ virtual std::string SchedulerStateAsStringForTesting();
protected:
explicit Proxy(scoped_ptr<Thread> impl_thread);
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 0c3946b..9d995ba 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -51,8 +51,6 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient {
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE;
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
virtual void BeginFrameOnImplThread(base::TimeTicks frame_time)
OVERRIDE {}
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 53db2c2..020c255 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -4,6 +4,8 @@
#include "cc/trees/thread_proxy.h"
+#include <string>
+
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
@@ -16,7 +18,6 @@
#include "cc/scheduler/delay_based_time_source.h"
#include "cc/scheduler/frame_rate_controller.h"
#include "cc/scheduler/scheduler.h"
-#include "cc/scheduler/vsync_time_source.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_impl.h"
@@ -32,6 +33,23 @@ const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
namespace cc {
+struct ThreadProxy::ReadbackRequest {
+ CompletionEvent completion;
+ bool success;
+ void* pixels;
+ gfx::Rect rect;
+};
+
+struct ThreadProxy::CommitPendingRequest {
+ CompletionEvent completion;
+ bool commit_pending;
+};
+
+struct ThreadProxy::SchedulerStateRequest {
+ CompletionEvent completion;
+ std::string state;
+};
+
scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host,
scoped_ptr<Thread> impl_thread) {
return make_scoped_ptr(
@@ -64,7 +82,6 @@ ThreadProxy::ThreadProxy(LayerTreeHost* layer_tree_host,
layer_tree_host->settings().begin_frame_scheduling_enabled),
using_synchronous_renderer_compositor_(
layer_tree_host->settings().using_synchronous_renderer_compositor),
- vsync_client_(NULL),
inside_draw_(false),
defer_commits_(false),
renew_tree_priority_on_impl_thread_pending_(false) {
@@ -328,36 +345,21 @@ void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
DCHECK(IsImplThread());
TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
- scheduler_on_impl_thread_->DidSwapBuffersComplete();
Proxy::MainThread()->PostTask(
base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
}
-void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) {
+void ThreadProxy::SetNeedsBeginFrameOnImplThread(bool enable) {
DCHECK(IsImplThread());
- TRACE_EVENT2("cc",
- "ThreadProxy::OnVSyncParametersChanged",
- "timebase",
- (timebase - base::TimeTicks()).InMilliseconds(),
- "interval",
- interval.InMilliseconds());
- scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval);
+ TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread",
+ "enable", enable);
+ layer_tree_host_impl_->SetNeedsBeginFrame(enable);
}
void ThreadProxy::BeginFrameOnImplThread(base::TimeTicks frame_time) {
DCHECK(IsImplThread());
- TRACE_EVENT0("cc", "ThreadProxy::OnBeginFrameOnImplThread");
- if (vsync_client_)
- vsync_client_->DidVSync(frame_time);
-}
-
-void ThreadProxy::RequestVSyncNotification(VSyncClient* client) {
- DCHECK(IsImplThread());
- TRACE_EVENT1(
- "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client);
- vsync_client_ = client;
- layer_tree_host_impl_->SetNeedsBeginFrame(!!client);
+ TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread");
+ scheduler_on_impl_thread_->BeginFrame(frame_time);
}
void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
@@ -1110,35 +1112,14 @@ void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
DCHECK(IsImplThread());
layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
- const base::TimeDelta display_refresh_interval =
- base::TimeDelta::FromMicroseconds(
- base::Time::kMicrosecondsPerSecond /
- layer_tree_host_->settings().refresh_rate);
- scoped_ptr<FrameRateController> frame_rate_controller;
- if (throttle_frame_production_) {
- if (begin_frame_scheduling_enabled_) {
- frame_rate_controller.reset(
- new FrameRateController(VSyncTimeSource::Create(
- this,
- using_synchronous_renderer_compositor_ ?
- VSyncTimeSource::DISABLE_SYNCHRONOUSLY :
- VSyncTimeSource::DISABLE_ON_NEXT_TICK)));
- } else {
- frame_rate_controller.reset(
- new FrameRateController(DelayBasedTimeSource::Create(
- display_refresh_interval, Proxy::ImplThread())));
- }
- } else {
- frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread()));
- }
const LayerTreeSettings& settings = layer_tree_host_->settings();
SchedulerSettings scheduler_settings;
scheduler_settings.impl_side_painting = settings.impl_side_painting;
scheduler_settings.timeout_and_draw_when_animation_checkerboards =
settings.timeout_and_draw_when_animation_checkerboards;
- scheduler_on_impl_thread_ = Scheduler::Create(this,
- frame_rate_controller.Pass(),
- scheduler_settings);
+ scheduler_settings.using_synchronous_renderer_compositor =
+ settings.using_synchronous_renderer_compositor;
+ scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings);
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
@@ -1164,16 +1145,6 @@ void ThreadProxy::InitializeOutputSurfaceOnImplThread(
if (*success) {
*capabilities = layer_tree_host_impl_->GetRendererCapabilities();
-
- OutputSurface* output_surface_ptr = layer_tree_host_impl_->output_surface();
- DCHECK(output_surface_ptr);
- int max_frames_pending =
- output_surface_ptr->capabilities().max_frames_pending;
- if (max_frames_pending <= 0)
- max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING;
-
- scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending);
-
scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
}
@@ -1218,7 +1189,6 @@ void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
scheduler_on_impl_thread_.reset();
layer_tree_host_impl_.reset();
weak_factory_on_impl_thread_.InvalidateWeakPtrs();
- vsync_client_ = NULL;
completion->Signal();
}
@@ -1278,6 +1248,29 @@ void ThreadProxy::CommitPendingOnImplThreadForTesting(
request->completion.Signal();
}
+std::string ThreadProxy::SchedulerStateAsStringForTesting() {
+ if (IsImplThread())
+ return scheduler_on_impl_thread_->StateAsStringForTesting();
+
+ SchedulerStateRequest scheduler_state_request;
+ {
+ DebugScopedSetMainThreadBlocked main_thread_blocked(this);
+ Proxy::ImplThread()->PostTask(
+ base::Bind(&ThreadProxy::SchedulerStateAsStringOnImplThreadForTesting,
+ impl_thread_weak_ptr_,
+ &scheduler_state_request));
+ scheduler_state_request.completion.Wait();
+ }
+ return scheduler_state_request.state;
+}
+
+void ThreadProxy::SchedulerStateAsStringOnImplThreadForTesting(
+ SchedulerStateRequest* request) {
+ DCHECK(IsImplThread());
+ request->state = scheduler_on_impl_thread_->StateAsStringForTesting();
+ request->completion.Signal();
+}
+
skia::RefPtr<SkPicture> ThreadProxy::CapturePicture() {
DCHECK(IsMainThread());
CompletionEvent completion;
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index 3cc905d..8013882 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_THREAD_PROXY_H_
#define CC_TREES_THREAD_PROXY_H_
+#include <string>
+
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time.h"
@@ -12,7 +14,6 @@
#include "cc/base/completion_event.h"
#include "cc/resources/resource_update_controller.h"
#include "cc/scheduler/scheduler.h"
-#include "cc/scheduler/vsync_time_source.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/proxy.h"
@@ -29,8 +30,7 @@ class Thread;
class ThreadProxy : public Proxy,
LayerTreeHostImplClient,
SchedulerClient,
- ResourceUpdateControllerClient,
- VSyncProvider {
+ ResourceUpdateControllerClient {
public:
static scoped_ptr<Proxy> Create(LayerTreeHost* layer_tree_host,
scoped_ptr<Thread> impl_thread);
@@ -59,6 +59,7 @@ class ThreadProxy : public Proxy,
virtual skia::RefPtr<SkPicture> CapturePicture() OVERRIDE;
virtual scoped_ptr<base::Value> AsValue() const OVERRIDE;
virtual bool CommitPendingForTesting() OVERRIDE;
+ virtual std::string SchedulerStateAsStringForTesting() OVERRIDE;
// LayerTreeHostImplClient implementation
virtual void DidTryInitializeRendererOnImplThread(
@@ -66,10 +67,7 @@ class ThreadProxy : public Proxy,
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE;
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
- virtual void BeginFrameOnImplThread(base::TimeTicks frame_time)
- OVERRIDE;
+ virtual void BeginFrameOnImplThread(base::TimeTicks frame_time) OVERRIDE;
virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE;
virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE;
virtual void SetNeedsRedrawOnImplThread() OVERRIDE;
@@ -91,6 +89,7 @@ class ThreadProxy : public Proxy,
virtual void DidActivatePendingTree() OVERRIDE;
// SchedulerClient implementation
+ virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE;
virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE;
virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapIfPossible() OVERRIDE;
@@ -106,17 +105,6 @@ class ThreadProxy : public Proxy,
// ResourceUpdateControllerClient implementation
virtual void ReadyToFinalizeTextureUpdates() OVERRIDE;
- // VSyncProvider implementation
- virtual void RequestVSyncNotification(VSyncClient* client) OVERRIDE;
-
- int MaxFramesPendingForTesting() const {
- return scheduler_on_impl_thread_->MaxFramesPending();
- }
-
- int NumFramesPendingForTesting() const {
- return scheduler_on_impl_thread_->NumFramesPendingForTesting();
- }
-
private:
ThreadProxy(LayerTreeHost* layer_tree_host, scoped_ptr<Thread> impl_thread);
@@ -143,16 +131,10 @@ class ThreadProxy : public Proxy,
const RendererCapabilities& capabilities);
// Called on impl thread.
- struct ReadbackRequest {
- CompletionEvent completion;
- bool success;
- void* pixels;
- gfx::Rect rect;
- };
- struct CommitPendingRequest {
- CompletionEvent completion;
- bool commit_pending;
- };
+ struct ReadbackRequest;
+ struct CommitPendingRequest;
+ struct SchedulerStateRequest;
+
void ForceCommitOnImplThread(CompletionEvent* completion);
void StartCommitOnImplThread(
CompletionEvent* completion,
@@ -182,6 +164,8 @@ class ThreadProxy : public Proxy,
void ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent* completion);
void CheckOutputSurfaceStatusOnImplThread();
void CommitPendingOnImplThreadForTesting(CommitPendingRequest* request);
+ void SchedulerStateAsStringOnImplThreadForTesting(
+ SchedulerStateRequest* request);
void CapturePictureOnImplThread(CompletionEvent* completion,
skia::RefPtr<SkPicture>* picture);
void AsValueOnImplThread(CompletionEvent* completion,
@@ -250,7 +234,6 @@ class ThreadProxy : public Proxy,
bool throttle_frame_production_;
bool begin_frame_scheduling_enabled_;
bool using_synchronous_renderer_compositor_;
- VSyncClient* vsync_client_;
bool inside_draw_;