Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / resources / picture_layer_tiling_set.cc
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.
4
5 #include "cc/resources/picture_layer_tiling_set.h"
6
7 #include <limits>
8
9 namespace cc {
10
11 namespace {
12
13 class LargestToSmallestScaleFunctor {
14  public:
15   bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
16     return left->contents_scale() > right->contents_scale();
17   }
18 };
19
20 }  // namespace
21
22 PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client)
23     : client_(client) {
24 }
25
26 PictureLayerTilingSet::~PictureLayerTilingSet() {
27 }
28
29 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
30   client_ = client;
31   for (size_t i = 0; i < tilings_.size(); ++i)
32     tilings_[i]->SetClient(client_);
33 }
34
35 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
36   for (size_t i = 0; i < tilings_.size(); ++i)
37     tilings_[i]->RemoveTilesInRegion(region);
38 }
39
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()) {
45     RemoveAllTilings();
46     return false;
47   }
48
49   tilings_.reserve(other.tilings_.size());
50
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;
60   }
61
62   bool have_high_res_tiling = false;
63
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());
71
72       this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
73                                             new_layer_bounds);
74       this_tiling->CreateMissingTilesInLiveTilesRect();
75       if (this_tiling->resolution() == HIGH_RESOLUTION)
76         have_high_res_tiling = true;
77
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();
84       continue;
85     }
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());
94   }
95   tilings_.sort(LargestToSmallestScaleFunctor());
96
97   return have_high_res_tiling;
98 }
99
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);
105
106   tilings_.push_back(
107       PictureLayerTiling::Create(contents_scale, layer_bounds, client_));
108   PictureLayerTiling* appended = tilings_.back();
109
110   tilings_.sort(LargestToSmallestScaleFunctor());
111   return appended;
112 }
113
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)
118       num_high_res++;
119   }
120   return num_high_res;
121 }
122
123 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
124   for (size_t i = 0; i < tilings_.size(); ++i) {
125     if (tilings_[i]->contents_scale() == scale)
126       return tilings_[i];
127   }
128   return NULL;
129 }
130
131 void PictureLayerTilingSet::RemoveAllTilings() {
132   tilings_.clear();
133 }
134
135 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
136   ScopedPtrVector<PictureLayerTiling>::iterator iter =
137     std::find(tilings_.begin(), tilings_.end(), tiling);
138   if (iter == tilings_.end())
139     return;
140   tilings_.erase(iter);
141 }
142
143 void PictureLayerTilingSet::RemoveAllTiles() {
144   for (size_t i = 0; i < tilings_.size(); ++i)
145     tilings_[i]->Reset();
146 }
147
148 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
149     const PictureLayerTilingSet* set,
150     float contents_scale,
151     const gfx::Rect& content_rect,
152     float ideal_contents_scale)
153     : set_(set),
154       contents_scale_(contents_scale),
155       ideal_contents_scale_(ideal_contents_scale),
156       current_tiling_(-1) {
157   missing_region_.Union(content_rect);
158
159   for (ideal_tiling_ = 0;
160        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
161        ++ideal_tiling_) {
162     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
163     if (tiling->contents_scale() < ideal_contents_scale_) {
164       if (ideal_tiling_ > 0)
165         ideal_tiling_--;
166       break;
167     }
168   }
169
170   DCHECK_LE(set_->tilings_.size(),
171             static_cast<size_t>(std::numeric_limits<int>::max()));
172
173   int num_tilings = set_->tilings_.size();
174   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
175     ideal_tiling_--;
176
177   ++(*this);
178 }
179
180 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
181 }
182
183 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
184   if (!tiling_iter_) {
185     if (!region_iter_.has_rect())
186       return gfx::Rect();
187     return region_iter_.rect();
188   }
189   return tiling_iter_.geometry_rect();
190 }
191
192 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
193   if (!tiling_iter_)
194     return gfx::RectF();
195   return tiling_iter_.texture_rect();
196 }
197
198 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
199   if (!tiling_iter_)
200     return gfx::Size();
201   return tiling_iter_.texture_size();
202 }
203
204 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
205   if (!tiling_iter_)
206     return NULL;
207   return *tiling_iter_;
208 }
209
210 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
211   if (!tiling_iter_)
212     return NULL;
213   return *tiling_iter_;
214 }
215
216 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const {
217   const PictureLayerTiling* tiling = CurrentTiling();
218   DCHECK(tiling);
219   return tiling->resolution();
220 }
221
222 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling()
223     const {
224   if (current_tiling_ < 0)
225     return NULL;
226   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
227     return NULL;
228   return set_->tilings_[current_tiling_];
229 }
230
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;
243   else
244     return ideal_tiling_ + 1;
245 }
246
247 PictureLayerTilingSet::CoverageIterator&
248 PictureLayerTilingSet::CoverageIterator::operator++() {
249   bool first_time = current_tiling_ < 0;
250
251   if (!*this && !first_time)
252     return *this;
253
254   if (tiling_iter_)
255     ++tiling_iter_;
256
257   // Loop until we find a valid place to stop.
258   while (true) {
259     while (tiling_iter_ &&
260            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
261       missing_region_.Union(tiling_iter_.geometry_rect());
262       ++tiling_iter_;
263     }
264     if (tiling_iter_)
265       return *this;
266
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_);
275
276       // All done and all filled.
277       if (!region_iter_.has_rect()) {
278         current_tiling_ = set_->tilings_.size();
279         return *this;
280       }
281
282       // No more valid tiles, return this checkerboard rect.
283       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
284         return *this;
285     }
286
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();
290     region_iter_.next();
291
292     // Done, found next checkerboard rect to return.
293     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
294       return *this;
295
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_],
300         contents_scale_,
301         last_rect);
302   }
303
304   return *this;
305 }
306
307 PictureLayerTilingSet::CoverageIterator::operator bool() const {
308   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
309       region_iter_.has_rect();
310 }
311
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();
317   }
318 }
319
320 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
321   size_t amount = 0;
322   for (size_t i = 0; i < tilings_.size(); ++i)
323     amount += tilings_[i]->GPUMemoryUsageInBytes();
324   return amount;
325 }
326
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);
340   }
341
342   TilingRange range(0, 0);
343   switch (type) {
344     case HIGHER_THAN_HIGH_RES:
345       range = TilingRange(0, high_res_range.start);
346       break;
347     case HIGH_RES:
348       range = high_res_range;
349       break;
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);
359       else
360         range = TilingRange(low_res_range.end, high_res_range.start);
361       break;
362     case LOW_RES:
363       range = low_res_range;
364       break;
365     case LOWER_THAN_LOW_RES:
366       range = TilingRange(low_res_range.end, tilings_.size());
367       break;
368   }
369
370   DCHECK_LE(range.start, range.end);
371   return range;
372 }
373
374 }  // namespace cc