blob: ea64287236c2b8edd83753f6da1574b9dbfc3aba [file] [log] [blame]
// 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/debug/overdraw_metrics.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/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/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 {
class TestOcclusionTrackerImpl : public OcclusionTrackerImpl {
public:
TestOcclusionTrackerImpl(gfx::Rect scissor_rect_in_screen,
bool record_metrics_for_frame = true)
: OcclusionTrackerImpl(scissor_rect_in_screen, record_metrics_for_frame),
scissor_rect_in_screen_(scissor_rect_in_screen) {}
protected:
virtual gfx::Rect LayerScissorRectInTargetSurface(
const LayerImpl* layer) const {
return scissor_rect_in_screen_;
}
private:
gfx::Rect scissor_rect_in_screen_;
DISALLOW_COPY_AND_ASSIGN(TestOcclusionTrackerImpl);
};
typedef LayerIterator<LayerImpl,
LayerImplList,
RenderSurfaceImpl,
LayerIteratorActions::FrontToBack> LayerIteratorType;
class QuadCullerTest : public testing::Test {
public:
QuadCullerTest()
: host_impl_(&proxy_),
layer_id_(1) {}
scoped_ptr<TiledLayerImpl> MakeLayer(
TiledLayerImpl* parent,
const gfx::Transform& draw_transform,
gfx::Rect layer_rect,
float opacity,
bool opaque,
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->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::MapClippedRect(
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::MapClippedRect(
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,
OcclusionTrackerImpl* occlusion_tracker) {
occlusion_tracker->EnterLayer(*it, false);
QuadCuller quad_culler(
quad_list, shared_state_list, layer, *occlusion_tracker, false, false);
AppendQuadsData data;
layer->AppendQuads(&quad_culler, &data);
occlusion_tracker->LeaveLayer(*it);
++it;
}
protected:
FakeImplProxy proxy_;
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, VerifyNoCulling) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
false,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 13u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
40000,
1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
TEST_F(QuadCullerTest, VerifyCullChildLinesUpTopLeft) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 9u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
40000,
1);
}
TEST_F(QuadCullerTest, VerifyCullWhenChildOpacityNotOne) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
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);
TestOcclusionTrackerImpl 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(quad_list.size(), 13u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
40000,
1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
TEST_F(QuadCullerTest, VerifyCullWhenChildOpaqueFlagFalse) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
false,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 13u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
40000,
1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
TEST_F(QuadCullerTest, VerifyCullCenterTileOnly) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 50);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_visible_rect1.height(), 50);
gfx::Rect quad_visible_rect3 = quad_list[7]->visible_rect;
EXPECT_EQ(quad_visible_rect3.width(), 50);
// Next index is 8, not 9, since centre quad culled.
gfx::Rect quad_visible_rect4 = quad_list[8]->visible_rect;
EXPECT_EQ(quad_visible_rect4.width(), 50);
EXPECT_EQ(quad_visible_rect4.x(), 250);
gfx::Rect quad_visible_rect6 = quad_list[10]->visible_rect;
EXPECT_EQ(quad_visible_rect6.height(), 50);
EXPECT_EQ(quad_visible_rect6.y(), 250);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 100000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
30000,
1);
}
TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize1) {
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,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 2u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 20363, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
TEST_F(QuadCullerTest, VerifyCullCenterTileNonIntegralSize2) {
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,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 2u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 19643, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
TEST_F(QuadCullerTest, VerifyCullChildLinesUpBottomRight) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(100, 100);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 9u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
40000,
1);
}
TEST_F(QuadCullerTest, VerifyCullSubRegion) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 50);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
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,
false,
child_opaque_rect,
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 12u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
30000,
1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
10000,
1);
}
TEST_F(QuadCullerTest, VerifyCullSubRegion2) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 10);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
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,
false,
child_opaque_rect,
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 12u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
25000,
1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
15000,
1);
}
TEST_F(QuadCullerTest, VerifyCullSubRegionCheckOvercull) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
child_transform.Translate(50, 49);
scoped_ptr<TiledLayerImpl> root_layer = MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
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,
false,
child_opaque_rect,
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 13u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 90000, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(),
30000,
1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
10000,
1);
}
TEST_F(QuadCullerTest, VerifyNonAxisAlignedQuadsDontOcclude) {
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,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
child_transform,
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 13u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 130000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
// 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, VerifyNonAxisAlignedQuadsSafelyCulled) {
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,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl 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(quad_list.size(), 12u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 100600, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
29400,
1);
}
TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverTile) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(200, 100, 100, 100));
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(quad_list.size(), 1u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 10000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
120000,
1);
}
TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverCulledTile) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(100, 100, 100, 100));
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(quad_list.size(), 1u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 10000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
120000,
1);
}
TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverPartialTiles) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(50, 50, 200, 200));
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(quad_list.size(), 9u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 40000, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
90000,
1);
}
TEST_F(QuadCullerTest, VerifyCullOutsideScissorOverNoTiles) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(500, 500, 100, 100));
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(quad_list.size(), 0u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(),
130000,
1);
}
TEST_F(QuadCullerTest, VerifyWithoutMetrics) {
DECLARE_AND_INITIALIZE_TEST_QUADS();
scoped_ptr<TiledLayerImpl> root_layer =
MakeLayer(NULL,
gfx::Transform(),
root_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
scoped_ptr<TiledLayerImpl> child_layer = MakeLayer(root_layer.get(),
gfx::Transform(),
child_rect,
1,
true,
gfx::Rect(),
render_surface_layer_list);
TestOcclusionTrackerImpl occlusion_tracker(gfx::Rect(50, 50, 200, 200),
false);
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(quad_list.size(), 9u);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_opaque(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_drawn_translucent(), 0, 1);
EXPECT_NEAR(
occlusion_tracker.overdraw_metrics()->pixels_culled_for_drawing(), 0, 1);
}
} // namespace
} // namespace cc