// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/trees/layer_tree_host.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/time/time.h"
#include "cc/test/fake_content_layer.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_painted_scrollbar_layer.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/damage_tracker.h"
#include "cc/trees/layer_tree_impl.h"

namespace cc {
namespace {

// These tests deal with damage tracking.
class LayerTreeHostDamageTest : public LayerTreeTest {};

// LayerTreeHost::SetNeedsRedraw should damage the whole viewport.
class LayerTreeHostDamageTestSetNeedsRedraw
    : public LayerTreeHostDamageTest {
  virtual void SetupTree() OVERRIDE {
    // Viewport is 10x10.
    scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
    root->SetBounds(gfx::Size(10, 10));

    layer_tree_host()->SetRootLayer(root);
    LayerTreeHostDamageTest::SetupTree();
  }

  virtual void BeginTest() OVERRIDE {
    draw_count_ = 0;
    PostSetNeedsCommitToMainThread();
  }

  virtual void DidCommitAndDrawFrame() OVERRIDE {
    switch (layer_tree_host()->source_frame_number()) {
      case 1:
        layer_tree_host()->SetNeedsRedraw();
        break;
    }
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);

    RenderSurfaceImpl* root_surface =
        impl->active_tree()->root_layer()->render_surface();
    gfx::RectF root_damage =
        root_surface->damage_tracker()->current_damage_rect();

    switch (draw_count_) {
      case 0:
        // The first frame has full damage.
        EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
        break;
      case 1:
        // The second frame has full damage.
        EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
        EndTest();
        break;
      case 2:
        NOTREACHED();
    }

    ++draw_count_;
    return draw_result;
  }

  virtual void AfterTest() OVERRIDE {}

  int draw_count_;
  FakeContentLayerClient client_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetNeedsRedraw);

// LayerTreeHost::SetViewportSize should damage the whole viewport.
class LayerTreeHostDamageTestSetViewportSize
    : public LayerTreeHostDamageTest {
  virtual void SetupTree() OVERRIDE {
    // Viewport is 10x10.
    scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
    root->SetBounds(gfx::Size(10, 10));

    layer_tree_host()->SetRootLayer(root);
    LayerTreeHostDamageTest::SetupTree();
  }

  virtual void BeginTest() OVERRIDE {
    draw_count_ = 0;
    PostSetNeedsCommitToMainThread();
  }

  virtual void DidCommitAndDrawFrame() OVERRIDE {
    switch (layer_tree_host()->source_frame_number()) {
      case 1:
        layer_tree_host()->SetViewportSize(gfx::Size(15, 15));
        break;
    }
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);

    RenderSurfaceImpl* root_surface =
        impl->active_tree()->root_layer()->render_surface();
    gfx::RectF root_damage =
        root_surface->damage_tracker()->current_damage_rect();

    switch (draw_count_) {
      case 0:
        // The first frame has full damage.
        EXPECT_EQ(gfx::RectF(10.f, 10.f).ToString(), root_damage.ToString());
        break;
      case 1:
        // The second frame has full damage.
        EXPECT_EQ(gfx::RectF(15.f, 15.f).ToString(), root_damage.ToString());
        EndTest();
        break;
      case 2:
        NOTREACHED();
    }

    ++draw_count_;
    return draw_result;
  }

  virtual void AfterTest() OVERRIDE {}

  int draw_count_;
  FakeContentLayerClient client_;
};

SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestSetViewportSize);

class LayerTreeHostDamageTestNoDamageDoesNotSwap
    : public LayerTreeHostDamageTest {
  virtual void BeginTest() OVERRIDE {
    expect_swap_and_succeed_ = 0;
    did_swaps_ = 0;
    did_swap_and_succeed_ = 0;
    PostSetNeedsCommitToMainThread();
  }

  virtual void SetupTree() OVERRIDE {
    scoped_refptr<FakeContentLayer> root = FakeContentLayer::Create(&client_);
    root->SetBounds(gfx::Size(10, 10));

    // Most of the layer isn't visible.
    content_ = FakeContentLayer::Create(&client_);
    content_->SetBounds(gfx::Size(2000, 100));
    root->AddChild(content_);

    layer_tree_host()->SetRootLayer(root);
    LayerTreeHostDamageTest::SetupTree();
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* host_impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);

    int source_frame = host_impl->active_tree()->source_frame_number();
    switch (source_frame) {
      case 0:
        // The first frame has damage, so we should draw and swap.
        ++expect_swap_and_succeed_;
        break;
      case 1:
        // The second frame has no damage, so we should not draw and swap.
        break;
      case 2:
        // The third frame has damage again, so we should draw and swap.
        ++expect_swap_and_succeed_;
        break;
      case 3:
        // The fourth frame has no visible damage, so we should not draw and
        // swap.
        EndTest();
        break;
    }
    return draw_result;
  }

  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
                                   bool result) OVERRIDE {
    ++did_swaps_;
    if (result)
      ++did_swap_and_succeed_;
    EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
  }

  virtual void DidCommit() OVERRIDE {
    int next_frame = layer_tree_host()->source_frame_number();
    switch (next_frame) {
      case 1:
        layer_tree_host()->SetNeedsCommit();
        break;
      case 2:
        // Cause visible damage.
        content_->SetNeedsDisplayRect(
            gfx::Rect(layer_tree_host()->device_viewport_size()));
        break;
      case 3:
        // Cause non-visible damage.
        content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
        layer_tree_host()->SetNeedsCommit();
        break;
    }
  }

  virtual void AfterTest() OVERRIDE {
    EXPECT_EQ(4, did_swaps_);
    EXPECT_EQ(2, expect_swap_and_succeed_);
    EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_);
  }

  FakeContentLayerClient client_;
  scoped_refptr<FakeContentLayer> content_;
  int expect_swap_and_succeed_;
  int did_swaps_;
  int did_swap_and_succeed_;
};

SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
    LayerTreeHostDamageTestNoDamageDoesNotSwap);

class LayerTreeHostDamageTestForcedFullDamage : public LayerTreeHostDamageTest {
  virtual void BeginTest() OVERRIDE {
    PostSetNeedsCommitToMainThread();
  }

  virtual void SetupTree() OVERRIDE {
    root_ = FakeContentLayer::Create(&client_);
    child_ = FakeContentLayer::Create(&client_);

    root_->SetBounds(gfx::Size(500, 500));
    child_->SetPosition(gfx::Point(100, 100));
    child_->SetBounds(gfx::Size(30, 30));

    root_->AddChild(child_);
    layer_tree_host()->SetRootLayer(root_);
    LayerTreeHostDamageTest::SetupTree();
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* host_impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);

    RenderSurfaceImpl* root_surface =
        host_impl->active_tree()->root_layer()->render_surface();
    gfx::RectF root_damage =
        root_surface->damage_tracker()->current_damage_rect();
    root_damage.Intersect(root_surface->content_rect());

    int source_frame = host_impl->active_tree()->source_frame_number();
    switch (source_frame) {
      case 0:
        // The first frame draws and clears any damage.
        EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
                  root_damage.ToString());
        EXPECT_FALSE(frame_data->has_no_damage);
        break;
      case 1:
        // If we get a frame without damage then we don't draw.
        EXPECT_EQ(gfx::RectF().ToString(), root_damage.ToString());
        EXPECT_TRUE(frame_data->has_no_damage);

        // Then we set full damage for the next frame.
        host_impl->SetFullRootLayerDamage();
        break;
      case 2:
        // The whole frame should be damaged as requested.
        EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
                  root_damage.ToString());
        EXPECT_FALSE(frame_data->has_no_damage);

        // Just a part of the next frame should be damaged.
        child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
        break;
      case 3:
        // The update rect in the child should be damaged and the damaged area
        // should match the invalidation.
        EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
                  root_damage.ToString());

        // TODO(danakj): Remove this when impl side painting is always on.
        if (delegating_renderer() ||
            host_impl->settings().impl_side_painting) {
          // When using a delegating renderer, or using impl side painting, the
          // entire child is considered damaged as we need to replace its
          // resources with newly created ones. The damaged area is kept as it
          // is, but entire child is painted.

          // The paint rect should match the layer bounds.
          gfx::RectF paint_rect = child_->LastPaintRect();
          paint_rect.set_origin(child_->position());
          EXPECT_EQ(gfx::RectF(100, 100, 30, 30).ToString(),
                    paint_rect.ToString());
        }
        EXPECT_FALSE(frame_data->has_no_damage);

        // If we damage part of the frame, but also damage the full
        // frame, then the whole frame should be damaged.
        child_damage_rect_ = gfx::RectF(10, 11, 12, 13);
        host_impl->SetFullRootLayerDamage();
        break;
      case 4:
        // The whole frame is damaged.
        EXPECT_EQ(gfx::RectF(root_surface->content_rect()).ToString(),
                  root_damage.ToString());
        EXPECT_FALSE(frame_data->has_no_damage);

        EndTest();
        break;
    }
    return draw_result;
  }

  virtual void DidCommitAndDrawFrame() OVERRIDE {
    if (!TestEnded())
      layer_tree_host()->SetNeedsCommit();

    if (!child_damage_rect_.IsEmpty()) {
      child_->SetNeedsDisplayRect(child_damage_rect_);
      child_damage_rect_ = gfx::RectF();
    }
  }

  virtual void AfterTest() OVERRIDE {}

  FakeContentLayerClient client_;
  scoped_refptr<FakeContentLayer> root_;
  scoped_refptr<FakeContentLayer> child_;
  gfx::RectF child_damage_rect_;
};

SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostDamageTestForcedFullDamage);

class LayerTreeHostScrollbarDamageTest : public LayerTreeHostDamageTest {
  virtual void SetupTree() OVERRIDE {
    scoped_refptr<Layer> root_layer = Layer::Create();
    root_layer->SetBounds(gfx::Size(400, 400));
    root_layer->SetMasksToBounds(true);
    layer_tree_host()->SetRootLayer(root_layer);

    scoped_refptr<Layer> scroll_clip_layer = Layer::Create();
    scoped_refptr<Layer> content_layer = FakeContentLayer::Create(&client_);
    content_layer->SetScrollClipLayerId(scroll_clip_layer->id());
    content_layer->SetScrollOffset(gfx::ScrollOffset(10, 20));
    content_layer->SetBounds(gfx::Size(100, 200));
    scroll_clip_layer->SetBounds(
        gfx::Size(content_layer->bounds().width() - 30,
                  content_layer->bounds().height() - 50));
    scroll_clip_layer->AddChild(content_layer);
    root_layer->AddChild(scroll_clip_layer);

    scoped_refptr<Layer> scrollbar_layer =
        FakePaintedScrollbarLayer::Create(false, true, content_layer->id());
    scrollbar_layer->SetPosition(gfx::Point(300, 300));
    scrollbar_layer->SetBounds(gfx::Size(10, 100));
    scrollbar_layer->ToScrollbarLayer()->SetClipLayer(scroll_clip_layer->id());
    scrollbar_layer->ToScrollbarLayer()->SetScrollLayer(content_layer->id());
    root_layer->AddChild(scrollbar_layer);

    gfx::RectF content_rect(content_layer->position(),
                            content_layer->bounds());
    gfx::RectF scrollbar_rect(scrollbar_layer->position(),
                              scrollbar_layer->bounds());
    EXPECT_FALSE(content_rect.Intersects(scrollbar_rect));

    LayerTreeHostDamageTest::SetupTree();
  }

 private:
  FakeContentLayerClient client_;
};

class LayerTreeHostDamageTestScrollbarDoesDamage
    : public LayerTreeHostScrollbarDamageTest {
  virtual void BeginTest() OVERRIDE {
    did_swaps_ = 0;
    PostSetNeedsCommitToMainThread();
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* host_impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);
    RenderSurfaceImpl* root_surface =
        host_impl->active_tree()->root_layer()->render_surface();
    gfx::RectF root_damage =
        root_surface->damage_tracker()->current_damage_rect();
    root_damage.Intersect(root_surface->content_rect());
    switch (did_swaps_) {
      case 0:
        // The first frame has damage, so we should draw and swap.
        break;
      case 1:
        // The second frame should not damage the scrollbars.
        EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
        break;
      case 2:
        // The third frame should damage the scrollbars.
        EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
        break;
      case 3:
        // The fourth frame should damage the scrollbars.
        EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
        EndTest();
        break;
    }
    return draw_result;
  }

  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
                                   bool result) OVERRIDE {
    ++did_swaps_;
    EXPECT_TRUE(result);
    LayerImpl* root = host_impl->active_tree()->root_layer();
    LayerImpl* scroll_clip_layer = root->children()[0];
    LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
    switch (did_swaps_) {
      case 1:
        // Test that modifying the position of the content layer (not
        // scrolling) won't damage the scrollbar.
        scroll_layer->SetPosition(gfx::Point(1, 1));
        scroll_layer->SetScrollOffset(scroll_layer->scroll_offset());
        host_impl->SetNeedsRedraw();
        break;
      case 2:
        scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
        host_impl->SetNeedsRedraw();
        break;
      case 3:
        scroll_layer->SetBounds(gfx::Size(root->bounds().width() + 60,
                                          root->bounds().height() + 100));
        host_impl->SetNeedsRedraw();
        break;
    }
  }

  virtual void AfterTest() OVERRIDE {
    EXPECT_EQ(4, did_swaps_);
  }

  int did_swaps_;
};

MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);

