summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-21 19:15:27 +0000
committerenne@chromium.org <enne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-21 19:15:27 +0000
commitcd696271b3c491f2de0109e4dc6d991884f89540 (patch)
tree9425a004275595dd0d354b730cf47d58e24d6b93 /cc
parent6c99c7bc949fc15b559793467fc1e1a6df857372 (diff)
downloadchromium_src-cd696271b3c491f2de0109e4dc6d991884f89540.zip
chromium_src-cd696271b3c491f2de0109e4dc6d991884f89540.tar.gz
chromium_src-cd696271b3c491f2de0109e4dc6d991884f89540.tar.bz2
cc: Add PictureLayerTilingSet to manage PictureLayerTiling
PictureLayerTilingSet has multiple tilings at different content scales. This should abstract managing the tilings from PictureLayerImpl. The layer can then ask the set to fill in a given (integer) rect at a given content scale and then get back the set of tiles/rects/texture coordinates to generate that set. Using an integer rect allows textures at different contents scales to fill a piece of geometry without cracks. R=nduca@chromium.org BUG=155209 Review URL: https://chromiumcodereview.appspot.com/11417111 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169083 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp5
-rw-r--r--cc/picture_layer.cc7
-rw-r--r--cc/picture_layer.h1
-rw-r--r--cc/picture_layer_impl.cc38
-rw-r--r--cc/picture_layer_impl.h3
-rw-r--r--cc/picture_layer_tiling.cc217
-rw-r--r--cc/picture_layer_tiling.h42
-rw-r--r--cc/picture_layer_tiling_set.cc157
-rw-r--r--cc/picture_layer_tiling_set.h76
-rw-r--r--cc/picture_layer_tiling_set_unittest.cc44
-rw-r--r--cc/picture_layer_tiling_unittest.cc121
-rw-r--r--cc/region.cc3
-rw-r--r--cc/region.h1
-rw-r--r--cc/scoped_ptr_vector.h4
-rw-r--r--cc/test/fake_picture_layer_tiling_client.cc30
-rw-r--r--cc/test/fake_picture_layer_tiling_client.h38
-rw-r--r--cc/test/fake_tile_manager_client.h22
-rw-r--r--cc/tile.h2
-rw-r--r--cc/tile_manager.cc2
-rw-r--r--cc/tile_manager.h6
21 files changed, 709 insertions, 112 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 126f0c9..071b207 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -120,6 +120,8 @@
'picture_layer_impl.h',
'picture_layer_tiling.cc',
'picture_layer_tiling.h',
+ 'picture_layer_tiling_set.cc',
+ 'picture_layer_tiling_set.h',
'picture_pile.cc',
'picture_pile.h',
'platform_color.h',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index e3c52b7..254ad3c 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -32,6 +32,8 @@
'nine_patch_layer_impl_unittest.cc',
'nine_patch_layer_unittest.cc',
'occlusion_tracker_unittest.cc',
+ 'picture_layer_tiling_set_unittest.cc',
+ 'picture_layer_tiling_unittest.cc',
'prioritized_resource_unittest.cc',
'quad_culler_unittest.cc',
'region_unittest.cc',
@@ -65,8 +67,11 @@
'test/fake_graphics_context_3d_unittest.cc',
'test/fake_layer_tree_host_client.cc',
'test/fake_layer_tree_host_client.h',
+ 'test/fake_picture_layer_tiling_client.cc',
+ 'test/fake_picture_layer_tiling_client.h',
'test/fake_proxy.cc',
'test/fake_proxy.h',
+ 'test/fake_tile_manager_client.h',
'test/fake_web_compositor_output_surface.h',
'test/fake_web_compositor_software_output_device.h',
'test/fake_web_graphics_context_3d.h',
diff --git a/cc/picture_layer.cc b/cc/picture_layer.cc
index 01eb454..fe93950 100644
--- a/cc/picture_layer.cc
+++ b/cc/picture_layer.cc
@@ -31,13 +31,14 @@ void PictureLayer::pushPropertiesTo(LayerImpl* base_layer) {
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
pile_.PushPropertiesTo(layer_impl->pile_);
- // TODO(enne): Need to sync tiling from active tree prior to this?
- // TODO(nduca): Need to invalidate tiles here from pile's invalidation info.
+ // TODO(enne): Need to sync tiling from active tree prior to this.
+ layer_impl->tilings_.Invalidate(invalidation_);
+ invalidation_.Clear();
}
void PictureLayer::setNeedsDisplayRect(const gfx::RectF& layer_rect) {
gfx::Rect rect = gfx::ToEnclosedRect(layer_rect);
- pile_.Invalidate(rect);
+ invalidation_.Union(rect);
}
void PictureLayer::update(ResourceUpdateQueue&, const OcclusionTracker*,
diff --git a/cc/picture_layer.h b/cc/picture_layer.h
index 896d561..54c83c5 100644
--- a/cc/picture_layer.h
+++ b/cc/picture_layer.h
@@ -36,6 +36,7 @@ protected:
private:
ContentLayerClient* client_;
PicturePile pile_;
+ Region invalidation_;
};
} // namespace cc
diff --git a/cc/picture_layer_impl.cc b/cc/picture_layer_impl.cc
index 5c1d8e8..6155ed0 100644
--- a/cc/picture_layer_impl.cc
+++ b/cc/picture_layer_impl.cc
@@ -12,7 +12,8 @@
namespace cc {
PictureLayerImpl::PictureLayerImpl(int id) :
- LayerImpl(id) {
+ LayerImpl(id),
+ tilings_(this) {
}
PictureLayerImpl::~PictureLayerImpl() {
@@ -25,24 +26,21 @@ const char* PictureLayerImpl::layerTypeAsString() const {
void PictureLayerImpl::appendQuads(QuadSink& quadSink,
AppendQuadsData& appendQuadsData) {
- const gfx::Rect& visible_rect = visibleContentRect();
+ const gfx::Rect& rect = visibleContentRect();
gfx::Rect content_rect(gfx::Point(), contentBounds());
- if (!tilings_.size())
- return;
-
SharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState());
bool clipped = false;
gfx::QuadF target_quad = MathUtil::mapQuad(
drawTransform(),
- gfx::QuadF(visible_rect),
+ gfx::QuadF(rect),
clipped);
bool isAxisAlignedInTarget = !clipped && target_quad.IsRectilinear();
bool useAA = !isAxisAlignedInTarget;
- // TODO(enne): Generate quads from multiple tilings.
- PictureLayerTiling* tiling = tilings_[0];
- for (PictureLayerTiling::Iterator iter(tiling, visible_rect); iter; ++iter) {
+ for (PictureLayerTilingSet::Iterator iter(&tilings_, contentsScaleX(), rect);
+ iter;
+ ++iter) {
ResourceProvider::ResourceId resource;
if (*iter)
resource = iter->resource_id();
@@ -54,7 +52,8 @@ void PictureLayerImpl::appendQuads(QuadSink& quadSink,
gfx::Rect geometry_rect = iter.geometry_rect();
gfx::RectF texture_rect = iter.texture_rect();
- gfx::Rect opaque_rect = iter.opaque_rect();
+ gfx::Rect opaque_rect = iter->opaque_rect();
+ opaque_rect.Intersect(content_rect);
bool outside_left_edge = geometry_rect.x() == content_rect.x();
bool outside_top_edge = geometry_rect.y() == content_rect.y();
@@ -95,26 +94,15 @@ scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling*,
}
void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
- tilings_.clear();
- for (size_t i = 0; i < other->tilings_.size(); ++i) {
- scoped_ptr<PictureLayerTiling> clone = other->tilings_[i]->Clone();
- clone->set_client(this);
- tilings_.append(clone.Pass());
- }
+ tilings_.CloneFrom(other->tilings_);
}
void PictureLayerImpl::Update() {
+ tilings_.SetLayerBounds(bounds());
// TODO(enne): Add more tilings during pinch zoom.
- if (!tilings_.size()) {
+ if (!tilings_.num_tilings()) {
gfx::Size tile_size = layerTreeHostImpl()->settings().defaultTileSize;
-
- scoped_ptr<PictureLayerTiling> tiling = PictureLayerTiling::Create(
- tile_size);
- tiling->set_client(this);
- tiling->SetBounds(contentBounds());
- tiling->create_tiles(gfx::Rect(gfx::Point(), contentBounds()));
- tilings_.append(tiling.Pass());
-
+ tilings_.AddTiling(contentsScaleX(), tile_size);
// TODO(enne): handle invalidations, create new tiles
}
}
diff --git a/cc/picture_layer_impl.h b/cc/picture_layer_impl.h
index 76b71b1..062cfb4 100644
--- a/cc/picture_layer_impl.h
+++ b/cc/picture_layer_impl.h
@@ -7,6 +7,7 @@
#include "cc/layer_impl.h"
#include "cc/picture_layer_tiling.h"
+#include "cc/picture_layer_tiling_set.h"
#include "cc/picture_pile.h"
#include "cc/scoped_ptr_vector.h"
@@ -42,7 +43,7 @@ public:
protected:
PictureLayerImpl(int id);
- ScopedPtrVector<PictureLayerTiling> tilings_;
+ PictureLayerTilingSet tilings_;
PicturePile pile_;
friend class PictureLayer;
diff --git a/cc/picture_layer_tiling.cc b/cc/picture_layer_tiling.cc
index c6ecb7f..abd6347 100644
--- a/cc/picture_layer_tiling.cc
+++ b/cc/picture_layer_tiling.cc
@@ -3,20 +3,25 @@
// found in the LICENSE file.
#include "cc/picture_layer_tiling.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/size_conversions.h"
namespace cc {
scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create(
+ float contents_scale,
gfx::Size tile_size) {
- return make_scoped_ptr(new PictureLayerTiling(tile_size));
+ return make_scoped_ptr(new PictureLayerTiling(contents_scale, tile_size));
}
scoped_ptr<PictureLayerTiling> PictureLayerTiling::Clone() const {
return make_scoped_ptr(new PictureLayerTiling(*this));
}
-PictureLayerTiling::PictureLayerTiling(gfx::Size tile_size)
+PictureLayerTiling::PictureLayerTiling(float contents_scale,
+ gfx::Size tile_size)
: client_(NULL),
+ contents_scale_(contents_scale),
tiling_data_(tile_size, gfx::Size(), true) {
}
@@ -30,26 +35,31 @@ const PictureLayerTiling& PictureLayerTiling::operator=(
return *this;
}
-void PictureLayerTiling::create_tiles(gfx::Rect rect) {
- for (Iterator iter(this, rect); iter; ++iter) {
- if (*iter)
- continue;
- tiles_[std::make_pair(iter.tile_i_, iter.tile_j_)] =
- client_->CreateTile(this, iter.full_tile_rect());
- }
+void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) {
+ client_ = client;
}
-void PictureLayerTiling::set_client(PictureLayerTilingClient* client) {
- client_ = client;
+gfx::Rect PictureLayerTiling::ContentRect() const {
+ gfx::Size content_bounds =
+ gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_));
+ return gfx::Rect(gfx::Point(), content_bounds);
}
Tile* PictureLayerTiling::TileAt(int i, int j) const {
- TileMap::const_iterator iter = tiles_.find(std::make_pair(i, j));
+ TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j));
if (iter == tiles_.end())
return NULL;
return iter->second.get();
}
+void PictureLayerTiling::CreateTile(int i, int j) {
+ gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(i, j);
+ tile_rect.set_size(tiling_data_.max_texture_size());
+ TileMapKey key(i, j);
+ DCHECK(!tiles_[key]);
+ tiles_[key] = client_->CreateTile(this, tile_rect);
+}
+
Region PictureLayerTiling::OpaqueRegionInContentRect(
const gfx::Rect& content_rect) const {
Region opaque_region;
@@ -57,16 +67,32 @@ Region PictureLayerTiling::OpaqueRegionInContentRect(
return opaque_region;
}
-void PictureLayerTiling::SetBounds(gfx::Size size) {
- tiling_data_.SetTotalSize(size);
- if (size.IsEmpty()) {
+void PictureLayerTiling::SetLayerBounds(gfx::Size layer_bounds) {
+ if (layer_bounds_ == layer_bounds)
+ return;
+
+ layer_bounds_ = layer_bounds;
+ gfx::Size content_bounds =
+ gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_));
+
+ tiling_data_.SetTotalSize(content_bounds);
+ if (layer_bounds_.IsEmpty()) {
tiles_.clear();
return;
}
+ int right = tiling_data_.TileXIndexFromSrcCoord(content_bounds.width() - 1);
+ int bottom = tiling_data_.TileYIndexFromSrcCoord(content_bounds.height() - 1);
+
+ // TODO(enne): Be more efficient about what tiles are created.
+ for (int j = 0; j <= bottom; ++j) {
+ for (int i = 0; i <= right; ++i) {
+ if (tiles_.find(TileMapKey(i, j)) == tiles_.end())
+ CreateTile(i, j);
+ }
+ }
+
// Any tiles outside our new bounds are invalid and should be dropped.
- int right = tiling_data_.TileXIndexFromSrcCoord(size.width() - 1);
- int bottom = tiling_data_.TileYIndexFromSrcCoord(size.height() - 1);
std::vector<TileMapKey> invalid_tile_keys;
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
if (it->first.first > right || it->first.second > bottom)
@@ -76,10 +102,51 @@ void PictureLayerTiling::SetBounds(gfx::Size size) {
tiles_.erase(invalid_tile_keys[i]);
}
+void PictureLayerTiling::Invalidate(const Region& layer_invalidation) {
+ std::vector<TileMapKey> new_tiles;
+
+ for (Region::Iterator region_iter(layer_invalidation);
+ region_iter.has_rect();
+ region_iter.next()) {
+
+ gfx::Rect rect =
+ gfx::ToEnclosingRect(ScaleRect(region_iter.rect(), contents_scale_));
+ rect.Intersect(ContentRect());
+
+ for (PictureLayerTiling::Iterator tile_iter(this, contents_scale_, rect);
+ tile_iter;
+ ++tile_iter) {
+ TileMapKey key(tile_iter.tile_i_, tile_iter.tile_j_);
+ if (!tiles_[key])
+ continue;
+
+ tiles_[key] = NULL;
+ new_tiles.push_back(key);
+ }
+ }
+
+ for (size_t i = 0; i < new_tiles.size(); ++i) {
+ CreateTile(new_tiles[i].first, new_tiles[i].second);
+ }
+}
+
+PictureLayerTiling::Iterator::Iterator()
+ : tiling_(NULL),
+ current_tile_(NULL),
+ tile_i_(0),
+ tile_j_(0),
+ left_(0),
+ top_(0),
+ right_(0),
+ bottom_(0) {
+}
+
PictureLayerTiling::Iterator::Iterator(PictureLayerTiling* tiling,
- gfx::Rect content_rect)
+ float dest_scale,
+ gfx::Rect dest_rect)
: tiling_(tiling),
- content_rect_(content_rect),
+ dest_rect_(dest_rect),
+ dest_to_content_scale_(tiling_->contents_scale_ / dest_scale),
current_tile_(NULL),
tile_i_(0),
tile_j_(0),
@@ -88,9 +155,12 @@ PictureLayerTiling::Iterator::Iterator(PictureLayerTiling* tiling,
right_(0),
bottom_(0) {
DCHECK(tiling_);
- if (content_rect_.IsEmpty())
+ if (dest_rect_.IsEmpty())
return;
+ gfx::Rect content_rect =
+ gfx::ToEnclosingRect(gfx::ScaleRect(dest_rect_, dest_to_content_scale_));
+
left_ = tiling_->tiling_data_.TileXIndexFromSrcCoord(content_rect.x());
top_ = tiling_->tiling_data_.TileYIndexFromSrcCoord(content_rect.y());
right_ = tiling_->tiling_data_.TileXIndexFromSrcCoord(
@@ -98,73 +168,96 @@ PictureLayerTiling::Iterator::Iterator(PictureLayerTiling* tiling,
bottom_ = tiling_->tiling_data_.TileYIndexFromSrcCoord(
content_rect.bottom() - 1);
- tile_i_ = left_;
+ tile_i_ = left_ - 1;
tile_j_ = top_;
- current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
+ ++(*this);
}
PictureLayerTiling::Iterator::~Iterator() {
}
PictureLayerTiling::Iterator& PictureLayerTiling::Iterator::operator++() {
- if (!current_tile_)
+ if (tile_j_ > bottom_)
return *this;
- do {
- tile_i_++;
- if (tile_i_ > right_) {
- tile_i_ = left_;
- tile_j_++;
- if (tile_j_ > top_)
- current_tile_ = NULL;
- return *this;
+ bool first_time = tile_i_ < left_;
+ bool new_row = false;
+ tile_i_++;
+ if (tile_i_ > right_) {
+ tile_i_ = left_;
+ tile_j_++;
+ new_row = true;
+ if (tile_j_ > bottom_) {
+ current_tile_ = NULL;
+ return *this;
}
- } while (!geometry_rect().IsEmpty());
+ }
current_tile_ = tiling_->TileAt(tile_i_, tile_j_);
+
+ // Calculate the current geometry rect. Due to floating point rounding
+ // and ToEnclosedRect, tiles might overlap in destination space on the
+ // edges.
+ gfx::Rect last_geometry_rect = current_geometry_rect_;
+
+ gfx::Rect content_rect = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_);
+ current_geometry_rect_ = gfx::ToEnclosingRect(
+ gfx::ScaleRect(content_rect, 1 / dest_to_content_scale_));
+ current_geometry_rect_.Intersect(dest_rect_);
+
+ if (first_time)
+ return *this;
+
+ // Iteration happens left->right, top->bottom. Running off the bottom-right
+ // edge is handled by the intersection above with dest_rect_. Here we make
+ // sure that the new current geometry rect doesn't overlap with the last.
+ int min_left;
+ int min_top;
+ if (new_row) {
+ min_left = dest_rect_.x();
+ min_top = last_geometry_rect.bottom();
+ } else {
+ min_left = last_geometry_rect.right();
+ min_top = last_geometry_rect.y();
+ }
+
+ int inset_left = std::max(0, min_left - current_geometry_rect_.x());
+ int inset_top = std::max(0, min_top - current_geometry_rect_.y());
+ current_geometry_rect_.Inset(inset_left, inset_top, 0, 0);
+
+ if (!new_row) {
+ DCHECK_EQ(last_geometry_rect.right(), current_geometry_rect_.x());
+ DCHECK_EQ(last_geometry_rect.bottom(), current_geometry_rect_.bottom());
+ DCHECK_EQ(last_geometry_rect.y(), current_geometry_rect_.y());
+ }
+
return *this;
}
gfx::Rect PictureLayerTiling::Iterator::geometry_rect() const {
- gfx::Rect geometry_rect = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_);
- geometry_rect.Intersect(content_rect_);
- return geometry_rect;
+ return current_geometry_rect_;
}
-gfx::Rect PictureLayerTiling::Iterator::full_tile_rect() const {
- gfx::Rect tile_rect =
- tiling_->tiling_data_.TileBoundsWithBorder(tile_i_, tile_j_);
- tile_rect.set_size(texture_size());
- return tile_rect;
-}
+gfx::RectF PictureLayerTiling::Iterator::texture_rect() const {
+ gfx::Rect full_bounds = tiling_->tiling_data_.TileBoundsWithBorder(tile_i_,
+ tile_j_);
+ full_bounds.set_size(texture_size());
-gfx::Rect PictureLayerTiling::Iterator::texture_rect() const {
- gfx::Rect full_bounds = tiling_->tiling_data_.TileBounds(tile_i_, tile_j_);
- gfx::Rect visible = geometry_rect();
- gfx::Vector2d display_offset = visible.origin() - full_bounds.origin();
- gfx::Vector2d offset = visible.origin() - full_bounds.origin();
- offset += tiling_->tiling_data_.TextureOffset(tile_i_, tile_j_);
+ // Convert from dest space => content space => texture space.
+ gfx::RectF texture_rect = gfx::ScaleRect(current_geometry_rect_,
+ dest_to_content_scale_);
+ texture_rect.Offset(-full_bounds.OffsetFromOrigin());
- return gfx::Rect(gfx::PointAtOffsetFromOrigin(offset), visible.size());
-}
+ DCHECK_GE(texture_rect.x(), 0);
+ DCHECK_GE(texture_rect.y(), 0);
+ DCHECK_LE(texture_rect.right(), texture_size().width());
+ DCHECK_LE(texture_rect.bottom(), texture_size().height());
-gfx::Rect PictureLayerTiling::Iterator::opaque_rect() const {
- gfx::Rect opaque_rect;
- opaque_rect = current_tile_->opaque_rect();
- opaque_rect.Intersect(content_rect_);
- return opaque_rect;
+ return texture_rect;
}
gfx::Size PictureLayerTiling::Iterator::texture_size() const {
return tiling_->tiling_data_.max_texture_size();
}
-bool PictureLayerTiling::Iterator::operator==(const Iterator& other) const {
- return tiling_ == other.tiling_ && current_tile_ == other.current_tile_;
-}
-
-bool PictureLayerTiling::Iterator::operator!=(const Iterator& other) const {
- return !(*this == other);
-}
-
} // namespace cc
diff --git a/cc/picture_layer_tiling.h b/cc/picture_layer_tiling.h
index 1c08ea1..d1ccc82 100644
--- a/cc/picture_layer_tiling.h
+++ b/cc/picture_layer_tiling.h
@@ -28,43 +28,50 @@ class CC_EXPORT PictureLayerTiling {
public:
~PictureLayerTiling();
- static scoped_ptr<PictureLayerTiling> Create(gfx::Size tile_size);
+ static scoped_ptr<PictureLayerTiling> Create(float contents_scale,
+ gfx::Size tile_size);
scoped_ptr<PictureLayerTiling> Clone() const;
const PictureLayerTiling& operator=(const PictureLayerTiling&);
- void SetBounds(gfx::Size);
- gfx::Size bounds() const { return tiling_data_.total_size(); }
+ void SetLayerBounds(gfx::Size layer_bounds);
+ void Invalidate(const Region& layer_invalidation);
- void create_tiles(gfx::Rect);
- void set_client(PictureLayerTilingClient* client);
+ void SetClient(PictureLayerTilingClient* client);
- class Iterator {
+ gfx::Rect ContentRect() const;
+ float contents_scale() const { return contents_scale_; }
+
+ // Iterate over all tiles to fill content_rect. Even if tiles are invalid
+ // (i.e. no valid resource) this tiling should still iterate over them.
+ // The union of all geometry_rect calls for each element iterated over should
+ // exactly equal content_rect and no two geometry_rects should intersect.
+ class CC_EXPORT Iterator {
public:
- Iterator(PictureLayerTiling* tiling, gfx::Rect content_rect);
+ Iterator();
+ Iterator(PictureLayerTiling* tiling, float dest_scale, gfx::Rect rect);
~Iterator();
- // Visible rect (no borders)
+ // Visible rect (no borders), always in the space of content_rect,
+ // regardless of the contents scale of the tiling.
gfx::Rect geometry_rect() const;
- // Full tile rect (not clipped, with borders)
- gfx::Rect full_tile_rect() const;
// Texture rect (in texels) for geometry_rect
- gfx::Rect texture_rect() const;
- gfx::Rect opaque_rect() const;
+ gfx::RectF texture_rect() const;
gfx::Size texture_size() const;
Tile* operator->() const { return current_tile_; }
Tile* operator*() const { return current_tile_; }
Iterator& operator++();
- bool operator==(const Iterator& other) const;
- bool operator!=(const Iterator& other) const;
operator bool() const { return current_tile_; }
private:
PictureLayerTiling* tiling_;
+ gfx::Rect dest_rect_;
+ float dest_to_content_scale_;
+
Tile* current_tile_;
- gfx::Rect content_rect_;
+ gfx::Rect current_geometry_rect_;
int tile_i_;
int tile_j_;
int left_;
@@ -83,10 +90,13 @@ class CC_EXPORT PictureLayerTiling {
typedef std::pair<int, int> TileMapKey;
typedef base::hash_map<TileMapKey, scoped_refptr<Tile> > TileMap;
- PictureLayerTiling(gfx::Size tileSize);
+ PictureLayerTiling(float contents_scale, gfx::Size tileSize);
Tile* TileAt(int, int) const;
+ void CreateTile(int i, int j);
PictureLayerTilingClient* client_;
+ float contents_scale_;
+ gfx::Size layer_bounds_;
TileMap tiles_;
TilingData tiling_data_;
diff --git a/cc/picture_layer_tiling_set.cc b/cc/picture_layer_tiling_set.cc
new file mode 100644
index 0000000..b5d97fe
--- /dev/null
+++ b/cc/picture_layer_tiling_set.cc
@@ -0,0 +1,157 @@
+// 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/picture_layer_tiling_set.h"
+
+namespace cc {
+
+PictureLayerTilingSet::PictureLayerTilingSet(
+ PictureLayerTilingClient * client)
+ : client_(client) {
+}
+
+PictureLayerTilingSet::~PictureLayerTilingSet() {
+}
+
+void PictureLayerTilingSet::CloneFrom(const PictureLayerTilingSet& other) {
+ layer_bounds_ = other.layer_bounds_;
+ tilings_.clear();
+ tilings_.reserve(other.tilings_.size());
+ for (size_t i = 0; i < other.tilings_.size(); ++i) {
+ tilings_.append(other.tilings_[i]->Clone());
+ }
+}
+
+void PictureLayerTilingSet::SetLayerBounds(gfx::Size layer_bounds) {
+ layer_bounds_ = layer_bounds;
+ for (size_t i = 0; i < tilings_.size(); ++i)
+ tilings_[i]->SetLayerBounds(layer_bounds);
+}
+
+gfx::Size PictureLayerTilingSet::LayerBounds() const {
+ return layer_bounds_;
+}
+
+void PictureLayerTilingSet::Invalidate(const Region& invalidation) {
+ for (size_t i = 0; i < tilings_.size(); ++i)
+ tilings_[i]->Invalidate(invalidation);
+}
+
+void PictureLayerTilingSet::AddTiling(float contents_scale,
+ gfx::Size tile_size) {
+ tilings_.append(PictureLayerTiling::Create(contents_scale, tile_size));
+ tilings_.last()->SetClient(client_);
+ tilings_.last()->SetLayerBounds(layer_bounds_);
+}
+
+PictureLayerTilingSet::Iterator::Iterator(PictureLayerTilingSet* set,
+ float contents_scale,
+ gfx::Rect content_rect)
+ : set_(set),
+ contents_scale_(contents_scale),
+ current_tiling_(-1) {
+ missing_region_.Union(content_rect);
+ ++(*this);
+}
+
+PictureLayerTilingSet::Iterator::~Iterator() {
+}
+
+gfx::Rect PictureLayerTilingSet::Iterator::geometry_rect() const {
+ if (!tiling_iter_) {
+ if (!region_iter_.has_rect())
+ return gfx::Rect();
+ return region_iter_.rect();
+ }
+ return tiling_iter_.geometry_rect();
+}
+
+gfx::RectF PictureLayerTilingSet::Iterator::texture_rect() const {
+ if (!tiling_iter_)
+ return gfx::RectF();
+ return tiling_iter_.texture_rect();
+}
+
+gfx::Size PictureLayerTilingSet::Iterator::texture_size() const {
+ if (!tiling_iter_)
+ return gfx::Size();
+ return tiling_iter_.texture_size();
+}
+
+Tile* PictureLayerTilingSet::Iterator::operator->() const {
+ if (!tiling_iter_)
+ return NULL;
+ return *tiling_iter_;
+}
+
+Tile* PictureLayerTilingSet::Iterator::operator*() const {
+ if (!tiling_iter_)
+ return NULL;
+ return *tiling_iter_;
+}
+
+PictureLayerTilingSet::Iterator& PictureLayerTilingSet::Iterator::operator++() {
+ bool first_time = current_tiling_ < 0;
+
+ if (!*this && !first_time)
+ return *this;
+
+ if (tiling_iter_)
+ ++tiling_iter_;
+
+ // Loop until we find a valid place to stop.
+ while (true) {
+ while (tiling_iter_ && !tiling_iter_->resource_id()) {
+ missing_region_.Union(tiling_iter_.geometry_rect());
+ ++tiling_iter_;
+ }
+ if (tiling_iter_)
+ return *this;
+
+ // If the set of current rects for this tiling is done, go to the next
+ // tiling and set up to iterate through all of the remaining holes.
+ // This will also happen the first time through the loop.
+ if (!region_iter_.has_rect()) {
+ current_tiling_++;
+ current_region_.Swap(missing_region_);
+ missing_region_.Clear();
+ region_iter_ = Region::Iterator(current_region_);
+
+ // All done and all filled.
+ if (!region_iter_.has_rect()) {
+ current_tiling_ = set_->tilings_.size();
+ return *this;
+ }
+
+ // No more valid tiles, return this checkerboard rect.
+ if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
+ return *this;
+ }
+
+ // Pop a rect off. If there are no more tilings, then these will be
+ // treated as geometry with null tiles that the caller can checkerboard.
+ gfx::Rect last_rect = region_iter_.rect();
+ region_iter_.next();
+
+ // Done, found next checkerboard rect to return.
+ if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
+ return *this;
+
+ // Construct a new iterator for the next tiling, but we need to loop
+ // again until we get to a valid one.
+ tiling_iter_ = PictureLayerTiling::Iterator(
+ set_->tilings_[current_tiling_],
+ contents_scale_,
+ last_rect);
+ }
+
+ return *this;
+}
+
+PictureLayerTilingSet::Iterator::operator bool() const {
+ return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
+ region_iter_.has_rect();
+}
+
+} // namespace cc
diff --git a/cc/picture_layer_tiling_set.h b/cc/picture_layer_tiling_set.h
new file mode 100644
index 0000000..d302125
--- /dev/null
+++ b/cc/picture_layer_tiling_set.h
@@ -0,0 +1,76 @@
+// 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.
+
+#ifndef CC_PICTURE_LAYER_TILING_SET_H_
+#define CC_PICTURE_LAYER_TILING_SET_H_
+
+#include "cc/picture_layer_tiling.h"
+#include "cc/region.h"
+#include "cc/scoped_ptr_vector.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+
+class CC_EXPORT PictureLayerTilingSet {
+ public:
+ PictureLayerTilingSet(PictureLayerTilingClient* client);
+ ~PictureLayerTilingSet();
+
+ // Shallow copies all data (except client) from other.
+ void CloneFrom(const PictureLayerTilingSet& other);
+
+ void SetLayerBounds(gfx::Size layer_bounds);
+ gfx::Size LayerBounds() const;
+
+ void Invalidate(const Region& invalidation);
+
+ void AddTiling(float contents_scale, gfx::Size tile_size);
+ size_t num_tilings() const { return tilings_.size(); }
+
+ // For a given rect, iterates through tiles that can fill it. If no
+ // set of tiles with resources can fill the rect, then it will iterate
+ // through null tiles with valid geometry_rect() until the rect is full.
+ // If all tiles have resources, the union of all geometry_rects will
+ // exactly fill rect with no overlap.
+ class CC_EXPORT Iterator {
+ public:
+ Iterator(PictureLayerTilingSet* set, float contents_scale, gfx::Rect rect);
+ ~Iterator();
+
+ // Visible rect (no borders), always in the space of rect,
+ // regardless of the relative contents scale of the tiling.
+ gfx::Rect geometry_rect() const;
+ // Texture rect (in texels) for geometry_rect
+ gfx::RectF texture_rect() const;
+ // Texture size in texels
+ gfx::Size texture_size() const;
+
+ Tile* operator->() const;
+ Tile* operator*() const;
+
+ Iterator& operator++();
+ operator bool() const;
+
+ private:
+ PictureLayerTilingSet* set_;
+ float contents_scale_;
+ PictureLayerTiling::Iterator tiling_iter_;
+ int current_tiling_;
+
+ Region current_region_;
+ Region missing_region_;
+ Region::Iterator region_iter_;
+ };
+
+ private:
+ PictureLayerTilingClient* client_;
+ gfx::Size layer_bounds_;
+ ScopedPtrVector<PictureLayerTiling> tilings_;
+
+ friend class Iterator;
+};
+
+} // namespace cc
+
+#endif // CC_PICTURE_LAYER_TILING_SET_H_
diff --git a/cc/picture_layer_tiling_set_unittest.cc b/cc/picture_layer_tiling_set_unittest.cc
new file mode 100644
index 0000000..8b0aa72
--- /dev/null
+++ b/cc/picture_layer_tiling_set_unittest.cc
@@ -0,0 +1,44 @@
+// 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/picture_layer_tiling_set.h"
+
+#include "cc/test/fake_picture_layer_tiling_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/size_conversions.h"
+
+namespace cc {
+
+TEST(PictureLayerTilingSetTest, NoResources) {
+ FakePictureLayerTilingClient client;
+ PictureLayerTilingSet set(&client);
+ gfx::Size default_tile_size(256, 256);
+
+ gfx::Size layer_bounds(1000, 800);
+ set.SetLayerBounds(layer_bounds);
+
+ set.AddTiling(1.0, default_tile_size);
+ set.AddTiling(1.5, default_tile_size);
+ set.AddTiling(2.0, default_tile_size);
+
+ float contents_scale = 2.0;
+ gfx::Size content_bounds(
+ gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
+ gfx::Rect content_rect(gfx::Point(), content_bounds);
+
+ Region remaining(content_rect);
+ PictureLayerTilingSet::Iterator iter(&set, contents_scale, content_rect);
+ for (; iter; ++iter) {
+ gfx::Rect geometry_rect = iter.geometry_rect();
+ EXPECT_TRUE(content_rect.Contains(geometry_rect));
+ ASSERT_TRUE(remaining.Contains(geometry_rect));
+ remaining.Subtract(geometry_rect);
+
+ // No tiles have resources, so no iter represents a real tile.
+ EXPECT_FALSE(*iter);
+ }
+ EXPECT_TRUE(remaining.IsEmpty());
+}
+
+} // namespace cc
diff --git a/cc/picture_layer_tiling_unittest.cc b/cc/picture_layer_tiling_unittest.cc
new file mode 100644
index 0000000..03bd9aa
--- /dev/null
+++ b/cc/picture_layer_tiling_unittest.cc
@@ -0,0 +1,121 @@
+// 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/picture_layer_tiling.h"
+
+#include "cc/test/fake_picture_layer_tiling_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/size_conversions.h"
+
+namespace cc {
+
+class PictureLayerTilingIteratorTest : public testing::Test {
+ public:
+ PictureLayerTilingIteratorTest() {}
+ virtual ~PictureLayerTilingIteratorTest() {}
+
+ void Initialize(gfx::Size tile_size,
+ float contents_scale,
+ gfx::Size layer_bounds) {
+ client_.SetTileSize(tile_size);
+ tiling_ = PictureLayerTiling::Create(contents_scale, tile_size);
+ tiling_->SetClient(&client_);
+ tiling_->SetLayerBounds(layer_bounds);
+ }
+
+ void VerifyTilesExactlyCoverRect(float rect_scale, gfx::Rect rect) {
+ // Iterators are not valid if this ratio is too large (i.e. the
+ // tiling is too high-res for a low-res destination rect.) This is an
+ // artifact of snapping geometry to integer coordinates and then mapping
+ // back to floating point texture coordinates.
+ float dest_to_contents_scale = tiling_->contents_scale() / rect_scale;
+ ASSERT_LE(dest_to_contents_scale, 2.0);
+
+ Region remaining = rect;
+ for (PictureLayerTiling::Iterator iter(tiling_.get(), rect_scale, rect);
+ iter;
+ ++iter) {
+
+ // Geometry cannot overlap previous geometry at all
+ gfx::Rect geometry = iter.geometry_rect();
+ EXPECT_TRUE(rect.Contains(geometry));
+ EXPECT_TRUE(remaining.Contains(geometry));
+ remaining.Subtract(geometry);
+
+ // Sanity check that texture coords are within the texture rect.
+ gfx::RectF texture_rect = iter.texture_rect();
+ EXPECT_GE(texture_rect.x(), 0);
+ EXPECT_GE(texture_rect.y(), 0);
+ EXPECT_LE(texture_rect.right(), client_.TileSize().width());
+ EXPECT_LE(texture_rect.bottom(), client_.TileSize().height());
+
+ EXPECT_EQ(iter.texture_size(), client_.TileSize());
+ }
+
+ // The entire rect must be filled by geometry from the tiling.
+ EXPECT_TRUE(remaining.IsEmpty());
+ }
+
+ protected:
+ FakePictureLayerTilingClient client_;
+ scoped_ptr<PictureLayerTiling> tiling_;
+
+ DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingIteratorTest);
+};
+
+TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsNoScale) {
+ Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect());
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1099, 801));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(52, 83, 789, 412));
+
+ // With borders, a size of 3x3 = 1 pixel of content.
+ Initialize(gfx::Size(3, 3), 1, gfx::Size(10, 10));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1, 1));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 2, 2));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(1, 1, 2, 2));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(3, 2, 5, 2));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsTilingScale) {
+ Initialize(gfx::Size(200, 100), 2.0f, gfx::Size(1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect());
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));
+
+ Initialize(gfx::Size(3, 3), 2.0f, gfx::Size(10, 10));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect());
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1, 1));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 2, 2));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(1, 1, 2, 2));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(3, 2, 5, 2));
+
+ Initialize(gfx::Size(100, 200), 0.5f, gfx::Size(1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));
+
+ Initialize(gfx::Size(150, 250), 0.37f, gfx::Size(1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));
+
+ Initialize(gfx::Size(312, 123), 0.01f, gfx::Size(1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1005, 2010));
+ VerifyTilesExactlyCoverRect(1, gfx::Rect(50, 112, 512, 381));
+}
+
+TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsBothScale) {
+ Initialize(gfx::Size(50, 50), 4.0f, gfx::Size(800, 600));
+ VerifyTilesExactlyCoverRect(2.0f, gfx::Rect());
+ VerifyTilesExactlyCoverRect(2.0f, gfx::Rect(0, 0, 1600, 1200));
+ VerifyTilesExactlyCoverRect(2.0f, gfx::Rect(512, 365, 253, 182));
+
+ float scale = 6.7f;
+ gfx::Size bounds(800, 600);
+ gfx::Rect full_rect(gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale)));
+ Initialize(gfx::Size(256, 512), 5.2f, bounds);
+ VerifyTilesExactlyCoverRect(scale, full_rect);
+ VerifyTilesExactlyCoverRect(scale, gfx::Rect(2014, 1579, 867, 1033));
+}
+
+} // namespace cc
diff --git a/cc/region.cc b/cc/region.cc
index 3cd9b5d..cf23011 100644
--- a/cc/region.cc
+++ b/cc/region.cc
@@ -103,6 +103,9 @@ std::string Region::ToString() const {
return result;
}
+Region::Iterator::Iterator() {
+}
+
Region::Iterator::Iterator(const Region& region)
: it_(region.skregion_) {
}
diff --git a/cc/region.h b/cc/region.h
index badd33c..7478152 100644
--- a/cc/region.h
+++ b/cc/region.h
@@ -55,6 +55,7 @@ class CC_EXPORT Region {
class CC_EXPORT Iterator {
public:
+ Iterator();
Iterator(const Region& region);
~Iterator();
diff --git a/cc/scoped_ptr_vector.h b/cc/scoped_ptr_vector.h
index 28c0014..b4271e82 100644
--- a/cc/scoped_ptr_vector.h
+++ b/cc/scoped_ptr_vector.h
@@ -67,6 +67,10 @@ class ScopedPtrVector {
data_.erase(data_.begin() + index);
}
+ void reserve(size_t size) {
+ data_.reserve(size);
+ }
+
void clear() {
STLDeleteElements(&data_);
}
diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc
new file mode 100644
index 0000000..b3853b6
--- /dev/null
+++ b/cc/test/fake_picture_layer_tiling_client.cc
@@ -0,0 +1,30 @@
+// 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/test/fake_picture_layer_tiling_client.h"
+
+namespace cc {
+
+FakePictureLayerTilingClient::FakePictureLayerTilingClient()
+ : tile_manager_(&tile_manager_client_) {
+}
+
+FakePictureLayerTilingClient::~FakePictureLayerTilingClient() {
+}
+
+scoped_refptr<Tile> FakePictureLayerTilingClient::CreateTile(
+ PictureLayerTiling*,
+ gfx::Rect rect) {
+ return make_scoped_refptr(new Tile(&tile_manager_,
+ &pile_,
+ tile_size_,
+ GL_RGBA,
+ rect));
+}
+
+void FakePictureLayerTilingClient::SetTileSize(gfx::Size tile_size) {
+ tile_size_ = tile_size;
+}
+
+}
diff --git a/cc/test/fake_picture_layer_tiling_client.h b/cc/test/fake_picture_layer_tiling_client.h
new file mode 100644
index 0000000..ecadac0
--- /dev/null
+++ b/cc/test/fake_picture_layer_tiling_client.h
@@ -0,0 +1,38 @@
+// 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.
+
+#ifndef CC_TEST_FAKE_PICTURE_LAYER_TILING_CLIENT_H_
+#define CC_TEST_FAKE_PICTURE_LAYER_TILING_CLIENT_H_
+
+#include "cc/picture_layer_tiling.h"
+#include "cc/picture_pile.h"
+#include "cc/test/fake_tile_manager_client.h"
+#include "cc/tile.h"
+#include "cc/tile_manager.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+class FakePictureLayerTilingClient : public PictureLayerTilingClient {
+ public:
+ FakePictureLayerTilingClient();
+ virtual ~FakePictureLayerTilingClient();
+
+ // PictureLayerTilingClient implementation.
+ virtual scoped_refptr<Tile> CreateTile(
+ PictureLayerTiling* tiling, gfx::Rect rect) OVERRIDE;
+
+ void SetTileSize(gfx::Size tile_size);
+ gfx::Size TileSize() const { return tile_size_; }
+
+ protected:
+ FakeTileManagerClient tile_manager_client_;
+ TileManager tile_manager_;
+ PicturePile pile_;
+ gfx::Size tile_size_;
+};
+
+} // namespace cc
+
+#endif // CC_TEST_FAKE_PICTURE_LAYER_TILING_CLIENT_H_
diff --git a/cc/test/fake_tile_manager_client.h b/cc/test/fake_tile_manager_client.h
new file mode 100644
index 0000000..6e94924
--- /dev/null
+++ b/cc/test/fake_tile_manager_client.h
@@ -0,0 +1,22 @@
+// 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.
+
+#ifndef CC_TEST_FAKE_TILE_MANAGER_CLIENT_H_
+#define CC_TEST_FAKE_TILE_MANAGER_CLIENT_H_
+
+#include "cc/tile_manager.h"
+
+namespace cc {
+
+class FakeTileManagerClient : public TileManagerClient {
+ public:
+ virtual ~FakeTileManagerClient() {}
+
+ // TileManagerClient implementation.
+ virtual void ScheduleManageTiles() OVERRIDE {}
+};
+
+} // namespace cc
+
+#endif // CC_TEST_FAKE_TILE_MANAGER_CLIENT_H_
diff --git a/cc/tile.h b/cc/tile.h
index 9a18069..d7ace30 100644
--- a/cc/tile.h
+++ b/cc/tile.h
@@ -20,7 +20,7 @@ namespace cc {
class Tile;
-class Tile : public base::RefCounted<Tile> {
+class CC_EXPORT Tile : public base::RefCounted<Tile> {
public:
Tile(TileManager* tile_manager,
PicturePile* picture_pile,
diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc
index eb55585..a1d3b07 100644
--- a/cc/tile_manager.cc
+++ b/cc/tile_manager.cc
@@ -54,7 +54,7 @@ void TileManager::WillModifyTilePriority(Tile*, WhichTree tree, const TilePriori
void TileManager::ScheduleManageTiles() {
if (manage_tiles_pending_)
return;
- ScheduleManageTiles();
+ client_->ScheduleManageTiles();
manage_tiles_pending_ = true;
}
diff --git a/cc/tile_manager.h b/cc/tile_manager.h
index 8f6bf88..47ad63b 100644
--- a/cc/tile_manager.h
+++ b/cc/tile_manager.h
@@ -17,7 +17,7 @@ class Tile;
class TileVersion;
class ResourceProvider;
-class TileManagerClient {
+class CC_EXPORT TileManagerClient {
public:
virtual void ScheduleManageTiles() = 0;
@@ -37,7 +37,7 @@ enum TileManagerBin {
// This is state that is specific to a tile that is
// managed by the TileManager.
-class ManagedTileState {
+class CC_EXPORT ManagedTileState {
public:
ManagedTileState()
: can_use_gpu_memory(false)
@@ -59,7 +59,7 @@ class ManagedTileState {
// should no longer have any memory assigned to them. Tile objects are "owned"
// by layers; they automatically register with the manager when they are
// created, and unregister from the manager when they are deleted.
-class TileManager {
+class CC_EXPORT TileManager {
public:
TileManager(TileManagerClient* client);
~TileManager();