Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: cc/output/output_surface_unittest.cc

Issue 16833003: cc: Emulate BeginFrame in OutputSurfaces that don't support it natively (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/output/output_surface_client.h ('k') | cc/scheduler/frame_rate_controller.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/output/output_surface.h" 5 #include "cc/output/output_surface.h"
6 #include "cc/output/output_surface_client.h" 6 #include "cc/output/output_surface_client.h"
7 #include "cc/output/software_output_device.h" 7 #include "cc/output/software_output_device.h"
8 #include "cc/test/scheduler_test_common.h"
8 #include "cc/test/test_web_graphics_context_3d.h" 9 #include "cc/test/test_web_graphics_context_3d.h"
9 #include "gpu/GLES2/gl2extchromium.h" 10 #include "gpu/GLES2/gl2extchromium.h"
10 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
11 12
12 namespace cc { 13 namespace cc {
13 namespace { 14 namespace {
14 15
15 class TestOutputSurface : public OutputSurface { 16 class TestOutputSurface : public OutputSurface {
16 public: 17 public:
17 explicit TestOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d) 18 explicit TestOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
18 : OutputSurface(context3d.Pass()) {} 19 : OutputSurface(context3d.Pass()) {}
19 20
20 explicit TestOutputSurface( 21 explicit TestOutputSurface(
21 scoped_ptr<cc::SoftwareOutputDevice> software_device) 22 scoped_ptr<cc::SoftwareOutputDevice> software_device)
22 : OutputSurface(software_device.Pass()) {} 23 : OutputSurface(software_device.Pass()) {}
23 24
24 TestOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d, 25 TestOutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
25 scoped_ptr<cc::SoftwareOutputDevice> software_device) 26 scoped_ptr<cc::SoftwareOutputDevice> software_device)
26 : OutputSurface(context3d.Pass(), software_device.Pass()) {} 27 : OutputSurface(context3d.Pass(), software_device.Pass()) {}
27 28
28 OutputSurfaceClient* client() { return client_; }
29
30 bool InitializeNewContext3D( 29 bool InitializeNewContext3D(
31 scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) { 30 scoped_ptr<WebKit::WebGraphicsContext3D> new_context3d) {
32 return InitializeAndSetContext3D(new_context3d.Pass(), 31 return InitializeAndSetContext3D(new_context3d.Pass(),
33 scoped_refptr<ContextProvider>()); 32 scoped_refptr<ContextProvider>());
34 } 33 }
34
35 bool HasClientForTesting() {
36 return HasClient();
37 }
38
39 void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
40 base::TimeDelta interval) {
41 OnVSyncParametersChanged(timebase, interval);
42 }
43
44 void BeginFrameForTesting(base::TimeTicks frame_time) {
45 BeginFrame(frame_time);
46 }
47
48 void DidSwapBuffersForTesting() {
49 DidSwapBuffers();
50 }
51
52 int pending_swap_buffers() {
53 return pending_swap_buffers_;
54 }
55
56 void OnSwapBuffersCompleteForTesting() {
57 OnSwapBuffersComplete(NULL);
58 }
35 }; 59 };
36 60
37 class FakeOutputSurfaceClient : public OutputSurfaceClient { 61 class FakeOutputSurfaceClient : public OutputSurfaceClient {
38 public: 62 public:
39 FakeOutputSurfaceClient() 63 FakeOutputSurfaceClient()
40 : deferred_initialize_result_(true), 64 : begin_frame_count_(0),
65 deferred_initialize_result_(true),
41 deferred_initialize_called_(false), 66 deferred_initialize_called_(false),
42 did_lose_output_surface_called_(false) {} 67 did_lose_output_surface_called_(false) {}
43 68
44 virtual bool DeferredInitialize( 69 virtual bool DeferredInitialize(
45 scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE { 70 scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {
46 deferred_initialize_called_ = true; 71 deferred_initialize_called_ = true;
47 return deferred_initialize_result_; 72 return deferred_initialize_result_;
48 } 73 }
49 virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {} 74 virtual void SetNeedsRedrawRect(gfx::Rect damage_rect) OVERRIDE {}
50 virtual void OnVSyncParametersChanged(base::TimeTicks timebase, 75 virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {
51 base::TimeDelta interval) OVERRIDE {} 76 begin_frame_count_++;
52 virtual void BeginFrame(base::TimeTicks frame_time) OVERRIDE {} 77 }
53 virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {} 78 virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {}
54 virtual void DidLoseOutputSurface() OVERRIDE { 79 virtual void DidLoseOutputSurface() OVERRIDE {
55 did_lose_output_surface_called_ = true; 80 did_lose_output_surface_called_ = true;
56 } 81 }
57 virtual void SetExternalDrawConstraints(const gfx::Transform& transform, 82 virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
58 gfx::Rect viewport) OVERRIDE {} 83 gfx::Rect viewport) OVERRIDE {}
59 84
85 int begin_frame_count() {
86 return begin_frame_count_;
87 }
88
60 void set_deferred_initialize_result(bool result) { 89 void set_deferred_initialize_result(bool result) {
61 deferred_initialize_result_ = result; 90 deferred_initialize_result_ = result;
62 } 91 }
63 92
64 bool deferred_initialize_called() { 93 bool deferred_initialize_called() {
65 return deferred_initialize_called_; 94 return deferred_initialize_called_;
66 } 95 }
67 96
68 bool did_lose_output_surface_called() { 97 bool did_lose_output_surface_called() {
69 return did_lose_output_surface_called_; 98 return did_lose_output_surface_called_;
70 } 99 }
71 100
72 private: 101 private:
102 int begin_frame_count_;
73 bool deferred_initialize_result_; 103 bool deferred_initialize_result_;
74 bool deferred_initialize_called_; 104 bool deferred_initialize_called_;
75 bool did_lose_output_surface_called_; 105 bool did_lose_output_surface_called_;
76 }; 106 };
77 107
78 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) { 108 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
79 scoped_ptr<TestWebGraphicsContext3D> context3d = 109 scoped_ptr<TestWebGraphicsContext3D> context3d =
80 TestWebGraphicsContext3D::Create(); 110 TestWebGraphicsContext3D::Create();
81 111
82 TestOutputSurface output_surface( 112 TestOutputSurface output_surface(
83 context3d.PassAs<WebKit::WebGraphicsContext3D>()); 113 context3d.PassAs<WebKit::WebGraphicsContext3D>());
84 EXPECT_EQ(NULL, output_surface.client()); 114 EXPECT_FALSE(output_surface.HasClientForTesting());
85 115
86 FakeOutputSurfaceClient client; 116 FakeOutputSurfaceClient client;
87 EXPECT_TRUE(output_surface.BindToClient(&client)); 117 EXPECT_TRUE(output_surface.BindToClient(&client));
88 EXPECT_EQ(&client, output_surface.client()); 118 EXPECT_TRUE(output_surface.HasClientForTesting());
89 EXPECT_FALSE(client.deferred_initialize_called()); 119 EXPECT_FALSE(client.deferred_initialize_called());
90 120
91 // Verify DidLoseOutputSurface callback is hooked up correctly. 121 // Verify DidLoseOutputSurface callback is hooked up correctly.
92 EXPECT_FALSE(client.did_lose_output_surface_called()); 122 EXPECT_FALSE(client.did_lose_output_surface_called());
93 output_surface.context3d()->loseContextCHROMIUM( 123 output_surface.context3d()->loseContextCHROMIUM(
94 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); 124 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
95 EXPECT_TRUE(client.did_lose_output_surface_called()); 125 EXPECT_TRUE(client.did_lose_output_surface_called());
96 } 126 }
97 127
98 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) { 128 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
99 scoped_ptr<TestWebGraphicsContext3D> context3d = 129 scoped_ptr<TestWebGraphicsContext3D> context3d =
100 TestWebGraphicsContext3D::Create(); 130 TestWebGraphicsContext3D::Create();
101 131
102 // Lose the context so BindToClient fails. 132 // Lose the context so BindToClient fails.
103 context3d->set_times_make_current_succeeds(0); 133 context3d->set_times_make_current_succeeds(0);
104 134
105 TestOutputSurface output_surface( 135 TestOutputSurface output_surface(
106 context3d.PassAs<WebKit::WebGraphicsContext3D>()); 136 context3d.PassAs<WebKit::WebGraphicsContext3D>());
107 EXPECT_EQ(NULL, output_surface.client()); 137 EXPECT_FALSE(output_surface.HasClientForTesting());
108 138
109 FakeOutputSurfaceClient client; 139 FakeOutputSurfaceClient client;
110 EXPECT_FALSE(output_surface.BindToClient(&client)); 140 EXPECT_FALSE(output_surface.BindToClient(&client));
111 EXPECT_EQ(NULL, output_surface.client()); 141 EXPECT_FALSE(output_surface.HasClientForTesting());
112 } 142 }
113 143
114 class InitializeNewContext3D : public ::testing::Test { 144 class InitializeNewContext3D : public ::testing::Test {
115 public: 145 public:
116 InitializeNewContext3D() 146 InitializeNewContext3D()
117 : context3d_(TestWebGraphicsContext3D::Create()), 147 : context3d_(TestWebGraphicsContext3D::Create()),
118 output_surface_( 148 output_surface_(
119 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) {} 149 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) {}
120 150
121 protected: 151 protected:
122 void BindOutputSurface() { 152 void BindOutputSurface() {
123 EXPECT_TRUE(output_surface_.BindToClient(&client_)); 153 EXPECT_TRUE(output_surface_.BindToClient(&client_));
124 EXPECT_EQ(&client_, output_surface_.client()); 154 EXPECT_TRUE(output_surface_.HasClientForTesting());
125 } 155 }
126 156
127 void InitializeNewContextExpectFail() { 157 void InitializeNewContextExpectFail() {
128 EXPECT_FALSE(output_surface_.InitializeNewContext3D( 158 EXPECT_FALSE(output_surface_.InitializeNewContext3D(
129 context3d_.PassAs<WebKit::WebGraphicsContext3D>())); 159 context3d_.PassAs<WebKit::WebGraphicsContext3D>()));
130 EXPECT_EQ(&client_, output_surface_.client()); 160 EXPECT_TRUE(output_surface_.HasClientForTesting());
131 161
132 EXPECT_FALSE(output_surface_.context3d()); 162 EXPECT_FALSE(output_surface_.context3d());
133 EXPECT_TRUE(output_surface_.software_device()); 163 EXPECT_TRUE(output_surface_.software_device());
134 } 164 }
135 165
136 scoped_ptr<TestWebGraphicsContext3D> context3d_; 166 scoped_ptr<TestWebGraphicsContext3D> context3d_;
137 TestOutputSurface output_surface_; 167 TestOutputSurface output_surface_;
138 FakeOutputSurfaceClient client_; 168 FakeOutputSurfaceClient client_;
139 }; 169 };
140 170
(...skipping 16 matching lines...) Expand all
157 context3d_->set_times_make_current_succeeds(0); 187 context3d_->set_times_make_current_succeeds(0);
158 InitializeNewContextExpectFail(); 188 InitializeNewContextExpectFail();
159 } 189 }
160 190
161 TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) { 191 TEST_F(InitializeNewContext3D, ClientDeferredInitializeFails) {
162 BindOutputSurface(); 192 BindOutputSurface();
163 client_.set_deferred_initialize_result(false); 193 client_.set_deferred_initialize_result(false);
164 InitializeNewContextExpectFail(); 194 InitializeNewContextExpectFail();
165 } 195 }
166 196
197 TEST(OutputSurfaceTest, BeginFrameEmulation) {
198 scoped_ptr<TestWebGraphicsContext3D> context3d =
199 TestWebGraphicsContext3D::Create();
200
201 TestOutputSurface output_surface(
202 context3d.PassAs<WebKit::WebGraphicsContext3D>());
203 EXPECT_FALSE(output_surface.HasClientForTesting());
204
205 FakeOutputSurfaceClient client;
206 EXPECT_TRUE(output_surface.BindToClient(&client));
207 EXPECT_TRUE(output_surface.HasClientForTesting());
208 EXPECT_FALSE(client.deferred_initialize_called());
209
210 // Initialize BeginFrame emulation
211 FakeThread impl_thread;
212 bool throttle_frame_production = true;
213 const base::TimeDelta display_refresh_interval =
214 base::TimeDelta::FromMicroseconds(16666);
215
216 output_surface.InitializeBeginFrameEmulation(
217 &impl_thread,
218 throttle_frame_production,
219 display_refresh_interval);
220
221 output_surface.SetMaxFramesPending(2);
222
223 // We should start off with 0 BeginFrames
224 EXPECT_EQ(client.begin_frame_count(), 0);
225 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
226
227 // We should not have a pending task until a BeginFrame has been requested.
228 EXPECT_FALSE(impl_thread.HasPendingTask());
229 output_surface.SetNeedsBeginFrame(true);
230 EXPECT_TRUE(impl_thread.HasPendingTask());
231
232 // BeginFrame should be called on the first tick.
233 impl_thread.RunPendingTask();
234 EXPECT_EQ(client.begin_frame_count(), 1);
235 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
236
237 // BeginFrame should not be called when there is a pending BeginFrame.
238 impl_thread.RunPendingTask();
239 EXPECT_EQ(client.begin_frame_count(), 1);
240 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
241
242 // DidSwapBuffers should clear the pending BeginFrame.
243 output_surface.DidSwapBuffersForTesting();
244 EXPECT_EQ(client.begin_frame_count(), 1);
245 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
246 impl_thread.RunPendingTask();
247 EXPECT_EQ(client.begin_frame_count(), 2);
248 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
249
250 // BeginFrame should be throttled by pending swap buffers.
251 output_surface.DidSwapBuffersForTesting();
252 EXPECT_EQ(client.begin_frame_count(), 2);
253 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
254 impl_thread.RunPendingTask();
255 EXPECT_EQ(client.begin_frame_count(), 2);
256 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
257
258 // SwapAck should decrement pending swap buffers and unblock BeginFrame again.
259 output_surface.OnSwapBuffersCompleteForTesting();
260 EXPECT_EQ(client.begin_frame_count(), 2);
261 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
262 impl_thread.RunPendingTask();
263 EXPECT_EQ(client.begin_frame_count(), 3);
264 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
265
266 // Calling SetNeedsBeginFrame again indicates a swap did not occur but
267 // the client still wants another BeginFrame.
268 output_surface.SetNeedsBeginFrame(true);
269 impl_thread.RunPendingTask();
270 EXPECT_EQ(client.begin_frame_count(), 4);
271 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
272
273 // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
274 output_surface.SetNeedsBeginFrame(false);
275 impl_thread.RunPendingTask();
276 EXPECT_FALSE(impl_thread.HasPendingTask());
277 EXPECT_EQ(client.begin_frame_count(), 4);
278 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
279
280 // Optimistically injected BeginFrames without a SetNeedsBeginFrame should be
281 // allowed.
282 output_surface.BeginFrameForTesting(base::TimeTicks::Now());
283 EXPECT_EQ(client.begin_frame_count(), 5);
284 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
285
286 // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
287 // still be throttled by pending begin frames however.
288 output_surface.BeginFrameForTesting(base::TimeTicks::Now());
289 EXPECT_EQ(client.begin_frame_count(), 5);
290 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
291
292 // Optimistically injected BeginFrames without a SetNeedsBeginFrame should
293 // also be throttled by pending swap buffers.
294 output_surface.DidSwapBuffersForTesting();
295 EXPECT_EQ(client.begin_frame_count(), 5);
296 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
297 output_surface.BeginFrameForTesting(base::TimeTicks::Now());
298 EXPECT_EQ(client.begin_frame_count(), 5);
299 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
300 }
301
167 } // namespace 302 } // namespace
168 } // namespace cc 303 } // namespace cc
OLDNEW
« no previous file with comments | « cc/output/output_surface_client.h ('k') | cc/scheduler/frame_rate_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698