OLD | NEW |
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 | 6 |
7 #include "base/test/test_simple_task_runner.h" | 7 #include "base/test/test_simple_task_runner.h" |
8 #include "cc/output/managed_memory_policy.h" | 8 #include "cc/output/managed_memory_policy.h" |
9 #include "cc/output/output_surface_client.h" | 9 #include "cc/output/output_surface_client.h" |
10 #include "cc/output/software_output_device.h" | 10 #include "cc/output/software_output_device.h" |
11 #include "cc/test/fake_output_surface.h" | 11 #include "cc/test/fake_output_surface.h" |
12 #include "cc/test/fake_output_surface_client.h" | 12 #include "cc/test/fake_output_surface_client.h" |
13 #include "cc/test/scheduler_test_common.h" | 13 #include "cc/test/scheduler_test_common.h" |
14 #include "cc/test/test_context_provider.h" | 14 #include "cc/test/test_context_provider.h" |
15 #include "cc/test/test_web_graphics_context_3d.h" | 15 #include "cc/test/test_web_graphics_context_3d.h" |
16 #include "gpu/GLES2/gl2extchromium.h" | 16 #include "gpu/GLES2/gl2extchromium.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 #include "ui/gfx/frame_time.h" | 18 #include "ui/gfx/frame_time.h" |
19 | 19 |
20 namespace cc { | 20 namespace cc { |
21 namespace { | 21 namespace { |
22 | 22 |
23 class TestOutputSurface : public OutputSurface { | 23 class TestOutputSurface : public OutputSurface { |
24 public: | 24 public: |
25 explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider) | 25 explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider) |
26 : OutputSurface(context_provider), | 26 : OutputSurface(context_provider) {} |
27 retroactive_begin_frame_deadline_enabled_(false), | |
28 override_retroactive_period_(false) {} | |
29 | 27 |
30 explicit TestOutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) | 28 explicit TestOutputSurface(scoped_ptr<SoftwareOutputDevice> software_device) |
31 : OutputSurface(software_device.Pass()), | 29 : OutputSurface(software_device.Pass()) {} |
32 retroactive_begin_frame_deadline_enabled_(false), | |
33 override_retroactive_period_(false) {} | |
34 | 30 |
35 TestOutputSurface(scoped_refptr<ContextProvider> context_provider, | 31 TestOutputSurface(scoped_refptr<ContextProvider> context_provider, |
36 scoped_ptr<SoftwareOutputDevice> software_device) | 32 scoped_ptr<SoftwareOutputDevice> software_device) |
37 : OutputSurface(context_provider, software_device.Pass()), | 33 : OutputSurface(context_provider, software_device.Pass()) {} |
38 retroactive_begin_frame_deadline_enabled_(false), | |
39 override_retroactive_period_(false) {} | |
40 | 34 |
41 bool InitializeNewContext3d( | 35 bool InitializeNewContext3d( |
42 scoped_refptr<ContextProvider> new_context_provider) { | 36 scoped_refptr<ContextProvider> new_context_provider) { |
43 return InitializeAndSetContext3d(new_context_provider, | 37 return InitializeAndSetContext3d(new_context_provider, |
44 scoped_refptr<ContextProvider>()); | 38 scoped_refptr<ContextProvider>()); |
45 } | 39 } |
46 | 40 |
47 using OutputSurface::ReleaseGL; | 41 using OutputSurface::ReleaseGL; |
48 | 42 |
49 void CommitVSyncParametersForTesting(base::TimeTicks timebase, | 43 void CommitVSyncParametersForTesting(base::TimeTicks timebase, |
50 base::TimeDelta interval) { | 44 base::TimeDelta interval) { |
51 CommitVSyncParameters(timebase, interval); | 45 CommitVSyncParameters(timebase, interval); |
52 } | 46 } |
53 | 47 |
54 void BeginFrameForTesting() { | 48 void BeginFrameForTesting() { |
55 OutputSurface::BeginFrame(BeginFrameArgs::CreateExpiredForTesting()); | 49 client_->BeginFrame(BeginFrameArgs::CreateExpiredForTesting()); |
56 } | 50 } |
57 | 51 |
58 void DidSwapBuffersForTesting() { | 52 void DidSwapBuffersForTesting() { client_->DidSwapBuffers(); } |
59 DidSwapBuffers(); | |
60 } | |
61 | 53 |
62 void OnSwapBuffersCompleteForTesting() { | 54 void OnSwapBuffersCompleteForTesting() { client_->DidSwapBuffersComplete(); } |
63 OnSwapBuffersComplete(); | |
64 } | |
65 | |
66 void EnableRetroactiveBeginFrameDeadline(bool enable, | |
67 bool override_retroactive_period, | |
68 base::TimeDelta period_override) { | |
69 retroactive_begin_frame_deadline_enabled_ = enable; | |
70 override_retroactive_period_ = override_retroactive_period; | |
71 retroactive_period_override_ = period_override; | |
72 } | |
73 | 55 |
74 protected: | 56 protected: |
75 virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE { | |
76 // For testing purposes, we check immediately rather than posting a task. | |
77 CheckForRetroactiveBeginFrame(); | |
78 } | |
79 | |
80 virtual base::TimeTicks RetroactiveBeginFrameDeadline() OVERRIDE { | |
81 if (retroactive_begin_frame_deadline_enabled_) { | |
82 if (override_retroactive_period_) { | |
83 return skipped_begin_frame_args_.frame_time + | |
84 retroactive_period_override_; | |
85 } else { | |
86 return OutputSurface::RetroactiveBeginFrameDeadline(); | |
87 } | |
88 } | |
89 return base::TimeTicks(); | |
90 } | |
91 | |
92 bool retroactive_begin_frame_deadline_enabled_; | |
93 bool override_retroactive_period_; | |
94 base::TimeDelta retroactive_period_override_; | |
95 }; | 57 }; |
96 | 58 |
97 class TestSoftwareOutputDevice : public SoftwareOutputDevice { | 59 class TestSoftwareOutputDevice : public SoftwareOutputDevice { |
98 public: | 60 public: |
99 TestSoftwareOutputDevice(); | 61 TestSoftwareOutputDevice(); |
100 virtual ~TestSoftwareOutputDevice(); | 62 virtual ~TestSoftwareOutputDevice(); |
101 | 63 |
102 // Overriden from cc:SoftwareOutputDevice | 64 // Overriden from cc:SoftwareOutputDevice |
103 virtual void DiscardBackbuffer() OVERRIDE; | 65 virtual void DiscardBackbuffer() OVERRIDE; |
104 virtual void EnsureBackbuffer() OVERRIDE; | 66 virtual void EnsureBackbuffer() OVERRIDE; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 context_provider_->UnboundTestContext3d()->set_context_lost(true); | 171 context_provider_->UnboundTestContext3d()->set_context_lost(true); |
210 InitializeNewContextExpectFail(); | 172 InitializeNewContextExpectFail(); |
211 } | 173 } |
212 | 174 |
213 TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) { | 175 TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) { |
214 BindOutputSurface(); | 176 BindOutputSurface(); |
215 client_.set_deferred_initialize_result(false); | 177 client_.set_deferred_initialize_result(false); |
216 InitializeNewContextExpectFail(); | 178 InitializeNewContextExpectFail(); |
217 } | 179 } |
218 | 180 |
219 TEST(OutputSurfaceTest, BeginFrameEmulation) { | |
220 TestOutputSurface output_surface(TestContextProvider::Create()); | |
221 EXPECT_FALSE(output_surface.HasClient()); | |
222 | |
223 FakeOutputSurfaceClient client; | |
224 EXPECT_TRUE(output_surface.BindToClient(&client)); | |
225 EXPECT_TRUE(output_surface.HasClient()); | |
226 EXPECT_FALSE(client.deferred_initialize_called()); | |
227 | |
228 // Initialize BeginFrame emulation | |
229 scoped_refptr<base::TestSimpleTaskRunner> task_runner = | |
230 new base::TestSimpleTaskRunner; | |
231 const base::TimeDelta display_refresh_interval = | |
232 BeginFrameArgs::DefaultInterval(); | |
233 | |
234 output_surface.InitializeBeginFrameEmulation(task_runner.get(), | |
235 display_refresh_interval); | |
236 | |
237 output_surface.EnableRetroactiveBeginFrameDeadline( | |
238 false, false, base::TimeDelta()); | |
239 | |
240 // We should start off with 0 BeginFrames | |
241 EXPECT_EQ(client.begin_frame_count(), 0); | |
242 | |
243 // We should not have a pending task until a BeginFrame has been | |
244 // requested. | |
245 EXPECT_FALSE(task_runner->HasPendingTask()); | |
246 output_surface.SetNeedsBeginFrame(true); | |
247 EXPECT_TRUE(task_runner->HasPendingTask()); | |
248 | |
249 // BeginFrame should be called on the first tick. | |
250 task_runner->RunPendingTasks(); | |
251 EXPECT_EQ(client.begin_frame_count(), 1); | |
252 | |
253 // BeginFrame should not be called when there is a pending BeginFrame. | |
254 task_runner->RunPendingTasks(); | |
255 EXPECT_EQ(client.begin_frame_count(), 1); | |
256 // SetNeedsBeginFrame should clear the pending BeginFrame after | |
257 // a SwapBuffers. | |
258 output_surface.DidSwapBuffersForTesting(); | |
259 output_surface.SetNeedsBeginFrame(true); | |
260 EXPECT_EQ(client.begin_frame_count(), 1); | |
261 task_runner->RunPendingTasks(); | |
262 EXPECT_EQ(client.begin_frame_count(), 2); | |
263 | |
264 // Calling SetNeedsBeginFrame again indicates a swap did not occur but | |
265 // the client still wants another BeginFrame. | |
266 output_surface.SetNeedsBeginFrame(true); | |
267 task_runner->RunPendingTasks(); | |
268 EXPECT_EQ(client.begin_frame_count(), 3); | |
269 | |
270 // Disabling SetNeedsBeginFrame should prevent further BeginFrames. | |
271 output_surface.SetNeedsBeginFrame(false); | |
272 task_runner->RunPendingTasks(); | |
273 EXPECT_FALSE(task_runner->HasPendingTask()); | |
274 EXPECT_EQ(client.begin_frame_count(), 3); | |
275 } | |
276 | |
277 TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) { | |
278 TestOutputSurface output_surface(TestContextProvider::Create()); | |
279 EXPECT_FALSE(output_surface.HasClient()); | |
280 | |
281 FakeOutputSurfaceClient client; | |
282 EXPECT_TRUE(output_surface.BindToClient(&client)); | |
283 EXPECT_TRUE(output_surface.HasClient()); | |
284 EXPECT_FALSE(client.deferred_initialize_called()); | |
285 | |
286 output_surface.EnableRetroactiveBeginFrameDeadline( | |
287 true, false, base::TimeDelta()); | |
288 | |
289 // Optimistically injected BeginFrames should be throttled if | |
290 // SetNeedsBeginFrame is false... | |
291 output_surface.SetNeedsBeginFrame(false); | |
292 output_surface.BeginFrameForTesting(); | |
293 EXPECT_EQ(client.begin_frame_count(), 0); | |
294 // ...and retroactively triggered by a SetNeedsBeginFrame. | |
295 output_surface.SetNeedsBeginFrame(true); | |
296 EXPECT_EQ(client.begin_frame_count(), 1); | |
297 | |
298 // Optimistically injected BeginFrames should be throttled by pending | |
299 // BeginFrames... | |
300 output_surface.BeginFrameForTesting(); | |
301 EXPECT_EQ(client.begin_frame_count(), 1); | |
302 // ...and retroactively triggered by a SetNeedsBeginFrame. | |
303 output_surface.SetNeedsBeginFrame(true); | |
304 EXPECT_EQ(client.begin_frame_count(), 2); | |
305 // ...or retroactively triggered by a Swap. | |
306 output_surface.BeginFrameForTesting(); | |
307 EXPECT_EQ(client.begin_frame_count(), 2); | |
308 output_surface.DidSwapBuffersForTesting(); | |
309 output_surface.SetNeedsBeginFrame(true); | |
310 EXPECT_EQ(client.begin_frame_count(), 3); | |
311 } | |
312 | |
313 TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) { | |
314 scoped_refptr<TestContextProvider> context_provider = | |
315 TestContextProvider::Create(); | |
316 | |
317 TestOutputSurface output_surface(context_provider); | |
318 EXPECT_FALSE(output_surface.HasClient()); | |
319 | |
320 FakeOutputSurfaceClient client; | |
321 EXPECT_TRUE(output_surface.BindToClient(&client)); | |
322 EXPECT_TRUE(output_surface.HasClient()); | |
323 EXPECT_FALSE(client.deferred_initialize_called()); | |
324 | |
325 base::TimeDelta big_interval = base::TimeDelta::FromSeconds(10); | |
326 | |
327 // Initialize BeginFrame emulation | |
328 scoped_refptr<base::TestSimpleTaskRunner> task_runner = | |
329 new base::TestSimpleTaskRunner; | |
330 const base::TimeDelta display_refresh_interval = big_interval; | |
331 | |
332 output_surface.InitializeBeginFrameEmulation(task_runner.get(), | |
333 display_refresh_interval); | |
334 | |
335 // We need to subtract an epsilon from Now() because some platforms have | |
336 // a slow clock. | |
337 output_surface.CommitVSyncParametersForTesting( | |
338 gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval); | |
339 | |
340 output_surface.EnableRetroactiveBeginFrameDeadline(true, true, big_interval); | |
341 | |
342 // We should start off with 0 BeginFrames | |
343 EXPECT_EQ(client.begin_frame_count(), 0); | |
344 | |
345 // The first SetNeedsBeginFrame(true) should start a retroactive | |
346 // BeginFrame. | |
347 EXPECT_FALSE(task_runner->HasPendingTask()); | |
348 output_surface.SetNeedsBeginFrame(true); | |
349 EXPECT_TRUE(task_runner->HasPendingTask()); | |
350 EXPECT_GT(task_runner->NextPendingTaskDelay(), big_interval / 2); | |
351 EXPECT_EQ(client.begin_frame_count(), 1); | |
352 | |
353 output_surface.SetNeedsBeginFrame(false); | |
354 EXPECT_TRUE(task_runner->HasPendingTask()); | |
355 EXPECT_EQ(client.begin_frame_count(), 1); | |
356 | |
357 // The second SetNeedBeginFrame(true) should not retroactively start a | |
358 // BeginFrame if the timestamp would be the same as the previous | |
359 // BeginFrame. | |
360 output_surface.SetNeedsBeginFrame(true); | |
361 EXPECT_TRUE(task_runner->HasPendingTask()); | |
362 EXPECT_EQ(client.begin_frame_count(), 1); | |
363 } | |
364 | |
365 TEST(OutputSurfaceTest, MemoryAllocation) { | 181 TEST(OutputSurfaceTest, MemoryAllocation) { |
366 scoped_refptr<TestContextProvider> context_provider = | 182 scoped_refptr<TestContextProvider> context_provider = |
367 TestContextProvider::Create(); | 183 TestContextProvider::Create(); |
368 | 184 |
369 TestOutputSurface output_surface(context_provider); | 185 TestOutputSurface output_surface(context_provider); |
370 | 186 |
371 FakeOutputSurfaceClient client; | 187 FakeOutputSurfaceClient client; |
372 EXPECT_TRUE(output_surface.BindToClient(&client)); | 188 EXPECT_TRUE(output_surface.BindToClient(&client)); |
373 | 189 |
374 ManagedMemoryPolicy policy(0); | 190 ManagedMemoryPolicy policy(0); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count()); | 225 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count()); |
410 EXPECT_EQ(0, software_output_device->discard_backbuffer_count()); | 226 EXPECT_EQ(0, software_output_device->discard_backbuffer_count()); |
411 output_surface.DiscardBackbuffer(); | 227 output_surface.DiscardBackbuffer(); |
412 | 228 |
413 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count()); | 229 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count()); |
414 EXPECT_EQ(1, software_output_device->discard_backbuffer_count()); | 230 EXPECT_EQ(1, software_output_device->discard_backbuffer_count()); |
415 } | 231 } |
416 | 232 |
417 } // namespace | 233 } // namespace |
418 } // namespace cc | 234 } // namespace cc |
OLD | NEW |