- add sources.
[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     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     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->ContentRect().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::SetCanUseLCDText(bool can_use_lcd_text) {
96   for (size_t i = 0; i < tilings_.size(); ++i)
97     tilings_[i]->SetCanUseLCDText(can_use_lcd_text);
98 }
99
100 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) {
101   for (size_t i = 0; i < tilings_.size(); ++i)
102     DCHECK_NE(tilings_[i]->contents_scale(), contents_scale);
103
104   tilings_.push_back(PictureLayerTiling::Create(contents_scale,
105                                                 layer_bounds_,
106                                                 client_));
107   PictureLayerTiling* appended = tilings_.back();
108
109   tilings_.sort(LargestToSmallestScaleFunctor());
110   return appended;
111 }
112
113 int PictureLayerTilingSet::NumHighResTilings() const {
114   int num_high_res = 0;
115   for (size_t i = 0; i < tilings_.size(); ++i) {
116     if (tilings_[i]->resolution() == HIGH_RESOLUTION)
117       num_high_res++;
118   }
119   return num_high_res;
120 }
121
122 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const {
123   for (size_t i = 0; i < tilings_.size(); ++i) {
124     if (tilings_[i]->contents_scale() == scale)
125       return tilings_[i];
126   }
127   return NULL;
128 }
129
130 void PictureLayerTilingSet::RemoveAllTilings() {
131   tilings_.clear();
132 }
133
134 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) {
135   ScopedPtrVector<PictureLayerTiling>::iterator iter =
136     std::find(tilings_.begin(), tilings_.end(), tiling);
137   if (iter == tilings_.end())
138     return;
139   tilings_.erase(iter);
140 }
141
142 void PictureLayerTilingSet::RemoveAllTiles() {
143   for (size_t i = 0; i < tilings_.size(); ++i)
144     tilings_[i]->Reset();
145 }
146
147 PictureLayerTilingSet::CoverageIterator::CoverageIterator(
148     const PictureLayerTilingSet* set,
149     float contents_scale,
150     gfx::Rect content_rect,
151     float ideal_contents_scale)
152     : set_(set),
153       contents_scale_(contents_scale),
154       ideal_contents_scale_(ideal_contents_scale),
155       current_tiling_(-1) {
156   missing_region_.Union(content_rect);
157
158   for (ideal_tiling_ = 0;
159        static_cast<size_t>(ideal_tiling_) < set_->tilings_.size();
160        ++ideal_tiling_) {
161     PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_];
162     if (tiling->contents_scale() < ideal_contents_scale_) {
163       if (ideal_tiling_ > 0)
164         ideal_tiling_--;
165       break;
166     }
167   }
168
169   DCHECK_LE(set_->tilings_.size(),
170             static_cast<size_t>(std::numeric_limits<int>::max()));
171
172   int num_tilings = set_->tilings_.size();
173   if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0)
174     ideal_tiling_--;
175
176   ++(*this);
177 }
178
179 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
180 }
181
182 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const {
183   if (!tiling_iter_) {
184     if (!region_iter_.has_rect())
185       return gfx::Rect();
186     return region_iter_.rect();
187   }
188   return tiling_iter_.geometry_rect();
189 }
190
191 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
192   if (!tiling_iter_)
193     return gfx::RectF();
194   return tiling_iter_.texture_rect();
195 }
196
197 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
198   if (!tiling_iter_)
199     return gfx::Size();
200   return tiling_iter_.texture_size();
201 }
202
203 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
204   if (!tiling_iter_)
205     return NULL;
206   return *tiling_iter_;
207 }
208
209 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
210   if (!tiling_iter_)
211     return NULL;
212   return *tiling_iter_;
213 }
214
215 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() {
216   if (current_tiling_ < 0)
217     return NULL;
218   if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size())
219     return NULL;
220   return set_->tilings_[current_tiling_];
221 }
222
223 int PictureLayerTilingSet::CoverageIterator::NextTiling() const {
224   // Order returned by this method is:
225   // 1. Ideal tiling index
226   // 2. Tiling index < Ideal in decreasing order (higher res than ideal)
227   // 3. Tiling index > Ideal in increasing order (lower res than ideal)
228   // 4. Tiling index > tilings.size() (invalid index)
229   if (current_tiling_ < 0)
230     return ideal_tiling_;
231   else if (current_tiling_ > ideal_tiling_)
232     return current_tiling_ + 1;
233   else if (current_tiling_)
234     return current_tiling_ - 1;
235   else
236     return ideal_tiling_ + 1;
237 }
238
239 PictureLayerTilingSet::CoverageIterator&
240 PictureLayerTilingSet::CoverageIterator::operator++() {
241   bool first_time = current_tiling_ < 0;
242
243   if (!*this && !first_time)
244     return *this;
245
246   if (tiling_iter_)
247     ++tiling_iter_;
248
249   // Loop until we find a valid place to stop.
250   while (true) {
251     while (tiling_iter_ &&
252            (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) {
253       missing_region_.Union(tiling_iter_.geometry_rect());
254       ++tiling_iter_;
255     }
256     if (tiling_iter_)
257       return *this;
258
259     // If the set of current rects for this tiling is done, go to the next
260     // tiling and set up to iterate through all of the remaining holes.
261     // This will also happen the first time through the loop.
262     if (!region_iter_.has_rect()) {
263       current_tiling_ = NextTiling();
264       current_region_.Swap(&missing_region_);
265       missing_region_.Clear();
266       region_iter_ = Region::Iterator(current_region_);
267
268       // All done and all filled.
269       if (!region_iter_.has_rect()) {
270         current_tiling_ = set_->tilings_.size();
271         return *this;
272       }
273
274       // No more valid tiles, return this checkerboard rect.
275       if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
276         return *this;
277     }
278
279     // Pop a rect off.  If there are no more tilings, then these will be
280     // treated as geometry with null tiles that the caller can checkerboard.
281     gfx::Rect last_rect = region_iter_.rect();
282     region_iter_.next();
283
284     // Done, found next checkerboard rect to return.
285     if (current_tiling_ >= static_cast<int>(set_->tilings_.size()))
286       return *this;
287
288     // Construct a new iterator for the next tiling, but we need to loop
289     // again until we get to a valid one.
290     tiling_iter_ = PictureLayerTiling::CoverageIterator(
291         set_->tilings_[current_tiling_],
292         contents_scale_,
293         last_rect);
294   }
295
296   return *this;
297 }
298
299 PictureLayerTilingSet::CoverageIterator::operator bool() const {
300   return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
301       region_iter_.has_rect();
302 }
303
304 void PictureLayerTilingSet::UpdateTilePriorities(
305     WhichTree tree,
306     gfx::Size device_viewport,
307     gfx::Rect viewport_in_content_space,
308     gfx::Rect visible_content_rect,
309     gfx::Size last_layer_bounds,
310     gfx::Size current_layer_bounds,
311     float last_layer_contents_scale,
312     float current_layer_contents_scale,
313     const gfx::Transform& last_screen_transform,
314     const gfx::Transform& current_screen_transform,
315     double current_frame_time_in_seconds,
316     size_t max_tiles_for_interest_area) {
317   gfx::Rect viewport_in_layer_space = gfx::ScaleToEnclosingRect(
318       viewport_in_content_space,
319       1.f / current_layer_contents_scale);
320   gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
321       visible_content_rect,
322       1.f / current_layer_contents_scale);
323
324   for (size_t i = 0; i < tilings_.size(); ++i) {
325     tilings_[i]->UpdateTilePriorities(
326         tree,
327         device_viewport,
328         viewport_in_layer_space,
329         visible_layer_rect,
330         last_layer_bounds,
331         current_layer_bounds,
332         last_layer_contents_scale,
333         current_layer_contents_scale,
334         last_screen_transform,
335         current_screen_transform,
336         current_frame_time_in_seconds,
337         max_tiles_for_interest_area);
338   }
339 }
340
341 void PictureLayerTilingSet::DidBecomeActive() {
342   for (size_t i = 0; i < tilings_.size(); ++i)
343     tilings_[i]->DidBecomeActive();
344 }
345
346 void PictureLayerTilingSet::DidBecomeRecycled() {
347   for (size_t i = 0; i < tilings_.size(); ++i)
348     tilings_[i]->DidBecomeRecycled();
349 }
350
351 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
352   scoped_ptr<base::ListValue> state(new base::ListValue());
353   for (size_t i = 0; i < tilings_.size(); ++i)
354     state->Append(tilings_[i]->AsValue().release());
355   return state.PassAs<base::Value>();
356 }
357
358 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
359   size_t amount = 0;
360   for (size_t i = 0; i < tilings_.size(); ++i)
361     amount += tilings_[i]->GPUMemoryUsageInBytes();
362   return amount;
363 }
364
365 }  // namespace cc