| Index: cc/output/output_surface_unittest.cc
|
| diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
|
| index ebc018f8ea61a0b2ea37ac26c1adffd8b8673b01..7dcb1cce0fe59ea65f5f6cc51634e3c0a85a9cf5 100644
|
| --- a/cc/output/output_surface_unittest.cc
|
| +++ b/cc/output/output_surface_unittest.cc
|
| @@ -5,6 +5,7 @@
|
| #include "cc/output/output_surface.h"
|
| #include "cc/output/output_surface_client.h"
|
| #include "cc/output/software_output_device.h"
|
| +#include "cc/test/scheduler_test_common.h"
|
| #include "cc/test/test_web_graphics_context_3d.h"
|
| #include "gpu/GLES2/gl2extchromium.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| @@ -25,19 +26,43 @@ class TestOutputSurface : public OutputSurface {
|
| scoped_ptr<cc::SoftwareOutputDevice> software_device)
|
| : OutputSurface(context3d.Pass(), software_device.Pass()) {}
|
|
|
| - OutputSurfaceClient* client() { return client_; }
|
| -
|
| bool InitializeNewContext3D(
|
| scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) {
|
| return InitializeAndSetContext3D(new_context3d.Pass(),
|
| scoped_refptr<ContextProvider>());
|
| }
|
| +
|
| + bool HasClientForTesting() {
|
| + return HasClient();
|
| + }
|
| +
|
| + void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
|
| + base::TimeDelta interval) {
|
| + OnVSyncParametersChanged(timebase, interval);
|
| + }
|
| +
|
| + void BeginFrameForTesting(base::TimeTicks frame_time) {
|
| + BeginFrame(frame_time);
|
| + }
|
| +
|
| + void DidSwapBuffersForTesting() {
|
| + DidSwapBuffers();
|
| + }
|
| +
|
| + int pending_swap_buffers() {
|
| + return pending_swap_buffers_;
|
| + }
|
| +
|
| + void OnSwapBuffersCompleteForTesting() {
|
| + OnSwapBuffersComplete(NULL);
|
| + }
|
| };
|
|
|
| class FakeOutputSurfaceClient : public OutputSurfaceClient {
|
| public:
|
| FakeOutputSurfaceClient()
|
| - : deferred_initialize_result_(true),
|
| + : begin_frame_count_(0),
|
| + deferred_initialize_result_(true),
|
| deferred_initialize_called_(false),
|
| did_lose_output_surface_called_(false) {}
|
|
|
| @@ -47,9 +72,9 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
|
| return deferred_initialize_result_;
|
| }
|
| virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
|
| - virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
|
| - base::TimeDelta interval) OVERRIDE {}
|
| - virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {}
|
| + virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {
|
| + begin_frame_count_++;
|
| + }
|
| virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {}
|
| virtual void DidLoseOutputSurface() OVERRIDE {
|
| did_lose_output_surface_called_ = true;
|
| @@ -57,6 +82,10 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
|
| virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
|
| gfx::Rect viewport) OVERRIDE {}
|
|
|
| + int begin_frame_count() {
|
| + return begin_frame_count_;
|
| + }
|
| +
|
| void set_deferred_initialize_result(bool result) {
|
| deferred_initialize_result_ = result;
|
| }
|
| @@ -70,6 +99,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
|
| }
|
|
|
| private:
|
| + int begin_frame_count_;
|
| bool deferred_initialize_result_;
|
| bool deferred_initialize_called_;
|
| bool did_lose_output_surface_called_;
|
| @@ -81,11 +111,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
|
|
|
| TestOutputSurface output_surface(
|
| context3d.PassAs<WebKit::WebGraphicsContext3D>());
|
| - EXPECT_EQ(NULL, output_surface.client());
|
| + EXPECT_FALSE(output_surface.HasClientForTesting());
|
|
|
| FakeOutputSurfaceClient client;
|
| EXPECT_TRUE(output_surface.BindToClient(&client));
|
| - EXPECT_EQ(&client, output_surface.client());
|
| + EXPECT_TRUE(output_surface.HasClientForTesting());
|
| EXPECT_FALSE(client.deferred_initialize_called());
|
|
|
| // Verify DidLoseOutputSurface callback is hooked up correctly.
|
| @@ -104,11 +134,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
|
|
|
| TestOutputSurface output_surface(
|
| context3d.PassAs<WebKit::WebGraphicsContext3D>());
|
| - EXPECT_EQ(NULL, output_surface.client());
|
| + EXPECT_FALSE(output_surface.HasClientForTesting());
|
|
|
| FakeOutputSurfaceClient client;
|
| EXPECT_FALSE(output_surface.BindToClient(&client));
|
| - EXPECT_EQ(NULL, output_surface.client());
|
| + EXPECT_FALSE(output_surface.HasClientForTesting());
|
| }
|
|
|
| class InitializeNewContext3D : public ::testing::Test {
|
| @@ -121,13 +151,13 @@ class InitializeNewContext3D : public ::testing::Test {
|
| protected:
|
| void BindOutputSurface() {
|
| EXPECT_TRUE(output_surface_.BindToClient(&client_));
|
| - EXPECT_EQ(&client_, output_surface_.client());
|
| + EXPECT_TRUE(output_surface_.HasClientForTesting());
|
| }
|
|
|
| void InitializeNewContextExpectFail() {
|
| EXPECT_FALSE(output_surface_.InitializeNewContext3D(
|
| context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
|
| - EXPECT_EQ(&client_, output_surface_.client());
|
| + EXPECT_TRUE(output_surface_.HasClientForTesting());
|
|
|
| EXPECT_FALSE(output_surface_.context3d());
|
| EXPECT_TRUE(output_surface_.software_device());
|
| @@ -164,5 +194,110 @@ TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) {
|
| InitializeNewContextExpectFail();
|
| }
|
|
|
| +TEST(OutputSurfaceTest, BeginFrameEmulation) {
|
| + scoped_ptr<TestWebGraphicsContext3D> context3d =
|
| + TestWebGraphicsContext3D::Create();
|
| +
|
| + TestOutputSurface output_surface(
|
| + context3d.PassAs<WebKit::WebGraphicsContext3D>());
|
| + EXPECT_FALSE(output_surface.HasClientForTesting());
|
| +
|
| + FakeOutputSurfaceClient client;
|
| + EXPECT_TRUE(output_surface.BindToClient(&client));
|
| + EXPECT_TRUE(output_surface.HasClientForTesting());
|
| + EXPECT_FALSE(client.deferred_initialize_called());
|
| +
|
| + // Initialize BeginFrame emulation
|
| + FakeThread impl_thread;
|
| + bool throttle_frame_production = true;
|
| + const base::TimeDelta display_refresh_interval =
|
| + base::TimeDelta::FromMicroseconds(16666);
|
| +
|
| + output_surface.InitializeBeginFrameEmulation(
|
| + &impl_thread,
|
| + throttle_frame_production,
|
| + display_refresh_interval);
|
| +
|
| + output_surface.SetMaxFramesPending(2);
|
| +
|
| + // We should start off with 0 BeginFrames
|
| + EXPECT_EQ(client.begin_frame_count(), 0);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
|
| +
|
| + // We should not have a pending task until a BeginFrame has been requested.
|
| + EXPECT_FALSE(impl_thread.HasPendingTask());
|
| + output_surface.SetNeedsBeginFrame(true);
|
| + EXPECT_TRUE(impl_thread.HasPendingTask());
|
| +
|
| + // BeginFrame should be called on the first tick.
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 1);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
|
| +
|
| + // BeginFrame should not be called when there is a pending BeginFrame.
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 1);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
|
| +
|
| + // DidSwapBuffers should clear the pending BeginFrame.
|
| + output_surface.DidSwapBuffersForTesting();
|
| + EXPECT_EQ(client.begin_frame_count(), 1);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 2);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // BeginFrame should be throttled by pending swap buffers.
|
| + output_surface.DidSwapBuffersForTesting();
|
| + EXPECT_EQ(client.begin_frame_count(), 2);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 2);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
|
| +
|
| + // SwapAck should decrement pending swap buffers and unblock BeginFrame again.
|
| + output_surface.OnSwapBuffersCompleteForTesting();
|
| + EXPECT_EQ(client.begin_frame_count(), 2);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 3);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // Calling SetNeedsBeginFrame again indicates a swap did not occur but
|
| + // the client still wants another BeginFrame.
|
| + output_surface.SetNeedsBeginFrame(true);
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_EQ(client.begin_frame_count(), 4);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
|
| + output_surface.SetNeedsBeginFrame(false);
|
| + impl_thread.RunPendingTask();
|
| + EXPECT_FALSE(impl_thread.HasPendingTask());
|
| + EXPECT_EQ(client.begin_frame_count(), 4);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // Optimistically injected BeginFrames without a SetNeedsBeginFrame should be
|
| + // allowed.
|
| + output_surface.BeginFrameForTesting(base::TimeTicks::Now());
|
| + EXPECT_EQ(client.begin_frame_count(), 5);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
|
| + // still be throttled by pending begin frames however.
|
| + output_surface.BeginFrameForTesting(base::TimeTicks::Now());
|
| + EXPECT_EQ(client.begin_frame_count(), 5);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
|
| +
|
| + // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
|
| + // also be throttled by pending swap buffers.
|
| + output_surface.DidSwapBuffersForTesting();
|
| + EXPECT_EQ(client.begin_frame_count(), 5);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
|
| + output_surface.BeginFrameForTesting(base::TimeTicks::Now());
|
| + EXPECT_EQ(client.begin_frame_count(), 5);
|
| + EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
|
| +}
|
| +
|
| } // namespace
|
| } // namespace cc
|
|
|