cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cc / test / layer_tree_test.cc
blob9afe3c4f8cf8e0d1b5e0d2644d50efdbc173f97a
1 // Copyright 2011 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/test/layer_tree_test.h"
7 #include "base/command_line.h"
8 #include "cc/animation/animation.h"
9 #include "cc/animation/animation_registrar.h"
10 #include "cc/animation/layer_animation_controller.h"
11 #include "cc/animation/timing_function.h"
12 #include "cc/base/switches.h"
13 #include "cc/debug/test_context_provider.h"
14 #include "cc/input/input_handler.h"
15 #include "cc/layers/content_layer.h"
16 #include "cc/layers/layer.h"
17 #include "cc/layers/layer_impl.h"
18 #include "cc/test/animation_test_common.h"
19 #include "cc/test/fake_layer_tree_host_client.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/occlusion_tracker_test_common.h"
22 #include "cc/test/tiled_layer_test_common.h"
23 #include "cc/trees/layer_tree_host_impl.h"
24 #include "cc/trees/single_thread_proxy.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "ui/gfx/size_conversions.h"
28 namespace cc {
30 TestHooks::TestHooks() {}
32 TestHooks::~TestHooks() {}
34 bool TestHooks::PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
35 LayerTreeHostImpl::FrameData* frame_data,
36 bool result) {
37 return true;
40 base::TimeDelta TestHooks::LowFrequencyAnimationInterval() const {
41 return base::TimeDelta::FromMilliseconds(16);
44 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
45 class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
46 public:
47 static scoped_ptr<LayerTreeHostImplForTesting> Create(
48 TestHooks* test_hooks,
49 const LayerTreeSettings& settings,
50 LayerTreeHostImplClient* host_impl_client,
51 Proxy* proxy,
52 RenderingStatsInstrumentation* stats_instrumentation) {
53 return make_scoped_ptr(
54 new LayerTreeHostImplForTesting(test_hooks,
55 settings,
56 host_impl_client,
57 proxy,
58 stats_instrumentation));
61 protected:
62 LayerTreeHostImplForTesting(
63 TestHooks* test_hooks,
64 const LayerTreeSettings& settings,
65 LayerTreeHostImplClient* host_impl_client,
66 Proxy* proxy,
67 RenderingStatsInstrumentation* stats_instrumentation)
68 : LayerTreeHostImpl(settings,
69 host_impl_client,
70 proxy,
71 stats_instrumentation),
72 test_hooks_(test_hooks),
73 block_notify_ready_to_activate_for_testing_(false),
74 notify_ready_to_activate_was_blocked_(false) {}
76 virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE {
77 test_hooks_->WillBeginImplFrameOnThread(this, args);
78 LayerTreeHostImpl::BeginFrame(args);
81 virtual void BeginCommit() OVERRIDE {
82 LayerTreeHostImpl::BeginCommit();
83 test_hooks_->BeginCommitOnThread(this);
86 virtual void CommitComplete() OVERRIDE {
87 LayerTreeHostImpl::CommitComplete();
88 test_hooks_->CommitCompleteOnThread(this);
90 if (!settings().impl_side_painting) {
91 test_hooks_->WillActivateTreeOnThread(this);
92 test_hooks_->DidActivateTreeOnThread(this);
96 virtual bool PrepareToDraw(FrameData* frame, gfx::Rect damage_rect) OVERRIDE {
97 bool result = LayerTreeHostImpl::PrepareToDraw(frame, damage_rect);
98 if (!test_hooks_->PrepareToDrawOnThread(this, frame, result))
99 result = false;
100 return result;
103 virtual void DrawLayers(FrameData* frame,
104 base::TimeTicks frame_begin_time) OVERRIDE {
105 LayerTreeHostImpl::DrawLayers(frame, frame_begin_time);
106 test_hooks_->DrawLayersOnThread(this);
109 virtual bool SwapBuffers(const LayerTreeHostImpl::FrameData& frame) OVERRIDE {
110 bool result = LayerTreeHostImpl::SwapBuffers(frame);
111 test_hooks_->SwapBuffersOnThread(this, result);
112 return result;
115 virtual void OnSwapBuffersComplete(const CompositorFrameAck* ack) OVERRIDE {
116 LayerTreeHostImpl::OnSwapBuffersComplete(ack);
117 test_hooks_->SwapBuffersCompleteOnThread(this);
120 virtual void NotifyReadyToActivate() OVERRIDE {
121 if (block_notify_ready_to_activate_for_testing_)
122 notify_ready_to_activate_was_blocked_ = true;
123 else
124 client_->NotifyReadyToActivate();
127 virtual void BlockNotifyReadyToActivateForTesting(bool block) OVERRIDE {
128 block_notify_ready_to_activate_for_testing_ = block;
129 if (!block && notify_ready_to_activate_was_blocked_) {
130 NotifyReadyToActivate();
131 notify_ready_to_activate_was_blocked_ = false;
135 virtual void ActivatePendingTree() OVERRIDE {
136 test_hooks_->WillActivateTreeOnThread(this);
137 LayerTreeHostImpl::ActivatePendingTree();
138 DCHECK(!pending_tree());
139 test_hooks_->DidActivateTreeOnThread(this);
142 virtual bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface)
143 OVERRIDE {
144 bool success = LayerTreeHostImpl::InitializeRenderer(output_surface.Pass());
145 test_hooks_->InitializedRendererOnThread(this, success);
146 return success;
149 virtual void SetVisible(bool visible) OVERRIDE {
150 LayerTreeHostImpl::SetVisible(visible);
151 test_hooks_->DidSetVisibleOnImplTree(this, visible);
154 virtual void AnimateLayers(base::TimeTicks monotonic_time,
155 base::Time wall_clock_time) OVERRIDE {
156 test_hooks_->WillAnimateLayers(this, monotonic_time);
157 LayerTreeHostImpl::AnimateLayers(monotonic_time, wall_clock_time);
158 test_hooks_->AnimateLayers(this, monotonic_time);
161 virtual void UpdateAnimationState(bool start_ready_animations) OVERRIDE {
162 LayerTreeHostImpl::UpdateAnimationState(start_ready_animations);
163 bool has_unfinished_animation = false;
164 AnimationRegistrar::AnimationControllerMap::const_iterator iter =
165 active_animation_controllers().begin();
166 for (; iter != active_animation_controllers().end(); ++iter) {
167 if (iter->second->HasActiveAnimation()) {
168 has_unfinished_animation = true;
169 break;
172 test_hooks_->UpdateAnimationState(this, has_unfinished_animation);
175 virtual base::TimeDelta LowFrequencyAnimationInterval() const OVERRIDE {
176 return test_hooks_->LowFrequencyAnimationInterval();
179 private:
180 TestHooks* test_hooks_;
181 bool block_notify_ready_to_activate_for_testing_;
182 bool notify_ready_to_activate_was_blocked_;
185 // Adapts LayerTreeHost for test. Injects LayerTreeHostImplForTesting.
186 class LayerTreeHostForTesting : public cc::LayerTreeHost {
187 public:
188 static scoped_ptr<LayerTreeHostForTesting> Create(
189 TestHooks* test_hooks,
190 cc::LayerTreeHostClient* host_client,
191 const cc::LayerTreeSettings& settings,
192 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
193 scoped_ptr<LayerTreeHostForTesting> layer_tree_host(
194 new LayerTreeHostForTesting(test_hooks, host_client, settings));
195 bool success = layer_tree_host->Initialize(impl_task_runner);
196 EXPECT_TRUE(success);
197 return layer_tree_host.Pass();
200 virtual scoped_ptr<cc::LayerTreeHostImpl> CreateLayerTreeHostImpl(
201 cc::LayerTreeHostImplClient* host_impl_client) OVERRIDE {
202 return LayerTreeHostImplForTesting::Create(
203 test_hooks_,
204 settings(),
205 host_impl_client,
206 proxy(),
207 rendering_stats_instrumentation()).PassAs<cc::LayerTreeHostImpl>();
210 virtual void SetNeedsCommit() OVERRIDE {
211 if (!test_started_)
212 return;
213 LayerTreeHost::SetNeedsCommit();
216 void set_test_started(bool started) { test_started_ = started; }
218 virtual void DidDeferCommit() OVERRIDE {
219 test_hooks_->DidDeferCommit();
222 private:
223 LayerTreeHostForTesting(TestHooks* test_hooks,
224 cc::LayerTreeHostClient* client,
225 const cc::LayerTreeSettings& settings)
226 : LayerTreeHost(client, settings),
227 test_hooks_(test_hooks),
228 test_started_(false) {}
230 TestHooks* test_hooks_;
231 bool test_started_;
234 // Implementation of LayerTreeHost callback interface.
235 class LayerTreeHostClientForTesting : public LayerTreeHostClient {
236 public:
237 static scoped_ptr<LayerTreeHostClientForTesting> Create(
238 TestHooks* test_hooks) {
239 return make_scoped_ptr(new LayerTreeHostClientForTesting(test_hooks));
241 virtual ~LayerTreeHostClientForTesting() {}
243 virtual void WillBeginFrame() OVERRIDE { test_hooks_->WillBeginFrame(); }
245 virtual void DidBeginFrame() OVERRIDE { test_hooks_->DidBeginFrame(); }
247 virtual void Animate(double monotonic_time) OVERRIDE {
248 test_hooks_->Animate(base::TimeTicks::FromInternalValue(
249 monotonic_time * base::Time::kMicrosecondsPerSecond));
252 virtual void Layout() OVERRIDE {
253 test_hooks_->Layout();
256 virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
257 float scale) OVERRIDE {
258 test_hooks_->ApplyScrollAndScale(scroll_delta, scale);
261 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
262 OVERRIDE {
263 return test_hooks_->CreateOutputSurface(fallback);
266 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
267 test_hooks_->DidInitializeOutputSurface(succeeded);
270 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
271 test_hooks_->DidFailToInitializeOutputSurface();
274 virtual void WillCommit() OVERRIDE { test_hooks_->WillCommit(); }
276 virtual void DidCommit() OVERRIDE {
277 test_hooks_->DidCommit();
280 virtual void DidCommitAndDrawFrame() OVERRIDE {
281 test_hooks_->DidCommitAndDrawFrame();
284 virtual void DidCompleteSwapBuffers() OVERRIDE {
285 test_hooks_->DidCompleteSwapBuffers();
288 virtual void ScheduleComposite() OVERRIDE {
289 test_hooks_->ScheduleComposite();
292 virtual scoped_refptr<cc::ContextProvider>
293 OffscreenContextProviderForMainThread() OVERRIDE {
294 return test_hooks_->OffscreenContextProviderForMainThread();
297 virtual scoped_refptr<cc::ContextProvider>
298 OffscreenContextProviderForCompositorThread() OVERRIDE {
299 return test_hooks_->OffscreenContextProviderForCompositorThread();
302 private:
303 explicit LayerTreeHostClientForTesting(TestHooks* test_hooks)
304 : test_hooks_(test_hooks) {}
306 TestHooks* test_hooks_;
309 LayerTreeTest::LayerTreeTest()
310 : beginning_(false),
311 end_when_begin_returns_(false),
312 timed_out_(false),
313 scheduled_(false),
314 schedule_when_set_visible_true_(false),
315 started_(false),
316 ended_(false),
317 delegating_renderer_(false),
318 timeout_seconds_(0),
319 weak_factory_(this) {
320 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
322 // Tests should timeout quickly unless --cc-layer-tree-test-no-timeout was
323 // specified (for running in a debugger).
324 CommandLine* command_line = CommandLine::ForCurrentProcess();
325 if (!command_line->HasSwitch(switches::kCCLayerTreeTestNoTimeout))
326 timeout_seconds_ = 5;
329 LayerTreeTest::~LayerTreeTest() {}
331 void LayerTreeTest::EndTest() {
332 // For the case where we EndTest during BeginTest(), set a flag to indicate
333 // that the test should end the second BeginTest regains control.
334 ended_ = true;
336 if (beginning_) {
337 end_when_begin_returns_ = true;
338 } else if (proxy()) {
339 // Racy timeouts and explicit EndTest calls might have cleaned up
340 // the tree host. Should check proxy first.
341 proxy()->MainThreadTaskRunner()->PostTask(
342 FROM_HERE,
343 base::Bind(&LayerTreeTest::RealEndTest, main_thread_weak_ptr_));
347 void LayerTreeTest::EndTestAfterDelay(int delay_milliseconds) {
348 proxy()->MainThreadTaskRunner()->PostTask(
349 FROM_HERE,
350 base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_));
353 void LayerTreeTest::PostAddAnimationToMainThread(
354 Layer* layer_to_receive_animation) {
355 proxy()->MainThreadTaskRunner()->PostTask(
356 FROM_HERE,
357 base::Bind(&LayerTreeTest::DispatchAddAnimation,
358 main_thread_weak_ptr_,
359 base::Unretained(layer_to_receive_animation)));
362 void LayerTreeTest::PostAddInstantAnimationToMainThread(
363 Layer* layer_to_receive_animation) {
364 proxy()->MainThreadTaskRunner()->PostTask(
365 FROM_HERE,
366 base::Bind(&LayerTreeTest::DispatchAddInstantAnimation,
367 main_thread_weak_ptr_,
368 base::Unretained(layer_to_receive_animation)));
371 void LayerTreeTest::PostSetNeedsCommitToMainThread() {
372 proxy()->MainThreadTaskRunner()->PostTask(
373 FROM_HERE,
374 base::Bind(&LayerTreeTest::DispatchSetNeedsCommit,
375 main_thread_weak_ptr_));
378 void LayerTreeTest::PostAcquireLayerTextures() {
379 proxy()->MainThreadTaskRunner()->PostTask(
380 FROM_HERE,
381 base::Bind(&LayerTreeTest::DispatchAcquireLayerTextures,
382 main_thread_weak_ptr_));
385 void LayerTreeTest::PostSetNeedsRedrawToMainThread() {
386 proxy()->MainThreadTaskRunner()->PostTask(
387 FROM_HERE,
388 base::Bind(&LayerTreeTest::DispatchSetNeedsRedraw,
389 main_thread_weak_ptr_));
392 void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(gfx::Rect damage_rect) {
393 proxy()->MainThreadTaskRunner()->PostTask(
394 FROM_HERE,
395 base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
396 main_thread_weak_ptr_, damage_rect));
399 void LayerTreeTest::PostSetVisibleToMainThread(bool visible) {
400 proxy()->MainThreadTaskRunner()->PostTask(
401 FROM_HERE,
402 base::Bind(&LayerTreeTest::DispatchSetVisible,
403 main_thread_weak_ptr_,
404 visible));
407 void LayerTreeTest::DoBeginTest() {
408 client_ = LayerTreeHostClientForTesting::Create(this);
410 DCHECK(!impl_thread_ || impl_thread_->message_loop_proxy().get());
411 layer_tree_host_ = LayerTreeHostForTesting::Create(
412 this,
413 client_.get(),
414 settings_,
415 impl_thread_ ? impl_thread_->message_loop_proxy() : NULL);
416 ASSERT_TRUE(layer_tree_host_);
418 started_ = true;
419 beginning_ = true;
420 SetupTree();
421 layer_tree_host_->SetLayerTreeHostClientReady();
422 BeginTest();
423 beginning_ = false;
424 if (end_when_begin_returns_)
425 RealEndTest();
427 // Allow commits to happen once BeginTest() has had a chance to post tasks
428 // so that those tasks will happen before the first commit.
429 if (layer_tree_host_) {
430 static_cast<LayerTreeHostForTesting*>(layer_tree_host_.get())->
431 set_test_started(true);
435 void LayerTreeTest::SetupTree() {
436 if (!layer_tree_host_->root_layer()) {
437 scoped_refptr<Layer> root_layer = Layer::Create();
438 root_layer->SetAnchorPoint(gfx::PointF());
439 root_layer->SetBounds(gfx::Size(1, 1));
440 root_layer->SetIsDrawable(true);
441 layer_tree_host_->SetRootLayer(root_layer);
444 gfx::Size root_bounds = layer_tree_host_->root_layer()->bounds();
445 gfx::Size device_root_bounds = gfx::ToCeiledSize(
446 gfx::ScaleSize(root_bounds, layer_tree_host_->device_scale_factor()));
447 layer_tree_host_->SetViewportSize(device_root_bounds);
450 void LayerTreeTest::Timeout() {
451 timed_out_ = true;
452 EndTest();
455 void LayerTreeTest::ScheduleComposite() {
456 if (!started_ || scheduled_)
457 return;
458 scheduled_ = true;
459 proxy()->MainThreadTaskRunner()->PostTask(
460 FROM_HERE,
461 base::Bind(&LayerTreeTest::DispatchComposite, main_thread_weak_ptr_));
464 void LayerTreeTest::RealEndTest() {
465 if (layer_tree_host_ && proxy()->CommitPendingForTesting()) {
466 proxy()->MainThreadTaskRunner()->PostTask(
467 FROM_HERE,
468 base::Bind(&LayerTreeTest::RealEndTest, main_thread_weak_ptr_));
469 return;
472 base::MessageLoop::current()->Quit();
475 void LayerTreeTest::DispatchAddInstantAnimation(
476 Layer* layer_to_receive_animation) {
477 DCHECK(!proxy() || proxy()->IsMainThread());
479 if (layer_to_receive_animation) {
480 AddOpacityTransitionToLayer(layer_to_receive_animation,
483 0.5,
484 false);
488 void LayerTreeTest::DispatchAddAnimation(Layer* layer_to_receive_animation) {
489 DCHECK(!proxy() || proxy()->IsMainThread());
491 if (layer_to_receive_animation) {
492 AddOpacityTransitionToLayer(layer_to_receive_animation,
493 0.000001,
495 0.5,
496 true);
500 void LayerTreeTest::DispatchSetNeedsCommit() {
501 DCHECK(!proxy() || proxy()->IsMainThread());
503 if (layer_tree_host_)
504 layer_tree_host_->SetNeedsCommit();
507 void LayerTreeTest::DispatchAcquireLayerTextures() {
508 DCHECK(!proxy() || proxy()->IsMainThread());
510 if (layer_tree_host_)
511 layer_tree_host_->AcquireLayerTextures();
514 void LayerTreeTest::DispatchSetNeedsRedraw() {
515 DCHECK(!proxy() || proxy()->IsMainThread());
517 if (layer_tree_host_)
518 layer_tree_host_->SetNeedsRedraw();
521 void LayerTreeTest::DispatchSetNeedsRedrawRect(gfx::Rect damage_rect) {
522 DCHECK(!proxy() || proxy()->IsMainThread());
524 if (layer_tree_host_)
525 layer_tree_host_->SetNeedsRedrawRect(damage_rect);
528 void LayerTreeTest::DispatchSetVisible(bool visible) {
529 DCHECK(!proxy() || proxy()->IsMainThread());
531 if (!layer_tree_host_)
532 return;
534 layer_tree_host_->SetVisible(visible);
536 // If the LTH is being made visible and a previous ScheduleComposite() was
537 // deferred because the LTH was not visible, re-schedule the composite now.
538 if (layer_tree_host_->visible() && schedule_when_set_visible_true_)
539 ScheduleComposite();
542 void LayerTreeTest::DispatchComposite() {
543 scheduled_ = false;
545 if (!layer_tree_host_)
546 return;
548 // If the LTH is not visible, defer the composite until the LTH is made
549 // visible.
550 if (!layer_tree_host_->visible()) {
551 schedule_when_set_visible_true_ = true;
552 return;
555 schedule_when_set_visible_true_ = false;
556 base::TimeTicks now = base::TimeTicks::Now();
557 layer_tree_host_->Composite(now);
560 void LayerTreeTest::RunTest(bool threaded,
561 bool delegating_renderer,
562 bool impl_side_painting) {
563 if (threaded) {
564 impl_thread_.reset(new base::Thread("Compositor"));
565 ASSERT_TRUE(impl_thread_->Start());
568 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_ =
569 base::MessageLoopProxy::current();
571 delegating_renderer_ = delegating_renderer;
573 // Spend less time waiting for BeginFrame because the output is
574 // mocked out.
575 settings_.refresh_rate = 200.0;
576 if (impl_side_painting) {
577 DCHECK(threaded) <<
578 "Don't run single thread + impl side painting, it doesn't exist.";
579 settings_.impl_side_painting = true;
581 InitializeSettings(&settings_);
583 main_task_runner_->PostTask(
584 FROM_HERE,
585 base::Bind(&LayerTreeTest::DoBeginTest, base::Unretained(this)));
587 if (timeout_seconds_) {
588 timeout_.Reset(base::Bind(&LayerTreeTest::Timeout, base::Unretained(this)));
589 main_task_runner_->PostDelayedTask(
590 FROM_HERE,
591 timeout_.callback(),
592 base::TimeDelta::FromSeconds(timeout_seconds_));
595 base::MessageLoop::current()->Run();
596 if (layer_tree_host_ && layer_tree_host_->root_layer())
597 layer_tree_host_->root_layer()->SetLayerTreeHost(NULL);
598 layer_tree_host_.reset();
600 timeout_.Cancel();
602 ASSERT_FALSE(layer_tree_host_.get());
603 client_.reset();
604 if (timed_out_) {
605 FAIL() << "Test timed out";
606 return;
608 AfterTest();
611 scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface(bool fallback) {
612 scoped_ptr<FakeOutputSurface> output_surface;
613 if (delegating_renderer_)
614 output_surface = FakeOutputSurface::CreateDelegating3d();
615 else
616 output_surface = FakeOutputSurface::Create3d();
617 output_surface_ = output_surface.get();
618 return output_surface.PassAs<OutputSurface>();
621 scoped_refptr<cc::ContextProvider> LayerTreeTest::
622 OffscreenContextProviderForMainThread() {
623 if (!main_thread_contexts_.get() ||
624 main_thread_contexts_->DestroyedOnMainThread()) {
625 main_thread_contexts_ = TestContextProvider::Create();
626 if (main_thread_contexts_ && !main_thread_contexts_->BindToCurrentThread())
627 main_thread_contexts_ = NULL;
629 return main_thread_contexts_;
632 scoped_refptr<cc::ContextProvider> LayerTreeTest::
633 OffscreenContextProviderForCompositorThread() {
634 if (!compositor_thread_contexts_.get() ||
635 compositor_thread_contexts_->DestroyedOnMainThread())
636 compositor_thread_contexts_ = TestContextProvider::Create();
637 return compositor_thread_contexts_;
640 } // namespace cc