Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / cc / resources / picture_layer_tiling_set.cc
blob51896a5b5f7f29cfb287e970fb8b301aaa4b83a0
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>
8 #include <set>
9 #include <vector>
11 namespace cc {
13 namespace {
15 class LargestToSmallestScaleFunctor {
16 public:
17 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
18 return left->contents_scale() > right->contents_scale();
22 inline float LargerRatio(float float1, float float2) {
23 DCHECK_GT(float1, 0.f);
24 DCHECK_GT(float2, 0.f);
25 return float1 > float2 ? float1 / float2 : float2 / float1;
28 } // namespace
30 // static
31 scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create(
32 PictureLayerTilingClient* client) {
33 return make_scoped_ptr(new PictureLayerTilingSet(client));
36 PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client)
37 : client_(client) {
40 PictureLayerTilingSet::~PictureLayerTilingSet() {
43 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
44 client_ = client;
45 for (size_t i = 0; i < tilings_.size(); ++i)
46 tilings_[i]->SetClient(client_);
49 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
50 for (size_t i = 0; i < tilings_.size(); ++i)
51 tilings_[i]->RemoveTilesInRegion(region);
54 void PictureLayerTilingSet::CleanUpTilings(
55 float min_acceptable_high_res_scale,
56 float max_acceptable_high_res_scale,
57 const std::vector<PictureLayerTiling*>& needed_tilings,
58 bool should_have_low_res,
59 PictureLayerTilingSet* twin_set,
60 PictureLayerTilingSet* recycled_twin_set) {
61 float twin_low_res_scale = 0.f;
62 if (twin_set) {
63 PictureLayerTiling* tiling =
64 twin_set->FindTilingWithResolution(LOW_RESOLUTION);
65 if (tiling)
66 twin_low_res_scale = tiling->contents_scale();
69 std::vector<PictureLayerTiling*> to_remove;
70 for (auto* tiling : tilings_) {
71 // Keep all tilings within the min/max scales.
72 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
73 tiling->contents_scale() <= max_acceptable_high_res_scale) {
74 continue;
77 // Keep low resolution tilings, if the tiling set should have them.
78 if (should_have_low_res &&
79 (tiling->resolution() == LOW_RESOLUTION ||
80 tiling->contents_scale() == twin_low_res_scale)) {
81 continue;
84 // Don't remove tilings that are required.
85 if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) !=
86 needed_tilings.end()) {
87 continue;
90 to_remove.push_back(tiling);
93 for (auto* tiling : to_remove) {
94 PictureLayerTiling* twin_tiling =
95 twin_set ? twin_set->FindTilingWithScale(tiling->contents_scale())
96 : nullptr;
97 // Only remove tilings from the twin layer if they have
98 // NON_IDEAL_RESOLUTION.
99 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
100 twin_set->Remove(twin_tiling);
102 PictureLayerTiling* recycled_twin_tiling =
103 recycled_twin_set
104 ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale())
105 : nullptr;
106 // Remove the tiling from the recycle tree. Note that we ignore resolution,
107 // since we don't need to maintain high/low res on the recycle set.
108 if (recycled_twin_tiling)
109 recycled_twin_set->Remove(recycled_twin_tiling);
111 DCHECK_NE(HIGH_RESOLUTION, tiling->resolution());
112 Remove(tiling);
116 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() {
117 for (auto* tiling : tilings_)
118 tiling->set_resolution(NON_IDEAL_RESOLUTION);
121 bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
122 const gfx::Size& new_layer_bounds,
123 const Region& layer_invalidation,
124 float minimum_contents_scale,
125 RasterSource* raster_source) {
126 if (new_layer_bounds.IsEmpty()) {
127 RemoveAllTilings();
128 return false;
131 tilings_.reserve(other.tilings_.size());
133 // Remove any tilings that aren't in |other| or don't meet the minimum.
134 for (size_t i = 0; i < tilings_.size(); ++i) {
135 float scale = tilings_[i]->contents_scale();
136 if (scale >= minimum_contents_scale && !!other.FindTilingWithScale(scale))
137 continue;
138 // Swap with the last element and remove it.
139 tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
140 tilings_.pop_back();
141 --i;
144 bool have_high_res_tiling = false;
146 // Add any missing tilings from |other| that meet the minimum.
147 for (size_t i = 0; i < other.tilings_.size(); ++i) {
148 float contents_scale = other.tilings_[i]->contents_scale();
149 if (contents_scale < minimum_contents_scale)
150 continue;
151 if (PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale)) {
152 this_tiling->set_resolution(other.tilings_[i]->resolution());
154 this_tiling->UpdateTilesToCurrentRasterSource(
155 raster_source, layer_invalidation, new_layer_bounds);
156 this_tiling->CreateMissingTilesInLiveTilesRect();
157 if (this_tiling->resolution() == HIGH_RESOLUTION)
158 have_high_res_tiling = true;
160 DCHECK(this_tiling->tile_size() ==
161 client_->CalculateTileSize(this_tiling->tiling_size()))
162 << "tile_size: " << this_tiling->tile_size().ToString()
163 << " tiling_size: " << this_tiling->tiling_size().ToString()
164 << " CalculateTileSize: "
165 << client_->CalculateTileSize(this_tiling->tiling_size()).ToString();
166 continue;
168 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
169 contents_scale,
170 new_layer_bounds,
171 client_);
172 new_tiling->set_resolution(other.tilings_[i]->resolution());
173 if (new_tiling->resolution() == HIGH_RESOLUTION)
174 have_high_res_tiling = true;
175 tilings_.push_back(new_tiling.Pass());
177 tilings_.sort(LargestToSmallestScaleFunctor());
179 return have_high_res_tiling;
182 PictureLayerTiling* PictureLayerTilingSet::AddTiling(
183 float contents_scale,
184 const gfx::Size& layer_bounds) {
185 for (size_t i = 0; i < tilings_.size(); ++i)
186 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
188 tilings_.push_back(
189 PictureLayerTiling::Create(contents_scale, layer_bounds, client_));
190 PictureLayerTiling* appended = tilings_.back();
192 tilings_.sort(LargestToSmallestScaleFunctor());
193 return appended;
196 int PictureLayerTilingSet::NumHighResTilings() const {
197 int num_high_res = 0;
198 for (size_t i = 0; i < tilings_.size(); ++i) {
199 if (tilings_[i]->resolution() == HIGH_RESOLUTION)
200 num_high_res++;
202 return num_high_res;
205 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale(
206 float scale) const {
207 for (size_t i = 0; i < tilings_.size(); ++i) {
208 if (tilings_[i]->contents_scale() == scale)
209 return tilings_[i];
211 return NULL;
214 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution(
215 TileResolution resolution) const {
216 auto iter = std::find_if(tilings_.begin(), tilings_.end(),
217 [resolution](const PictureLayerTiling* tiling) {
218 return tiling->resolution() == resolution;
220 if (iter == tilings_.end())
221 return NULL;
222 return *iter;
225 void PictureLayerTilingSet::RemoveAllTilings() {
226 tilings_.clear();
229 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
230 ScopedPtrVector<PictureLayerTiling>::iterator iter =
231 std::find(tilings_.begin(), tilings_.end(), tiling);
232 if (iter == tilings_.end())
233 return;
234 tilings_.erase(iter);
237 void PictureLayerTilingSet::RemoveAllTiles() {
238 for (size_t i = 0; i < tilings_.size(); ++i)
239 tilings_[i]->Reset();
242 float PictureLayerTilingSet::GetSnappedContentsScale(
243 float start_scale,
244 float snap_to_existing_tiling_ratio) const {
245 // If a tiling exists within the max snapping ratio, snap to its scale.
246 float snapped_contents_scale = start_scale;
247 float snapped_ratio = snap_to_existing_tiling_ratio;
248 for (const auto* tiling : tilings_) {
249 float tiling_contents_scale = tiling->contents_scale();
250 float ratio = LargerRatio(tiling_contents_scale, start_scale);
251 if (ratio < snapped_ratio) {
252 snapped_contents_scale = tiling_contents_scale;
253 snapped_ratio = ratio;
256 return snapped_contents_scale;
259 float PictureLayerTilingSet::GetMaximumContentsScale() const {
260 if (tilings_.empty())
261 return 0.f;
262 // The first tiling has the largest contents scale.
263 return tilings_[0]->contents_scale();
266 bool PictureLayerTilingSet::UpdateTilePriorities(
267 const gfx::Rect& required_rect_in_layer_space,
268 float ideal_contents_scale,
269 double current_frame_time_in_seconds,
270 const Occlusion& occlusion_in_layer_space,
271 bool can_require_tiles_for_activation) {
272 bool tiling_needs_update = false;
273 // TODO(vmpstr): Check if we have to early out here, or if we can just do it
274 // as part of computing tile priority rects for tilings.
275 for (auto* tiling : tilings_) {
276 if (tiling->NeedsUpdateForFrameAtTimeAndViewport(
277 current_frame_time_in_seconds, required_rect_in_layer_space)) {
278 tiling_needs_update = true;
279 break;
282 if (!tiling_needs_update)
283 return false;
285 for (auto* tiling : tilings_) {
286 tiling->set_can_require_tiles_for_activation(
287 can_require_tiles_for_activation);
288 tiling->ComputeTilePriorityRects(
289 required_rect_in_layer_space, ideal_contents_scale,
290 current_frame_time_in_seconds, occlusion_in_layer_space);
292 return true;
295 void PictureLayerTilingSet::GetAllTilesForTracing(
296 std::set<const Tile*>* tiles) const {
297 for (auto* tiling : tilings_)
298 tiling->GetAllTilesForTracing(tiles);
301 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
302 const PictureLayerTilingSet* set,
303 float contents_scale,
304 const gfx::Rect& content_rect,
305 float ideal_contents_scale)
306 : set_(set),
307 contents_scale_(contents_scale),
308 ideal_contents_scale_(ideal_contents_scale),
309 current_tiling_(-1) {
310 missing_region_.Union(content_rect);
312 for (ideal_tiling_ = 0;
313 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
314 ++ideal_tiling_) {
315 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
316 if (tiling->contents_scale() < ideal_contents_scale_) {
317 if (ideal_tiling_ > 0)
318 ideal_tiling_--;
319 break;
323 DCHECK_LE(set_->tilings_.size(),
324 static_cast<size_t>(std::numeric_limits<int>::max()));
326 int num_tilings = set_->tilings_.size();
327 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
328 ideal_tiling_--;
330 ++(*this);
333 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
336 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
337 if (!tiling_iter_) {
338 if (!region_iter_.has_rect())
339 return gfx::Rect();
340 return region_iter_.rect();
342 return tiling_iter_.geometry_rect();
345 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
346 if (!tiling_iter_)
347 return gfx::RectF();
348 return tiling_iter_.texture_rect();
351 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
352 if (!tiling_iter_)
353 return gfx::Size();
354 return tiling_iter_.texture_size();
357 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
358 if (!tiling_iter_)
359 return NULL;
360 return *tiling_iter_;
363 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
364 if (!tiling_iter_)
365 return NULL;
366 return *tiling_iter_;
369 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
370 const PictureLayerTiling* tiling = CurrentTiling();
371 DCHECK(tiling);
372 return tiling->resolution();
375 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
376 const {
377 if (current_tiling_ < 0)
378 return NULL;
379 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
380 return NULL;
381 return set_->tilings_[current_tiling_];
384 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
385 // Order returned by this method is:
386 // 1. Ideal tiling index
387 // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
388 // 3. Tiling index > Ideal in increasing order (lower res than ideal)
389 // 4. Tiling index > tilings.size() (invalid index)
390 if (current_tiling_ < 0)
391 return ideal_tiling_;
392 else if (current_tiling_ > ideal_tiling_)
393 return current_tiling_ + 1;
394 else if (current_tiling_)
395 return current_tiling_ - 1;
396 else
397 return ideal_tiling_ + 1;
400 PictureLayerTilingSet::CoverageIterator&
401 PictureLayerTilingSet::CoverageIterator::operator++() {
402 bool first_time = current_tiling_ < 0;
404 if (!*this && !first_time)
405 return *this;
407 if (tiling_iter_)
408 ++tiling_iter_;
410 // Loop until we find a valid place to stop.
411 while (true) {
412 while (tiling_iter_ &&
413 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
414 missing_region_.Union(tiling_iter_.geometry_rect());
415 ++tiling_iter_;
417 if (tiling_iter_)
418 return *this;
420 // If the set of current rects for this tiling is done, go to the next
421 // tiling and set up to iterate through all of the remaining holes.
422 // This will also happen the first time through the loop.
423 if (!region_iter_.has_rect()) {
424 current_tiling_ = NextTiling();
425 current_region_.Swap(&missing_region_);
426 missing_region_.Clear();
427 region_iter_ = Region::Iterator(current_region_);
429 // All done and all filled.
430 if (!region_iter_.has_rect()) {
431 current_tiling_ = set_->tilings_.size();
432 return *this;
435 // No more valid tiles, return this checkerboard rect.
436 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
437 return *this;
440 // Pop a rect off. If there are no more tilings, then these will be
441 // treated as geometry with null tiles that the caller can checkerboard.
442 gfx::Rect last_rect = region_iter_.rect();
443 region_iter_.next();
445 // Done, found next checkerboard rect to return.
446 if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
447 return *this;
449 // Construct a new iterator for the next tiling, but we need to loop
450 // again until we get to a valid one.
451 tiling_iter_ = PictureLayerTiling::CoverageIterator(
452 set_->tilings_[current_tiling_],
453 contents_scale_,
454 last_rect);
457 return *this;
460 PictureLayerTilingSet::CoverageIterator::operator bool() const {
461 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
462 region_iter_.has_rect();
465 void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
466 for (size_t i = 0; i < tilings_.size(); ++i) {
467 state->BeginDictionary();
468 tilings_[i]->AsValueInto(state);
469 state->EndDictionary();
473 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
474 size_t amount = 0;
475 for (size_t i = 0; i < tilings_.size(); ++i)
476 amount += tilings_[i]->GPUMemoryUsageInBytes();
477 return amount;
480 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
481 TilingRangeType type) const {
482 // Doesn't seem to be the case right now but if it ever becomes a performance
483 // problem to compute these ranges each time this function is called, we can
484 // compute them only when the tiling set has changed instead.
485 TilingRange high_res_range(0, 0);
486 TilingRange low_res_range(tilings_.size(), tilings_.size());
487 for (size_t i = 0; i < tilings_.size(); ++i) {
488 const PictureLayerTiling* tiling = tilings_[i];
489 if (tiling->resolution() == HIGH_RESOLUTION)
490 high_res_range = TilingRange(i, i + 1);
491 if (tiling->resolution() == LOW_RESOLUTION)
492 low_res_range = TilingRange(i, i + 1);
495 TilingRange range(0, 0);
496 switch (type) {
497 case HIGHER_THAN_HIGH_RES:
498 range = TilingRange(0, high_res_range.start);
499 break;
500 case HIGH_RES:
501 range = high_res_range;
502 break;
503 case BETWEEN_HIGH_AND_LOW_RES:
504 // TODO(vmpstr): This code assumes that high res tiling will come before
505 // low res tiling, however there are cases where this assumption is
506 // violated. As a result, it's better to be safe in these situations,
507 // since otherwise we can end up accessing a tiling that doesn't exist.
508 // See crbug.com/429397 for high res tiling appearing after low res
509 // tiling discussion/fixes.
510 if (high_res_range.start <= low_res_range.start)
511 range = TilingRange(high_res_range.end, low_res_range.start);
512 else
513 range = TilingRange(low_res_range.end, high_res_range.start);
514 break;
515 case LOW_RES:
516 range = low_res_range;
517 break;
518 case LOWER_THAN_LOW_RES:
519 range = TilingRange(low_res_range.end, tilings_.size());
520 break;
523 DCHECK_LE(range.start, range.end);
524 return range;
527 } // namespace cc