Upstream version 10.39.225.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
23 PictureLayerTilingSet::PictureLayerTilingSet(
24     PictureLayerTilingClient* client,
25     const gfx::Size& layer_bounds)
26     : client_(client),
27       layer_bounds_(layer_bounds) {
28 }
29
30 PictureLayerTilingSet::~PictureLayerTilingSet() {
31 }
32
33 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) {
34   client_ = client;
35   for (size_t i = 0; i < tilings_.size(); ++i)
36     tilings_[i]->SetClient(client_);
37 }
38
39 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
40   for (size_t i = 0; i < tilings_.size(); ++i)
41     tilings_[i]->RemoveTilesInRegion(region);
42 }
43
44 bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other,
45                                         const gfx::Size& new_layer_bounds,
46                                         const Region& layer_invalidation,
47                                         float minimum_contents_scale) {
48   if (new_layer_bounds.IsEmpty()) {
49     RemoveAllTilings();
50     layer_bounds_ = new_layer_bounds;
51     return false;
52   }
53
54   tilings_.reserve(other.tilings_.size());
55
56   // Remove any tilings that aren't in |other| or don't meet the minimum.
57   for (size_t i = 0; i < tilings_.size(); ++i) {
58     float scale = tilings_[i]->contents_scale();
59     if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
60       continue;
61     // Swap with the last element and remove it.
62     tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
63     tilings_.pop_back();
64     --i;
65   }
66
67   bool have_high_res_tiling = false;
68
69   // Add any missing tilings from |other| that meet the minimum.
70   for (size_t i = 0; i < other.tilings_.size(); ++i) {
71     float contents_scale = other.tilings_[i]->contents_scale();
72     if (contents_scale < minimum_contents_scale)
73       continue;
74     if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
75       this_tiling->set_resolution(other.tilings_[i]->resolution());
76
77       this_tiling->UpdateTilesToCurrentPile(layer_invalidation,
78                                             new_layer_bounds);
79       this_tiling->CreateMissingTilesInLiveTilesRect();
80       if (this_tiling->resolution() == HIGH_RESOLUTION)
81         have_high_res_tiling = true;
82
83       DCHECK(this_tiling->tile_size() ==
84              client_->CalculateTileSize(this_tiling->tiling_size()))
85           << "tile_size: " << this_tiling->tile_size().ToString()
86           << " tiling_size: " << this_tiling->tiling_size().ToString()
87           << " CalculateTileSize: "
88           << client_->CalculateTileSize(this_tiling->tiling_size()).ToString();
89       continue;
90     }
91     scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
92         contents_scale,
93         new_layer_bounds,
94         client_);
95     new_tiling->set_resolution(other.tilings_[i]->resolution());
96     if (new_tiling->resolution() == HIGH_RESOLUTION)
97       have_high_res_tiling = true;
98     tilings_.push_back(new_tiling.Pass());
99   }
100   tilings_.sort(LargestToSmallestScaleFunctor());
101
102   layer_bounds_ = new_layer_bounds;
103   return have_high_res_tiling;
104 }
105
106 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
107   for (size_t i = 0; i < tilings_.size(); ++i)
108     DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
109
110   tilings_.push_back(PictureLayerTiling::Create(contents_scale,
111                                                 layer_bounds_,
112                                                 client_));
113   PictureLayerTiling* appended = tilings_.back();
114
115   tilings_.sort(LargestToSmallestScaleFunctor());
116   return appended;
117 }
118
119 int PictureLayerTilingSet::NumHighResTilings() const {
120   int num_high_res = 0;
121   for (size_t i = 0; i < tilings_.size(); ++i) {
122     if (tilings_[i]->resolution() == HIGH_RESOLUTION)
123       num_high_res++;
124   }
125   return num_high_res;
126 }
127
128 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
129   for (size_t i = 0; i < tilings_.size(); ++i) {
130     if (tilings_[i]->contents_scale() == scale)
131       return tilings_[i];
132   }
133   return NULL;
134 }
135
136 void PictureLayerTilingSet::RemoveAllTilings() {
137   tilings_.clear();
138 }
139
140 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
141   ScopedPtrVector<PictureLayerTiling>::iterator iter =
142     std::find(tilings_.begin(), tilings_.end(), tiling);
143   if (iter == tilings_.end())
144     return;
145   tilings_.erase(iter);
146 }
147
148 void PictureLayerTilingSet::RemoveAllTiles() {
149   for (size_t i = 0; i < tilings_.size(); ++i)
150     tilings_[i]->Reset();
151 }
152
153 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
154     const PictureLayerTilingSet* set,
155     float contents_scale,
156     const gfx::Rect& content_rect,
157     float ideal_contents_scale)
158     : set_(set),
159       contents_scale_(contents_scale),
160       ideal_contents_scale_(ideal_contents_scale),
161       current_tiling_(-1) {
162   missing_region_.Union(content_rect);
163
164   for (ideal_tiling_ = 0;
165        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
166        ++ideal_tiling_) {
167     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
168     if (tiling->contents_scale() < ideal_contents_scale_) {
169       if (ideal_tiling_ > 0)
170         ideal_tiling_--;
171       break;
172     }
173   }
174
175   DCHECK_LE(set_->tilings_.size(),
176             static_cast<size_t>(std::numeric_limits<int>::max()));
177
178   int num_tilings = set_->tilings_.size();
179   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
180     ideal_tiling_--;
181
182   ++(*this);
183 }
184
185 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
186 }
187
188 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
189   if (!tiling_iter_) {
190     if (!region_iter_.has_rect())
191       return gfx::Rect();
192     return region_iter_.rect();
193   }
194   return tiling_iter_.geometry_rect();
195 }
196
197 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
198   if (!tiling_iter_)
199     return gfx::RectF();
200   return tiling_iter_.texture_rect();
201 }
202
203 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
204   if (!tiling_iter_)
205     return gfx::Size();
206   return tiling_iter_.texture_size();
207 }
208
209 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
210   if (!tiling_iter_)
211     return NULL;
212   return *tiling_iter_;
213 }
214
215 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
216   if (!tiling_iter_)
217     return NULL;
218   return *tiling_iter_;
219 }
220
221 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
222   if (current_tiling_ < 0)
223     return NULL;
224   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
225     return NULL;
226   return set_->tilings_[current_tiling_];
227 }
228
229 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
230   // Order returned by this method is:
231   // 1. Ideal tiling index
232   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
233   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
234   // 4. Tiling index > tilings.size() (invalid index)
235   if (current_tiling_ < 0)
236     return ideal_tiling_;
237   else if (current_tiling_ > ideal_tiling_)
238     return current_tiling_ + 1;
239   else if (current_tiling_)
240     return current_tiling_ - 1;
241   else
242     return ideal_tiling_ + 1;
243 }
244
245 PictureLayerTilingSet::CoverageIterator&
246 PictureLayerTilingSet::CoverageIterator::operator++() {
247   bool first_time = current_tiling_ < 0;
248
249   if (!*this && !first_time)
250     return *this;
251
252   if (tiling_iter_)
253     ++tiling_iter_;
254
255   // Loop until we find a valid place to stop.
256   while (true) {
257     while (tiling_iter_ &&
258            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
259       missing_region_.Union(tiling_iter_.geometry_rect());
260       ++tiling_iter_;
261     }
262     if (tiling_iter_)
263       return *this;
264
265     // If the set of current rects for this tiling is done, go to the next
266     // tiling and set up to iterate through all of the remaining holes.
267     // This will also happen the first time through the loop.
268     if (!region_iter_.has_rect()) {
269       current_tiling_ = NextTiling();
270       current_region_.Swap(&missing_region_);
271       missing_region_.Clear();
272       region_iter_ = Region::Iterator(current_region_);
273
274       // All done and all filled.
275       if (!region_iter_.has_rect()) {
276         current_tiling_ = set_->tilings_.size();
277         return *this;
278       }
279
280       // No more valid tiles, return this checkerboard rect.
281       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
282         return *this;
283     }
284
285     // Pop a rect off.  If there are no more tilings, then these will be
286     // treated as geometry with null tiles that the caller can checkerboard.
287     gfx::Rect last_rect = region_iter_.rect();
288     region_iter_.next();
289
290     // Done, found next checkerboard rect to return.
291     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
292       return *this;
293
294     // Construct a new iterator for the next tiling, but we need to loop
295     // again until we get to a valid one.
296     tiling_iter_ = PictureLayerTiling::CoverageIterator(
297         set_->tilings_[current_tiling_],
298         contents_scale_,
299         last_rect);
300   }
301
302   return *this;
303 }
304
305 PictureLayerTilingSet::CoverageIterator::operator bool() const {
306   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
307       region_iter_.has_rect();
308 }
309
310 void PictureLayerTilingSet::DidBecomeActive() {
311   for (size_t i = 0; i < tilings_.size(); ++i)
312     tilings_[i]->DidBecomeActive();
313 }
314
315 void PictureLayerTilingSet::DidBecomeRecycled() {
316   for (size_t i = 0; i < tilings_.size(); ++i)
317     tilings_[i]->DidBecomeRecycled();
318 }
319
320 void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
321   for (size_t i = 0; i < tilings_.size(); ++i) {
322     state->BeginDictionary();
323     tilings_[i]->AsValueInto(state);
324     state->EndDictionary();
325   }
326 }
327
328 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
329   size_t amount = 0;
330   for (size_t i = 0; i < tilings_.size(); ++i)
331     amount += tilings_[i]->GPUMemoryUsageInBytes();
332   return amount;
333 }
334
335 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange(
336     TilingRangeType type) const {
337   // Doesn't seem to be the case right now but if it ever becomes a performance
338   // problem to compute these ranges each time this function is called, we can
339   // compute them only when the tiling set has changed instead.
340   TilingRange high_res_range(0, 0);
341   TilingRange low_res_range(tilings_.size(), tilings_.size());
342   for (size_t i = 0; i < tilings_.size(); ++i) {
343     const PictureLayerTiling* tiling = tilings_[i];
344     if (tiling->resolution() == HIGH_RESOLUTION)
345       high_res_range = TilingRange(i, i + 1);
346     if (tiling->resolution() == LOW_RESOLUTION)
347       low_res_range = TilingRange(i, i + 1);
348   }
349
350   switch (type) {
351     case HIGHER_THAN_HIGH_RES:
352       return TilingRange(0, high_res_range.start);
353     case HIGH_RES:
354       return high_res_range;
355     case BETWEEN_HIGH_AND_LOW_RES:
356       return TilingRange(high_res_range.end, low_res_range.start);
357     case LOW_RES:
358       return low_res_range;
359     case LOWER_THAN_LOW_RES:
360       return TilingRange(low_res_range.end, tilings_.size());
361   }
362
363   NOTREACHED();
364   return TilingRange(0, 0);
365 }
366
367 }  // namespace cc