root/cc/trees/quad_culler_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. layer_id_
  2. MakeLayer
  3. AppendQuads
  4. TEST_F
  5. TEST_F
  6. TEST_F
  7. TEST_F
  8. TEST_F
  9. TEST_F
  10. TEST_F
  11. TEST_F
  12. TEST_F
  13. TEST_F
  14. TEST_F
  15. TEST_F
  16. TEST_F
  17. TEST_F
  18. TEST_F

// 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/quad_culler.h"

#include <vector>

#include "cc/base/math_util.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/layers/tiled_layer_impl.h"
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/resources/layer_tiling_data.h"
#include "cc/test/fake_impl_proxy.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/test_occlusion_tracker.h"
#include "cc/test/test_shared_bitmap_manager.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/transform.h"

namespace cc {
namespace {

typedef LayerIterator<LayerImpl> LayerIteratorType;

class QuadCullerTest : public testing::Test {
 public:
  QuadCullerTest()
      : host_impl_(&proxy_, &shared_bitmap_manager_), layer_id_(1) {}

  scoped_ptr<TiledLayerImpl> MakeLayer(TiledLayerImpl* parent,
                                       const gfx::Transform& draw_transform,
                                       const gfx::Rect& layer_rect,
                                       float opacity,
                                       bool opaque,
                                       const gfx::Rect& layer_opaque_rect,
                                       LayerImplList& surface_layer_list) {
    scoped_ptr<TiledLayerImpl> layer =
        TiledLayerImpl::Create(host_impl_.active_tree(), layer_id_++);
    scoped_ptr<LayerTilingData> tiler = LayerTilingData::Create(
        gfx::Size(100, 100), LayerTilingData::NO_BORDER_TEXELS);
    tiler->SetBounds(layer_rect.size());
    layer->SetTilingData(*tiler);
    layer->set_skips_draw(false);
    layer->SetDrawsContent(true);
    layer->draw_properties().target_space_transform = draw_transform;
    layer->draw_properties().screen_space_transform = draw_transform;
    layer->draw_properties().visible_content_rect = layer_rect;
    layer->draw_properties().opacity = opacity;
    layer->SetContentsOpaque(opaque);
    layer->SetBounds(layer_rect.size());
    layer->SetContentBounds(layer_rect.size());

    ResourceProvider::ResourceId resource_id = 1;
    for (int i = 0; i < tiler->num_tiles_x(); ++i) {
      for (int j = 0; j < tiler->num_tiles_y(); ++j) {
        gfx::Rect tile_opaque_rect =
            opaque
            ? tiler->tile_bounds(i, j)
            : gfx::IntersectRects(tiler->tile_bounds(i, j), layer_opaque_rect);
        layer->PushTileProperties(i, j, resource_id++, tile_opaque_rect, false);
      }
    }

    gfx::Rect rect_in_target = MathUtil::MapEnclosingClippedRect(
        layer->draw_transform(), layer->visible_content_rect());
    if (!parent) {
      layer->CreateRenderSurface();
      layer->render_surface()->SetContentRect(rect_in_target);
      surface_layer_list.push_back(layer.get());
      layer->render_surface()->layer_list().push_back(layer.get());
    } else {
      layer->draw_properties().render_target = parent->render_target();
      parent->render_surface()->layer_list().push_back(layer.get());
      rect_in_target.Union(MathUtil::MapEnclosingClippedRect(
          parent->draw_transform(), parent->visible_content_rect()));
      parent->render_surface()->SetContentRect(rect_in_target);
    }
    layer->draw_properties().drawable_content_rect = rect_in_target;

    return layer.Pass();
  }

  void AppendQuads(QuadList* quad_list,
                   SharedQuadStateList* shared_state_list,
                   TiledLayerImpl* layer,
                   LayerIteratorType* it,
                   OcclusionTracker<LayerImpl>* occlusion_tracker) {
    occlusion_tracker->EnterLayer(*it);
    QuadCuller quad_culler(
        quad_list, shared_state_list, layer, *occlusion_tracker, false);
    AppendQuadsData data;
    layer->AppendQuads(&quad_culler, &data);
    occlusion_tracker->LeaveLayer(*it);
    ++it;
  }

