diff options
author | vmpstr@chromium.org <vmpstr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-20 22:23:22 +0000 |
---|---|---|
committer | vmpstr@chromium.org <vmpstr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-20 22:23:22 +0000 |
commit | 10f1b3a61e6a5cb41ea442c4922eb896622d35d9 (patch) | |
tree | 19a0b0e643d1b2276eec106e0c3e5d07d6c2a3a5 | |
parent | a5f6ce57a82c294c66ea1afc90dac65e6afe8e42 (diff) | |
download | chromium_src-10f1b3a61e6a5cb41ea442c4922eb896622d35d9.zip chromium_src-10f1b3a61e6a5cb41ea442c4922eb896622d35d9.tar.gz chromium_src-10f1b3a61e6a5cb41ea442c4922eb896622d35d9.tar.bz2 |
cc: Add layer raster tile iterator
This patch continues to build on top of tiling
raster tile iterators and introduces a layer
raster tile iterator that uses the tiling one.
Comes with a unittest and a perftest. The next
step after this should be a raster iterator
in the tile manager
R=enne@chromium.org
Review URL: https://codereview.chromium.org/195583002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258437 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/cc_tests.gyp | 1 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.cc | 104 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl.h | 30 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_perftest.cc | 132 | ||||
-rw-r--r-- | cc/layers/picture_layer_impl_unittest.cc | 94 | ||||
-rw-r--r-- | cc/resources/picture_layer_tiling.h | 3 |
6 files changed, 361 insertions, 3 deletions
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index ed55846..73e4a06 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -300,6 +300,7 @@ ], 'sources': [ 'layers/layer_perftest.cc', + 'layers/picture_layer_impl_perftest.cc', 'resources/picture_layer_tiling_perftest.cc', 'resources/raster_worker_pool_perftest.cc', 'resources/task_graph_runner_perftest.cc', diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index a0fd950..c85e0c5 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc @@ -1273,4 +1273,108 @@ bool PictureLayerImpl::IsOnActiveOrPendingTree() const { return !layer_tree_impl()->IsRecycleTree(); } +PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator() + : layer_(NULL) {} + +PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator( + PictureLayerImpl* layer, + bool prioritize_low_res) + : layer_(layer), current_stage_(0) { + DCHECK(layer_); + if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) + return; + + WhichTree tree = + layer_->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; + + // Find high and low res tilings and initialize the iterators. + for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) { + PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); + if (tiling->resolution() == HIGH_RESOLUTION) { + iterators_[HIGH_RES] = + PictureLayerTiling::TilingRasterTileIterator(tiling, tree); + } + + if (tiling->resolution() == LOW_RESOLUTION) { + iterators_[LOW_RES] = + PictureLayerTiling::TilingRasterTileIterator(tiling, tree); + } + } + + if (prioritize_low_res) { + stages_[0].iterator_type = LOW_RES; + stages_[0].tile_type = + PictureLayerTiling::TilingRasterTileIterator::VISIBLE; + + stages_[1].iterator_type = HIGH_RES; + stages_[1].tile_type = + PictureLayerTiling::TilingRasterTileIterator::VISIBLE; + } else { + stages_[0].iterator_type = HIGH_RES; + stages_[0].tile_type = + PictureLayerTiling::TilingRasterTileIterator::VISIBLE; + + stages_[1].iterator_type = LOW_RES; + stages_[1].tile_type = + PictureLayerTiling::TilingRasterTileIterator::VISIBLE; + } + + stages_[2].iterator_type = HIGH_RES; + stages_[2].tile_type = PictureLayerTiling::TilingRasterTileIterator::SKEWPORT; + + stages_[3].iterator_type = HIGH_RES; + stages_[3].tile_type = + PictureLayerTiling::TilingRasterTileIterator::EVENTUALLY; + + IteratorType index = stages_[current_stage_].iterator_type; + PictureLayerTiling::TilingRasterTileIterator::Type tile_type = + stages_[current_stage_].tile_type; + if (!iterators_[index] || iterators_[index].get_type() != tile_type) + ++(*this); +} + +PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {} + +PictureLayerImpl::LayerRasterTileIterator::operator bool() const { + return layer_ && static_cast<size_t>(current_stage_) < arraysize(stages_); +} + +PictureLayerImpl::LayerRasterTileIterator& +PictureLayerImpl::LayerRasterTileIterator:: +operator++() { + IteratorType index = stages_[current_stage_].iterator_type; + PictureLayerTiling::TilingRasterTileIterator::Type tile_type = + stages_[current_stage_].tile_type; + + // First advance the iterator. + if (iterators_[index]) + ++iterators_[index]; + + if (iterators_[index] && iterators_[index].get_type() == tile_type) + return *this; + + // Next, advance the stage. + int stage_count = arraysize(stages_); + ++current_stage_; + while (current_stage_ < stage_count) { + index = stages_[current_stage_].iterator_type; + tile_type = stages_[current_stage_].tile_type; + + if (iterators_[index] && iterators_[index].get_type() == tile_type) + break; + ++current_stage_; + } + return *this; +} + +Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() { + DCHECK(*this); + + IteratorType index = stages_[current_stage_].iterator_type; + DCHECK(iterators_[index]); + DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type); + + return *iterators_[index]; +} + } // namespace cc diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index 00c2066..4b997fa 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h @@ -22,11 +22,39 @@ namespace cc { struct AppendQuadsData; class QuadSink; class MicroBenchmarkImpl; +class Tile; class CC_EXPORT PictureLayerImpl : public LayerImpl, NON_EXPORTED_BASE(public PictureLayerTilingClient) { public: + class CC_EXPORT LayerRasterTileIterator { + public: + LayerRasterTileIterator(); + LayerRasterTileIterator(PictureLayerImpl* layer, bool prioritize_low_res); + ~LayerRasterTileIterator(); + + Tile* operator*(); + LayerRasterTileIterator& operator++(); + operator bool() const; + + private: + enum IteratorType { LOW_RES, HIGH_RES, NUM_ITERATORS }; + + PictureLayerImpl* layer_; + + struct IterationStage { + IteratorType iterator_type; + PictureLayerTiling::TilingRasterTileIterator::Type tile_type; + }; + + int current_stage_; + + // One low res stage, and three high res stages. + IterationStage stages_[4]; + PictureLayerTiling::TilingRasterTileIterator iterators_[NUM_ITERATORS]; + }; + static scoped_ptr<PictureLayerImpl> Create(LayerTreeImpl* tree_impl, int id) { return make_scoped_ptr(new PictureLayerImpl(tree_impl, id)); } @@ -87,6 +115,8 @@ class CC_EXPORT PictureLayerImpl bool IsOnActiveOrPendingTree() const; protected: + friend class LayerRasterTileIterator; + PictureLayerImpl(LayerTreeImpl* tree_impl, int id); PictureLayerTiling* AddTiling(float contents_scale); void RemoveTiling(float contents_scale); diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc new file mode 100644 index 0000000..5279c92 --- /dev/null +++ b/cc/layers/picture_layer_impl_perftest.cc @@ -0,0 +1,132 @@ +// 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/layers/picture_layer_impl.h" + +#include "cc/test/fake_impl_proxy.h" +#include "cc/test/fake_layer_tree_host_impl.h" +#include "cc/test/fake_output_surface.h" +#include "cc/test/fake_picture_layer_impl.h" +#include "cc/test/fake_picture_pile_impl.h" +#include "cc/test/impl_side_painting_settings.h" +#include "cc/test/test_shared_bitmap_manager.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 PictureLayerImplPerfTest : public testing::Test { + public: + PictureLayerImplPerfTest() + : num_runs_(0), + proxy_(base::MessageLoopProxy::current()), + host_impl_(ImplSidePaintingSettings(), + &proxy_, + &shared_bitmap_manager_) {} + + virtual void SetUp() OVERRIDE { + host_impl_.InitializeRenderer( + FakeOutputSurface::Create3d().PassAs<OutputSurface>()); + } + + void SetupPendingTree(const gfx::Size& layer_bounds, + const gfx::Size& tile_size) { + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + host_impl_.CreatePendingTree(); + LayerTreeImpl* pending_tree = host_impl_.pending_tree(); + pending_tree->DetachLayerTree(); + + scoped_ptr<FakePictureLayerImpl> pending_layer = + FakePictureLayerImpl::CreateWithPile(pending_tree, 7, pile); + pending_layer->SetDrawsContent(true); + pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>()); + + pending_layer_ = static_cast<FakePictureLayerImpl*>( + host_impl_.pending_tree()->LayerById(7)); + pending_layer_->DoPostCommitInitializationIfNeeded(); + } + + void EndTest() { elapsed_ = base::TimeTicks::HighResNow() - start_time_; } + + bool DidRun() { + ++num_runs_; + if (num_runs_ == kWarmupRuns) + start_time_ = base::TimeTicks::HighResNow(); + + if (!start_time_.is_null() && (num_runs_ % kTimeCheckInterval) == 0) { + base::TimeDelta elapsed = base::TimeTicks::HighResNow() - start_time_; + if (elapsed >= base::TimeDelta::FromMilliseconds(kTimeLimitMillis)) { + elapsed_ = elapsed; + return false; + } + } + return true; + } + + void RunLayerRasterTileIteratorTest(const std::string& test_name, + int num_tiles, + const gfx::Size& viewport_size) { + start_time_ = base::TimeTicks(); + num_runs_ = 0; + + host_impl_.SetViewportSize(viewport_size); + host_impl_.pending_tree()->UpdateDrawProperties(); + + do { + int count = num_tiles; + for (PictureLayerImpl::LayerRasterTileIterator it(pending_layer_, false); + it && count; + ++it) { + --count; + } + } while (DidRun()); + + perf_test::PrintResult("layer_raster_tile_iterator", + "", + test_name, + num_runs_ / elapsed_.InSecondsF(), + "runs/s", + true); + } + + protected: + base::TimeTicks start_time_; + base::TimeDelta elapsed_; + int num_runs_; + + TestSharedBitmapManager shared_bitmap_manager_; + FakeImplProxy proxy_; + FakeLayerTreeHostImpl host_impl_; + FakePictureLayerImpl* pending_layer_; + + private: + DISALLOW_COPY_AND_ASSIGN(PictureLayerImplPerfTest); +}; + +TEST_F(PictureLayerImplPerfTest, LayerRasterTileIterator) { + SetupPendingTree(gfx::Size(10000, 10000), gfx::Size(256, 256)); + + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + + pending_layer_->AddTiling(low_res_factor); + pending_layer_->AddTiling(0.3f); + pending_layer_->AddTiling(0.7f); + pending_layer_->AddTiling(1.0f); + pending_layer_->AddTiling(2.0f); + + RunLayerRasterTileIteratorTest("32_100x100", 32, gfx::Size(100, 100)); + RunLayerRasterTileIteratorTest("32_500x500", 32, gfx::Size(500, 500)); + RunLayerRasterTileIteratorTest("64_100x100", 64, gfx::Size(100, 100)); + RunLayerRasterTileIteratorTest("64_500x500", 64, gfx::Size(500, 500)); +} + +} // namespace +} // namespace cc diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 1fa309b..c606be4 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc @@ -4,6 +4,7 @@ #include "cc/layers/picture_layer_impl.h" +#include <set> #include <utility> #include "cc/layers/append_quads_data.h" @@ -1690,5 +1691,98 @@ TEST_F(GpuRasterizationPictureLayerImplTest, Tiling) { ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings()); } +TEST_F(PictureLayerImplTest, LayerRasterTileIterator) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1000, 1000); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupPendingTree(pending_pile); + + ASSERT_TRUE(pending_layer_->CanHaveTilings()); + + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + + pending_layer_->AddTiling(low_res_factor); + pending_layer_->AddTiling(0.3f); + pending_layer_->AddTiling(0.7f); + PictureLayerTiling* high_res_tiling = pending_layer_->AddTiling(1.0f); + pending_layer_->AddTiling(2.0f); + + host_impl_.SetViewportSize(gfx::Size(500, 500)); + host_impl_.pending_tree()->UpdateDrawProperties(); + + PictureLayerImpl::LayerRasterTileIterator it; + EXPECT_FALSE(it); + + std::set<Tile*> unique_tiles; + bool reached_prepaint = false; + size_t non_ideal_tile_count = 0u; + size_t low_res_tile_count = 0u; + size_t high_res_tile_count = 0u; + for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false); + it; + ++it) { + Tile* tile = *it; + TilePriority priority = tile->priority(PENDING_TREE); + + EXPECT_TRUE(tile); + + // Non-high res tiles only get visible tiles. Also, prepaint should only + // come at the end of the iteration. + if (priority.resolution != HIGH_RESOLUTION) + EXPECT_EQ(TilePriority::NOW, priority.priority_bin); + else if (reached_prepaint) + EXPECT_NE(TilePriority::NOW, priority.priority_bin); + else + reached_prepaint = priority.priority_bin != TilePriority::NOW; + + non_ideal_tile_count += priority.resolution == NON_IDEAL_RESOLUTION; + low_res_tile_count += priority.resolution == LOW_RESOLUTION; + high_res_tile_count += priority.resolution == HIGH_RESOLUTION; + + unique_tiles.insert(tile); + } + + EXPECT_TRUE(reached_prepaint); + EXPECT_EQ(0u, non_ideal_tile_count); + EXPECT_EQ(1u, low_res_tile_count); + EXPECT_EQ(16u, high_res_tile_count); + EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count, + unique_tiles.size()); + + std::vector<Tile*> high_res_tiles = high_res_tiling->AllTilesForTesting(); + for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin(); + tile_it != high_res_tiles.end(); + ++tile_it) { + Tile* tile = *tile_it; + ManagedTileState::TileVersion& tile_version = + tile->GetTileVersionForTesting( + tile->DetermineRasterModeForTree(ACTIVE_TREE)); + tile_version.SetSolidColorForTesting(SK_ColorRED); + } + + non_ideal_tile_count = 0; + low_res_tile_count = 0; + high_res_tile_count = 0; + for (it = PictureLayerImpl::LayerRasterTileIterator(pending_layer_, false); + it; + ++it) { + Tile* tile = *it; + TilePriority priority = tile->priority(PENDING_TREE); + + EXPECT_TRUE(tile); + + non_ideal_tile_count += priority.resolution == NON_IDEAL_RESOLUTION; + low_res_tile_count += priority.resolution == LOW_RESOLUTION; + high_res_tile_count += priority.resolution == HIGH_RESOLUTION; + } + + EXPECT_EQ(0u, non_ideal_tile_count); + EXPECT_EQ(1u, low_res_tile_count); + EXPECT_EQ(0u, high_res_tile_count); +} + } // namespace } // namespace cc diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h index e79aa00..d27d39a 100644 --- a/cc/resources/picture_layer_tiling.h +++ b/cc/resources/picture_layer_tiling.h @@ -78,8 +78,6 @@ class CC_EXPORT PictureLayerTiling { return tile->NeedsRasterForMode(mode); }; - void UpdateCurrentTilePriority(); - PictureLayerTiling* tiling_; Type type_; @@ -89,7 +87,6 @@ class CC_EXPORT PictureLayerTiling { WhichTree tree_; Tile* current_tile_; - bool current_tile_priority_updated_; TilingData::Iterator visible_iterator_; TilingData::SpiralDifferenceIterator spiral_iterator_; }; |