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:
operator ()(PictureLayerTiling * left,PictureLayerTiling * right)15 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) {
16 return left->contents_scale() > right->contents_scale();
17 }
18 };
19
20 } // namespace
21
22
PictureLayerTilingSet(PictureLayerTilingClient * client,gfx::Size layer_bounds)23 PictureLayerTilingSet::PictureLayerTilingSet(
24 PictureLayerTilingClient* client,
25 gfx::Size layer_bounds)
26 : client_(client),
27 layer_bounds_(layer_bounds) {
28 }
29
~PictureLayerTilingSet()30 PictureLayerTilingSet::~PictureLayerTilingSet() {
31 }
32
SetClient(PictureLayerTilingClient * client)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
SyncTilings(const PictureLayerTilingSet & other,gfx::Size new_layer_bounds,const Region & layer_invalidation,float minimum_contents_scale)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
SetCanUseLCDText(bool can_use_lcd_text)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
AddTiling(float contents_scale)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
NumHighResTilings() const113 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
TilingAtScale(float scale) const122 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
RemoveAllTilings()130 void PictureLayerTilingSet::RemoveAllTilings() {
131 tilings_.clear();
132 }
133
Remove(PictureLayerTiling * tiling)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
RemoveAllTiles()142 void PictureLayerTilingSet::RemoveAllTiles() {
143 for (size_t i = 0; i < tilings_.size(); ++i)
144 tilings_[i]->Reset();
145 }
146
CoverageIterator(const PictureLayerTilingSet * set,float contents_scale,gfx::Rect content_rect,float ideal_contents_scale)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
~CoverageIterator()179 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() {
180 }
181
geometry_rect() const182 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
texture_rect() const191 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const {
192 if (!tiling_iter_)
193 return gfx::RectF();
194 return tiling_iter_.texture_rect();
195 }
196
texture_size() const197 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const {
198 if (!tiling_iter_)
199 return gfx::Size();
200 return tiling_iter_.texture_size();
201 }
202
operator ->() const203 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const {
204 if (!tiling_iter_)
205 return NULL;
206 return *tiling_iter_;
207 }
208
operator *() const209 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const {
210 if (!tiling_iter_)
211 return NULL;
212 return *tiling_iter_;
213 }
214
CurrentTiling()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
NextTiling() const223 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&
operator ++()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
operator bool() const299 PictureLayerTilingSet::CoverageIterator::operator bool() const {
300 return current_tiling_ < static_cast<int>(set_->tilings_.size()) ||
301 region_iter_.has_rect();
302 }
303
UpdateTilePriorities(WhichTree tree,gfx::Size device_viewport,gfx::Rect viewport_in_content_space,gfx::Rect visible_content_rect,gfx::Size last_layer_bounds,gfx::Size current_layer_bounds,float last_layer_contents_scale,float current_layer_contents_scale,const gfx::Transform & last_screen_transform,const gfx::Transform & current_screen_transform,double current_frame_time_in_seconds,size_t max_tiles_for_interest_area)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
DidBecomeActive()341 void PictureLayerTilingSet::DidBecomeActive() {
342 for (size_t i = 0; i < tilings_.size(); ++i)
343 tilings_[i]->DidBecomeActive();
344 }
345
DidBecomeRecycled()346 void PictureLayerTilingSet::DidBecomeRecycled() {
347 for (size_t i = 0; i < tilings_.size(); ++i)
348 tilings_[i]->DidBecomeRecycled();
349 }
350
AsValue() const351 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
GPUMemoryUsageInBytes() const358 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
366