diff options
Diffstat (limited to 'cc/trees')
-rw-r--r-- | cc/trees/layer_tree_host_common.cc | 11 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 8 | ||||
-rw-r--r-- | cc/trees/layer_tree_impl.cc | 5 | ||||
-rw-r--r-- | cc/trees/occlusion_tracker.cc | 34 | ||||
-rw-r--r-- | cc/trees/occlusion_tracker_perftest.cc | 141 | ||||
-rw-r--r-- | cc/trees/occlusion_tracker_unittest.cc | 2 | ||||
-rw-r--r-- | cc/trees/quad_culler_unittest.cc | 4 |
7 files changed, 171 insertions, 34 deletions
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index b0b3b73..5e696f3 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc @@ -97,8 +97,8 @@ inline gfx::Rect CalculateVisibleRectWithCachedLayerRect( return layer_bound_rect; } - gfx::Rect layer_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - surface_to_layer, gfx::RectF(minimal_surface_rect))); + gfx::Rect layer_rect = MathUtil::ProjectEnclosingClippedRect( + surface_to_layer, minimal_surface_rect); layer_rect.Intersect(layer_bound_rect); return layer_rect; } @@ -108,7 +108,7 @@ gfx::Rect LayerTreeHostCommon::CalculateVisibleRect( const gfx::Rect& layer_bound_rect, const gfx::Transform& transform) { gfx::Rect layer_in_surface_space = - MathUtil::MapClippedRect(transform, layer_bound_rect); + MathUtil::MapEnclosingClippedRect(transform, layer_bound_rect); return CalculateVisibleRectWithCachedLayerRect( target_surface_rect, layer_bound_rect, layer_in_surface_space, transform); } @@ -1739,9 +1739,8 @@ static void CalculateDrawPropertiesInternal( // here, or DCHECK that the transform is invertible. } - gfx::Rect projected_surface_rect = gfx::ToEnclosingRect( - MathUtil::ProjectClippedRect(inverse_surface_draw_transform, - ancestor_clip_rect_in_target_space)); + gfx::Rect projected_surface_rect = MathUtil::ProjectEnclosingClippedRect( + inverse_surface_draw_transform, ancestor_clip_rect_in_target_space); if (layer_draw_properties.num_unclipped_descendants > 0) { // If we have unclipped descendants, we cannot count on the render diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 84d9f89..9939822 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -665,8 +665,8 @@ static void AppendQuadsToFillScreen( fill_rects.next()) { // The root layer transform is composed of translations and scales only, // no perspective, so mapping is sufficient (as opposed to projecting). - gfx::Rect layer_rect = - MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect()); + gfx::Rect layer_rect = MathUtil::MapEnclosingClippedRect( + transform_to_layer_space, fill_rects.rect()); // Skip the quad culler and just append the quads directly to avoid // occlusion checks. scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); @@ -678,8 +678,8 @@ static void AppendQuadsToFillScreen( fill_rects.has_rect(); fill_rects.next()) { DCHECK(overhang_resource_id); - gfx::Rect layer_rect = - MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect()); + gfx::Rect layer_rect = MathUtil::MapEnclosingClippedRect( + transform_to_layer_space, fill_rects.rect()); scoped_ptr<TextureDrawQuad> tex_quad = TextureDrawQuad::Create(); const float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f}; tex_quad->SetNew( diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 309939d..99129ee 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -360,9 +360,8 @@ gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const { if (!root_scroll_layer || root_scroll_layer->children().empty()) return gfx::Rect(); LayerImpl* layer = root_scroll_layer->children()[0]; - return MathUtil::MapClippedRect( - layer->screen_space_transform(), - gfx::Rect(layer->content_bounds())); + return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(), + gfx::Rect(layer->content_bounds())); } static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) { diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index c7fc06d..11982a8 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc @@ -62,8 +62,8 @@ static gfx::Rect ScreenSpaceClipRectInTargetSurface( &inverse_screen_space_transform)) return target_surface->content_rect(); - return gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( - inverse_screen_space_transform, screen_space_clip_rect)); + return MathUtil::ProjectEnclosingClippedRect(inverse_screen_space_transform, + screen_space_clip_rect); } template <typename RenderSurfaceType> @@ -248,8 +248,8 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, if (surface_rect.IsEmpty()) return; - gfx::Rect affected_area_in_target = gfx::ToEnclosingRect( - MathUtil::MapClippedRect(surface_transform, gfx::RectF(surface_rect))); + gfx::Rect affected_area_in_target = + MathUtil::MapEnclosingClippedRect(surface_transform, surface_rect); if (contributing_layer->render_surface()->is_clipped()) { affected_area_in_target.Intersect( contributing_layer->render_surface()->clip_rect()); @@ -529,8 +529,8 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded( // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( - MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); + Region unoccluded_region_in_target_surface = + MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); unoccluded_region_in_target_surface.Subtract( stack_.back().occlusion_from_inside_target); gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = @@ -578,18 +578,17 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>:: // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( - MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); + Region unoccluded_region_in_target_surface = + MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); unoccluded_region_in_target_surface.Subtract( stack_.back().occlusion_from_inside_target); unoccluded_region_in_target_surface.Subtract( stack_.back().occlusion_from_outside_target); - gfx::RectF unoccluded_rect_in_target_surface = + gfx::Rect unoccluded_rect_in_target_surface = unoccluded_region_in_target_surface.bounds(); - gfx::Rect unoccluded_rect = gfx::ToEnclosingRect( - MathUtil::ProjectClippedRect(inverse_draw_transform, - unoccluded_rect_in_target_surface)); + gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( + inverse_draw_transform, unoccluded_rect_in_target_surface); unoccluded_rect.Intersect(content_rect); return unoccluded_rect; @@ -636,8 +635,8 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>:: // Take the ToEnclosingRect at each step, as we want to contain any unoccluded // partial pixels in the resulting Rect. - Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( - MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); + Region unoccluded_region_in_target_surface = + MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); // Layers can't clip across surfaces, so count this as internal occlusion. if (surface->is_clipped()) unoccluded_region_in_target_surface.Intersect(surface->clip_rect()); @@ -657,11 +656,10 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>:: contributing_surface_render_target->render_surface(), screen_space_clip_rect_)); - gfx::RectF unoccluded_rect_in_target_surface = + gfx::Rect unoccluded_rect_in_target_surface = unoccluded_region_in_target_surface.bounds(); - gfx::Rect unoccluded_rect = gfx::ToEnclosingRect( - MathUtil::ProjectClippedRect(inverse_draw_transform, - unoccluded_rect_in_target_surface)); + gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( + inverse_draw_transform, unoccluded_rect_in_target_surface); unoccluded_rect.Intersect(content_rect); return unoccluded_rect; diff --git a/cc/trees/occlusion_tracker_perftest.cc b/cc/trees/occlusion_tracker_perftest.cc new file mode 100644 index 0000000..32b85a4 --- /dev/null +++ b/cc/trees/occlusion_tracker_perftest.cc @@ -0,0 +1,141 @@ +// Copyright 2014 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/occlusion_tracker.h" + +#include "base/time/time.h" +#include "cc/layers/layer_iterator.h" +#include "cc/layers/solid_color_layer_impl.h" +#include "cc/test/fake_layer_tree_host_impl_client.h" +#include "cc/test/fake_output_surface.h" +#include "cc/test/fake_proxy.h" +#include "cc/test/fake_rendering_stats_instrumentation.h" +#include "cc/test/lap_timer.h" +#include "cc/trees/layer_tree_host_impl.h" +#include "cc/trees/layer_tree_impl.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace cc { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kWarmupRuns = 5; +static const int kTimeCheckInterval = 10; + +class OcclusionTrackerPerfTest : public testing::Test { + public: + OcclusionTrackerPerfTest() + : timer_(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval) {} + void CreateHost() { + LayerTreeSettings settings; + host_impl_ = LayerTreeHostImpl::Create( + settings, &client_, &proxy_, &stats_, NULL, 1); + host_impl_->InitializeRenderer( + FakeOutputSurface::Create3d().PassAs<OutputSurface>()); + + scoped_ptr<LayerImpl> root_layer = LayerImpl::Create(active_tree(), 1); + active_tree()->SetRootLayer(root_layer.Pass()); + } + + LayerTreeImpl* active_tree() { return host_impl_->active_tree(); } + + void SetTestName(const std::string& name) { test_name_ = name; } + + void PrintResults() { + CHECK(!test_name_.empty()) << "Must SetTestName() before AfterTest()."; + perf_test::PrintResult("occlusion_tracker_time", + "", + test_name_, + 1000 * timer_.MsPerLap(), + "us", + true); + } + + protected: + LapTimer timer_; + std::string test_name_; + FakeLayerTreeHostImplClient client_; + FakeProxy proxy_; + FakeRenderingStatsInstrumentation stats_; + scoped_ptr<LayerTreeHostImpl> host_impl_; +}; + +// Simulates a page with several large, transformed and animated layers. +TEST_F(OcclusionTrackerPerfTest, UnoccludedContentRect_FullyOccluded) { + SetTestName("unoccluded_content_rect_fully_occluded"); + + gfx::Rect viewport_rect(768, 1038); + OcclusionTrackerBase<LayerImpl, LayerImpl::RenderSurfaceType> tracker( + viewport_rect, false); + + CreateHost(); + host_impl_->SetViewportSize(viewport_rect.size()); + + scoped_ptr<SolidColorLayerImpl> opaque_layer = + SolidColorLayerImpl::Create(active_tree(), 2); + opaque_layer->SetBackgroundColor(SK_ColorRED); + opaque_layer->SetContentsOpaque(true); + opaque_layer->SetDrawsContent(true); + opaque_layer->SetBounds(viewport_rect.size()); + opaque_layer->SetContentBounds(viewport_rect.size()); + active_tree()->root_layer()->AddChild(opaque_layer.PassAs<LayerImpl>()); + + active_tree()->UpdateDrawProperties(); + const LayerImplList& rsll = active_tree()->RenderSurfaceLayerList(); + ASSERT_EQ(1u, rsll.size()); + EXPECT_EQ(1u, rsll[0]->render_surface()->layer_list().size()); + + typedef LayerIterator<LayerImpl, + LayerImpl::LayerListType, + LayerImpl::RenderSurfaceType, + LayerIteratorActions::FrontToBack> IteratorType; + IteratorType begin = IteratorType::Begin(&rsll); + IteratorType end = IteratorType::End(&rsll); + + LayerIteratorPosition<LayerImpl> pos = begin; + + // The opaque_layer adds occlusion over the whole viewport. + tracker.EnterLayer(pos); + tracker.LeaveLayer(pos); + + gfx::Transform transform_to_target; + transform_to_target.Translate(0, 96); + bool impl_draw_transform_is_unknown = false; + + do { + for (int x = 0; x < viewport_rect.width(); x += 256) { + for (int y = 0; y < viewport_rect.height(); y += 256) { + gfx::Rect query_content_rect(x, y, 256, 256); + gfx::Rect unoccluded = + tracker.UnoccludedContentRect(pos.target_render_surface_layer, + query_content_rect, + transform_to_target, + impl_draw_transform_is_unknown); + // Sanity test that we're not hitting early outs. + bool expect_empty = + query_content_rect.right() <= viewport_rect.width() && + query_content_rect.bottom() + 96 <= viewport_rect.height(); + CHECK_EQ(expect_empty, unoccluded.IsEmpty()) + << query_content_rect.ToString(); + } + } + + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + ++begin; + LayerIteratorPosition<LayerImpl> next = begin; + EXPECT_EQ(active_tree()->root_layer(), next.current_layer); + + ++begin; + EXPECT_EQ(end, begin); + + PrintResults(); +} + +} // namespace +} // namespace cc diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc index 59261f3..c6322db 100644 --- a/cc/trees/occlusion_tracker_unittest.cc +++ b/cc/trees/occlusion_tracker_unittest.cc @@ -1172,7 +1172,7 @@ class OcclusionTrackerTestSurfaceRotatedOffAxis typename Types::RenderSurfaceType> occlusion( gfx::Rect(0, 0, 1000, 1000)); - gfx::Rect clipped_layer_in_child = MathUtil::MapClippedRect( + gfx::Rect clipped_layer_in_child = MathUtil::MapEnclosingClippedRect( layer_transform, layer->visible_content_rect()); this->VisitLayer(layer, &occlusion); diff --git a/cc/trees/quad_culler_unittest.cc b/cc/trees/quad_culler_unittest.cc index 880035a..9a5b562 100644 --- a/cc/trees/quad_culler_unittest.cc +++ b/cc/trees/quad_culler_unittest.cc @@ -84,7 +84,7 @@ class QuadCullerTest : public testing::Test { } } - gfx::Rect rect_in_target = MathUtil::MapClippedRect( + gfx::Rect rect_in_target = MathUtil::MapEnclosingClippedRect( layer->draw_transform(), layer->visible_content_rect()); if (!parent) { layer->CreateRenderSurface(); @@ -94,7 +94,7 @@ class QuadCullerTest : public testing::Test { } else { layer->draw_properties().render_target = parent->render_target(); parent->render_surface()->layer_list().push_back(layer.get()); - rect_in_target.Union(MathUtil::MapClippedRect( + rect_in_target.Union(MathUtil::MapEnclosingClippedRect( parent->draw_transform(), parent->visible_content_rect())); parent->render_surface()->SetContentRect(rect_in_target); } |