Home | History | Annotate | Download | only in test
      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.
      4 
      5 #include "cc/test/layer_tree_test.h"
      6 
      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/input/input_handler.h"
     14 #include "cc/layers/content_layer.h"
     15 #include "cc/layers/layer.h"
     16 #include "cc/layers/layer_impl.h"
     17 #include "cc/test/animation_test_common.h"
     18 #include "cc/test/fake_layer_tree_host_client.h"
     19 #include "cc/test/fake_output_surface.h"
     20 #include "cc/test/test_context_provider.h"
     21 #include "cc/test/test_shared_bitmap_manager.h"
     22 #include "cc/test/tiled_layer_test_common.h"
     23 #include "cc/trees/layer_tree_host_client.h"
     24 #include "cc/trees/layer_tree_host_impl.h"
     25 #include "cc/trees/layer_tree_host_single_thread_client.h"
     26 #include "cc/trees/layer_tree_impl.h"
     27 #include "cc/trees/single_thread_proxy.h"
     28 #include "cc/trees/thread_proxy.h"
     29 #include "testing/gmock/include/gmock/gmock.h"
     30 #include "ui/gfx/frame_time.h"
     31 #include "ui/gfx/size_conversions.h"
     32 
     33 namespace cc {
     34 
     35 TestHooks::TestHooks() {}
     36 
     37 TestHooks::~TestHooks() {}
     38 
     39 DrawResult TestHooks::PrepareToDrawOnThread(
     40     LayerTreeHostImpl* host_impl,
     41     LayerTreeHostImpl::FrameData* frame_data,
     42     DrawResult draw_result) {
     43   return draw_result;
     44 }
     45 
     46 base::TimeDelta TestHooks::LowFrequencyAnimationInterval() const {
     47   return base::TimeDelta::FromMilliseconds(16);
     48 }
     49 
     50 // Adapts ThreadProxy for test. Injects test hooks for testing.
     51 class ThreadProxyForTest : public ThreadProxy {
     52  public:
     53   static scoped_ptr<Proxy> Create(
     54       TestHooks* test_hooks,
     55       LayerTreeHost* host,
     56       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
     57       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
     58     return make_scoped_ptr(
     59                new ThreadProxyForTest(
     60                    test_hooks, host, main_task_runner, impl_task_runner))
     61         .PassAs<Proxy>();
     62   }
     63 
     64   virtual ~ThreadProxyForTest() {}
     65 
     66   void test() {
     67     test_hooks_->Layout();
     68   }
     69 
     70  private:
     71   TestHooks* test_hooks_;
     72 
     73   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
     74     test_hooks_->ScheduledActionWillSendBeginMainFrame();
     75     ThreadProxy::ScheduledActionSendBeginMainFrame();
     76     test_hooks_->ScheduledActionSendBeginMainFrame();
     77   }
     78 
     79   virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
     80     DrawResult result = ThreadProxy::ScheduledActionDrawAndSwapIfPossible();
     81     test_hooks_->ScheduledActionDrawAndSwapIfPossible();
     82     return result;
     83   }
     84 
     85   virtual void ScheduledActionAnimate() OVERRIDE {
     86     ThreadProxy::ScheduledActionAnimate();
     87     test_hooks_->ScheduledActionAnimate();
     88   }
     89 
     90   virtual void ScheduledActionCommit() OVERRIDE {
     91     ThreadProxy::ScheduledActionCommit();
     92     test_hooks_->ScheduledActionCommit();
     93   }
     94 
     95   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
     96     ThreadProxy::ScheduledActionBeginOutputSurfaceCreation();
     97     test_hooks_->ScheduledActionBeginOutputSurfaceCreation();
     98   }
     99 
    100   ThreadProxyForTest(
    101       TestHooks* test_hooks,
    102       LayerTreeHost* host,
    103       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    104       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
    105       : ThreadProxy(host, main_task_runner, impl_task_runner),
    106         test_hooks_(test_hooks) {}
    107 };
    108 
    109 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
    110 class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
    111  public:
    112   static scoped_ptr<LayerTreeHostImplForTesting> Create(
    113       TestHooks* test_hooks,
    114       const LayerTreeSettings& settings,
    115       LayerTreeHostImplClient* host_impl_client,
    116       Proxy* proxy,
    117       SharedBitmapManager* manager,
    118       RenderingStatsInstrumentation* stats_instrumentation) {
    119     return make_scoped_ptr(
    120         new LayerTreeHostImplForTesting(test_hooks,
    121                                         settings,
    122                                         host_impl_client,
    123                                         proxy,
    124                                         manager,
    125                                         stats_instrumentation));
    126   }
    127 
    128  protected:
    129   LayerTreeHostImplForTesting(
    130       TestHooks* test_hooks,
    131       const LayerTreeSettings& settings,
    132       LayerTreeHostImplClient* host_impl_client,
    133       Proxy* proxy,
    134       SharedBitmapManager* manager,
    135       RenderingStatsInstrumentation* stats_instrumentation)
    136       : LayerTreeHostImpl(settings,
    137                           host_impl_client,
    138                           proxy,
    139                           stats_instrumentation,
    140                           manager,
    141                           0),
    142         test_hooks_(test_hooks),
    143         block_notify_ready_to_activate_for_testing_(false),
    144         notify_ready_to_activate_was_blocked_(false) {}
    145 
    146   virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
    147     LayerTreeHostImpl::WillBeginImplFrame(args);
    148     test_hooks_->WillBeginImplFrameOnThread(this, args);
    149   }
    150 
    151   virtual void BeginMainFrameAborted(bool did_handle) OVERRIDE {
    152     LayerTreeHostImpl::BeginMainFrameAborted(did_handle);
    153     test_hooks_->BeginMainFrameAbortedOnThread(this, did_handle);
    154   }
    155 
    156   virtual void BeginCommit() OVERRIDE {
    157     LayerTreeHostImpl::BeginCommit();
    158     test_hooks_->BeginCommitOnThread(this);
    159   }
    160 
    161   virtual void CommitComplete() OVERRIDE {
    162     LayerTreeHostImpl::CommitComplete();
    163     test_hooks_->CommitCompleteOnThread(this);
    164   }
    165 
    166   virtual DrawResult PrepareToDraw(FrameData* frame) OVERRIDE {
    167     DrawResult draw_result = LayerTreeHostImpl::PrepareToDraw(frame);
    168     return test_hooks_->PrepareToDrawOnThread(this, frame, draw_result);
    169   }
    170 
    171   virtual void DrawLayers(FrameData* frame,
    172                           base::TimeTicks frame_begin_time) OVERRIDE {
    173     LayerTreeHostImpl::DrawLayers(frame, frame_begin_time);
    174     test_hooks_->DrawLayersOnThread(this);
    175   }
    176 
    177   virtual bool SwapBuffers(const LayerTreeHostImpl::FrameData& frame) OVERRIDE {
    178     bool result = LayerTreeHostImpl::SwapBuffers(frame);
    179     test_hooks_->SwapBuffersOnThread(this, result);
    180     return result;
    181   }
    182 
    183   virtual void DidSwapBuffersComplete() OVERRIDE {
    184     LayerTreeHostImpl::DidSwapBuffersComplete();
    185     test_hooks_->SwapBuffersCompleteOnThread(this);
    186   }
    187 
    188   virtual void ReclaimResources(const CompositorFrameAck* ack) OVERRIDE {
    189     LayerTreeHostImpl::ReclaimResources(ack);
    190   }
    191 
    192   virtual void UpdateVisibleTiles() OVERRIDE {
    193     LayerTreeHostImpl::UpdateVisibleTiles();
    194     test_hooks_->UpdateVisibleTilesOnThread(this);
    195   }
    196 
    197   virtual void NotifyReadyToActivate() OVERRIDE {
    198     if (block_notify_ready_to_activate_for_testing_)
    199       notify_ready_to_activate_was_blocked_ = true;
    200     else
    201       client_->NotifyReadyToActivate();
    202   }
    203 
    204   virtual void BlockNotifyReadyToActivateForTesting(bool block) OVERRIDE {
    205     block_notify_ready_to_activate_for_testing_ = block;
    206     if (!block && notify_ready_to_activate_was_blocked_) {
    207       NotifyReadyToActivate();
    208       notify_ready_to_activate_was_blocked_ = false;
    209     }
    210   }
    211 
    212   virtual void ActivateSyncTree() OVERRIDE {
    213     test_hooks_->WillActivateTreeOnThread(this);
    214     LayerTreeHostImpl::ActivateSyncTree();
    215     DCHECK(!pending_tree());
    216     test_hooks_->DidActivateTreeOnThread(this);
    217   }
    218 
    219   virtual bool InitializeRenderer(scoped_ptr<OutputSurface> output_surface)
    220       OVERRIDE {
    221     bool success = LayerTreeHostImpl::InitializeRenderer(output_surface.Pass());
    222     test_hooks_->InitializedRendererOnThread(this, success);
    223     return success;
    224   }
    225 
    226   virtual void SetVisible(bool visible) OVERRIDE {
    227     LayerTreeHostImpl::SetVisible(visible);
    228     test_hooks_->DidSetVisibleOnImplTree(this, visible);
    229   }
    230 
    231   virtual void AnimateLayers(base::TimeTicks monotonic_time) OVERRIDE {
    232     test_hooks_->WillAnimateLayers(this, monotonic_time);
    233     LayerTreeHostImpl::AnimateLayers(monotonic_time);
    234     test_hooks_->AnimateLayers(this, monotonic_time);
    235   }
    236 
    237   virtual void UpdateAnimationState(bool start_ready_animations) OVERRIDE {
    238     LayerTreeHostImpl::UpdateAnimationState(start_ready_animations);
    239     bool has_unfinished_animation = false;
    240     AnimationRegistrar::AnimationControllerMap::const_iterator iter =
    241         active_animation_controllers().begin();
    242     for (; iter != active_animation_controllers().end(); ++iter) {
    243       if (iter->second->HasActiveAnimation()) {
    244         has_unfinished_animation = true;
    245         break;
    246       }
    247     }
    248     test_hooks_->UpdateAnimationState(this, has_unfinished_animation);
    249   }
    250 
    251   virtual base::TimeDelta LowFrequencyAnimationInterval() const OVERRIDE {
    252     return test_hooks_->LowFrequencyAnimationInterval();
    253   }
    254 
    255  private:
    256   TestHooks* test_hooks_;
    257   bool block_notify_ready_to_activate_for_testing_;
    258   bool notify_ready_to_activate_was_blocked_;
    259 };
    260 
    261 // Implementation of LayerTreeHost callback interface.
    262 class LayerTreeHostClientForTesting : public LayerTreeHostClient,
    263                                       public LayerTreeHostSingleThreadClient {
    264  public:
    265   static scoped_ptr<LayerTreeHostClientForTesting> Create(
    266       TestHooks* test_hooks) {
    267     return make_scoped_ptr(new LayerTreeHostClientForTesting(test_hooks));
    268   }
    269   virtual ~LayerTreeHostClientForTesting() {}
    270 
    271   virtual void WillBeginMainFrame(int frame_id) OVERRIDE {
    272     test_hooks_->WillBeginMainFrame();
    273   }
    274 
    275   virtual void DidBeginMainFrame() OVERRIDE {
    276     test_hooks_->DidBeginMainFrame();
    277   }
    278 
    279   virtual void BeginMainFrame(const BeginFrameArgs& args) OVERRIDE {
    280     test_hooks_->BeginMainFrame(args);
    281   }
    282 
    283   virtual void Layout() OVERRIDE { test_hooks_->Layout(); }
    284 
    285   virtual void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta,
    286                                    float scale,
    287                                    float top_controls_delta) OVERRIDE {
    288     test_hooks_->ApplyViewportDeltas(scroll_delta,
    289                                      scale,
    290                                      top_controls_delta);
    291   }
    292 
    293   virtual void RequestNewOutputSurface(bool fallback) OVERRIDE {
    294     test_hooks_->RequestNewOutputSurface(fallback);
    295   }
    296 
    297   virtual void DidInitializeOutputSurface() OVERRIDE {
    298     test_hooks_->DidInitializeOutputSurface();
    299   }
    300 
    301   virtual void DidFailToInitializeOutputSurface() OVERRIDE {
    302     test_hooks_->DidFailToInitializeOutputSurface();
    303   }
    304 
    305   virtual void WillCommit() OVERRIDE { test_hooks_->WillCommit(); }
    306 
    307   virtual void DidCommit() OVERRIDE { test_hooks_->DidCommit(); }
    308 
    309   virtual void DidCommitAndDrawFrame() OVERRIDE {
    310     test_hooks_->DidCommitAndDrawFrame();
    311   }
    312 
    313   virtual void DidCompleteSwapBuffers() OVERRIDE {
    314     test_hooks_->DidCompleteSwapBuffers();
    315   }
    316 
    317   virtual void DidPostSwapBuffers() OVERRIDE {}
    318   virtual void DidAbortSwapBuffers() OVERRIDE {}
    319 
    320  private:
    321   explicit LayerTreeHostClientForTesting(TestHooks* test_hooks)
    322       : test_hooks_(test_hooks) {}
    323 
    324   TestHooks* test_hooks_;
    325 };
    326 
    327 // Adapts LayerTreeHost for test. Injects LayerTreeHostImplForTesting.
    328 class LayerTreeHostForTesting : public LayerTreeHost {
    329  public:
    330   static scoped_ptr<LayerTreeHostForTesting> Create(
    331       TestHooks* test_hooks,
    332       LayerTreeHostClientForTesting* client,
    333       const LayerTreeSettings& settings,
    334       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    335       scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
    336     scoped_ptr<LayerTreeHostForTesting> layer_tree_host(
    337         new LayerTreeHostForTesting(test_hooks, client, settings));
    338     if (impl_task_runner.get()) {
    339       layer_tree_host->InitializeForTesting(
    340           ThreadProxyForTest::Create(test_hooks,
    341                                      layer_tree_host.get(),
    342                                      main_task_runner,
    343                                      impl_task_runner));
    344     } else {
    345       layer_tree_host->InitializeForTesting(SingleThreadProxy::Create(
    346           layer_tree_host.get(), client, main_task_runner));
    347     }
    348     return layer_tree_host.Pass();
    349   }
    350 
    351   virtual scoped_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl(
    352       LayerTreeHostImplClient* host_impl_client) OVERRIDE {
    353     return LayerTreeHostImplForTesting::Create(
    354                test_hooks_,
    355                settings(),
    356                host_impl_client,
    357                proxy(),
    358                shared_bitmap_manager_.get(),
    359                rendering_stats_instrumentation()).PassAs<LayerTreeHostImpl>();
    360   }
    361 
    362   virtual void SetNeedsCommit() OVERRIDE {
    363     if (!test_started_)
    364       return;
    365     LayerTreeHost::SetNeedsCommit();
    366   }
    367 
    368   void set_test_started(bool started) { test_started_ = started; }
    369 
    370   virtual void DidDeferCommit() OVERRIDE { test_hooks_->DidDeferCommit(); }
    371 
    372  private:
    373   LayerTreeHostForTesting(TestHooks* test_hooks,
    374                           LayerTreeHostClient* client,
    375                           const LayerTreeSettings& settings)
    376       : LayerTreeHost(client, NULL, settings),
    377         shared_bitmap_manager_(new TestSharedBitmapManager()),
    378         test_hooks_(test_hooks),
    379         test_started_(false) {}
    380 
    381   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
    382   TestHooks* test_hooks_;
    383   bool test_started_;
    384 };
    385 
    386 LayerTreeTest::LayerTreeTest()
    387     : beginning_(false),
    388       end_when_begin_returns_(false),
    389       timed_out_(false),
    390       scheduled_(false),
    391       started_(false),
    392       ended_(false),
    393       delegating_renderer_(false),
    394       timeout_seconds_(0),
    395       weak_factory_(this) {
    396   main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
    397 
    398   // Tests should timeout quickly unless --cc-layer-tree-test-no-timeout was
    399   // specified (for running in a debugger).
    400   CommandLine* command_line = CommandLine::ForCurrentProcess();
    401   if (!command_line->HasSwitch(switches::kCCLayerTreeTestNoTimeout))
    402     timeout_seconds_ = 5;
    403 }
    404 
    405 LayerTreeTest::~LayerTreeTest() {}
    406 
    407 void LayerTreeTest::EndTest() {
    408   if (ended_)
    409     return;
    410   ended_ = true;
    411 
    412   // For the case where we EndTest during BeginTest(), set a flag to indicate
    413   // that the test should end the second BeginTest regains control.
    414   if (beginning_) {
    415     end_when_begin_returns_ = true;
    416   } else {
    417     main_task_runner_->PostTask(
    418         FROM_HERE,
    419         base::Bind(&LayerTreeTest::RealEndTest, main_thread_weak_ptr_));
    420   }
    421 }
    422 
    423 void LayerTreeTest::EndTestAfterDelay(int delay_milliseconds) {
    424   main_task_runner_->PostDelayedTask(
    425       FROM_HERE,
    426       base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_),
    427       base::TimeDelta::FromMilliseconds(delay_milliseconds));
    428 }
    429 
    430 void LayerTreeTest::PostAddAnimationToMainThread(
    431     Layer* layer_to_receive_animation) {
    432   main_task_runner_->PostTask(
    433       FROM_HERE,
    434       base::Bind(&LayerTreeTest::DispatchAddAnimation,
    435                  main_thread_weak_ptr_,
    436                  base::Unretained(layer_to_receive_animation),
    437                  0.000001));
    438 }
    439 
    440 void LayerTreeTest::PostAddInstantAnimationToMainThread(
    441     Layer* layer_to_receive_animation) {
    442   main_task_runner_->PostTask(
    443       FROM_HERE,
    444       base::Bind(&LayerTreeTest::DispatchAddAnimation,
    445                  main_thread_weak_ptr_,
    446                  base::Unretained(layer_to_receive_animation),
    447                  0.0));
    448 }
    449 
    450 void LayerTreeTest::PostAddLongAnimationToMainThread(
    451     Layer* layer_to_receive_animation) {
    452   main_task_runner_->PostTask(
    453       FROM_HERE,
    454       base::Bind(&LayerTreeTest::DispatchAddAnimation,
    455                  main_thread_weak_ptr_,
    456                  base::Unretained(layer_to_receive_animation),
    457                  1.0));
    458 }
    459 
    460 void LayerTreeTest::PostSetNeedsCommitToMainThread() {
    461   main_task_runner_->PostTask(FROM_HERE,
    462                               base::Bind(&LayerTreeTest::DispatchSetNeedsCommit,
    463                                          main_thread_weak_ptr_));
    464 }
    465 
    466 void LayerTreeTest::PostSetNeedsUpdateLayersToMainThread() {
    467   main_task_runner_->PostTask(
    468       FROM_HERE,
    469       base::Bind(&LayerTreeTest::DispatchSetNeedsUpdateLayers,
    470                  main_thread_weak_ptr_));
    471 }
    472 
    473 void LayerTreeTest::PostSetNeedsRedrawToMainThread() {
    474   main_task_runner_->PostTask(FROM_HERE,
    475                               base::Bind(&LayerTreeTest::DispatchSetNeedsRedraw,
    476                                          main_thread_weak_ptr_));
    477 }
    478 
    479 void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(
    480     const gfx::Rect& damage_rect) {
    481   main_task_runner_->PostTask(
    482       FROM_HERE,
    483       base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
    484                  main_thread_weak_ptr_,
    485                  damage_rect));
    486 }
    487 
    488 void LayerTreeTest::PostSetVisibleToMainThread(bool visible) {
    489   main_task_runner_->PostTask(
    490       FROM_HERE,
    491       base::Bind(
    492           &LayerTreeTest::DispatchSetVisible, main_thread_weak_ptr_, visible));
    493 }
    494 
    495 void LayerTreeTest::PostSetNextCommitForcesRedrawToMainThread() {
    496   main_task_runner_->PostTask(
    497       FROM_HERE,
    498       base::Bind(&LayerTreeTest::DispatchSetNextCommitForcesRedraw,
    499                  main_thread_weak_ptr_));
    500 }
    501 
    502 void LayerTreeTest::WillBeginTest() {
    503   layer_tree_host_->SetLayerTreeHostClientReady();
    504 }
    505 
    506 void LayerTreeTest::DoBeginTest() {
    507   client_ = LayerTreeHostClientForTesting::Create(this);
    508 
    509   DCHECK(!impl_thread_ || impl_thread_->message_loop_proxy().get());
    510   layer_tree_host_ = LayerTreeHostForTesting::Create(
    511       this,
    512       client_.get(),
    513       settings_,
    514       base::MessageLoopProxy::current(),
    515       impl_thread_ ? impl_thread_->message_loop_proxy() : NULL);
    516   ASSERT_TRUE(layer_tree_host_);
    517 
    518   started_ = true;
    519   beginning_ = true;
    520   SetupTree();
    521   WillBeginTest();
    522   BeginTest();
    523   beginning_ = false;
    524   if (end_when_begin_returns_)
    525     RealEndTest();
    526 
    527   // Allow commits to happen once BeginTest() has had a chance to post tasks
    528   // so that those tasks will happen before the first commit.
    529   if (layer_tree_host_) {
    530     static_cast<LayerTreeHostForTesting*>(layer_tree_host_.get())
    531         ->set_test_started(true);
    532   }
    533 }
    534 
    535 void LayerTreeTest::SetupTree() {
    536   if (!layer_tree_host_->root_layer()) {
    537     scoped_refptr<Layer> root_layer = Layer::Create();
    538     root_layer->SetBounds(gfx::Size(1, 1));
    539     root_layer->SetIsDrawable(true);
    540     layer_tree_host_->SetRootLayer(root_layer);
    541   }
    542 
    543   gfx::Size root_bounds = layer_tree_host_->root_layer()->bounds();
    544   gfx::Size device_root_bounds = gfx::ToCeiledSize(
    545       gfx::ScaleSize(root_bounds, layer_tree_host_->device_scale_factor()));
    546   layer_tree_host_->SetViewportSize(device_root_bounds);
    547 }
    548 
    549 void LayerTreeTest::Timeout() {
    550   timed_out_ = true;
    551   EndTest();
    552 }
    553 
    554 void LayerTreeTest::RealEndTest() {
    555   if (layer_tree_host_ && !timed_out_ &&
    556       proxy()->MainFrameWillHappenForTesting()) {
    557     main_task_runner_->PostTask(
    558         FROM_HERE,
    559         base::Bind(&LayerTreeTest::RealEndTest, main_thread_weak_ptr_));
    560     return;
    561   }
    562 
    563   base::MessageLoop::current()->Quit();
    564 }
    565 
    566 void LayerTreeTest::DispatchAddAnimation(Layer* layer_to_receive_animation,
    567                                          double animation_duration) {
    568   DCHECK(!proxy() || proxy()->IsMainThread());
    569 
    570   if (layer_to_receive_animation) {
    571     AddOpacityTransitionToLayer(
    572         layer_to_receive_animation, animation_duration, 0, 0.5, true);
    573   }
    574 }
    575 
    576 void LayerTreeTest::DispatchSetNeedsCommit() {
    577   DCHECK(!proxy() || proxy()->IsMainThread());
    578 
    579   if (layer_tree_host_)
    580     layer_tree_host_->SetNeedsCommit();
    581 }
    582 
    583 void LayerTreeTest::DispatchSetNeedsUpdateLayers() {
    584   DCHECK(!proxy() || proxy()->IsMainThread());
    585 
    586   if (layer_tree_host_)
    587     layer_tree_host_->SetNeedsUpdateLayers();
    588 }
    589 
    590 void LayerTreeTest::DispatchSetNeedsRedraw() {
    591   DCHECK(!proxy() || proxy()->IsMainThread());
    592 
    593   if (layer_tree_host_)
    594     layer_tree_host_->SetNeedsRedraw();
    595 }
    596 
    597 void LayerTreeTest::DispatchSetNeedsRedrawRect(const gfx::Rect& damage_rect) {
    598   DCHECK(!proxy() || proxy()->IsMainThread());
    599 
    600   if (layer_tree_host_)
    601     layer_tree_host_->SetNeedsRedrawRect(damage_rect);
    602 }
    603 
    604 void LayerTreeTest::DispatchSetVisible(bool visible) {
    605   DCHECK(!proxy() || proxy()->IsMainThread());
    606   if (layer_tree_host_)
    607     layer_tree_host_->SetVisible(visible);
    608 }
    609 
    610 void LayerTreeTest::DispatchSetNextCommitForcesRedraw() {
    611   DCHECK(!proxy() || proxy()->IsMainThread());
    612 
    613   if (layer_tree_host_)
    614     layer_tree_host_->SetNextCommitForcesRedraw();
    615 }
    616 
    617 void LayerTreeTest::RunTest(bool threaded,
    618                             bool delegating_renderer,
    619                             bool impl_side_painting) {
    620   if (threaded) {
    621     impl_thread_.reset(new base::Thread("Compositor"));
    622     ASSERT_TRUE(impl_thread_->Start());
    623   }
    624 
    625   main_task_runner_ = base::MessageLoopProxy::current();
    626 
    627   delegating_renderer_ = delegating_renderer;
    628 
    629   // Spend less time waiting for BeginFrame because the output is
    630   // mocked out.
    631   settings_.refresh_rate = 200.0;
    632   if (impl_side_painting) {
    633     DCHECK(threaded)
    634         << "Don't run single thread + impl side painting, it doesn't exist.";
    635     settings_.impl_side_painting = true;
    636   }
    637   InitializeSettings(&settings_);
    638 
    639   main_task_runner_->PostTask(
    640       FROM_HERE,
    641       base::Bind(&LayerTreeTest::DoBeginTest, base::Unretained(this)));
    642 
    643   if (timeout_seconds_) {
    644     timeout_.Reset(base::Bind(&LayerTreeTest::Timeout, base::Unretained(this)));
    645     main_task_runner_->PostDelayedTask(
    646         FROM_HERE,
    647         timeout_.callback(),
    648         base::TimeDelta::FromSeconds(timeout_seconds_));
    649   }
    650 
    651   base::MessageLoop::current()->Run();
    652   DestroyLayerTreeHost();
    653 
    654   timeout_.Cancel();
    655 
    656   ASSERT_FALSE(layer_tree_host_.get());
    657   client_.reset();
    658   if (timed_out_) {
    659     FAIL() << "Test timed out";
    660     return;
    661   }
    662   AfterTest();
    663 }
    664 
    665 void LayerTreeTest::RunTestWithImplSidePainting() {
    666   RunTest(true, false, true);
    667 }
    668 
    669 void LayerTreeTest::RequestNewOutputSurface(bool fallback) {
    670   layer_tree_host_->SetOutputSurface(CreateOutputSurface(fallback));
    671 }
    672 
    673 scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface(bool fallback) {
    674   scoped_ptr<FakeOutputSurface> output_surface =
    675       CreateFakeOutputSurface(fallback);
    676   if (output_surface) {
    677     DCHECK_EQ(delegating_renderer_,
    678               output_surface->capabilities().delegated_rendering);
    679   }
    680   output_surface_ = output_surface.get();
    681   return output_surface.PassAs<OutputSurface>();
    682 }
    683 
    684 scoped_ptr<FakeOutputSurface> LayerTreeTest::CreateFakeOutputSurface(
    685     bool fallback) {
    686   if (delegating_renderer_)
    687     return FakeOutputSurface::CreateDelegating3d();
    688   else
    689     return FakeOutputSurface::Create3d();
    690 }
    691 
    692 TestWebGraphicsContext3D* LayerTreeTest::TestContext() {
    693   return static_cast<TestContextProvider*>(output_surface_->context_provider())
    694       ->TestContext3d();
    695 }
    696 
    697 int LayerTreeTest::LastCommittedSourceFrameNumber(LayerTreeHostImpl* impl)
    698     const {
    699   if (impl->pending_tree())
    700     return impl->pending_tree()->source_frame_number();
    701   if (impl->active_tree())
    702     return impl->active_tree()->source_frame_number();
    703   // Source frames start at 0, so this is invalid.
    704   return -1;
    705 }
    706 
    707 void LayerTreeTest::DestroyLayerTreeHost() {
    708   if (layer_tree_host_ && layer_tree_host_->root_layer())
    709     layer_tree_host_->root_layer()->SetLayerTreeHost(NULL);
    710   layer_tree_host_.reset();
    711 }
    712 
    713 }  // namespace cc
    714