 protected:
  FakeImplProxy proxy_;
  TestSharedBitmapManager shared_bitmap_manager_;
  FakeLayerTreeHostImpl host_impl_;
  int layer_id_;

 private:
  DISALLOW_COPY_AND_ASSIGN(QuadCullerTest);
};

#define DECLARE_AND_INITIALIZE_TEST_QUADS()                                    \
  QuadList quad_list;                                                          \
  SharedQuadStateList shared_state_list;                                       \
  LayerImplList render_surface_layer_list;                                     \
  gfx::Transform child_transform;                                              \
  gfx::Size root_size = gfx::Size(300, 300);                                   \
  gfx::Rect root_rect = gfx::Rect(root_size);                                  \
  gfx::Size child_size = gfx::Size(200, 200);                                  \
  gfx::Rect child_rect = gfx::Rect(child_size);

TEST_F(QuadCullerTest, NoCulling) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     gfx::Transform(),
                                                     child_rect,
                                                     1.f,
                                                     false,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(13u, quad_list.size());
}

TEST_F(QuadCullerTest, CullChildLinesUpTopLeft) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     gfx::Transform(),
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(9u, quad_list.size());
}

TEST_F(QuadCullerTest, CullWhenChildOpacityNotOne) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     0.9f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(13u, quad_list.size());
}

TEST_F(QuadCullerTest, CullWhenChildOpaqueFlagFalse) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     false,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(13u, quad_list.size());
}

TEST_F(QuadCullerTest, CullCenterTileOnly) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(50, 50);
  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  ASSERT_EQ(quad_list.size(), 12u);

  gfx::Rect quad_visible_rect1 = quad_list[5]->visible_rect;
  EXPECT_EQ(50, quad_visible_rect1.height());

  gfx::Rect quad_visible_rect3 = quad_list[7]->visible_rect;
  EXPECT_EQ(50, quad_visible_rect3.width());

  // Next index is 8, not 9, since centre quad culled.
  gfx::Rect quad_visible_rect4 = quad_list[8]->visible_rect;
  EXPECT_EQ(50, quad_visible_rect4.width());
  EXPECT_EQ(250, quad_visible_rect4.x());

  gfx::Rect quad_visible_rect6 = quad_list[10]->visible_rect;
  EXPECT_EQ(50, quad_visible_rect6.height());
  EXPECT_EQ(250, quad_visible_rect6.y());
}

TEST_F(QuadCullerTest, CullCenterTileNonIntegralSize1) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(100, 100);

  // Make the root layer's quad have extent (99.1, 99.1) -> (200.9, 200.9) to
  // make sure it doesn't get culled due to transform rounding.
  gfx::Transform root_transform;
  root_transform.Translate(99.1f, 99.1f);
  root_transform.Scale(1.018f, 1.018f);

  root_rect = child_rect = gfx::Rect(0, 0, 100, 100);

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    root_transform,
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(2u, quad_list.size());
}

TEST_F(QuadCullerTest, CullCenterTileNonIntegralSize2) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  // Make the child's quad slightly smaller than, and centred over, the root
  // layer tile.  Verify the child does not cause the quad below to be culled
  // due to rounding.
  child_transform.Translate(100.1f, 100.1f);
  child_transform.Scale(0.982f, 0.982f);

  gfx::Transform root_transform;
  root_transform.Translate(100, 100);

  root_rect = child_rect = gfx::Rect(0, 0, 100, 100);

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    root_transform,
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(2u, quad_list.size());
}

TEST_F(QuadCullerTest, CullChildLinesUpBottomRight) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(100, 100);
  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(9u, quad_list.size());
}

TEST_F(QuadCullerTest, CullSubRegion) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(50, 50);
  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  gfx::Rect child_opaque_rect(child_rect.x() + child_rect.width() / 4,
                              child_rect.y() + child_rect.height() / 4,
                              child_rect.width() / 2,
                              child_rect.height() / 2);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     false,
                                                     child_opaque_rect,
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(12u, quad_list.size());
}

