summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 17:10:56 +0000
committerskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 17:10:56 +0000
commitc7480aff12d1133ab4216fa6580e2edbef4d7078 (patch)
tree434dfe820371e751e9fb2e686ee0f72c19a61443 /cc
parent8426f3aaa2ba2fe446512c4dbcd7bcf3b4c7eb4a (diff)
downloadchromium_src-c7480aff12d1133ab4216fa6580e2edbef4d7078.zip
chromium_src-c7480aff12d1133ab4216fa6580e2edbef4d7078.tar.gz
chromium_src-c7480aff12d1133ab4216fa6580e2edbef4d7078.tar.bz2
Revert 205750 "cc: Emulate BeginFrame in OutputSurfaces that don..."
> cc: Emulate BeginFrame in OutputSurfaces that don't support it natively > > This will allow us to avoid having two different code paths > in the Scheduler. It also allows us to more easily remove the > VSyncTimeSource and FrameRateController from the Scheduler. > > This patch instantiates the FrameRateController inside of > OutputSurface for now, but the FrameRateController could be > removed in future patches. > > BUG=245920 > BUG=243497 > > Review URL: https://chromiumcodereview.appspot.com/15836005 TBR=brianderson@chromium.org Review URL: https://codereview.chromium.org/16679010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205838 0039d316-1c4b-4281-b951-d872f2087c98
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, 805 insertions, 692 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index dcc8b23..d08ade1 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -321,6 +321,8 @@
'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 f214015..07cecc0 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -68,6 +68,7 @@
'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 6efa083..0889b96 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -9,14 +9,12 @@
#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"
@@ -34,7 +32,7 @@ class OutputSurfaceCallbacks
WebGraphicsSwapBuffersCompleteCallbackCHROMIUM,
public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
- explicit OutputSurfaceCallbacks(OutputSurface* client)
+ explicit OutputSurfaceCallbacks(OutputSurfaceClient* client)
: client_(client) {
DCHECK(client_);
}
@@ -46,155 +44,50 @@ class OutputSurfaceCallbacks
virtual void onContextLost() { client_->DidLoseOutputSurface(); }
private:
- OutputSurface* client_;
+ OutputSurfaceClient* client_;
};
OutputSurface::OutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
- : context3d_(context3d.Pass()),
+ : client_(NULL),
+ context3d_(context3d.Pass()),
has_gl_discard_backbuffer_(false),
has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this),
- max_frames_pending_(0),
- pending_swap_buffers_(0),
- begin_frame_pending_(false),
- client_(NULL) {
+ weak_ptr_factory_(this) {
}
OutputSurface::OutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device)
- : software_device_(software_device.Pass()),
+ : client_(NULL),
+ software_device_(software_device.Pass()),
has_gl_discard_backbuffer_(false),
has_swap_buffers_complete_callback_(false),
device_scale_factor_(-1),
- weak_ptr_factory_(this),
- max_frames_pending_(0),
- pending_swap_buffers_(0),
- begin_frame_pending_(false),
- client_(NULL) {
+ weak_ptr_factory_(this) {
}
OutputSurface::OutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
scoped_ptr<cc::SoftwareOutputDevice> software_device)
- : context3d_(context3d.Pass()),
+ : client_(NULL),
+ 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),
- 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);
+ weak_ptr_factory_(this) {
}
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;
@@ -250,7 +143,7 @@ void OutputSurface::SetContext3D(
context3d_ = context3d.Pass();
- callbacks_.reset(new OutputSurfaceCallbacks(this));
+ callbacks_.reset(new OutputSurfaceCallbacks(client_));
context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get());
context3d_->setContextLostCallback(callbacks_.get());
}
@@ -313,16 +206,20 @@ 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::OnSwapBuffersComplete,
- weak_ptr_factory_.GetWeakPtr(),
- static_cast<CompositorFrameAck*>(NULL)));
+ base::Bind(&OutputSurface::SwapBuffersComplete,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void OutputSurface::SwapBuffersComplete() {
+ if (!client_)
+ return;
+
+ client_->OnSwapBuffersComplete(NULL);
}
} // namespace cc
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 8f782d7..d263d3a 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -12,7 +12,6 @@
#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; }
@@ -20,16 +19,13 @@ 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:
@@ -38,7 +34,7 @@ class Thread;
// 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 : public FrameRateControllerClient {
+class CC_EXPORT OutputSurface {
public:
explicit OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
@@ -87,13 +83,6 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// 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();
@@ -114,7 +103,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// 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.
@@ -127,6 +116,7 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
void PostSwapBuffersComplete();
+ OutputSurfaceClient* client_;
struct cc::OutputSurface::Capabilities capabilities_;
scoped_ptr<OutputSurfaceCallbacks> callbacks_;
scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
@@ -135,34 +125,12 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
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:
- OutputSurfaceClient* client_;
- friend class OutputSurfaceCallbacks;
-
void SetContext3D(scoped_ptr<WebKit::WebGraphicsContext3D> context3d);
+ void SwapBuffersComplete();
+
+ base::WeakPtrFactory<OutputSurface> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OutputSurface);
};
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h
index d727629..f5999c3 100644
--- a/cc/output/output_surface_client.h
+++ b/cc/output/output_surface_client.h
@@ -27,6 +27,8 @@ 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 7dcb1cc..ebc018f 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -5,7 +5,6 @@
#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"
@@ -26,43 +25,19 @@ 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()
- : begin_frame_count_(0),
- deferred_initialize_result_(true),
+ : deferred_initialize_result_(true),
deferred_initialize_called_(false),
did_lose_output_surface_called_(false) {}
@@ -72,9 +47,9 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
return deferred_initialize_result_;
}
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
- virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {
- begin_frame_count_++;
- }
+ virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
+ base::TimeDelta interval) OVERRIDE {}
+ virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {}
virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {}
virtual void DidLoseOutputSurface() OVERRIDE {
did_lose_output_surface_called_ = true;
@@ -82,10 +57,6 @@ 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;
}
@@ -99,7 +70,6 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
}
private:
- int begin_frame_count_;
bool deferred_initialize_result_;
bool deferred_initialize_called_;
bool did_lose_output_surface_called_;
@@ -111,11 +81,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_FALSE(output_surface.HasClientForTesting());
+ EXPECT_EQ(NULL, output_surface.client());
FakeOutputSurfaceClient client;
EXPECT_TRUE(output_surface.BindToClient(&client));
- EXPECT_TRUE(output_surface.HasClientForTesting());
+ EXPECT_EQ(&client, output_surface.client());
EXPECT_FALSE(client.deferred_initialize_called());
// Verify DidLoseOutputSurface callback is hooked up correctly.
@@ -134,11 +104,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_FALSE(output_surface.HasClientForTesting());
+ EXPECT_EQ(NULL, output_surface.client());
FakeOutputSurfaceClient client;
EXPECT_FALSE(output_surface.BindToClient(&client));
- EXPECT_FALSE(output_surface.HasClientForTesting());
+ EXPECT_EQ(NULL, output_surface.client());
}
class InitializeNewContext3D : public ::testing::Test {
@@ -151,13 +121,13 @@ class InitializeNewContext3D : public ::testing::Test {
protected:
void BindOutputSurface() {
EXPECT_TRUE(output_surface_.BindToClient(&client_));
- EXPECT_TRUE(output_surface_.HasClientForTesting());
+ EXPECT_EQ(&client_, output_surface_.client());
}
void InitializeNewContextExpectFail() {
EXPECT_FALSE(output_surface_.InitializeNewContext3D(
context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
- EXPECT_TRUE(output_surface_.HasClientForTesting());
+ EXPECT_EQ(&client_, output_surface_.client());
EXPECT_FALSE(output_surface_.context3d());
EXPECT_TRUE(output_surface_.software_device());
@@ -194,110 +164,5 @@ 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 90cf0d7..b4f1272 100644
--- a/cc/scheduler/frame_rate_controller.cc
+++ b/cc/scheduler/frame_rate_controller.cc
@@ -21,9 +21,7 @@ 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(
@@ -36,7 +34,7 @@ class FrameRateControllerTimeSourceAdapter : public TimeSourceClient {
FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
: client_(NULL),
num_frames_pending_(0),
- max_swaps_pending_(0),
+ max_frames_pending_(0),
time_source_(timer),
active_(false),
is_time_source_throttling_(true),
@@ -50,7 +48,7 @@ FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
FrameRateController::FrameRateController(Thread* thread)
: client_(NULL),
num_frames_pending_(0),
- max_swaps_pending_(0),
+ max_frames_pending_(0),
active_(false),
is_time_source_throttling_(false),
weak_factory_(this),
@@ -77,9 +75,9 @@ void FrameRateController::SetActive(bool active) {
}
}
-void FrameRateController::SetMaxSwapsPending(int max_swaps_pending) {
- DCHECK_GE(max_swaps_pending, 0);
- max_swaps_pending_ = max_swaps_pending;
+void FrameRateController::SetMaxFramesPending(int max_frames_pending) {
+ DCHECK_GE(max_frames_pending, 0);
+ max_frames_pending_ = max_frames_pending;
}
void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase,
@@ -89,17 +87,15 @@ 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_swaps_pending_ && num_frames_pending_ >= max_swaps_pending_;
+ max_frames_pending_ && num_frames_pending_ >= max_frames_pending_;
TRACE_COUNTER_ID1("cc", "ThrottledCompositor", thread_, throttled);
- if (client_) {
- client_->FrameRateControllerTick(throttled);
- }
+ if (client_)
+ client_->BeginFrame(throttled);
if (!is_time_source_throttling_ && !throttled)
PostManualTick();
@@ -112,9 +108,7 @@ 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 70964e2..070c26a 100644
--- a/cc/scheduler/frame_rate_controller.h
+++ b/cc/scheduler/frame_rate_controller.h
@@ -15,21 +15,18 @@ namespace cc {
class Thread;
class TimeSource;
-class FrameRateController;
class CC_EXPORT FrameRateControllerClient {
- protected:
- virtual ~FrameRateControllerClient() {}
-
public:
// Throttled is true when we have a maximum number of frames pending.
- virtual void FrameRateControllerTick(bool throttled) = 0;
+ virtual void BeginFrame(bool throttled) = 0;
+
+ protected:
+ virtual ~FrameRateControllerClient() {}
};
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 {
@@ -44,7 +41,6 @@ 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.
//
@@ -55,9 +51,9 @@ class CC_EXPORT FrameRateController {
void DidSwapBuffers();
void DidSwapBuffersComplete();
void DidAbortAllPendingFrames();
- void SetMaxSwapsPending(int max_swaps_pending); // 0 for unlimited.
- int MaxSwapsPending() const { return max_swaps_pending_; }
- int NumSwapsPendingForTesting() const { return num_frames_pending_; }
+ void SetMaxFramesPending(int max_frames_pending); // 0 for unlimited.
+ int MaxFramesPending() const { return max_frames_pending_; }
+ int NumFramesPendingForTesting() const { return num_frames_pending_; }
// This returns null for unthrottled frame-rate.
base::TimeTicks NextTickTime();
@@ -77,7 +73,7 @@ class CC_EXPORT FrameRateController {
FrameRateControllerClient* client_;
int num_frames_pending_;
- int max_swaps_pending_;
+ int max_frames_pending_;
scoped_refptr<TimeSource> time_source_;
scoped_ptr<FrameRateControllerTimeSourceAdapter> time_source_client_adapter_;
bool active_;
@@ -87,7 +83,6 @@ 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 3fcf4a7..183f576 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 FrameRateControllerTick(bool throttled) OVERRIDE {
+ virtual void BeginFrame(bool throttled) OVERRIDE {
began_frame_ = !throttled;
}
@@ -74,7 +74,7 @@ TEST(FrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight) {
controller.SetClient(&client);
controller.SetActive(true);
- controller.SetMaxSwapsPending(2);
+ controller.SetMaxFramesPending(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.SetMaxSwapsPending(2);
+ controller.SetMaxFramesPending(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 7110bff..d308b0d 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -7,29 +7,23 @@
#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),
- 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)),
+ frame_rate_controller_(frame_rate_controller.Pass()),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false) {
DCHECK(client_);
+ frame_rate_controller_->SetClient(this);
DCHECK(!state_machine_.BeginFrameNeededByImplThread());
}
-Scheduler::~Scheduler() {
- client_->SetNeedsBeginFrameOnImplThread(false);
-}
+Scheduler::~Scheduler() { frame_rate_controller_->SetActive(false); }
void Scheduler::SetCanStart() {
state_machine_.SetCanStart();
@@ -94,6 +88,23 @@ 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();
@@ -102,69 +113,31 @@ 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() {
- 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);
+ return frame_rate_controller_->NextTickTime();
}
base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
- 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);
- }
+ return frame_rate_controller_->LastTickTime();
}
-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);
+void Scheduler::BeginFrame(bool throttled) {
+ TRACE_EVENT1("cc", "Scheduler::BeginFrame", "throttled", throttled);
+ if (!throttled)
+ state_machine_.DidEnterBeginFrame();
ProcessScheduledActions();
- 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;
+ if (!throttled)
+ state_machine_.DidLeaveBeginFrame();
}
void Scheduler::ProcessScheduledActions() {
@@ -178,6 +151,9 @@ 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;
@@ -193,12 +169,23 @@ void Scheduler::ProcessScheduledActions() {
case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED:
client_->ScheduledActionActivatePendingTreeIfNeeded();
break;
- case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE:
- DrawAndSwapIfPossible();
+ 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();
break;
- case SchedulerStateMachine::ACTION_DRAW_FORCED:
- DrawAndSwapForced();
+ }
+ case SchedulerStateMachine::ACTION_DRAW_FORCED: {
+ frame_rate_controller_->DidSwapBuffers();
+ ScheduledActionDrawAndSwapResult result =
+ client_->ScheduledActionDrawAndSwapForced();
+ if (!result.did_swap)
+ frame_rate_controller_->DidSwapBuffersComplete();
break;
+ }
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
client_->ScheduledActionBeginOutputSurfaceCreation();
break;
@@ -209,8 +196,10 @@ void Scheduler::ProcessScheduledActions() {
action = state_machine_.NextAction();
}
- SetupNextBeginFrameIfNeeded();
- client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime());
+ // Activate or deactivate the frame rate controller.
+ frame_rate_controller_->SetActive(
+ state_machine_.BeginFrameNeededByImplThread());
+ client_->DidAnticipatedDrawTimeChange(frame_rate_controller_->NextTickTime());
}
bool Scheduler::WillDrawIfNeeded() const {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index d8151fa..6ecd889 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -11,6 +11,7 @@
#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"
@@ -32,7 +33,6 @@ struct ScheduledActionDrawAndSwapResult {
class SchedulerClient {
public:
- virtual void SetNeedsBeginFrameOnImplThread(bool enable) = 0;
virtual void ScheduledActionSendBeginFrameToMainThread() = 0;
virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapIfPossible() = 0;
@@ -49,12 +49,14 @@ class SchedulerClient {
virtual ~SchedulerClient() {}
};
-class CC_EXPORT Scheduler {
+class CC_EXPORT Scheduler : FrameRateControllerClient {
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, scheduler_settings));
+ return make_scoped_ptr(new Scheduler(
+ client, frame_rate_controller.Pass(), scheduler_settings));
}
virtual ~Scheduler();
@@ -84,6 +86,12 @@ class CC_EXPORT Scheduler {
void FinishCommit();
void BeginFrameAbortedByMainThread();
+ void SetMaxFramesPending(int max);
+ int MaxFramesPending() const;
+ int NumFramesPendingForTesting() const;
+
+ void DidSwapBuffersComplete();
+
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
bool HasInitializedOutputSurface() const {
@@ -95,32 +103,28 @@ class CC_EXPORT Scheduler {
bool WillDrawIfNeeded() const;
+ void SetTimebaseAndInterval(base::TimeTicks timebase,
+ base::TimeDelta interval);
+
base::TimeTicks AnticipatedDrawTime();
base::TimeTicks LastBeginFrameOnImplThreadTime();
- void BeginFrame(base::TimeTicks frame_time);
+ // FrameRateControllerClient implementation
+ virtual void BeginFrame(bool throttled) OVERRIDE;
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_;
-
- 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_;
-
+ scoped_ptr<FrameRateController> frame_rate_controller_;
SchedulerStateMachine state_machine_;
bool inside_process_scheduled_actions_;
diff --git a/cc/scheduler/scheduler_settings.cc b/cc/scheduler/scheduler_settings.cc
index 4850a108..29c525b 100644
--- a/cc/scheduler/scheduler_settings.cc
+++ b/cc/scheduler/scheduler_settings.cc
@@ -8,8 +8,7 @@ namespace cc {
SchedulerSettings::SchedulerSettings()
: impl_side_painting(false),
- timeout_and_draw_when_animation_checkerboards(true),
- using_synchronous_renderer_compositor(false) {}
+ timeout_and_draw_when_animation_checkerboards(true) {}
SchedulerSettings::~SchedulerSettings() {}
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index c06e28f..ebcfc6a 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -16,7 +16,6 @@ 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 fda6e6b..76f7bb1 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -4,7 +4,6 @@
#include "cc/scheduler/scheduler_state_machine.h"
-#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
@@ -13,7 +12,6 @@ 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),
@@ -44,7 +42,6 @@ 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,
@@ -83,8 +80,6 @@ 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_);
@@ -278,7 +273,6 @@ 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
@@ -338,11 +332,6 @@ 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_)
@@ -366,10 +355,6 @@ 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 59e940c..1be0749 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/basictypes.h"
-#include "base/time.h"
#include "cc/base/cc_export.h"
#include "cc/scheduler/scheduler_settings.h"
@@ -79,9 +78,7 @@ 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);
@@ -171,7 +168,6 @@ 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_;
@@ -188,7 +184,6 @@ 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_;
@@ -198,7 +193,6 @@ 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 c535212..001a229 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_TRUE(state.BeginFrameNeededByImplThread());
+ EXPECT_FALSE(state.BeginFrameNeededByImplThread());
}
}
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index bc7d575..68aecaf 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -30,11 +30,7 @@ namespace {
class FakeSchedulerClient : public SchedulerClient {
public:
- FakeSchedulerClient()
- : needs_begin_frame_(false) {
- Reset();
- }
-
+ FakeSchedulerClient() { Reset(); }
void Reset() {
actions_.clear();
states_.clear();
@@ -43,12 +39,15 @@ class FakeSchedulerClient : public SchedulerClient {
num_draws_ = 0;
}
- Scheduler* CreateScheduler(const SchedulerSettings& settings) {
- scheduler_ = Scheduler::Create(this, settings);
+ Scheduler* CreateScheduler(
+ scoped_ptr<FrameRateController> frame_rate_controller,
+ const SchedulerSettings& settings) {
+ scheduler_ =
+ Scheduler::Create(this, frame_rate_controller.Pass(), 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]; }
@@ -69,11 +68,6 @@ 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());
@@ -117,7 +111,6 @@ 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_;
@@ -128,8 +121,11 @@ class FakeSchedulerClient : public SchedulerClient {
TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
FakeSchedulerClient client;
+ scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -142,8 +138,11 @@ TEST(SchedulerTest, InitializeOutputSurfaceDoesNotBeginFrame) {
TEST(SchedulerTest, RequestCommit) {
FakeSchedulerClient client;
+ scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -154,29 +153,33 @@ TEST(SchedulerTest, RequestCommit) {
// SetNeedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_SINGLE_ACTION("ScheduledActionSendBeginFrameToMainThread", client);
+ EXPECT_FALSE(time_source->Active());
client.Reset();
// FinishCommit should commit
scheduler->FinishCommit();
EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
client.Reset();
- // 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());
+ // Tick should draw.
+ time_source->Tick();
+ EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client);
+ EXPECT_FALSE(time_source->Active());
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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -187,8 +190,7 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
// SetNedsCommit should begin the frame.
scheduler->SetNeedsCommit();
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ EXPECT_SINGLE_ACTION("ScheduledActionSendBeginFrameToMainThread", client);
client.Reset();
// Now SetNeedsCommit again. Calling here means we need a second frame.
@@ -201,85 +203,78 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) {
client.Reset();
// Tick should draw but then begin another frame.
- scheduler->BeginFrame(base::TimeTicks::Now());
- EXPECT_TRUE(client.needs_begin_frame());
+ time_source->Tick();
+ EXPECT_FALSE(time_source->Active());
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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
- EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
+ EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client);
client.Reset();
scheduler->DidCreateAndInitializeOutputSurface();
+
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
- client.Reset();
- scheduler->BeginFrame(base::TimeTicks::Now());
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ time_source->Tick();
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_frame());
-
+ EXPECT_FALSE(time_source->Active());
client.Reset();
+
scheduler->SetMainThreadNeedsLayerTextures();
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
0,
- 3);
+ 2);
// A commit was started by SetMainThreadNeedsLayerTextures().
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 3);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 2, 3);
-
- // We should request a BeginFrame in anticipation of a draw.
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2);
client.Reset();
+
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// No draw happens since the textures are acquired by the main thread.
- client.Reset();
- scheduler->BeginFrame(base::TimeTicks::Now());
- EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client);
+ time_source->Tick();
+ EXPECT_EQ(0, client.num_actions_());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
- // Commit will release the texture.
- client.Reset();
scheduler->FinishCommit();
- EXPECT_SINGLE_ACTION("ScheduledActionCommit", client);
+ EXPECT_ACTION("ScheduledActionCommit", client, 0, 1);
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
+ client.Reset();
// Now we can draw again after the commit happens.
- client.Reset();
- scheduler->BeginFrame(base::TimeTicks::Now());
- EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2);
+ time_source->Tick();
+ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1);
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(time_source->Active());
client.Reset();
}
TEST(SchedulerTest, TextureAcquisitionCollision) {
FakeSchedulerClient client;
+ scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -290,22 +285,19 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
scheduler->SetNeedsCommit();
scheduler->SetMainThreadNeedsLayerTextures();
- EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 3);
- EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 3);
+ EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2);
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
- 2,
- 3);
+ 1,
+ 2);
client.Reset();
- // 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());
+ // Compositor not scheduled to draw because textures are locked by main thread
+ EXPECT_FALSE(time_source->Active());
// Trigger the commit
scheduler->FinishCommit();
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
client.Reset();
// Between commit and draw, texture acquisition for main thread delayed,
@@ -315,7 +307,7 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
client.Reset();
// Once compositor draw complete, the delayed texture acquisition fires.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 3);
EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread",
client,
@@ -327,8 +319,11 @@ TEST(SchedulerTest, TextureAcquisitionCollision) {
TEST(SchedulerTest, VisibilitySwitchWithTextureAcquisition) {
FakeSchedulerClient client;
+ scoped_refptr<FakeTimeSource> time_source(new FakeTimeSource());
SchedulerSettings default_scheduler_settings;
- Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -384,8 +379,11 @@ 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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -393,25 +391,28 @@ TEST(SchedulerTest, RequestRedrawInsideDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
EXPECT_EQ(0, client.num_draws());
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(2, client.num_draws());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_FALSE(client.needs_begin_frame());
+ EXPECT_FALSE(time_source->Active());
}
// 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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -421,33 +422,33 @@ TEST(SchedulerTest, RequestRedrawInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
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(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// Fail the draw again.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_FALSE(time_source->Active());
}
class SchedulerClientThatsetNeedsCommitInsideDraw : public FakeSchedulerClient {
@@ -476,8 +477,11 @@ 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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -486,26 +490,28 @@ TEST(SchedulerTest, RequestCommitInsideDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
EXPECT_EQ(0, client.num_draws());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
+ EXPECT_FALSE(time_source->Active());
EXPECT_EQ(1, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
- EXPECT_TRUE(client.needs_begin_frame());
scheduler->FinishCommit();
- scheduler->BeginFrame(base::TimeTicks::Now());
- EXPECT_EQ(2, client.num_draws());;
+ time_source->Tick();
+ EXPECT_EQ(2, client.num_draws());
+ EXPECT_FALSE(time_source->Active());
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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ make_scoped_ptr(new FrameRateController(time_source)),
+ default_scheduler_settings);
scheduler->SetCanStart();
scheduler->SetVisible(true);
scheduler->SetCanDraw(true);
@@ -515,77 +521,128 @@ TEST(SchedulerTest, RequestCommitInsideFailedDraw) {
scheduler->SetNeedsRedraw();
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
EXPECT_EQ(0, client.num_draws());
// Fail the draw.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
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(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// Fail the draw again.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(2, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_TRUE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// Draw successfully.
client.SetDrawWillHappen(true);
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
EXPECT_EQ(3, client.num_draws());
EXPECT_TRUE(scheduler->CommitPending());
EXPECT_FALSE(scheduler->RedrawPending());
- EXPECT_TRUE(client.needs_begin_frame());
+ EXPECT_FALSE(time_source->Active());
}
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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ controller.PassAs<FrameRateController>(),
+ 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(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
EXPECT_EQ(0, client.num_draws());
// Draw successfully, this starts a new frame.
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
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(client.needs_begin_frame());
+ EXPECT_TRUE(time_source->Active());
// Fail to draw, this should not start a frame.
client.SetDrawWillHappen(false);
- scheduler->BeginFrame(base::TimeTicks::Now());
+ time_source->Tick();
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(default_scheduler_settings);
+ Scheduler* scheduler = client.CreateScheduler(
+ controller.PassAs<FrameRateController>(),
+ default_scheduler_settings);
+
+ EXPECT_EQ(0, controller_ptr->NumFramesPending());
// 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
new file mode 100644
index 0000000..206e2376
--- /dev/null
+++ b/cc/scheduler/vsync_time_source.cc
@@ -0,0 +1,76 @@
+// 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
new file mode 100644
index 0000000..4cd0441
--- /dev/null
+++ b/cc/scheduler/vsync_time_source.h
@@ -0,0 +1,78 @@
+// 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
new file mode 100644
index 0000000..4834630
--- /dev/null
+++ b/cc/scheduler/vsync_time_source_unittest.cc
@@ -0,0 +1,124 @@
+// 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 58816cc..dad4014 100644
--- a/cc/test/fake_layer_tree_host_impl_client.h
+++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -17,6 +17,9 @@ 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 9ceadda..c3f3e1a 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -8,7 +8,6 @@
#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 {
@@ -18,8 +17,7 @@ FakeOutputSurface::FakeOutputSurface(
: OutputSurface(context3d.Pass()),
num_sent_frames_(0),
needs_begin_frame_(false),
- forced_draw_to_software_device_(false),
- fake_weak_ptr_factory_(this) {
+ forced_draw_to_software_device_(false) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -30,8 +28,7 @@ FakeOutputSurface::FakeOutputSurface(
scoped_ptr<SoftwareOutputDevice> software_device, bool delegated_rendering)
: OutputSurface(software_device.Pass()),
num_sent_frames_(0),
- forced_draw_to_software_device_(false),
- fake_weak_ptr_factory_(this) {
+ forced_draw_to_software_device_(false) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -44,8 +41,7 @@ FakeOutputSurface::FakeOutputSurface(
bool delegated_rendering)
: OutputSurface(context3d.Pass(), software_device.Pass()),
num_sent_frames_(0),
- forced_draw_to_software_device_(false),
- fake_weak_ptr_factory_(this) {
+ forced_draw_to_software_device_(false) {
if (delegated_rendering) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
@@ -60,7 +56,6 @@ void FakeOutputSurface::SwapBuffers(CompositorFrame* frame) {
frame->AssignTo(&last_sent_frame_);
++num_sent_frames_;
PostSwapBuffersComplete();
- DidSwapBuffers();
} else {
OutputSurface::SwapBuffers(frame);
frame->AssignTo(&last_sent_frame_);
@@ -70,23 +65,12 @@ 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::OnBeginFrame() {
- OutputSurface::BeginFrame(base::TimeTicks::Now());
+void FakeOutputSurface::BeginFrame(base::TimeTicks frame_time) {
+ client_->BeginFrame(frame_time);
}
-
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 7bc1a4f..d54ffd3 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -74,6 +74,7 @@ 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;
@@ -94,13 +95,10 @@ 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 b6f47ab..b8c5366 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -589,13 +589,9 @@ void LayerTreeTest::RunTest(bool threaded,
}
scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface() {
- scoped_ptr<FakeOutputSurface> output_surface;
if (delegating_renderer_)
- output_surface = FakeOutputSurface::CreateDelegating3d();
- else
- output_surface = FakeOutputSurface::Create3d();
- output_surface_ = output_surface.get();
- return output_surface.PassAs<OutputSurface>();
+ return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
+ return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
}
scoped_refptr<cc::ContextProvider> LayerTreeTest::
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 2d67a44..856caaa 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -24,7 +24,6 @@ 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 {
@@ -161,7 +160,6 @@ 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 8ccf47e..c1aa200 100644
--- a/cc/test/scheduler_test_common.cc
+++ b/cc/test/scheduler_test_common.cc
@@ -35,6 +35,16 @@ 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 8834e62..b3b2c2d 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -62,6 +62,36 @@ 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 2670bf8..a497421 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1071,6 +1071,11 @@ 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);
}
@@ -1509,25 +1514,6 @@ 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 e2a303e..72c542d 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -54,6 +54,8 @@ 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;
@@ -181,6 +183,8 @@ 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;
@@ -201,12 +205,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 360e4e3..d643656 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -95,6 +95,8 @@ 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 e4d192e..b8a2e9c 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2049,6 +2049,36 @@ 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:
@@ -2223,10 +2253,32 @@ 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,
@@ -2772,6 +2824,11 @@ 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:
@@ -2838,9 +2895,6 @@ 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 29cc4f4..c448002 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* host_impl) OVERRIDE {
+ virtual void DrawLayersOnThread(LayerTreeHostImpl* tree_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 fd39ed0..8d2d2b7 100644
--- a/cc/trees/proxy.cc
+++ b/cc/trees/proxy.cc
@@ -78,8 +78,4 @@ Proxy::~Proxy() {
DCHECK(IsMainThread());
}
-std::string Proxy::SchedulerStateAsStringForTesting() {
- return "";
-}
-
} // namespace cc
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 4e6171c..aaab780 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -5,8 +5,6 @@
#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"
@@ -100,7 +98,6 @@ 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 9d995ba..0c3946b 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -51,6 +51,8 @@ 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 020c255..53db2c2 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -4,8 +4,6 @@
#include "cc/trees/thread_proxy.h"
-#include <string>
-
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
@@ -18,6 +16,7 @@
#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"
@@ -33,23 +32,6 @@ 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(
@@ -82,6 +64,7 @@ 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) {
@@ -345,21 +328,36 @@ 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::SetNeedsBeginFrameOnImplThread(bool enable) {
+void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase,
+ base::TimeDelta interval) {
DCHECK(IsImplThread());
- TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread",
- "enable", enable);
- layer_tree_host_impl_->SetNeedsBeginFrame(enable);
+ TRACE_EVENT2("cc",
+ "ThreadProxy::OnVSyncParametersChanged",
+ "timebase",
+ (timebase - base::TimeTicks()).InMilliseconds(),
+ "interval",
+ interval.InMilliseconds());
+ scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval);
}
void ThreadProxy::BeginFrameOnImplThread(base::TimeTicks frame_time) {
DCHECK(IsImplThread());
- TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread");
- scheduler_on_impl_thread_->BeginFrame(frame_time);
+ 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);
}
void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
@@ -1112,14 +1110,35 @@ 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_settings.using_synchronous_renderer_compositor =
- settings.using_synchronous_renderer_compositor;
- scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings);
+ scheduler_on_impl_thread_ = Scheduler::Create(this,
+ frame_rate_controller.Pass(),
+ scheduler_settings);
scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
@@ -1145,6 +1164,16 @@ 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();
}
@@ -1189,6 +1218,7 @@ 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();
}
@@ -1248,29 +1278,6 @@ 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 8013882..3cc905d 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -5,8 +5,6 @@
#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"
@@ -14,6 +12,7 @@
#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"
@@ -30,7 +29,8 @@ class Thread;
class ThreadProxy : public Proxy,
LayerTreeHostImplClient,
SchedulerClient,
- ResourceUpdateControllerClient {
+ ResourceUpdateControllerClient,
+ VSyncProvider {
public:
static scoped_ptr<Proxy> Create(LayerTreeHost* layer_tree_host,
scoped_ptr<Thread> impl_thread);
@@ -59,7 +59,6 @@ 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(
@@ -67,7 +66,10 @@ class ThreadProxy : public Proxy,
scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE;
virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE;
virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE;
- virtual void BeginFrameOnImplThread(base::TimeTicks frame_time) 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;
virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE;
virtual void SetNeedsRedrawOnImplThread() OVERRIDE;
@@ -89,7 +91,6 @@ class ThreadProxy : public Proxy,
virtual void DidActivatePendingTree() OVERRIDE;
// SchedulerClient implementation
- virtual void SetNeedsBeginFrameOnImplThread(bool enable) OVERRIDE;
virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE;
virtual ScheduledActionDrawAndSwapResult
ScheduledActionDrawAndSwapIfPossible() OVERRIDE;
@@ -105,6 +106,17 @@ 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);
@@ -131,10 +143,16 @@ class ThreadProxy : public Proxy,
const RendererCapabilities& capabilities);
// Called on impl thread.
- struct ReadbackRequest;
- struct CommitPendingRequest;
- struct SchedulerStateRequest;
-
+ struct ReadbackRequest {
+ CompletionEvent completion;
+ bool success;
+ void* pixels;
+ gfx::Rect rect;
+ };
+ struct CommitPendingRequest {
+ CompletionEvent completion;
+ bool commit_pending;
+ };
void ForceCommitOnImplThread(CompletionEvent* completion);
void StartCommitOnImplThread(
CompletionEvent* completion,
@@ -164,8 +182,6 @@ 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,
@@ -234,6 +250,7 @@ class ThreadProxy : public Proxy,
bool throttle_frame_production_;
bool begin_frame_scheduling_enabled_;
bool using_synchronous_renderer_compositor_;
+ VSyncClient* vsync_client_;
bool inside_draw_;