Move prefs::kLastPolicyStatisticsUpdate to the policy component.
[chromium-blink-merge.git] / cc / output / output_surface_unittest.cc
blobc8324a697952c4337c782f742bfea6e0ff8e16c4
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
3 // found in the LICENSE file.
5 #include "cc/output/output_surface.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "cc/debug/test_context_provider.h"
9 #include "cc/debug/test_web_graphics_context_3d.h"
10 #include "cc/output/managed_memory_policy.h"
11 #include "cc/output/output_surface_client.h"
12 #include "cc/output/software_output_device.h"
13 #include "cc/test/fake_output_surface.h"
14 #include "cc/test/fake_output_surface_client.h"
15 #include "cc/test/scheduler_test_common.h"
16 #include "gpu/GLES2/gl2extchromium.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace cc {
20 namespace {
22 class TestOutputSurface : public OutputSurface {
23 public:
24 explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider)
25 : OutputSurface(context_provider) {}
27 explicit TestOutputSurface(
28 scoped_ptr<cc::SoftwareOutputDevice> software_device)
29 : OutputSurface(software_device.Pass()) {}
31 TestOutputSurface(scoped_refptr<ContextProvider> context_provider,
32 scoped_ptr<cc::SoftwareOutputDevice> software_device)
33 : OutputSurface(context_provider, software_device.Pass()) {}
35 bool InitializeNewContext3d(
36 scoped_refptr<ContextProvider> new_context_provider) {
37 return InitializeAndSetContext3d(new_context_provider,
38 scoped_refptr<ContextProvider>());
41 using OutputSurface::ReleaseGL;
43 void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
44 base::TimeDelta interval) {
45 OnVSyncParametersChanged(timebase, interval);
48 void BeginFrameForTesting() {
49 OutputSurface::BeginFrame(BeginFrameArgs::CreateExpiredForTesting());
52 void DidSwapBuffersForTesting() {
53 DidSwapBuffers();
56 int pending_swap_buffers() {
57 return pending_swap_buffers_;
60 void OnSwapBuffersCompleteForTesting() {
61 OnSwapBuffersComplete();
64 void SetAlternateRetroactiveBeginFramePeriod(base::TimeDelta period) {
65 alternate_retroactive_begin_frame_period_ = period;
68 protected:
69 virtual void PostCheckForRetroactiveBeginFrame() OVERRIDE {
70 // For testing purposes, we check immediately rather than posting a task.
71 CheckForRetroactiveBeginFrame();
74 virtual base::TimeDelta AlternateRetroactiveBeginFramePeriod() OVERRIDE {
75 return alternate_retroactive_begin_frame_period_;
78 base::TimeDelta alternate_retroactive_begin_frame_period_;
81 class TestSoftwareOutputDevice : public SoftwareOutputDevice {
82 public:
83 TestSoftwareOutputDevice();
84 virtual ~TestSoftwareOutputDevice();
86 // Overriden from cc:SoftwareOutputDevice
87 virtual void DiscardBackbuffer() OVERRIDE;
88 virtual void EnsureBackbuffer() OVERRIDE;
90 int discard_backbuffer_count() { return discard_backbuffer_count_; }
91 int ensure_backbuffer_count() { return ensure_backbuffer_count_; }
93 private:
94 int discard_backbuffer_count_;
95 int ensure_backbuffer_count_;
98 TestSoftwareOutputDevice::TestSoftwareOutputDevice()
99 : discard_backbuffer_count_(0), ensure_backbuffer_count_(0) {}
101 TestSoftwareOutputDevice::~TestSoftwareOutputDevice() {}
103 void TestSoftwareOutputDevice::DiscardBackbuffer() {
104 SoftwareOutputDevice::DiscardBackbuffer();
105 discard_backbuffer_count_++;
108 void TestSoftwareOutputDevice::EnsureBackbuffer() {
109 SoftwareOutputDevice::EnsureBackbuffer();
110 ensure_backbuffer_count_++;
113 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
114 TestOutputSurface output_surface(TestContextProvider::Create());
115 EXPECT_FALSE(output_surface.HasClient());
117 FakeOutputSurfaceClient client;
118 EXPECT_TRUE(output_surface.BindToClient(&client));
119 EXPECT_TRUE(output_surface.HasClient());
120 EXPECT_FALSE(client.deferred_initialize_called());
122 // Verify DidLoseOutputSurface callback is hooked up correctly.
123 EXPECT_FALSE(client.did_lose_output_surface_called());
124 output_surface.context_provider()->Context3d()->loseContextCHROMIUM(
125 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
126 EXPECT_TRUE(client.did_lose_output_surface_called());
129 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
130 scoped_refptr<TestContextProvider> context_provider =
131 TestContextProvider::Create();
133 // Lose the context so BindToClient fails.
134 context_provider->UnboundTestContext3d()->set_times_make_current_succeeds(0);
136 TestOutputSurface output_surface(context_provider);
137 EXPECT_FALSE(output_surface.HasClient());
139 FakeOutputSurfaceClient client;
140 EXPECT_FALSE(output_surface.BindToClient(&client));
141 EXPECT_FALSE(output_surface.HasClient());
144 class OutputSurfaceTestInitializeNewContext3d : public ::testing::Test {
145 public:
146 OutputSurfaceTestInitializeNewContext3d()
147 : context_provider_(TestContextProvider::Create()),
148 output_surface_(
149 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) {}
151 protected:
152 void BindOutputSurface() {
153 EXPECT_TRUE(output_surface_.BindToClient(&client_));
154 EXPECT_TRUE(output_surface_.HasClient());
157 void InitializeNewContextExpectFail() {
158 EXPECT_FALSE(output_surface_.InitializeNewContext3d(context_provider_));
159 EXPECT_TRUE(output_surface_.HasClient());
161 EXPECT_FALSE(output_surface_.context_provider());
162 EXPECT_TRUE(output_surface_.software_device());
165 scoped_refptr<TestContextProvider> context_provider_;
166 TestOutputSurface output_surface_;
167 FakeOutputSurfaceClient client_;
170 TEST_F(OutputSurfaceTestInitializeNewContext3d, Success) {
171 BindOutputSurface();
172 EXPECT_FALSE(client_.deferred_initialize_called());
174 EXPECT_TRUE(output_surface_.InitializeNewContext3d(context_provider_));
175 EXPECT_TRUE(client_.deferred_initialize_called());
176 EXPECT_EQ(context_provider_, output_surface_.context_provider());
178 EXPECT_FALSE(client_.did_lose_output_surface_called());
179 context_provider_->Context3d()->loseContextCHROMIUM(
180 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
181 EXPECT_TRUE(client_.did_lose_output_surface_called());
183 output_surface_.ReleaseGL();
184 EXPECT_FALSE(output_surface_.context_provider());
187 TEST_F(OutputSurfaceTestInitializeNewContext3d, Context3dMakeCurrentFails) {
188 BindOutputSurface();
190 context_provider_->UnboundTestContext3d()
191 ->set_times_make_current_succeeds(0);
192 InitializeNewContextExpectFail();
195 TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) {
196 BindOutputSurface();
197 client_.set_deferred_initialize_result(false);
198 InitializeNewContextExpectFail();
201 TEST(OutputSurfaceTest, BeginFrameEmulation) {
202 TestOutputSurface output_surface(TestContextProvider::Create());
203 EXPECT_FALSE(output_surface.HasClient());
205 FakeOutputSurfaceClient client;
206 EXPECT_TRUE(output_surface.BindToClient(&client));
207 EXPECT_TRUE(output_surface.HasClient());
208 EXPECT_FALSE(client.deferred_initialize_called());
210 // Initialize BeginFrame emulation
211 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
212 new base::TestSimpleTaskRunner;
213 bool throttle_frame_production = true;
214 const base::TimeDelta display_refresh_interval =
215 BeginFrameArgs::DefaultInterval();
217 output_surface.InitializeBeginFrameEmulation(
218 task_runner.get(),
219 throttle_frame_production,
220 display_refresh_interval);
222 output_surface.SetMaxFramesPending(2);
223 output_surface.SetAlternateRetroactiveBeginFramePeriod(
224 base::TimeDelta::FromSeconds(-1));
226 // We should start off with 0 BeginFrames
227 EXPECT_EQ(client.begin_frame_count(), 0);
228 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
230 // We should not have a pending task until a BeginFrame has been requested.
231 EXPECT_FALSE(task_runner->HasPendingTask());
232 output_surface.SetNeedsBeginFrame(true);
233 EXPECT_TRUE(task_runner->HasPendingTask());
235 // BeginFrame should be called on the first tick.
236 task_runner->RunPendingTasks();
237 EXPECT_EQ(client.begin_frame_count(), 1);
238 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
240 // BeginFrame should not be called when there is a pending BeginFrame.
241 task_runner->RunPendingTasks();
242 EXPECT_EQ(client.begin_frame_count(), 1);
243 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
245 // SetNeedsBeginFrame should clear the pending BeginFrame after
246 // a SwapBuffers.
247 output_surface.DidSwapBuffersForTesting();
248 output_surface.SetNeedsBeginFrame(true);
249 EXPECT_EQ(client.begin_frame_count(), 1);
250 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
251 task_runner->RunPendingTasks();
252 EXPECT_EQ(client.begin_frame_count(), 2);
253 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
255 // BeginFrame should be throttled by pending swap buffers.
256 output_surface.DidSwapBuffersForTesting();
257 output_surface.SetNeedsBeginFrame(true);
258 EXPECT_EQ(client.begin_frame_count(), 2);
259 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
260 task_runner->RunPendingTasks();
261 EXPECT_EQ(client.begin_frame_count(), 2);
262 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
264 // SwapAck should decrement pending swap buffers and unblock BeginFrame again.
265 output_surface.OnSwapBuffersCompleteForTesting();
266 EXPECT_EQ(client.begin_frame_count(), 2);
267 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
268 task_runner->RunPendingTasks();
269 EXPECT_EQ(client.begin_frame_count(), 3);
270 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
272 // Calling SetNeedsBeginFrame again indicates a swap did not occur but
273 // the client still wants another BeginFrame.
274 output_surface.SetNeedsBeginFrame(true);
275 task_runner->RunPendingTasks();
276 EXPECT_EQ(client.begin_frame_count(), 4);
277 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
279 // Disabling SetNeedsBeginFrame should prevent further BeginFrames.
280 output_surface.SetNeedsBeginFrame(false);
281 task_runner->RunPendingTasks();
282 EXPECT_FALSE(task_runner->HasPendingTask());
283 EXPECT_EQ(client.begin_frame_count(), 4);
284 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
287 TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginFrames) {
288 TestOutputSurface output_surface(TestContextProvider::Create());
289 EXPECT_FALSE(output_surface.HasClient());
291 FakeOutputSurfaceClient client;
292 EXPECT_TRUE(output_surface.BindToClient(&client));
293 EXPECT_TRUE(output_surface.HasClient());
294 EXPECT_FALSE(client.deferred_initialize_called());
296 output_surface.SetMaxFramesPending(2);
298 // Enable retroactive BeginFrames.
299 output_surface.SetAlternateRetroactiveBeginFramePeriod(
300 base::TimeDelta::FromSeconds(100000));
302 // Optimistically injected BeginFrames should be throttled if
303 // SetNeedsBeginFrame is false...
304 output_surface.SetNeedsBeginFrame(false);
305 output_surface.BeginFrameForTesting();
306 EXPECT_EQ(client.begin_frame_count(), 0);
307 // ...and retroactively triggered by a SetNeedsBeginFrame.
308 output_surface.SetNeedsBeginFrame(true);
309 EXPECT_EQ(client.begin_frame_count(), 1);
311 // Optimistically injected BeginFrames should be throttled by pending
312 // BeginFrames...
313 output_surface.BeginFrameForTesting();
314 EXPECT_EQ(client.begin_frame_count(), 1);
315 // ...and retroactively triggered by a SetNeedsBeginFrame.
316 output_surface.SetNeedsBeginFrame(true);
317 EXPECT_EQ(client.begin_frame_count(), 2);
318 // ...or retroactively triggered by a Swap.
319 output_surface.BeginFrameForTesting();
320 EXPECT_EQ(client.begin_frame_count(), 2);
321 output_surface.DidSwapBuffersForTesting();
322 output_surface.SetNeedsBeginFrame(true);
323 EXPECT_EQ(client.begin_frame_count(), 3);
324 EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
326 // Optimistically injected BeginFrames should be by throttled by pending
327 // swap buffers...
328 output_surface.DidSwapBuffersForTesting();
329 output_surface.SetNeedsBeginFrame(true);
330 EXPECT_EQ(client.begin_frame_count(), 3);
331 EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
332 output_surface.BeginFrameForTesting();
333 EXPECT_EQ(client.begin_frame_count(), 3);
334 // ...and retroactively triggered by OnSwapBuffersComplete
335 output_surface.OnSwapBuffersCompleteForTesting();
336 EXPECT_EQ(client.begin_frame_count(), 4);
339 TEST(OutputSurfaceTest, RetroactiveBeginFrameDoesNotDoubleTickWhenEmulating) {
340 scoped_refptr<TestContextProvider> context_provider =
341 TestContextProvider::Create();
343 TestOutputSurface output_surface(context_provider);
344 EXPECT_FALSE(output_surface.HasClient());
346 FakeOutputSurfaceClient client;
347 EXPECT_TRUE(output_surface.BindToClient(&client));
348 EXPECT_TRUE(output_surface.HasClient());
349 EXPECT_FALSE(client.deferred_initialize_called());
351 base::TimeDelta big_interval = base::TimeDelta::FromSeconds(1000);
353 // Initialize BeginFrame emulation
354 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
355 new base::TestSimpleTaskRunner;
356 bool throttle_frame_production = true;
357 const base::TimeDelta display_refresh_interval = big_interval;
359 output_surface.InitializeBeginFrameEmulation(
360 task_runner.get(),
361 throttle_frame_production,
362 display_refresh_interval);
364 // We need to subtract an epsilon from Now() because some platforms have
365 // a slow clock.
366 output_surface.OnVSyncParametersChangedForTesting(
367 base::TimeTicks::Now() - base::TimeDelta::FromMilliseconds(1),
368 display_refresh_interval);
370 output_surface.SetMaxFramesPending(2);
371 output_surface.SetAlternateRetroactiveBeginFramePeriod(
372 base::TimeDelta::FromSeconds(-1));
374 // We should start off with 0 BeginFrames
375 EXPECT_EQ(client.begin_frame_count(), 0);
376 EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
378 // The first SetNeedsBeginFrame(true) should start a retroactive BeginFrame.
379 output_surface.SetNeedsBeginFrame(true);
380 EXPECT_TRUE(task_runner->HasPendingTask());
381 EXPECT_GT(task_runner->NextPendingTaskDelay(), big_interval / 2);
382 EXPECT_EQ(client.begin_frame_count(), 1);
384 output_surface.SetNeedsBeginFrame(false);
385 EXPECT_TRUE(task_runner->HasPendingTask());
386 EXPECT_EQ(client.begin_frame_count(), 1);
388 // The second SetNeedBeginFrame(true) should not retroactively start a
389 // BeginFrame if the timestamp would be the same as the previous BeginFrame.
390 output_surface.SetNeedsBeginFrame(true);
391 EXPECT_TRUE(task_runner->HasPendingTask());
392 EXPECT_EQ(client.begin_frame_count(), 1);
395 TEST(OutputSurfaceTest, MemoryAllocation) {
396 scoped_refptr<TestContextProvider> context_provider =
397 TestContextProvider::Create();
399 TestOutputSurface output_surface(context_provider);
401 FakeOutputSurfaceClient client;
402 EXPECT_TRUE(output_surface.BindToClient(&client));
404 ManagedMemoryPolicy policy(0);
405 policy.bytes_limit_when_visible = 1234;
406 policy.priority_cutoff_when_visible =
407 ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY;
408 policy.bytes_limit_when_not_visible = 4567;
409 policy.priority_cutoff_when_not_visible =
410 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING;
412 bool discard_backbuffer_when_not_visible = false;
414 context_provider->SetMemoryAllocation(policy,
415 discard_backbuffer_when_not_visible);
416 EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
417 EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY,
418 client.memory_policy().priority_cutoff_when_visible);
419 EXPECT_EQ(4567u, client.memory_policy().bytes_limit_when_not_visible);
420 EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING,
421 client.memory_policy().priority_cutoff_when_not_visible);
422 EXPECT_FALSE(client.discard_backbuffer_when_not_visible());
424 discard_backbuffer_when_not_visible = true;
425 context_provider->SetMemoryAllocation(policy,
426 discard_backbuffer_when_not_visible);
427 EXPECT_TRUE(client.discard_backbuffer_when_not_visible());
429 policy.priority_cutoff_when_visible =
430 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING;
431 policy.priority_cutoff_when_not_visible =
432 ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE;
433 context_provider->SetMemoryAllocation(policy,
434 discard_backbuffer_when_not_visible);
435 EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
436 client.memory_policy().priority_cutoff_when_visible);
437 EXPECT_EQ(ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE,
438 client.memory_policy().priority_cutoff_when_not_visible);
440 // 0 bytes limit should be ignored.
441 policy.bytes_limit_when_visible = 0;
442 context_provider->SetMemoryAllocation(policy,
443 discard_backbuffer_when_not_visible);
444 EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
447 TEST(OutputSurfaceTest, SoftwareOutputDeviceBackbufferManagement) {
448 TestSoftwareOutputDevice* software_output_device =
449 new TestSoftwareOutputDevice();
451 // TestOutputSurface now owns software_output_device and has responsibility to
452 // free it.
453 scoped_ptr<TestSoftwareOutputDevice> p(software_output_device);
454 TestOutputSurface output_surface(p.PassAs<SoftwareOutputDevice>());
456 EXPECT_EQ(0, software_output_device->ensure_backbuffer_count());
457 EXPECT_EQ(0, software_output_device->discard_backbuffer_count());
459 output_surface.EnsureBackbuffer();
460 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count());
461 EXPECT_EQ(0, software_output_device->discard_backbuffer_count());
462 output_surface.DiscardBackbuffer();
464 EXPECT_EQ(1, software_output_device->ensure_backbuffer_count());
465 EXPECT_EQ(1, software_output_device->discard_backbuffer_count());
468 } // namespace
469 } // namespace cc