class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage
    : public LayerTreeHostScrollbarDamageTest {
  virtual void BeginTest() OVERRIDE {
    did_swaps_ = 0;
    PostSetNeedsCommitToMainThread();
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* host_impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);
    RenderSurfaceImpl* root_surface =
        host_impl->active_tree()->root_layer()->render_surface();
    gfx::RectF root_damage =
        root_surface->damage_tracker()->current_damage_rect();
    root_damage.Intersect(root_surface->content_rect());
    int frame = host_impl->active_tree()->source_frame_number();
    switch (did_swaps_) {
      case 0:
        // The first frame has damage, so we should draw and swap.
        EXPECT_EQ(0, frame);
        break;
      case 1:
        // The second frame has scrolled, so the scrollbar should be damaged.
        EXPECT_EQ(0, frame);
        EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
        break;
      case 2:
        // The third frame (after the commit) has no changes, so it shouldn't.
        EXPECT_EQ(1, frame);
        EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
        break;
      default:
        NOTREACHED();
        break;
    }
    return draw_result;
  }

  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
                                   bool result) OVERRIDE {
    ++did_swaps_;
    EXPECT_TRUE(result);
    LayerImpl* root = host_impl->active_tree()->root_layer();
    LayerImpl* scroll_clip_layer = root->children()[0];
    LayerImpl* scroll_layer = scroll_clip_layer->children()[0];
    switch (did_swaps_) {
      case 1:
        // Scroll on the thread.  This should damage the scrollbar for the
        // next draw on the thread.
        scroll_layer->ScrollBy(gfx::Vector2dF(10.f, 10.f));
        host_impl->SetNeedsRedraw();
        break;
      case 2:
        // Forcibly send the scroll to the main thread.
        PostSetNeedsCommitToMainThread();
        break;
      case 3:
        // First swap after second commit.
        EndTest();
        break;
      default:
        NOTREACHED();
        break;
    }
  }

  virtual void AfterTest() OVERRIDE {
    EXPECT_EQ(3, did_swaps_);
  }

  int did_swaps_;
};

MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);

class LayerTreeHostDamageTestVisibleTilesStillTriggerDraws
    : public LayerTreeHostDamageTest {

  virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
    settings->impl_side_painting = true;
  }

  virtual void BeginTest() OVERRIDE {
    PostSetNeedsCommitToMainThread();
  }

  virtual void SetupTree() OVERRIDE {
    scoped_refptr<FakePictureLayer> root = FakePictureLayer::Create(&client_);
    root->SetBounds(gfx::Size(500, 500));
    layer_tree_host()->SetRootLayer(root);
    LayerTreeHostDamageTest::SetupTree();

    swap_count_ = 0;
    prepare_to_draw_count_ = 0;
    update_visible_tile_count_ = 0;
  }

  virtual DrawResult PrepareToDrawOnThread(
      LayerTreeHostImpl* host_impl,
      LayerTreeHostImpl::FrameData* frame_data,
      DrawResult draw_result) OVERRIDE {
    EXPECT_EQ(DRAW_SUCCESS, draw_result);
    prepare_to_draw_count_++;
    switch (prepare_to_draw_count_) {
      case 1:
        // Detect that we have an incomplete tile, during the first frame.
        // The first frame should have damage.
        frame_data->contains_incomplete_tile = true;
        DCHECK(!frame_data->has_no_damage);
        break;
      case 2:
        // Make a no-damage frame. We early out and can't detect
        // incomplete tiles, even if they still exist.
        frame_data->contains_incomplete_tile = false;
        frame_data->has_no_damage = true;
        break;
      case 3:
        // Trigger the last swap for the completed tile.
        frame_data->contains_incomplete_tile = false;
        frame_data->has_no_damage = false;
        EndTest();
        break;
      default:
        NOTREACHED();
        break;
    }

    return draw_result;
  }

  virtual void UpdateVisibleTilesOnThread(
      LayerTreeHostImpl* host_impl) OVERRIDE {
    // Simulate creating some visible tiles (that trigger prepare-to-draws).
    // The first we make into a no-damage-frame during prepare-to-draw (see
    // above). This is to ensure we still get UpdateVisibleTiles calls after
    // a no-damage or aborted frame.
    update_visible_tile_count_++;
    switch (update_visible_tile_count_) {
      case 3:
      case 6:
        host_impl->DidInitializeVisibleTileForTesting();
        break;
      case 7:
        NOTREACHED();
        break;
    }
  }

  virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
                                   bool didSwap) OVERRIDE {
    if (!didSwap)
      return;
    ++swap_count_;
  }

  virtual void AfterTest() OVERRIDE {
    // We should keep getting update-visible-tiles calls
    // until we report there are no more incomplete-tiles.
    EXPECT_EQ(update_visible_tile_count_, 6);
    // First frame, plus two triggered by DidInitializeVisibleTile()
    EXPECT_EQ(prepare_to_draw_count_, 3);
    // First swap, plus final swap (contained damage).
    EXPECT_EQ(swap_count_, 2);
  }

  FakeContentLayerClient client_;
  int swap_count_;
  int prepare_to_draw_count_;
  int update_visible_tile_count_;
};

MULTI_THREAD_TEST_F(LayerTreeHostDamageTestVisibleTilesStillTriggerDraws);

}  // namespace
}  // namespace cc
