Skip to content

Commit

Permalink
cc: Add layer raster tile iterator
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vmpstr@chromium.org committed Mar 20, 2014
1 parent a5f6ce5 commit 10f1b3a
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 3 deletions.
1 change: 1 addition & 0 deletions cc/cc_tests.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
104 changes: 104 additions & 0 deletions cc/layers/picture_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
30 changes: 30 additions & 0 deletions cc/layers/picture_layer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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);
Expand Down
132 changes: 132 additions & 0 deletions cc/layers/picture_layer_impl_perftest.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 10f1b3a

Please sign in to comment.