Temporarily re-enabling SizeAfterPrefChange test with traces.
[chromium-blink-merge.git] / cc / resources / picture_layer_tiling_set.cc
blobd292d83fab2a53d05ba39d7ca579e3db11c2c0cc
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"
7 #include <limits>
9 namespace cc {
11 namespace {
13 class LargestToSmallestScaleFunctor {
14 public:
15 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
16 return left->contents_scale() > right->contents_scale();
20 } // namespace
23 PictureLayerTilingSet::PictureLayerTilingSet(
24 PictureLayerTilingClient* client,
25 const gfx::Size& layer_bounds)
26 : client_(client),
27 layer_bounds_(layer_bounds) {
30 PictureLayerTilingSet::~PictureLayerTilingSet() {
33 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
34 client_ = client;
35 for (size_t i = 0; i < tilings_.size(); ++i)
36 tilings_[i]->SetClient(client_);
39 bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
40 const gfx::Size& new_layer_bounds,
41 const Region& layer_invalidation,
42 float minimum_contents_scale) {
43 if (new_layer_bounds.IsEmpty()) {
44 RemoveAllTilings();
45 layer_bounds_ = new_layer_bounds;
46 return false;
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))
55 continue;
56 // Swap with the last element and remove it.
57 tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
58 tilings_.pop_back();
59 --i;
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)
68 continue;
69 if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
70 this_tiling->set_resolution(other.tilings_[i]->resolution());
72 // These two calls must come before updating the pile, because they may
73 // destroy tiles that the new pile cannot raster.
74 this_tiling->SetLayerBounds(new_layer_bounds);
75 this_tiling->Invalidate(layer_invalidation);
77 this_tiling->UpdateTilesToCurrentPile();
78 this_tiling->CreateMissingTilesInLiveTilesRect();
79 if (this_tiling->resolution() == HIGH_RESOLUTION)
80 have_high_res_tiling = true;
82 DCHECK(this_tiling->tile_size() ==
83 client_->CalculateTileSize(this_tiling->TilingRect().size()));
84 continue;
86 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
87 contents_scale,
88 new_layer_bounds,
89 client_);
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 layer_bounds_ = new_layer_bounds;
98 return have_high_res_tiling;
101 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
102 for (size_t i = 0; i < tilings_.size(); ++i)
103 tilings_[i]->RemoveTilesInRegion(region);
106 void PictureLayerTilingSet::SetCanUseLCDText(bool can_use_lcd_text) {
107 for (size_t i = 0; i < tilings_.size(); ++i)
108 tilings_[i]->SetCanUseLCDText(can_use_lcd_text);
111 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
112 for (size_t i = 0; i < tilings_.size(); ++i) {
113 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350.
114 // If a duplicate tiling gets added, then many assumptions in
115 // PictureLayerImpl fail.
116 CHECK_NE(tilings_[i]->contents_scale(), contents_scale);
119 tilings_.push_back(PictureLayerTiling::Create(contents_scale,
120 layer_bounds_,
121 client_));
122 PictureLayerTiling* appended = tilings_.back();
124 tilings_.sort(LargestToSmallestScaleFunctor());
125 return appended;
128 int PictureLayerTilingSet::NumHighResTilings() const {
129 int num_high_res = 0;
130 for (size_t i = 0; i < tilings_.size(); ++i) {
131 if (tilings_[i]->resolution() == HIGH_RESOLUTION)
132 num_high_res++;
134 return num_high_res;
137 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
138 for (size_t i = 0; i < tilings_.size(); ++i) {
139 if (tilings_[i]->contents_scale() == scale)
140 return tilings_[i];
142 return NULL;
145 void PictureLayerTilingSet::RemoveAllTilings() {
146 tilings_.clear();
149 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
150 ScopedPtrVector<PictureLayerTiling>::iterator iter =
151 std::find(tilings_.begin(), tilings_.end(), tiling);
152 if (iter == tilings_.end())
153 return;
154 tilings_.erase(iter);
157 void PictureLayerTilingSet::RemoveAllTiles() {
158 for (size_t i = 0; i < tilings_.size(); ++i)
159 tilings_[i]->Reset();
162 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
163 const PictureLayerTilingSet* set,
164 float contents_scale,
165 const gfx::Rect& content_rect,
166 float ideal_contents_scale)
167 : set_(set),
168 contents_scale_(contents_scale),
169 ideal_contents_scale_(ideal_contents_scale),
170 current_tiling_(-1) {
171 missing_region_.Union(content_rect);
173 for (ideal_tiling_ = 0;
174 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
175 ++ideal_tiling_) {
176 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
177 if (tiling->contents_scale() < ideal_contents_scale_) {
178 if (ideal_tiling_ > 0)
179 ideal_tiling_--;
180 break;
184 DCHECK_LE(set_->tilings_.size(),
185 static_cast<size_t>(std::numeric_limits<int>::max()));
187 int num_tilings = set_->tilings_.size();
188 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
189 ideal_tiling_--;
191 ++(*this);
194 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
197 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
198 if (!tiling_iter_) {
199 if (!region_iter_.has_rect())
200 return gfx::Rect();
201 return region_iter_.rect();
203 return tiling_iter_.geometry_rect();
206 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
207 if (!tiling_iter_)
208 return gfx::RectF();
209 return tiling_iter_.texture_rect();
212 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
213 if (!tiling_iter_)
214 return gfx::Size();
215 return tiling_iter_.texture_size();
218 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
219 if (!tiling_iter_)
220 return NULL;
221 return *tiling_iter_;
224 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
225 if (!tiling_iter_)
226 return NULL;
227 return *tiling_iter_;
230 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
231 if (current_tiling_ < 0)
232 return NULL;
233 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
234 return NULL;
235 return set_->tilings_[current_tiling_];
238 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
239 // Order returned by this method is:
240 // 1. Ideal tiling index
241 // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
242 // 3. Tiling index > Ideal in increasing order (lower res than ideal)
243 // 4. Tiling index > tilings.size() (invalid index)
244 if (current_tiling_ < 0)
245 return ideal_tiling_;
246 else if (current_tiling_ > ideal_tiling_)
247 return current_tiling_ + 1;
248 else if (current_tiling_)
249 return current_tiling_ - 1;
250 else
251 return ideal_tiling_ + 1;
254 PictureLayerTilingSet::CoverageIterator&
255 PictureLayerTilingSet::CoverageIterator::operator++() {
256 bool first_time = current_tiling_ < 0;
258 if (!*this && !first_time)
259 return *this;
261 if (tiling_iter_)
262 ++tiling_iter_;
264 // Loop until we find a valid place to stop.
265 while (true) {
266 while (tiling_iter_ &&
267 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
268 missing_region_.Union(tiling_iter_.geometry_rect());
269 ++tiling_iter_;
271 if (tiling_iter_)
272 return *this;
274 // If the set of current rects for this tiling is done, go to the next
275 // tiling and set up to iterate through all of the remaining holes.
276 // This will also happen the first time through the loop.
277 if (!region_iter_.has_rect()) {
278 current_tiling_ = NextTiling();
279 current_region_.Swap(&missing_region_);
280 missing_region_.Clear();
281 region_iter_ = Region::Iterator(current_region_);
283 // All done and all filled.
284 if (!region_iter_.has_rect()) {
285 current_tiling_ = set_->tilings_.size();
286 return *this;
289 // No more valid tiles, return this checkerboard rect.
290 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
291 return *this;
294 // Pop a rect off. If there are no more tilings, then these will be
295 // treated as geometry with null tiles that the caller can checkerboard.
296 gfx::Rect last_rect = region_iter_.rect();
297 region_iter_.next();
299 // Done, found next checkerboard rect to return.
300 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
301 return *this;
303 // Construct a new iterator for the next tiling, but we need to loop
304 // again until we get to a valid one.
305 tiling_iter_ = PictureLayerTiling::CoverageIterator(
306 set_->tilings_[current_tiling_],
307 contents_scale_,
308 last_rect);
311 return *this;
314 PictureLayerTilingSet::CoverageIterator::operator bool() const {
315 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
316 region_iter_.has_rect();
319 void PictureLayerTilingSet::UpdateTilePriorities(
320 WhichTree tree,
321 const gfx::Rect& visible_content_rect,
322 float layer_contents_scale,
323 double current_frame_time_in_seconds) {
324 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
325 visible_content_rect, 1.f / layer_contents_scale);
327 for (size_t i = 0; i < tilings_.size(); ++i) {
328 tilings_[i]->UpdateTilePriorities(tree,
329 visible_layer_rect,
330 layer_contents_scale,
331 current_frame_time_in_seconds);
335 void PictureLayerTilingSet::DidBecomeActive() {
336 for (size_t i = 0; i < tilings_.size(); ++i)
337 tilings_[i]->DidBecomeActive();
340 void PictureLayerTilingSet::DidBecomeRecycled() {
341 for (size_t i = 0; i < tilings_.size(); ++i)
342 tilings_[i]->DidBecomeRecycled();
345 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
346 scoped_ptr<base::ListValue> state(new base::ListValue());
347 for (size_t i = 0; i < tilings_.size(); ++i)
348 state->Append(tilings_[i]->AsValue().release());
349 return state.PassAs<base::Value>();
352 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
353 size_t amount = 0;
354 for (size_t i = 0; i < tilings_.size(); ++i)
355 amount += tilings_[i]->GPUMemoryUsageInBytes();
356 return amount;
359 } // namespace cc