1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/picture_layer_tiling_set.h"
13 class LargestToSmallestScaleFunctor {
15 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
16 return left->contents_scale() > right->contents_scale();
23 PictureLayerTilingSet::PictureLayerTilingSet(
24 PictureLayerTilingClient* client,
25 const gfx::Size& layer_bounds)
27 layer_bounds_(layer_bounds) {
30 PictureLayerTilingSet::~PictureLayerTilingSet() {
33 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
35 for (size_t i = 0; i < tilings_.size(); ++i)
36 tilings_[i]->SetClient(client_);
39 void PictureLayerTilingSet::SyncTilings(
40 const PictureLayerTilingSet& other,
41 const gfx::Size& new_layer_bounds,
42 const Region& layer_invalidation,
43 float minimum_contents_scale) {
44 if (new_layer_bounds.IsEmpty()) {
46 layer_bounds_ = new_layer_bounds;
50 tilings_.reserve(other.tilings_.size());
52 // Remove any tilings that aren't in |other| or don't meet the minimum.
53 for (size_t i = 0; i < tilings_.size(); ++i) {
54 float scale = tilings_[i]->contents_scale();
55 if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
57 // Swap with the last element and remove it.
58 tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
63 // Add any missing tilings from |other| that meet the minimum.
64 for (size_t i = 0; i < other.tilings_.size(); ++i) {
65 float contents_scale = other.tilings_[i]->contents_scale();
66 if (contents_scale < minimum_contents_scale)
68 if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
69 this_tiling->set_resolution(other.tilings_[i]->resolution());
71 // These two calls must come before updating the pile, because they may
72 // destroy tiles that the new pile cannot raster.
73 this_tiling->SetLayerBounds(new_layer_bounds);
74 this_tiling->Invalidate(layer_invalidation);
76 this_tiling->UpdateTilesToCurrentPile();
77 this_tiling->CreateMissingTilesInLiveTilesRect();
79 DCHECK(this_tiling->tile_size() ==
80 client_->CalculateTileSize(this_tiling->TilingRect().size()));
83 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
87 new_tiling->set_resolution(other.tilings_[i]->resolution());
88 tilings_.push_back(new_tiling.Pass());
90 tilings_.sort(LargestToSmallestScaleFunctor());
92 layer_bounds_ = new_layer_bounds;
95 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
96 for (size_t i = 0; i < tilings_.size(); ++i)
97 tilings_[i]->RemoveTilesInRegion(region);
100 void PictureLayerTilingSet::SetCanUseLCDText(bool can_use_lcd_text) {
101 for (size_t i = 0; i < tilings_.size(); ++i)
102 tilings_[i]->SetCanUseLCDText(can_use_lcd_text);
105 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
106 for (size_t i = 0; i < tilings_.size(); ++i) {
107 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350.
108 // If a duplicate tiling gets added, then many assumptions in
109 // PictureLayerImpl fail.
110 CHECK_NE(tilings_[i]->contents_scale(), contents_scale);
113 tilings_.push_back(PictureLayerTiling::Create(contents_scale,
116 PictureLayerTiling* appended = tilings_.back();
118 tilings_.sort(LargestToSmallestScaleFunctor());
122 int PictureLayerTilingSet::NumHighResTilings() const {
123 int num_high_res = 0;
124 for (size_t i = 0; i < tilings_.size(); ++i) {
125 if (tilings_[i]->resolution() == HIGH_RESOLUTION)
131 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
132 for (size_t i = 0; i < tilings_.size(); ++i) {
133 if (tilings_[i]->contents_scale() == scale)
139 void PictureLayerTilingSet::RemoveAllTilings() {
143 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
144 ScopedPtrVector<PictureLayerTiling>::iterator iter =
145 std::find(tilings_.begin(), tilings_.end(), tiling);
146 if (iter == tilings_.end())
148 tilings_.erase(iter);
151 void PictureLayerTilingSet::RemoveAllTiles() {
152 for (size_t i = 0; i < tilings_.size(); ++i)
153 tilings_[i]->Reset();
156 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
157 const PictureLayerTilingSet* set,
158 float contents_scale,
159 const gfx::Rect& content_rect,
160 float ideal_contents_scale)
162 contents_scale_(contents_scale),
163 ideal_contents_scale_(ideal_contents_scale),
164 current_tiling_(-1) {
165 missing_region_.Union(content_rect);
167 for (ideal_tiling_ = 0;
168 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
170 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
171 if (tiling->contents_scale() < ideal_contents_scale_) {
172 if (ideal_tiling_ > 0)
178 DCHECK_LE(set_->tilings_.size(),
179 static_cast<size_t>(std::numeric_limits<int>::max()));
181 int num_tilings = set_->tilings_.size();
182 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
188 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
191 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
193 if (!region_iter_.has_rect())
195 return region_iter_.rect();
197 return tiling_iter_.geometry_rect();
200 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
203 return tiling_iter_.texture_rect();
206 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
209 return tiling_iter_.texture_size();
212 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
215 return *tiling_iter_;
218 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
221 return *tiling_iter_;
224 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
225 if (current_tiling_ < 0)
227 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
229 return set_->tilings_[current_tiling_];
232 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
233 // Order returned by this method is:
234 // 1. Ideal tiling index
235 // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
236 // 3. Tiling index > Ideal in increasing order (lower res than ideal)
237 // 4. Tiling index > tilings.size() (invalid index)
238 if (current_tiling_ < 0)
239 return ideal_tiling_;
240 else if (current_tiling_ > ideal_tiling_)
241 return current_tiling_ + 1;
242 else if (current_tiling_)
243 return current_tiling_ - 1;
245 return ideal_tiling_ + 1;
248 PictureLayerTilingSet::CoverageIterator&
249 PictureLayerTilingSet::CoverageIterator::operator++() {
250 bool first_time = current_tiling_ < 0;
252 if (!*this && !first_time)
258 // Loop until we find a valid place to stop.
260 while (tiling_iter_ &&
261 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
262 missing_region_.Union(tiling_iter_.geometry_rect());
268 // If the set of current rects for this tiling is done, go to the next
269 // tiling and set up to iterate through all of the remaining holes.
270 // This will also happen the first time through the loop.
271 if (!region_iter_.has_rect()) {
272 current_tiling_ = NextTiling();
273 current_region_.Swap(&missing_region_);
274 missing_region_.Clear();
275 region_iter_ = Region::Iterator(current_region_);
277 // All done and all filled.
278 if (!region_iter_.has_rect()) {
279 current_tiling_ = set_->tilings_.size();
283 // No more valid tiles, return this checkerboard rect.
284 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
288 // Pop a rect off. If there are no more tilings, then these will be
289 // treated as geometry with null tiles that the caller can checkerboard.
290 gfx::Rect last_rect = region_iter_.rect();
293 // Done, found next checkerboard rect to return.
294 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
297 // Construct a new iterator for the next tiling, but we need to loop
298 // again until we get to a valid one.
299 tiling_iter_ = PictureLayerTiling::CoverageIterator(
300 set_->tilings_[current_tiling_],
308 PictureLayerTilingSet::CoverageIterator::operator bool() const {
309 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
310 region_iter_.has_rect();
313 void PictureLayerTilingSet::UpdateTilePriorities(
315 const gfx::Rect& visible_content_rect,
316 float layer_contents_scale,
317 double current_frame_time_in_seconds) {
318 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
319 visible_content_rect, 1.f / layer_contents_scale);
321 for (size_t i = 0; i < tilings_.size(); ++i) {
322 tilings_[i]->UpdateTilePriorities(tree,
324 layer_contents_scale,
325 current_frame_time_in_seconds);
329 void PictureLayerTilingSet::DidBecomeActive() {
330 for (size_t i = 0; i < tilings_.size(); ++i)
331 tilings_[i]->DidBecomeActive();
334 void PictureLayerTilingSet::DidBecomeRecycled() {
335 for (size_t i = 0; i < tilings_.size(); ++i)
336 tilings_[i]->DidBecomeRecycled();
339 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
340 scoped_ptr<base::ListValue> state(new base::ListValue());
341 for (size_t i = 0; i < tilings_.size(); ++i)
342 state->Append(tilings_[i]->AsValue().release());
343 return state.PassAs<base::Value>();
346 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
348 for (size_t i = 0; i < tilings_.size(); ++i)
349 amount += tilings_[i]->GPUMemoryUsageInBytes();