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();
22 PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client)
26 PictureLayerTilingSet::~PictureLayerTilingSet() {
29 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
31 for (size_t i = 0; i < tilings_.size(); ++i)
32 tilings_[i]->SetClient(client_);
35 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
36 for (size_t i = 0; i < tilings_.size(); ++i)
37 tilings_[i]->RemoveTilesInRegion(region);
40 bool PictureLayerTilingSet::SyncTilings(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()) {
49 tilings_.reserve(other.tilings_.size());
51 // Remove any tilings that aren't in |other| or don't meet the minimum.
52 for (size_t i = 0; i < tilings_.size(); ++i) {
53 float scale = tilings_[i]->contents_scale();
54 if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
56 // Swap with the last element and remove it.
57 tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
62 bool have_high_res_tiling = false;
64 // Add any missing tilings from |other| that meet the minimum.
65 for (size_t i = 0; i < other.tilings_.size(); ++i) {
66 float contents_scale = other.tilings_[i]->contents_scale();
67 if (contents_scale < minimum_contents_scale)
69 if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
70 this_tiling->set_resolution(other.tilings_[i]->resolution());
72 this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
74 this_tiling->CreateMissingTilesInLiveTilesRect();
75 if (this_tiling->resolution() == HIGH_RESOLUTION)
76 have_high_res_tiling = true;
78 DCHECK(this_tiling->tile_size() ==
79 client_->CalculateTileSize(this_tiling->tiling_size()))
80 << "tile_size: " << this_tiling->tile_size().ToString()
81 << " tiling_size: " << this_tiling->tiling_size().ToString()
82 << " CalculateTileSize: "
83 << client_->CalculateTileSize(this_tiling->tiling_size()).ToString();
86 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
90 new_tiling->set_resolution(other.tilings_[i]->resolution());
91 if (new_tiling->resolution() == HIGH_RESOLUTION)
92 have_high_res_tiling = true;
93 tilings_.push_back(new_tiling.Pass());
95 tilings_.sort(LargestToSmallestScaleFunctor());
97 return have_high_res_tiling;
100 PictureLayerTiling* PictureLayerTilingSet::AddTiling(
101 float contents_scale,
102 const gfx::Size& layer_bounds) {
103 for (size_t i = 0; i < tilings_.size(); ++i)
104 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
107 PictureLayerTiling::Create(contents_scale, layer_bounds, client_));
108 PictureLayerTiling* appended = tilings_.back();
110 tilings_.sort(LargestToSmallestScaleFunctor());
114 int PictureLayerTilingSet::NumHighResTilings() const {
115 int num_high_res = 0;
116 for (size_t i = 0; i < tilings_.size(); ++i) {
117 if (tilings_[i]->resolution() == HIGH_RESOLUTION)
123 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
124 for (size_t i = 0; i < tilings_.size(); ++i) {
125 if (tilings_[i]->contents_scale() == scale)
131 void PictureLayerTilingSet::RemoveAllTilings() {
135 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
136 ScopedPtrVector<PictureLayerTiling>::iterator iter =
137 std::find(tilings_.begin(), tilings_.end(), tiling);
138 if (iter == tilings_.end())
140 tilings_.erase(iter);
143 void PictureLayerTilingSet::RemoveAllTiles() {
144 for (size_t i = 0; i < tilings_.size(); ++i)
145 tilings_[i]->Reset();
148 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
149 const PictureLayerTilingSet* set,
150 float contents_scale,
151 const gfx::Rect& content_rect,
152 float ideal_contents_scale)
154 contents_scale_(contents_scale),
155 ideal_contents_scale_(ideal_contents_scale),
156 current_tiling_(-1) {
157 missing_region_.Union(content_rect);
159 for (ideal_tiling_ = 0;
160 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
162 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
163 if (tiling->contents_scale() < ideal_contents_scale_) {
164 if (ideal_tiling_ > 0)
170 DCHECK_LE(set_->tilings_.size(),
171 static_cast<size_t>(std::numeric_limits<int>::max()));
173 int num_tilings = set_->tilings_.size();
174 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
180 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
183 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
185 if (!region_iter_.has_rect())
187 return region_iter_.rect();
189 return tiling_iter_.geometry_rect();
192 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
195 return tiling_iter_.texture_rect();
198 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
201 return tiling_iter_.texture_size();
204 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
207 return *tiling_iter_;
210 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
213 return *tiling_iter_;
216 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
217 const PictureLayerTiling* tiling = CurrentTiling();
219 return tiling->resolution();
222 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
224 if (current_tiling_ < 0)
226 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
228 return set_->tilings_[current_tiling_];
231 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
232 // Order returned by this method is:
233 // 1. Ideal tiling index
234 // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
235 // 3. Tiling index > Ideal in increasing order (lower res than ideal)
236 // 4. Tiling index > tilings.size() (invalid index)
237 if (current_tiling_ < 0)
238 return ideal_tiling_;
239 else if (current_tiling_ > ideal_tiling_)
240 return current_tiling_ + 1;
241 else if (current_tiling_)
242 return current_tiling_ - 1;
244 return ideal_tiling_ + 1;
247 PictureLayerTilingSet::CoverageIterator&
248 PictureLayerTilingSet::CoverageIterator::operator++() {
249 bool first_time = current_tiling_ < 0;
251 if (!*this && !first_time)
257 // Loop until we find a valid place to stop.
259 while (tiling_iter_ &&
260 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
261 missing_region_.Union(tiling_iter_.geometry_rect());
267 // If the set of current rects for this tiling is done, go to the next
268 // tiling and set up to iterate through all of the remaining holes.
269 // This will also happen the first time through the loop.
270 if (!region_iter_.has_rect()) {
271 current_tiling_ = NextTiling();
272 current_region_.Swap(&missing_region_);
273 missing_region_.Clear();
274 region_iter_ = Region::Iterator(current_region_);
276 // All done and all filled.
277 if (!region_iter_.has_rect()) {
278 current_tiling_ = set_->tilings_.size();
282 // No more valid tiles, return this checkerboard rect.
283 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
287 // Pop a rect off. If there are no more tilings, then these will be
288 // treated as geometry with null tiles that the caller can checkerboard.
289 gfx::Rect last_rect = region_iter_.rect();
292 // Done, found next checkerboard rect to return.
293 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
296 // Construct a new iterator for the next tiling, but we need to loop
297 // again until we get to a valid one.
298 tiling_iter_ = PictureLayerTiling::CoverageIterator(
299 set_->tilings_[current_tiling_],
307 PictureLayerTilingSet::CoverageIterator::operator bool() const {
308 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
309 region_iter_.has_rect();
312 void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
313 for (size_t i = 0; i < tilings_.size(); ++i) {
314 state->BeginDictionary();
315 tilings_[i]->AsValueInto(state);
316 state->EndDictionary();
320 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
322 for (size_t i = 0; i < tilings_.size(); ++i)
323 amount += tilings_[i]->GPUMemoryUsageInBytes();
327 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
328 TilingRangeType type) const {
329 // Doesn't seem to be the case right now but if it ever becomes a performance
330 // problem to compute these ranges each time this function is called, we can
331 // compute them only when the tiling set has changed instead.
332 TilingRange high_res_range(0, 0);
333 TilingRange low_res_range(tilings_.size(), tilings_.size());
334 for (size_t i = 0; i < tilings_.size(); ++i) {
335 const PictureLayerTiling* tiling = tilings_[i];
336 if (tiling->resolution() == HIGH_RESOLUTION)
337 high_res_range = TilingRange(i, i + 1);
338 if (tiling->resolution() == LOW_RESOLUTION)
339 low_res_range = TilingRange(i, i + 1);
342 TilingRange range(0, 0);
344 case HIGHER_THAN_HIGH_RES:
345 range = TilingRange(0, high_res_range.start);
348 range = high_res_range;
350 case BETWEEN_HIGH_AND_LOW_RES:
351 // TODO(vmpstr): This code assumes that high res tiling will come before
352 // low res tiling, however there are cases where this assumption is
353 // violated. As a result, it's better to be safe in these situations,
354 // since otherwise we can end up accessing a tiling that doesn't exist.
355 // See crbug.com/429397 for high res tiling appearing after low res
356 // tiling discussion/fixes.
357 if (high_res_range.start <= low_res_range.start)
358 range = TilingRange(high_res_range.end, low_res_range.start);
360 range = TilingRange(low_res_range.end, high_res_range.start);
363 range = low_res_range;
365 case LOWER_THAN_LOW_RES:
366 range = TilingRange(low_res_range.end, tilings_.size());
370 DCHECK_LE(range.start, range.end);