summaryrefslogtreecommitdiffstats
path: root/cc/output/output_surface_unittest.cc
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 13:21:48 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-12 13:21:48 +0000
commitbe62216f3ea56d5e9dc9bccf2c37e6e7937de290 (patch)
treef7da60411946679e8666addc93d4fe9a82216aa5 /cc/output/output_surface_unittest.cc
parentff0f4128d79ff878318a0c266947ee5ad14fc662 (diff)
downloadchromium_src-be62216f3ea56d5e9dc9bccf2c37e6e7937de290.zip
chromium_src-be62216f3ea56d5e9dc9bccf2c37e6e7937de290.tar.gz
chromium_src-be62216f3ea56d5e9dc9bccf2c37e6e7937de290.tar.bz2
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 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205750 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/output/output_surface_unittest.cc')
-rw-r--r--cc/output/output_surface_unittest.cc159
1 files changed, 147 insertions, 12 deletions
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index ebc018f..7dcb1cc 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -5,6 +5,7 @@
#include "cc/output/output_surface.h"
#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
+#include "cc/test/scheduler_test_common.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -25,19 +26,43 @@ class TestOutputSurface : public OutputSurface {
scoped_ptr<cc::SoftwareOutputDevice> software_device)
: OutputSurface(context3d.Pass(), software_device.Pass()) {}
- OutputSurfaceClient* client() { return client_; }
-
bool InitializeNewContext3D(
scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) {
return InitializeAndSetContext3D(new_context3d.Pass(),
scoped_refptr<ContextProvider>());
}
+
+ bool HasClientForTesting() {
+ return HasClient();
+ }
+
+ void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ OnVSyncParametersChanged(timebase, interval);
+ }
+
+ void BeginFrameForTesting(base::TimeTicks frame_time) {
+ BeginFrame(frame_time);
+ }
+
+ void DidSwapBuffersForTesting() {
+ DidSwapBuffers();
+ }
+
+ int pending_swap_buffers() {
+ return pending_swap_buffers_;
+ }
+
+ void OnSwapBuffersCompleteForTesting() {
+ OnSwapBuffersComplete(NULL);
+ }
};
class FakeOutputSurfaceClient : public OutputSurfaceClient {
public:
FakeOutputSurfaceClient()
- : deferred_initialize_result_(true),
+ : begin_frame_count_(0),
+ deferred_initialize_result_(true),
deferred_initialize_called_(false),
did_lose_output_surface_called_(false) {}
@@ -47,9 +72,9 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
return deferred_initialize_result_;
}
virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
- virtual void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
- virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {}
+ virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {
+ begin_frame_count_++;
+ }
virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {}
virtual void DidLoseOutputSurface() OVERRIDE {
did_lose_output_surface_called_ = true;
@@ -57,6 +82,10 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
gfx::Rect viewport) OVERRIDE {}
+ int begin_frame_count() {
+ return begin_frame_count_;
+ }
+
void set_deferred_initialize_result(bool result) {
deferred_initialize_result_ = result;
}
@@ -70,6 +99,7 @@ class FakeOutputSurfaceClient : public OutputSurfaceClient {
}
private:
+ int begin_frame_count_;
bool deferred_initialize_result_;
bool deferred_initialize_called_;
bool did_lose_output_surface_called_;
@@ -81,11 +111,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
FakeOutputSurfaceClient client;
EXPECT_TRUE(output_surface.BindToClient(&client));
- EXPECT_EQ(&client, output_surface.client());
+ EXPECT_TRUE(output_surface.HasClientForTesting());
EXPECT_FALSE(client.deferred_initialize_called());
// Verify DidLoseOutputSurface callback is hooked up correctly.
@@ -104,11 +134,11 @@ TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
TestOutputSurface output_surface(
context3d.PassAs<WebKit::WebGraphicsContext3D>());
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
FakeOutputSurfaceClient client;
EXPECT_FALSE(output_surface.BindToClient(&client));
- EXPECT_EQ(NULL, output_surface.client());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
}
class InitializeNewContext3D : public ::testing::Test {
@@ -121,13 +151,13 @@ class InitializeNewContext3D : public ::testing::Test {
protected:
void BindOutputSurface() {
EXPECT_TRUE(output_surface_.BindToClient(&client_));
- EXPECT_EQ(&client_, output_surface_.client());
+ EXPECT_TRUE(output_surface_.HasClientForTesting());
}
void InitializeNewContextExpectFail() {
EXPECT_FALSE(output_surface_.InitializeNewContext3D(
context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
- EXPECT_EQ(&client_, output_surface_.client());
+ EXPECT_TRUE(output_surface_.HasClientForTesting());
EXPECT_FALSE(output_surface_.context3d());
EXPECT_TRUE(output_surface_.software_device());
@@ -164,5 +194,110 @@ TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) {
InitializeNewContextExpectFail();
}
+TEST(OutputSurfaceTest, BeginFrameEmulation) {
+ scoped_ptr<TestWebGraphicsContext3D> context3d =
+ TestWebGraphicsContext3D::Create();
+
+ TestOutputSurface output_surface(
+ context3d.PassAs<WebKit::WebGraphicsContext3D>());
+ EXPECT_FALSE(output_surface.HasClientForTesting());
+
+ FakeOutputSurfaceClient client;
+ EXPECT_TRUE(output_surface.BindToClient(&client));
+ EXPECT_TRUE(output_surface.HasClientForTesting());
+ EXPECT_FALSE(client.deferred_initialize_called());
+
+ // Initialize BeginFrame emulation
+ FakeThread impl_thread;
+ bool throttle_frame_production = true;
+ const base::TimeDelta display_refresh_interval =
+ base::TimeDelta::FromMicroseconds(16666);
+
+ output_surface.InitializeBeginFrameEmulation(
+ &impl_thread,
+ throttle_frame_production,
+ display_refresh_interval);
+
+ output_surface.SetMaxFramesPending(2);
+
+ // We should start off with 0 BeginFrames
+ EXPECT_EQ(client.begin_frame_count(), 0);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
+
+ // We should not have a pending task until a BeginFrame has been requested.
+ EXPECT_FALSE(impl_thread.HasPendingTask());
+ output_surface.SetNeedsBeginFrame(true);
+ EXPECT_TRUE(impl_thread.HasPendingTask());
+
+ // BeginFrame should be called on the first tick.
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
+
+ // BeginFrame should not be called when there is a pending BeginFrame.
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
+
+ // DidSwapBuffers should clear the pending BeginFrame.
+ output_surface.DidSwapBuffersForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 1);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // BeginFrame should be throttled by pending swap buffers.
+ output_surface.DidSwapBuffersForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+
+ // SwapAck should decrement pending swap buffers and unblock BeginFrame again.
+ output_surface.OnSwapBuffersCompleteForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 2);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 3);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Calling SetNeedsBeginFrame again indicates a swap did not occur but
+ // the client still wants another BeginFrame.
+ output_surface.SetNeedsBeginFrame(true);
+ impl_thread.RunPendingTask();
+ EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
+ output_surface.SetNeedsBeginFrame(false);
+ impl_thread.RunPendingTask();
+ EXPECT_FALSE(impl_thread.HasPendingTask());
+ EXPECT_EQ(client.begin_frame_count(), 4);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should be
+ // allowed.
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
+ // still be throttled by pending begin frames however.
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
+
+ // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
+ // also be throttled by pending swap buffers.
+ output_surface.DidSwapBuffersForTesting();
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+ output_surface.BeginFrameForTesting(base::TimeTicks::Now());
+ EXPECT_EQ(client.begin_frame_count(), 5);
+ EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
+}
+
} // namespace
} // namespace cc