Upstream version 7.36.149.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::SyncTilings(
40     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     layer_bounds_ = new_layer_bounds;
47     return;
48   }
49
50   tilings_.reserve(other.tilings_.size());
51
52   // Remove any tilings that aren't in |other| or don't meet the minimum.
53   for (size_t i = 0; i < tilings_.size(); ++i) {
54     float scale = tilings_[i]->contents_scale();
55     if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale))
56       continue;
57     // Swap with the last element and remove it.
58     tilings_.swap(tilings_.begin() + i, tilings_.end() - 1);
59     tilings_.pop_back();
60     --i;
61   }
62
63   // Add any missing tilings from |other| that meet the minimum.
64   for (size_t i = 0; i < other.tilings_.size(); ++i) {
65     float contents_scale = other.tilings_[i]->contents_scale();
66     if (contents_scale < minimum_contents_scale)
67       continue;
68     if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) {
69       this_tiling->set_resolution(other.tilings_[i]->resolution());
70
71       // These two calls must come before updating the pile, because they may
72       // destroy tiles that the new pile cannot raster.
73       this_tiling->SetLayerBounds(new_layer_bounds);
74       this_tiling->Invalidate(layer_invalidation);
75
76       this_tiling->UpdateTilesToCurrentPile();
77       this_tiling->CreateMissingTilesInLiveTilesRect();
78
79       DCHECK(this_tiling->tile_size() ==
80              client_->CalculateTileSize(this_tiling->TilingRect().size()));
81       continue;
82     }
83     scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create(
84         contents_scale,
85         new_layer_bounds,
86         client_);
87     new_tiling->set_resolution(other.tilings_[i]->resolution());
88     tilings_.push_back(new_tiling.Pass());
89   }
90   tilings_.sort(LargestToSmallestScaleFunctor());
91
92   layer_bounds_ = new_layer_bounds;
93 }
94
95 void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) {
96   for (size_t i = 0; i < tilings_.size(); ++i)
97     tilings_[i]->RemoveTilesInRegion(region);
98 }
99
100 void PictureLayerTilingSet::SetCanUseLCDText(bool can_use_lcd_text) {
101   for (size_t i = 0; i < tilings_.size(); ++i)
102     tilings_[i]->SetCanUseLCDText(can_use_lcd_text);
103 }
104
105 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
106   for (size_t i = 0; i < tilings_.size(); ++i) {
107     // TODO(enne): temporary sanity CHECK for http://crbug.com/358350.
108     // If a duplicate tiling gets added, then many assumptions in
109     // PictureLayerImpl fail.
110     CHECK_NE(tilings_[i]->contents_scale(), contents_scale);
111   }
112
113   tilings_.push_back(PictureLayerTiling::Create(contents_scale,
114                                                 layer_bounds_,
115                                                 client_));
116   PictureLayerTiling* appended = tilings_.back();
117
118   tilings_.sort(LargestToSmallestScaleFunctor());
119   return appended;
120 }
121
122 int PictureLayerTilingSet::NumHighResTilings() const {
123   int num_high_res = 0;
124   for (size_t i = 0; i < tilings_.size(); ++i) {
125     if (tilings_[i]->resolution() == HIGH_RESOLUTION)
126       num_high_res++;
127   }
128   return num_high_res;
129 }
130
131 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
132   for (size_t i = 0; i < tilings_.size(); ++i) {
133     if (tilings_[i]->contents_scale() == scale)
134       return tilings_[i];
135   }
136   return NULL;
137 }
138
139 void PictureLayerTilingSet::RemoveAllTilings() {
140   tilings_.clear();
141 }
142
143 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
144   ScopedPtrVector<PictureLayerTiling>::iterator iter =
145     std::find(tilings_.begin(), tilings_.end(), tiling);
146   if (iter == tilings_.end())
147     return;
148   tilings_.erase(iter);
149 }
150
151 void PictureLayerTilingSet::RemoveAllTiles() {
152   for (size_t i = 0; i < tilings_.size(); ++i)
153     tilings_[i]->Reset();
154 }
155
156 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
157     const PictureLayerTilingSet* set,
158     float contents_scale,
159     const gfx::Rect& content_rect,
160     float ideal_contents_scale)
161     : set_(set),
162       contents_scale_(contents_scale),
163       ideal_contents_scale_(ideal_contents_scale),
164       current_tiling_(-1) {
165   missing_region_.Union(content_rect);
166
167   for (ideal_tiling_ = 0;
168        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
169        ++ideal_tiling_) {
170     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
171     if (tiling->contents_scale() < ideal_contents_scale_) {
172       if (ideal_tiling_ > 0)
173         ideal_tiling_--;
174       break;
175     }
176   }
177
178   DCHECK_LE(set_->tilings_.size(),
179             static_cast<size_t>(std::numeric_limits<int>::max()));
180
181   int num_tilings = set_->tilings_.size();
182   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
183     ideal_tiling_--;
184
185   ++(*this);
186 }
187
188 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
189 }
190
191 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
192   if (!tiling_iter_) {
193     if (!region_iter_.has_rect())
194       return gfx::Rect();
195     return region_iter_.rect();
196   }
197   return tiling_iter_.geometry_rect();
198 }
199
200 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
201   if (!tiling_iter_)
202     return gfx::RectF();
203   return tiling_iter_.texture_rect();
204 }
205
206 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
207   if (!tiling_iter_)
208     return gfx::Size();
209   return tiling_iter_.texture_size();
210 }
211
212 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
213   if (!tiling_iter_)
214     return NULL;
215   return *tiling_iter_;
216 }
217
218 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
219   if (!tiling_iter_)
220     return NULL;
221   return *tiling_iter_;
222 }
223
224 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
225   if (current_tiling_ < 0)
226     return NULL;
227   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
228     return NULL;
229   return set_->tilings_[current_tiling_];
230 }
231
232 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
233   // Order returned by this method is:
234   // 1. Ideal tiling index
235   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
236   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
237   // 4. Tiling index > tilings.size() (invalid index)
238   if (current_tiling_ < 0)
239     return ideal_tiling_;
240   else if (current_tiling_ > ideal_tiling_)
241     return current_tiling_ + 1;
242   else if (current_tiling_)
243     return current_tiling_ - 1;
244   else
245     return ideal_tiling_ + 1;
246 }
247
248 PictureLayerTilingSet::CoverageIterator&
249 PictureLayerTilingSet::CoverageIterator::operator++() {
250   bool first_time = current_tiling_ < 0;
251
252   if (!*this && !first_time)
253     return *this;
254
255   if (tiling_iter_)
256     ++tiling_iter_;
257
258   // Loop until we find a valid place to stop.
259   while (true) {
260     while (tiling_iter_ &&
261            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
262       missing_region_.Union(tiling_iter_.geometry_rect());
263       ++tiling_iter_;
264     }
265     if (tiling_iter_)
266       return *this;
267
268     // If the set of current rects for this tiling is done, go to the next
269     // tiling and set up to iterate through all of the remaining holes.
270     // This will also happen the first time through the loop.
271     if (!region_iter_.has_rect()) {
272       current_tiling_ = NextTiling();
273       current_region_.Swap(&missing_region_);
274       missing_region_.Clear();
275       region_iter_ = Region::Iterator(current_region_);
276
277       // All done and all filled.
278       if (!region_iter_.has_rect()) {
279         current_tiling_ = set_->tilings_.size();
280         return *this;
281       }
282
283       // No more valid tiles, return this checkerboard rect.
284       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
285         return *this;
286     }
287
288     // Pop a rect off.  If there are no more tilings, then these will be
289     // treated as geometry with null tiles that the caller can checkerboard.
290     gfx::Rect last_rect = region_iter_.rect();
291     region_iter_.next();
292
293     // Done, found next checkerboard rect to return.
294     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
295       return *this;
296
297     // Construct a new iterator for the next tiling, but we need to loop
298     // again until we get to a valid one.
299     tiling_iter_ = PictureLayerTiling::CoverageIterator(
300         set_->tilings_[current_tiling_],
301         contents_scale_,
302         last_rect);
303   }
304
305   return *this;
306 }
307
308 PictureLayerTilingSet::CoverageIterator::operator bool() const {
309   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
310       region_iter_.has_rect();
311 }
312
313 void PictureLayerTilingSet::UpdateTilePriorities(
314     WhichTree tree,
315     const gfx::Rect& visible_content_rect,
316     float layer_contents_scale,
317     double current_frame_time_in_seconds) {
318   gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
319       visible_content_rect, 1.f / layer_contents_scale);
320
321   for (size_t i = 0; i < tilings_.size(); ++i) {
322     tilings_[i]->UpdateTilePriorities(tree,
323                                       visible_layer_rect,
324                                       layer_contents_scale,
325                                       current_frame_time_in_seconds);
326   }
327 }
328
329 void PictureLayerTilingSet::DidBecomeActive() {
330   for (size_t i = 0; i < tilings_.size(); ++i)
331     tilings_[i]->DidBecomeActive();
332 }
333
334 void PictureLayerTilingSet::DidBecomeRecycled() {
335   for (size_t i = 0; i < tilings_.size(); ++i)
336     tilings_[i]->DidBecomeRecycled();
337 }
338
339 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
340   scoped_ptr<base::ListValue> state(new base::ListValue());
341   for (size_t i = 0; i < tilings_.size(); ++i)
342     state->Append(tilings_[i]->AsValue().release());
343   return state.PassAs<base::Value>();
344 }
345
346 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
347   size_t amount = 0;
348   for (size_t i = 0; i < tilings_.size(); ++i)
349     amount += tilings_[i]->GPUMemoryUsageInBytes();
350   return amount;
351 }
352
353 }  // namespace cc