- add sources.
[platform/framework/web/crosswalk.git] / src / cc / output / output_surface_unittest.cc
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.
4
5 #include "cc/output/output_surface.h"
6
7 #include "base/test/test_simple_task_runner.h"
8 #include "cc/output/managed_memory_policy.h"
9 #include "cc/output/output_surface_client.h"
10 #include "cc/output/software_output_device.h"
11 #include "cc/test/fake_output_surface.h"
12 #include "cc/test/fake_output_surface_client.h"
13 #include "cc/test/scheduler_test_common.h"
14 #include "cc/test/test_context_provider.h"
15 #include "cc/test/test_web_graphics_context_3d.h"
16 #include "gpu/GLES2/gl2extchromium.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/gfx/frame_time.h"
19
20 namespace cc {
21 namespace {
22
23 class TestOutputSurface : public OutputSurface {
24  public:
25   explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider)
26       : OutputSurface(context_provider),
27         retroactive_begin_impl_frame_deadline_enabled_(false),
28         override_retroactive_period_(false) {}
29
30   explicit TestOutputSurface(
31       scoped_ptr<cc::SoftwareOutputDevice> software_device)
32       : OutputSurface(software_device.Pass()),
33         retroactive_begin_impl_frame_deadline_enabled_(false),
34         override_retroactive_period_(false) {}
35
36   TestOutputSurface(scoped_refptr<ContextProvider> context_provider,
37                     scoped_ptr<cc::SoftwareOutputDevice> software_device)
38       : OutputSurface(context_provider, software_device.Pass()),
39         retroactive_begin_impl_frame_deadline_enabled_(false),
40         override_retroactive_period_(false) {}
41
42   bool InitializeNewContext3d(
43       scoped_refptr<ContextProvider> new_context_provider) {
44     return InitializeAndSetContext3d(new_context_provider,
45                                      scoped_refptr<ContextProvider>());
46   }
47
48   using OutputSurface::ReleaseGL;
49
50   void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
51                                           base::TimeDelta interval) {
52     OnVSyncParametersChanged(timebase, interval);
53   }
54
55   void BeginImplFrameForTesting() {
56     OutputSurface::BeginImplFrame(BeginFrameArgs::CreateExpiredForTesting());
57   }
58
59   void DidSwapBuffersForTesting() {
60     DidSwapBuffers();
61   }
62
63   int pending_swap_buffers() {
64     return pending_swap_buffers_;
65   }
66
67   void OnSwapBuffersCompleteForTesting() {
68     OnSwapBuffersComplete();
69   }
70
71   void EnableRetroactiveBeginImplFrameDeadline(
72       bool enable,
73       bool override_retroactive_period,
74       base::TimeDelta period_override) {
75     retroactive_begin_impl_frame_deadline_enabled_ = enable;
76     override_retroactive_period_ = override_retroactive_period;
77     retroactive_period_override_ = period_override;
78   }
79
80  protected:
81   virtual void PostCheckForRetroactiveBeginImplFrame() OVERRIDE {
82     // For testing purposes, we check immediately rather than posting a task.
83     CheckForRetroactiveBeginImplFrame();
84   }
85
86   virtual base::TimeTicks RetroactiveBeginImplFrameDeadline() OVERRIDE {
87     if (retroactive_begin_impl_frame_deadline_enabled_) {
88       if (override_retroactive_period_) {
89         return skipped_begin_impl_frame_args_.frame_time +
90                retroactive_period_override_;
91       } else {
92         return OutputSurface::RetroactiveBeginImplFrameDeadline();
93       }
94     }
95     return base::TimeTicks();
96   }
97
98   bool retroactive_begin_impl_frame_deadline_enabled_;
99   bool override_retroactive_period_;
100   base::TimeDelta retroactive_period_override_;
101 };
102
103 class TestSoftwareOutputDevice : public SoftwareOutputDevice {
104  public:
105   TestSoftwareOutputDevice();
106   virtual ~TestSoftwareOutputDevice();
107
108   // Overriden from cc:SoftwareOutputDevice
109   virtual void DiscardBackbuffer() OVERRIDE;
110   virtual void EnsureBackbuffer() OVERRIDE;
111
112   int discard_backbuffer_count() { return discard_backbuffer_count_; }
113   int ensure_backbuffer_count() { return ensure_backbuffer_count_; }
114
115  private:
116   int discard_backbuffer_count_;
117   int ensure_backbuffer_count_;
118 };
119
120 TestSoftwareOutputDevice::TestSoftwareOutputDevice()
121     : discard_backbuffer_count_(0), ensure_backbuffer_count_(0) {}
122
123 TestSoftwareOutputDevice::~TestSoftwareOutputDevice() {}
124
125 void TestSoftwareOutputDevice::DiscardBackbuffer() {
126   SoftwareOutputDevice::DiscardBackbuffer();
127   discard_backbuffer_count_++;
128 }
129
130 void TestSoftwareOutputDevice::EnsureBackbuffer() {
131   SoftwareOutputDevice::EnsureBackbuffer();
132   ensure_backbuffer_count_++;
133 }
134
135 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientSuccess) {
136   TestOutputSurface output_surface(TestContextProvider::Create());
137   EXPECT_FALSE(output_surface.HasClient());
138
139   FakeOutputSurfaceClient client;
140   EXPECT_TRUE(output_surface.BindToClient(&client));
141   EXPECT_TRUE(output_surface.HasClient());
142   EXPECT_FALSE(client.deferred_initialize_called());
143
144   // Verify DidLoseOutputSurface callback is hooked up correctly.
145   EXPECT_FALSE(client.did_lose_output_surface_called());
146   output_surface.context_provider()->Context3d()->loseContextCHROMIUM(
147       GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
148   EXPECT_TRUE(client.did_lose_output_surface_called());
149 }
150
151 TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
152   scoped_refptr<TestContextProvider> context_provider =
153       TestContextProvider::Create();
154
155   // Lose the context so BindToClient fails.
156   context_provider->UnboundTestContext3d()->set_times_make_current_succeeds(0);
157
158   TestOutputSurface output_surface(context_provider);
159   EXPECT_FALSE(output_surface.HasClient());
160
161   FakeOutputSurfaceClient client;
162   EXPECT_FALSE(output_surface.BindToClient(&client));
163   EXPECT_FALSE(output_surface.HasClient());
164 }
165
166 class OutputSurfaceTestInitializeNewContext3d : public ::testing::Test {
167  public:
168   OutputSurfaceTestInitializeNewContext3d()
169       : context_provider_(TestContextProvider::Create()),
170         output_surface_(
171             scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)) {}
172
173  protected:
174   void BindOutputSurface() {
175     EXPECT_TRUE(output_surface_.BindToClient(&client_));
176     EXPECT_TRUE(output_surface_.HasClient());
177   }
178
179   void InitializeNewContextExpectFail() {
180     EXPECT_FALSE(output_surface_.InitializeNewContext3d(context_provider_));
181     EXPECT_TRUE(output_surface_.HasClient());
182
183     EXPECT_FALSE(output_surface_.context_provider());
184     EXPECT_TRUE(output_surface_.software_device());
185   }
186
187   scoped_refptr<TestContextProvider> context_provider_;
188   TestOutputSurface output_surface_;
189   FakeOutputSurfaceClient client_;
190 };
191
192 TEST_F(OutputSurfaceTestInitializeNewContext3d, Success) {
193   BindOutputSurface();
194   EXPECT_FALSE(client_.deferred_initialize_called());
195
196   EXPECT_TRUE(output_surface_.InitializeNewContext3d(context_provider_));
197   EXPECT_TRUE(client_.deferred_initialize_called());
198   EXPECT_EQ(context_provider_, output_surface_.context_provider());
199
200   EXPECT_FALSE(client_.did_lose_output_surface_called());
201   context_provider_->Context3d()->loseContextCHROMIUM(
202       GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
203   EXPECT_TRUE(client_.did_lose_output_surface_called());
204
205   output_surface_.ReleaseGL();
206   EXPECT_FALSE(output_surface_.context_provider());
207 }
208
209 TEST_F(OutputSurfaceTestInitializeNewContext3d, Context3dMakeCurrentFails) {
210   BindOutputSurface();
211
212   context_provider_->UnboundTestContext3d()
213       ->set_times_make_current_succeeds(0);
214   InitializeNewContextExpectFail();
215 }
216
217 TEST_F(OutputSurfaceTestInitializeNewContext3d, ClientDeferredInitializeFails) {
218   BindOutputSurface();
219   client_.set_deferred_initialize_result(false);
220   InitializeNewContextExpectFail();
221 }
222
223 TEST(OutputSurfaceTest, BeginImplFrameEmulation) {
224   TestOutputSurface output_surface(TestContextProvider::Create());
225   EXPECT_FALSE(output_surface.HasClient());
226
227   FakeOutputSurfaceClient client;
228   EXPECT_TRUE(output_surface.BindToClient(&client));
229   EXPECT_TRUE(output_surface.HasClient());
230   EXPECT_FALSE(client.deferred_initialize_called());
231
232   // Initialize BeginImplFrame emulation
233   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
234       new base::TestSimpleTaskRunner;
235   bool throttle_frame_production = true;
236   const base::TimeDelta display_refresh_interval =
237       BeginFrameArgs::DefaultInterval();
238
239   output_surface.InitializeBeginImplFrameEmulation(
240       task_runner.get(),
241       throttle_frame_production,
242       display_refresh_interval);
243
244   output_surface.SetMaxFramesPending(2);
245   output_surface.EnableRetroactiveBeginImplFrameDeadline(
246       false, false, base::TimeDelta());
247
248   // We should start off with 0 BeginImplFrames
249   EXPECT_EQ(client.begin_impl_frame_count(), 0);
250   EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
251
252   // We should not have a pending task until a BeginImplFrame has been
253   // requested.
254   EXPECT_FALSE(task_runner->HasPendingTask());
255   output_surface.SetNeedsBeginImplFrame(true);
256   EXPECT_TRUE(task_runner->HasPendingTask());
257
258   // BeginImplFrame should be called on the first tick.
259   task_runner->RunPendingTasks();
260   EXPECT_EQ(client.begin_impl_frame_count(), 1);
261   EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
262
263   // BeginImplFrame should not be called when there is a pending BeginImplFrame.
264   task_runner->RunPendingTasks();
265   EXPECT_EQ(client.begin_impl_frame_count(), 1);
266   EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
267
268   // SetNeedsBeginImplFrame should clear the pending BeginImplFrame after
269   // a SwapBuffers.
270   output_surface.DidSwapBuffersForTesting();
271   output_surface.SetNeedsBeginImplFrame(true);
272   EXPECT_EQ(client.begin_impl_frame_count(), 1);
273   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
274   task_runner->RunPendingTasks();
275   EXPECT_EQ(client.begin_impl_frame_count(), 2);
276   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
277
278   // BeginImplFrame should be throttled by pending swap buffers.
279   output_surface.DidSwapBuffersForTesting();
280   output_surface.SetNeedsBeginImplFrame(true);
281   EXPECT_EQ(client.begin_impl_frame_count(), 2);
282   EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
283   task_runner->RunPendingTasks();
284   EXPECT_EQ(client.begin_impl_frame_count(), 2);
285   EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
286
287   // SwapAck should decrement pending swap buffers and unblock BeginImplFrame
288   // again.
289   output_surface.OnSwapBuffersCompleteForTesting();
290   EXPECT_EQ(client.begin_impl_frame_count(), 2);
291   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
292   task_runner->RunPendingTasks();
293   EXPECT_EQ(client.begin_impl_frame_count(), 3);
294   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
295
296   // Calling SetNeedsBeginImplFrame again indicates a swap did not occur but
297   // the client still wants another BeginImplFrame.
298   output_surface.SetNeedsBeginImplFrame(true);
299   task_runner->RunPendingTasks();
300   EXPECT_EQ(client.begin_impl_frame_count(), 4);
301   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
302
303   // Disabling SetNeedsBeginImplFrame should prevent further BeginImplFrames.
304   output_surface.SetNeedsBeginImplFrame(false);
305   task_runner->RunPendingTasks();
306   EXPECT_FALSE(task_runner->HasPendingTask());
307   EXPECT_EQ(client.begin_impl_frame_count(), 4);
308   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
309 }
310
311 TEST(OutputSurfaceTest, OptimisticAndRetroactiveBeginImplFrames) {
312   TestOutputSurface output_surface(TestContextProvider::Create());
313   EXPECT_FALSE(output_surface.HasClient());
314
315   FakeOutputSurfaceClient client;
316   EXPECT_TRUE(output_surface.BindToClient(&client));
317   EXPECT_TRUE(output_surface.HasClient());
318   EXPECT_FALSE(client.deferred_initialize_called());
319
320   output_surface.SetMaxFramesPending(2);
321   output_surface.EnableRetroactiveBeginImplFrameDeadline(
322       true, false, base::TimeDelta());
323
324   // Optimistically injected BeginImplFrames should be throttled if
325   // SetNeedsBeginImplFrame is false...
326   output_surface.SetNeedsBeginImplFrame(false);
327   output_surface.BeginImplFrameForTesting();
328   EXPECT_EQ(client.begin_impl_frame_count(), 0);
329   // ...and retroactively triggered by a SetNeedsBeginImplFrame.
330   output_surface.SetNeedsBeginImplFrame(true);
331   EXPECT_EQ(client.begin_impl_frame_count(), 1);
332
333   // Optimistically injected BeginImplFrames should be throttled by pending
334   // BeginImplFrames...
335   output_surface.BeginImplFrameForTesting();
336   EXPECT_EQ(client.begin_impl_frame_count(), 1);
337   // ...and retroactively triggered by a SetNeedsBeginImplFrame.
338   output_surface.SetNeedsBeginImplFrame(true);
339   EXPECT_EQ(client.begin_impl_frame_count(), 2);
340   // ...or retroactively triggered by a Swap.
341   output_surface.BeginImplFrameForTesting();
342   EXPECT_EQ(client.begin_impl_frame_count(), 2);
343   output_surface.DidSwapBuffersForTesting();
344   output_surface.SetNeedsBeginImplFrame(true);
345   EXPECT_EQ(client.begin_impl_frame_count(), 3);
346   EXPECT_EQ(output_surface.pending_swap_buffers(), 1);
347
348   // Optimistically injected BeginImplFrames should be by throttled by pending
349   // swap buffers...
350   output_surface.DidSwapBuffersForTesting();
351   output_surface.SetNeedsBeginImplFrame(true);
352   EXPECT_EQ(client.begin_impl_frame_count(), 3);
353   EXPECT_EQ(output_surface.pending_swap_buffers(), 2);
354   output_surface.BeginImplFrameForTesting();
355   EXPECT_EQ(client.begin_impl_frame_count(), 3);
356   // ...and retroactively triggered by OnSwapBuffersComplete
357   output_surface.OnSwapBuffersCompleteForTesting();
358   EXPECT_EQ(client.begin_impl_frame_count(), 4);
359 }
360
361 TEST(OutputSurfaceTest,
362      RetroactiveBeginImplFrameDoesNotDoubleTickWhenEmulating) {
363   scoped_refptr<TestContextProvider> context_provider =
364       TestContextProvider::Create();
365
366   TestOutputSurface output_surface(context_provider);
367   EXPECT_FALSE(output_surface.HasClient());
368
369   FakeOutputSurfaceClient client;
370   EXPECT_TRUE(output_surface.BindToClient(&client));
371   EXPECT_TRUE(output_surface.HasClient());
372   EXPECT_FALSE(client.deferred_initialize_called());
373
374   base::TimeDelta big_interval = base::TimeDelta::FromSeconds(10);
375
376   // Initialize BeginImplFrame emulation
377   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
378       new base::TestSimpleTaskRunner;
379   bool throttle_frame_production = true;
380   const base::TimeDelta display_refresh_interval = big_interval;
381
382   output_surface.InitializeBeginImplFrameEmulation(
383       task_runner.get(),
384       throttle_frame_production,
385       display_refresh_interval);
386
387   // We need to subtract an epsilon from Now() because some platforms have
388   // a slow clock.
389   output_surface.OnVSyncParametersChangedForTesting(
390       gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval);
391
392   output_surface.SetMaxFramesPending(2);
393   output_surface.EnableRetroactiveBeginImplFrameDeadline(
394       true, true, big_interval);
395
396   // We should start off with 0 BeginImplFrames
397   EXPECT_EQ(client.begin_impl_frame_count(), 0);
398   EXPECT_EQ(output_surface.pending_swap_buffers(), 0);
399
400   // The first SetNeedsBeginImplFrame(true) should start a retroactive
401   // BeginImplFrame.
402   EXPECT_FALSE(task_runner->HasPendingTask());
403   output_surface.SetNeedsBeginImplFrame(true);
404   EXPECT_TRUE(task_runner->HasPendingTask());
405   EXPECT_GT(task_runner->NextPendingTaskDelay(), big_interval / 2);
406   EXPECT_EQ(client.begin_impl_frame_count(), 1);
407
408   output_surface.SetNeedsBeginImplFrame(false);
409   EXPECT_TRUE(task_runner->HasPendingTask());
410   EXPECT_EQ(client.begin_impl_frame_count(), 1);
411
412   // The second SetNeedBeginImplFrame(true) should not retroactively start a
413   // BeginImplFrame if the timestamp would be the same as the previous
414   // BeginImplFrame.
415   output_surface.SetNeedsBeginImplFrame(true);
416   EXPECT_TRUE(task_runner->HasPendingTask());
417   EXPECT_EQ(client.begin_impl_frame_count(), 1);
418 }
419
420 TEST(OutputSurfaceTest, MemoryAllocation) {
421   scoped_refptr<TestContextProvider> context_provider =
422       TestContextProvider::Create();
423
424   TestOutputSurface output_surface(context_provider);
425
426   FakeOutputSurfaceClient client;
427   EXPECT_TRUE(output_surface.BindToClient(&client));
428
429   ManagedMemoryPolicy policy(0);
430   policy.bytes_limit_when_visible = 1234;
431   policy.priority_cutoff_when_visible =
432       gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY;
433
434   context_provider->SetMemoryAllocation(policy);
435   EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
436   EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY,
437             client.memory_policy().priority_cutoff_when_visible);
438
439   policy.priority_cutoff_when_visible =
440       gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING;
441   context_provider->SetMemoryAllocation(policy);
442   EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING,
443             client.memory_policy().priority_cutoff_when_visible);
444
445   // 0 bytes limit should be ignored.
446   policy.bytes_limit_when_visible = 0;
447   context_provider->SetMemoryAllocation(policy);
448   EXPECT_EQ(1234u, client.memory_policy().bytes_limit_when_visible);
449 }
450
451 TEST(OutputSurfaceTest, SoftwareOutputDeviceBackbufferManagement) {
452   TestSoftwareOutputDevice* software_output_device =
453       new TestSoftwareOutputDevice();
454
455   // TestOutputSurface now owns software_output_device and has responsibility to
456   // free it.
457   scoped_ptr<TestSoftwareOutputDevice> p(software_output_device);
458   TestOutputSurface output_surface(p.PassAs<SoftwareOutputDevice>());
459
460   EXPECT_EQ(0, software_output_device->ensure_backbuffer_count());
461   EXPECT_EQ(0, software_output_device->discard_backbuffer_count());
462
463   output_surface.EnsureBackbuffer();
464   EXPECT_EQ(1, software_output_device->ensure_backbuffer_count());
465   EXPECT_EQ(0, software_output_device->discard_backbuffer_count());
466   output_surface.DiscardBackbuffer();
467
468   EXPECT_EQ(1, software_output_device->ensure_backbuffer_count());
469   EXPECT_EQ(1, software_output_device->discard_backbuffer_count());
470 }
471
472 }  // namespace
473 }  // namespace cc