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