TEST_F(QuadCullerTest, CullSubRegion2) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(50, 10);
  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  gfx::Rect child_opaque_rect(child_rect.x() + child_rect.width() / 4,
                              child_rect.y() + child_rect.height() / 4,
                              child_rect.width() / 2,
                              child_rect.height() * 3 / 4);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     false,
                                                     child_opaque_rect,
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(12u, quad_list.size());
}

TEST_F(QuadCullerTest, CullSubRegionCheckOvercull) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  child_transform.Translate(50, 49);
  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  gfx::Rect child_opaque_rect(child_rect.x() + child_rect.width() / 4,
                              child_rect.y() + child_rect.height() / 4,
                              child_rect.width() / 2,
                              child_rect.height() / 2);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     false,
                                                     child_opaque_rect,
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(13u, quad_list.size());
}

TEST_F(QuadCullerTest, NonAxisAlignedQuadsDontOcclude) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  // Use a small rotation so as to not disturb the geometry significantly.
  child_transform.Rotate(1);

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    gfx::Transform(),
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     child_transform,
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(13u, quad_list.size());
}

// This test requires some explanation: here we are rotating the quads to be
// culled.  The 2x2 tile child layer remains in the top-left corner, unrotated,
// but the 3x3 tile parent layer is rotated by 1 degree. Of the four tiles the
// child would normally occlude, three will move (slightly) out from under the
// child layer, and one moves further under the child. Only this last tile
// should be culled.
TEST_F(QuadCullerTest, NonAxisAlignedQuadsSafelyCulled) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  // Use a small rotation so as to not disturb the geometry significantly.
  gfx::Transform parent_transform;
  parent_transform.Rotate(1);

  scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
                                                    parent_transform,
                                                    root_rect,
                                                    1.f,
                                                    true,
                                                    gfx::Rect(),
                                                    render_surface_layer_list);
  scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
                                                     gfx::Transform(),
                                                     child_rect,
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);
  TestOcclusionTracker<LayerImpl> occlusion_tracker(
      gfx::Rect(-100, -100, 1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  AppendQuads(&quad_list,
              &shared_state_list,
              child_layer.get(),
              &it,
              &occlusion_tracker);
  AppendQuads(&quad_list,
              &shared_state_list,
              root_layer.get(),
              &it,
              &occlusion_tracker);
  EXPECT_EQ(12u, quad_list.size());
}

TEST_F(QuadCullerTest, PartialCullingNotDestroyed) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> dummy_layer = MakeLayer(NULL,
                                                     gfx::Transform(),
                                                     gfx::Rect(),
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);

  TestOcclusionTracker<LayerImpl> occlusion_tracker(gfx::Rect(1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  QuadCuller culler(&quad_list,
                    &shared_state_list,
                    dummy_layer.get(),
                    occlusion_tracker,
                    false);

  SharedQuadState* sqs = culler.UseSharedQuadState(SharedQuadState::Create());

  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
  color_quad->SetNew(
      sqs, gfx::Rect(100, 100), gfx::Rect(100, 100), SK_ColorRED, false);

  scoped_ptr<RenderPassDrawQuad> pass_quad = RenderPassDrawQuad::Create();
  pass_quad->SetNew(sqs,
                    gfx::Rect(100, 100),
                    gfx::Rect(100, 100),
                    RenderPass::Id(10, 10),
                    false,
                    0,
                    gfx::Rect(),
                    gfx::RectF(),
                    FilterOperations(),
                    FilterOperations());

  scoped_ptr<RenderPassDrawQuad> replica_quad = RenderPassDrawQuad::Create();
  replica_quad->SetNew(sqs,
                       gfx::Rect(100, 100),
                       gfx::Rect(100, 100),
                       RenderPass::Id(10, 10),
                       true,
                       0,
                       gfx::Rect(),
                       gfx::RectF(),
                       FilterOperations(),
                       FilterOperations());

  // Set a visible rect on the quads.
  color_quad->visible_rect = gfx::Rect(20, 30, 10, 11);
  pass_quad->visible_rect = gfx::Rect(50, 60, 13, 14);
  replica_quad->visible_rect = gfx::Rect(30, 40, 15, 16);

  // Nothing is occluding.
  occlusion_tracker.EnterLayer(it);

  EXPECT_EQ(0u, quad_list.size());

  culler.MaybeAppend(color_quad.PassAs<DrawQuad>());
  culler.MaybeAppend(pass_quad.PassAs<DrawQuad>());
  culler.MaybeAppend(replica_quad.PassAs<DrawQuad>());

  ASSERT_EQ(3u, quad_list.size());

  // The partial culling is preserved.
  EXPECT_EQ(gfx::Rect(20, 30, 10, 11).ToString(),
            quad_list[0]->visible_rect.ToString());
  EXPECT_EQ(gfx::Rect(50, 60, 13, 14).ToString(),
            quad_list[1]->visible_rect.ToString());
  EXPECT_EQ(gfx::Rect(30, 40, 15, 16).ToString(),
            quad_list[2]->visible_rect.ToString());
}

TEST_F(QuadCullerTest, PartialCullingWithOcclusionNotDestroyed) {
  DECLARE_AND_INITIALIZE_TEST_QUADS();

  scoped_ptr<TiledLayerImpl> dummy_layer = MakeLayer(NULL,
                                                     gfx::Transform(),
                                                     gfx::Rect(),
                                                     1.f,
                                                     true,
                                                     gfx::Rect(),
                                                     render_surface_layer_list);

  TestOcclusionTracker<LayerImpl> occlusion_tracker(gfx::Rect(1000, 1000));
  LayerIteratorType it = LayerIteratorType::Begin(&render_surface_layer_list);

  QuadCuller culler(&quad_list,
                    &shared_state_list,
                    dummy_layer.get(),
                    occlusion_tracker,
                    false);

  SharedQuadState* sqs = culler.UseSharedQuadState(SharedQuadState::Create());

  scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
  color_quad->SetNew(
      sqs, gfx::Rect(100, 100), gfx::Rect(100, 100), SK_ColorRED, false);

  scoped_ptr<RenderPassDrawQuad> pass_quad = RenderPassDrawQuad::Create();
  pass_quad->SetNew(sqs,
                    gfx::Rect(100, 100),
                    gfx::Rect(100, 100),
                    RenderPass::Id(10, 10),
                    false,
                    0,
                    gfx::Rect(),
                    gfx::RectF(),
                    FilterOperations(),
                    FilterOperations());

  scoped_ptr<RenderPassDrawQuad> replica_quad = RenderPassDrawQuad::Create();
  replica_quad->SetNew(sqs,
                       gfx::Rect(100, 100),
                       gfx::Rect(100, 100),
                       RenderPass::Id(10, 10),
                       true,
                       0,
                       gfx::Rect(),
                       gfx::RectF(),
                       FilterOperations(),
                       FilterOperations());

  // Set a visible rect on the quads.
  color_quad->visible_rect = gfx::Rect(10, 10, 10, 11);
  pass_quad->visible_rect = gfx::Rect(10, 20, 13, 14);
  replica_quad->visible_rect = gfx::Rect(10, 30, 15, 16);

  // Occlude the left part of the visible rects.
  occlusion_tracker.EnterLayer(it);
  occlusion_tracker.set_occlusion_from_outside_target(gfx::Rect(0, 0, 15, 100));

  EXPECT_EQ(0u, quad_list.size());

  culler.MaybeAppend(color_quad.PassAs<DrawQuad>());
  culler.MaybeAppend(pass_quad.PassAs<DrawQuad>());
  culler.MaybeAppend(replica_quad.PassAs<DrawQuad>());

  ASSERT_EQ(3u, quad_list.size());

  // The partial culling is preserved, while the left side of the quads is newly
  // occluded.
  EXPECT_EQ(gfx::Rect(15, 10, 5, 11).ToString(),
            quad_list[0]->visible_rect.ToString());
  EXPECT_EQ(gfx::Rect(15, 20, 8, 14).ToString(),
            quad_list[1]->visible_rect.ToString());
  EXPECT_EQ(gfx::Rect(15, 30, 10, 16).ToString(),
            quad_list[2]->visible_rect.ToString());
}

}  // namespace
}  // namespace cc

/* [<][>][^][v][top][bottom][index][help] */