OLD | NEW |
| (Empty) |
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/picture_layer_impl.h" | |
6 | |
7 #include "base/time.h" | |
8 #include "cc/append_quads_data.h" | |
9 #include "cc/base/math_util.h" | |
10 #include "cc/base/util.h" | |
11 #include "cc/debug/debug_colors.h" | |
12 #include "cc/quad_sink.h" | |
13 #include "cc/quads/checkerboard_draw_quad.h" | |
14 #include "cc/quads/debug_border_draw_quad.h" | |
15 #include "cc/quads/solid_color_draw_quad.h" | |
16 #include "cc/quads/tile_draw_quad.h" | |
17 #include "cc/trees/layer_tree_impl.h" | |
18 #include "ui/gfx/quad_f.h" | |
19 #include "ui/gfx/rect_conversions.h" | |
20 #include "ui/gfx/size_conversions.h" | |
21 | |
22 namespace { | |
23 const float kMaxScaleRatioDuringPinch = 2.0f; | |
24 } | |
25 | |
26 namespace cc { | |
27 | |
28 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) | |
29 : LayerImpl(tree_impl, id), | |
30 pile_(PicturePileImpl::Create()), | |
31 last_content_scale_(0), | |
32 ideal_contents_scale_(0), | |
33 is_mask_(false), | |
34 ideal_page_scale_(0.f), | |
35 ideal_device_scale_(0.f), | |
36 ideal_source_scale_(0.f), | |
37 raster_page_scale_(0.f), | |
38 raster_device_scale_(0.f), | |
39 raster_source_scale_(0.f), | |
40 raster_source_scale_was_animating_(false) { | |
41 } | |
42 | |
43 PictureLayerImpl::~PictureLayerImpl() { | |
44 } | |
45 | |
46 const char* PictureLayerImpl::LayerTypeAsString() const { | |
47 return "PictureLayer"; | |
48 } | |
49 | |
50 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( | |
51 LayerTreeImpl* tree_impl) { | |
52 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); | |
53 } | |
54 | |
55 void PictureLayerImpl::CreateTilingSet() { | |
56 DCHECK(layer_tree_impl()->IsPendingTree()); | |
57 DCHECK(!tilings_); | |
58 tilings_.reset(new PictureLayerTilingSet(this)); | |
59 tilings_->SetLayerBounds(bounds()); | |
60 } | |
61 | |
62 void PictureLayerImpl::TransferTilingSet( | |
63 scoped_ptr<PictureLayerTilingSet> tilings) { | |
64 DCHECK(layer_tree_impl()->IsActiveTree()); | |
65 tilings->SetClient(this); | |
66 tilings_ = tilings.Pass(); | |
67 } | |
68 | |
69 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { | |
70 LayerImpl::PushPropertiesTo(base_layer); | |
71 | |
72 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); | |
73 | |
74 layer_impl->SetIsMask(is_mask_); | |
75 layer_impl->TransferTilingSet(tilings_.Pass()); | |
76 layer_impl->pile_ = pile_; | |
77 pile_ = PicturePileImpl::Create(); | |
78 | |
79 layer_impl->raster_page_scale_ = raster_page_scale_; | |
80 layer_impl->raster_device_scale_ = raster_device_scale_; | |
81 layer_impl->raster_source_scale_ = raster_source_scale_; | |
82 } | |
83 | |
84 | |
85 void PictureLayerImpl::AppendQuads(QuadSink* quadSink, | |
86 AppendQuadsData* appendQuadsData) { | |
87 const gfx::Rect& rect = visible_content_rect(); | |
88 gfx::Rect content_rect(content_bounds()); | |
89 | |
90 SharedQuadState* sharedQuadState = | |
91 quadSink->UseSharedQuadState(CreateSharedQuadState()); | |
92 AppendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData); | |
93 | |
94 bool clipped = false; | |
95 gfx::QuadF target_quad = MathUtil::MapQuad( | |
96 draw_transform(), | |
97 gfx::QuadF(rect), | |
98 &clipped); | |
99 bool is_axis_aligned_in_target = !clipped && target_quad.IsRectilinear(); | |
100 | |
101 bool is_pixel_aligned = is_axis_aligned_in_target && | |
102 draw_transform().IsIdentityOrIntegerTranslation(); | |
103 PictureLayerTiling::LayerDeviceAlignment layerDeviceAlignment = | |
104 is_pixel_aligned ? PictureLayerTiling::LayerAlignedToDevice | |
105 : PictureLayerTiling::LayerNotAlignedToDevice; | |
106 | |
107 if (ShowDebugBorders()) { | |
108 for (PictureLayerTilingSet::Iterator iter(tilings_.get(), | |
109 contents_scale_x(), | |
110 rect, | |
111 ideal_contents_scale_, | |
112 layerDeviceAlignment); | |
113 iter; | |
114 ++iter) { | |
115 SkColor color; | |
116 float width; | |
117 if (*iter && iter->drawing_info().IsReadyToDraw()) { | |
118 ManagedTileState::DrawingInfo::Mode mode = iter->drawing_info().mode(); | |
119 if (mode == ManagedTileState::DrawingInfo::SOLID_COLOR_MODE || | |
120 mode == ManagedTileState::DrawingInfo::TRANSPARENT_MODE) { | |
121 color = DebugColors::SolidColorTileBorderColor(); | |
122 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl()); | |
123 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) { | |
124 color = DebugColors::HighResTileBorderColor(); | |
125 width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); | |
126 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) { | |
127 color = DebugColors::LowResTileBorderColor(); | |
128 width = DebugColors::LowResTileBorderWidth(layer_tree_impl()); | |
129 } else if (iter->contents_scale() > contents_scale_x()) { | |
130 color = DebugColors::ExtraHighResTileBorderColor(); | |
131 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl()); | |
132 } else { | |
133 color = DebugColors::ExtraLowResTileBorderColor(); | |
134 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl()); | |
135 } | |
136 } else { | |
137 color = DebugColors::MissingTileBorderColor(); | |
138 width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); | |
139 } | |
140 | |
141 scoped_ptr<DebugBorderDrawQuad> debugBorderQuad = | |
142 DebugBorderDrawQuad::Create(); | |
143 gfx::Rect geometry_rect = iter.geometry_rect(); | |
144 debugBorderQuad->SetNew(sharedQuadState, geometry_rect, color, width); | |
145 quadSink->Append(debugBorderQuad.PassAs<DrawQuad>(), appendQuadsData); | |
146 } | |
147 } | |
148 | |
149 // Keep track of the tilings that were used so that tilings that are | |
150 // unused can be considered for removal. | |
151 std::vector<PictureLayerTiling*> seen_tilings; | |
152 | |
153 for (PictureLayerTilingSet::Iterator iter(tilings_.get(), | |
154 contents_scale_x(), | |
155 rect, | |
156 ideal_contents_scale_, | |
157 layerDeviceAlignment); | |
158 iter; | |
159 ++iter) { | |
160 | |
161 gfx::Rect geometry_rect = iter.geometry_rect(); | |
162 if (!*iter || !iter->drawing_info().IsReadyToDraw()) { | |
163 if (DrawCheckerboardForMissingTiles()) { | |
164 // TODO(enne): Figure out how to show debug "invalidated checker" color | |
165 scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create(); | |
166 SkColor color = DebugColors::DefaultCheckerboardColor(); | |
167 quad->SetNew(sharedQuadState, geometry_rect, color); | |
168 if (quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData)) | |
169 appendQuadsData->numMissingTiles++; | |
170 } else { | |
171 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); | |
172 quad->SetNew(sharedQuadState, geometry_rect, background_color()); | |
173 if (quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData)) | |
174 appendQuadsData->numMissingTiles++; | |
175 } | |
176 | |
177 appendQuadsData->hadIncompleteTile = true; | |
178 continue; | |
179 } | |
180 | |
181 const ManagedTileState::DrawingInfo& drawing_info = iter->drawing_info(); | |
182 switch (drawing_info.mode()) { | |
183 case ManagedTileState::DrawingInfo::TEXTURE_MODE: { | |
184 if (iter->contents_scale() != ideal_contents_scale_) | |
185 appendQuadsData->hadIncompleteTile = true; | |
186 | |
187 gfx::RectF texture_rect = iter.texture_rect(); | |
188 gfx::Rect opaque_rect = iter->opaque_rect(); | |
189 opaque_rect.Intersect(content_rect); | |
190 | |
191 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); | |
192 quad->SetNew(sharedQuadState, | |
193 geometry_rect, | |
194 opaque_rect, | |
195 drawing_info.get_resource_id(), | |
196 texture_rect, | |
197 iter.texture_size(), | |
198 drawing_info.contents_swizzled()); | |
199 quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData); | |
200 break; | |
201 } | |
202 case ManagedTileState::DrawingInfo::SOLID_COLOR_MODE: { | |
203 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); | |
204 quad->SetNew(sharedQuadState, | |
205 geometry_rect, | |
206 drawing_info.get_solid_color()); | |
207 quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData); | |
208 break; | |
209 } | |
210 case ManagedTileState::DrawingInfo::TRANSPARENT_MODE: | |
211 break; | |
212 case ManagedTileState::DrawingInfo::PICTURE_PILE_MODE: | |
213 // TODO: crbug.com/173011 would fill this part in. | |
214 default: | |
215 NOTREACHED(); | |
216 } | |
217 | |
218 if (!seen_tilings.size() || seen_tilings.back() != iter.CurrentTiling()) | |
219 seen_tilings.push_back(iter.CurrentTiling()); | |
220 } | |
221 | |
222 // Aggressively remove any tilings that are not seen to save memory. Note | |
223 // that this is at the expense of doing cause more frequent re-painting. A | |
224 // better scheme would be to maintain a tighter visibleContentRect for the | |
225 // finer tilings. | |
226 CleanUpTilingsOnActiveLayer(seen_tilings); | |
227 } | |
228 | |
229 void PictureLayerImpl::DumpLayerProperties(std::string*, int indent) const { | |
230 // TODO(enne): implement me | |
231 } | |
232 | |
233 void PictureLayerImpl::UpdateTilePriorities() { | |
234 int current_source_frame_number = layer_tree_impl()->source_frame_number(); | |
235 double current_frame_time = | |
236 (layer_tree_impl()->CurrentFrameTime() - base::TimeTicks()).InSecondsF(); | |
237 | |
238 gfx::Transform current_screen_space_transform = screen_space_transform(); | |
239 | |
240 gfx::Rect viewport_in_content_space; | |
241 gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization); | |
242 if (screen_space_transform().GetInverse(&screen_to_layer)) { | |
243 gfx::Rect device_viewport(layer_tree_impl()->device_viewport_size()); | |
244 viewport_in_content_space = gfx::ToEnclosingRect( | |
245 MathUtil::ProjectClippedRect(screen_to_layer, device_viewport)); | |
246 } | |
247 | |
248 WhichTree tree = | |
249 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; | |
250 bool store_screen_space_quads_on_tiles = | |
251 layer_tree_impl()->debug_state().traceAllRenderedFrames; | |
252 tilings_->UpdateTilePriorities( | |
253 tree, | |
254 layer_tree_impl()->device_viewport_size(), | |
255 viewport_in_content_space, | |
256 last_bounds_, | |
257 bounds(), | |
258 last_content_scale_, | |
259 contents_scale_x(), | |
260 last_screen_space_transform_, | |
261 current_screen_space_transform, | |
262 current_source_frame_number, | |
263 current_frame_time, | |
264 store_screen_space_quads_on_tiles); | |
265 | |
266 last_screen_space_transform_ = current_screen_space_transform; | |
267 last_bounds_ = bounds(); | |
268 last_content_scale_ = contents_scale_x(); | |
269 } | |
270 | |
271 void PictureLayerImpl::DidBecomeActive() { | |
272 LayerImpl::DidBecomeActive(); | |
273 tilings_->DidBecomeActive(); | |
274 } | |
275 | |
276 void PictureLayerImpl::DidLoseOutputSurface() { | |
277 if (tilings_) | |
278 tilings_->RemoveAllTilings(); | |
279 } | |
280 | |
281 void PictureLayerImpl::CalculateContentsScale( | |
282 float ideal_contents_scale, | |
283 bool animating_transform_to_screen, | |
284 float* contents_scale_x, | |
285 float* contents_scale_y, | |
286 gfx::Size* content_bounds) { | |
287 if (!DrawsContent()) { | |
288 DCHECK(!tilings_->num_tilings()); | |
289 return; | |
290 } | |
291 | |
292 float min_contents_scale = MinimumContentsScale(); | |
293 float min_page_scale = layer_tree_impl()->min_page_scale_factor(); | |
294 float min_device_scale = 1.f; | |
295 float min_source_scale = | |
296 min_contents_scale / min_page_scale / min_device_scale; | |
297 | |
298 float ideal_page_scale = layer_tree_impl()->total_page_scale_factor(); | |
299 float ideal_device_scale = layer_tree_impl()->device_scale_factor(); | |
300 float ideal_source_scale = | |
301 ideal_contents_scale / ideal_page_scale / ideal_device_scale; | |
302 | |
303 ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale); | |
304 ideal_page_scale_ = ideal_page_scale; | |
305 ideal_device_scale_ = ideal_device_scale; | |
306 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale); | |
307 | |
308 ManageTilings(animating_transform_to_screen); | |
309 | |
310 // The content scale and bounds for a PictureLayerImpl is somewhat fictitious. | |
311 // There are (usually) several tilings at different scales. However, the | |
312 // content bounds is the (integer!) space in which quads are generated. | |
313 // In order to guarantee that we can fill this integer space with any set of | |
314 // tilings (and then map back to floating point texture coordinates), the | |
315 // contents scale must be at least as large as the largest of the tilings. | |
316 float max_contents_scale = min_contents_scale; | |
317 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { | |
318 const PictureLayerTiling* tiling = tilings_->tiling_at(i); | |
319 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale()); | |
320 } | |
321 | |
322 *contents_scale_x = max_contents_scale; | |
323 *contents_scale_y = max_contents_scale; | |
324 *content_bounds = gfx::ToCeiledSize( | |
325 gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale)); | |
326 } | |
327 | |
328 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() { | |
329 return pile_->GetFlattenedPicture(); | |
330 } | |
331 | |
332 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling, | |
333 gfx::Rect content_rect) { | |
334 if (!pile_->CanRaster(tiling->contents_scale(), content_rect)) | |
335 return scoped_refptr<Tile>(); | |
336 | |
337 return make_scoped_refptr(new Tile( | |
338 layer_tree_impl()->tile_manager(), | |
339 pile_.get(), | |
340 content_rect.size(), | |
341 GL_RGBA, | |
342 content_rect, | |
343 contents_opaque() ? content_rect : gfx::Rect(), | |
344 tiling->contents_scale(), | |
345 id())); | |
346 } | |
347 | |
348 void PictureLayerImpl::UpdatePile(Tile* tile) { | |
349 tile->set_picture_pile(pile_); | |
350 } | |
351 | |
352 gfx::Size PictureLayerImpl::CalculateTileSize( | |
353 gfx::Size current_tile_size, | |
354 gfx::Size content_bounds) { | |
355 if (is_mask_) { | |
356 int max_size = layer_tree_impl()->MaxTextureSize(); | |
357 return gfx::Size( | |
358 std::min(max_size, content_bounds.width()), | |
359 std::min(max_size, content_bounds.height())); | |
360 } | |
361 | |
362 gfx::Size default_tile_size = layer_tree_impl()->settings().defaultTileSize; | |
363 gfx::Size max_untiled_content_size = | |
364 layer_tree_impl()->settings().maxUntiledLayerSize; | |
365 | |
366 bool any_dimension_too_large = | |
367 content_bounds.width() > max_untiled_content_size.width() || | |
368 content_bounds.height() > max_untiled_content_size.height(); | |
369 | |
370 bool any_dimension_one_tile = | |
371 content_bounds.width() <= default_tile_size.width() || | |
372 content_bounds.height() <= default_tile_size.height(); | |
373 | |
374 // If long and skinny, tile at the max untiled content size, and clamp | |
375 // the smaller dimension to the content size, e.g. 1000x12 layer with | |
376 // 500x500 max untiled size would get 500x12 tiles. Also do this | |
377 // if the layer is small. | |
378 if (any_dimension_one_tile || !any_dimension_too_large) { | |
379 int width = | |
380 std::min(max_untiled_content_size.width(), content_bounds.width()); | |
381 int height = | |
382 std::min(max_untiled_content_size.height(), content_bounds.height()); | |
383 // Round width and height up to the closest multiple of 64, or 56 if | |
384 // we should avoid power-of-two textures. This helps reduce the number | |
385 // of different textures sizes to help recycling, and also keeps all | |
386 // textures multiple-of-eight, which is preferred on some drivers (IMG). | |
387 bool avoid_pow2 = | |
388 layer_tree_impl()->rendererCapabilities().avoid_pow2_textures; | |
389 int round_up_to = avoid_pow2 ? 56 : 64; | |
390 width = RoundUp(width, round_up_to); | |
391 height = RoundUp(height, round_up_to); | |
392 return gfx::Size(width, height); | |
393 } | |
394 | |
395 return default_tile_size; | |
396 } | |
397 | |
398 void PictureLayerImpl::SyncFromActiveLayer() { | |
399 DCHECK(layer_tree_impl()->IsPendingTree()); | |
400 | |
401 if (!DrawsContent()) { | |
402 raster_page_scale_ = 0; | |
403 raster_device_scale_ = 0; | |
404 raster_source_scale_ = 0; | |
405 return; | |
406 } | |
407 | |
408 // If there is an active tree version of this layer, get a copy of its | |
409 // tiles. This needs to be done last, after setting invalidation and the | |
410 // pile. | |
411 if (PictureLayerImpl* active_twin = ActiveTwin()) | |
412 SyncFromActiveLayer(active_twin); | |
413 } | |
414 | |
415 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { | |
416 raster_page_scale_ = other->raster_page_scale_; | |
417 raster_device_scale_ = other->raster_device_scale_; | |
418 raster_source_scale_ = other->raster_source_scale_; | |
419 | |
420 // Add synthetic invalidations for any recordings that were dropped. As | |
421 // tiles are updated to point to this new pile, this will force the dropping | |
422 // of tiles that can no longer be rastered. This is not ideal, but is a | |
423 // trade-off for memory (use the same pile as much as possible, by switching | |
424 // during DidBecomeActive) and for time (don't bother checking every tile | |
425 // during activation to see if the new pile can still raster it). | |
426 // | |
427 // TODO(enne): Clean up this double loop. | |
428 for (int x = 0; x < pile_->num_tiles_x(); ++x) { | |
429 for (int y = 0; y < pile_->num_tiles_y(); ++y) { | |
430 bool previously_had = other->pile_->HasRecordingAt(x, y); | |
431 bool now_has = pile_->HasRecordingAt(x, y); | |
432 if (now_has || !previously_had) | |
433 continue; | |
434 gfx::Rect layer_rect = pile_->tile_bounds(x, y); | |
435 invalidation_.Union(layer_rect); | |
436 } | |
437 } | |
438 | |
439 tilings_->CloneAll(*other->tilings_, invalidation_, MinimumContentsScale()); | |
440 DCHECK(bounds() == tilings_->LayerBounds()); | |
441 | |
442 // It's a sad but unfortunate fact that PicturePile tiling edges do not line | |
443 // up with PictureLayerTiling edges. Tiles can only be added if they are | |
444 // entirely covered by recordings (that may come from multiple PicturePile | |
445 // tiles). This check happens in this class's CreateTile() call. | |
446 for (int x = 0; x < pile_->num_tiles_x(); ++x) { | |
447 for (int y = 0; y < pile_->num_tiles_y(); ++y) { | |
448 bool previously_had = other->pile_->HasRecordingAt(x, y); | |
449 bool now_has = pile_->HasRecordingAt(x, y); | |
450 if (!now_has || previously_had) | |
451 continue; | |
452 gfx::Rect layer_rect = pile_->tile_bounds(x, y); | |
453 tilings_->CreateTilesFromLayerRect(layer_rect); | |
454 } | |
455 } | |
456 } | |
457 | |
458 void PictureLayerImpl::SyncTiling( | |
459 const PictureLayerTiling* tiling, | |
460 const Region& pending_layer_invalidation) { | |
461 if (!DrawsContent() || tiling->contents_scale() < MinimumContentsScale()) | |
462 return; | |
463 tilings_->Clone(tiling, pending_layer_invalidation); | |
464 } | |
465 | |
466 void PictureLayerImpl::SetIsMask(bool is_mask) { | |
467 if (is_mask_ == is_mask) | |
468 return; | |
469 is_mask_ = is_mask; | |
470 if (tilings_) | |
471 tilings_->RemoveAllTiles(); | |
472 } | |
473 | |
474 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const { | |
475 gfx::Rect content_rect(content_bounds()); | |
476 float scale = contents_scale_x(); | |
477 for (PictureLayerTilingSet::Iterator | |
478 iter(tilings_.get(), | |
479 scale, | |
480 content_rect, | |
481 ideal_contents_scale_, | |
482 PictureLayerTiling::LayerDeviceAlignmentUnknown); | |
483 iter; | |
484 ++iter) { | |
485 // Mask resource not ready yet. | |
486 if (!*iter || | |
487 iter->drawing_info().mode() != | |
488 ManagedTileState::DrawingInfo::TEXTURE_MODE || | |
489 !iter->drawing_info().IsReadyToDraw()) | |
490 return 0; | |
491 // Masks only supported if they fit on exactly one tile. | |
492 if (iter.geometry_rect() != content_rect) | |
493 return 0; | |
494 return iter->drawing_info().get_resource_id(); | |
495 } | |
496 return 0; | |
497 } | |
498 | |
499 bool PictureLayerImpl::AreVisibleResourcesReady() const { | |
500 DCHECK(layer_tree_impl()->IsPendingTree()); | |
501 DCHECK(ideal_contents_scale_); | |
502 | |
503 const gfx::Rect& rect = visible_content_rect(); | |
504 | |
505 float raster_contents_scale = | |
506 raster_page_scale_ * | |
507 raster_device_scale_ * | |
508 raster_source_scale_; | |
509 | |
510 float min_acceptable_scale = | |
511 std::min(raster_contents_scale, ideal_contents_scale_); | |
512 | |
513 TreePriority tree_priority = | |
514 layer_tree_impl()->tile_manager()->GlobalState().tree_priority; | |
515 bool should_force_uploads = | |
516 tree_priority != SMOOTHNESS_TAKES_PRIORITY && | |
517 layer_tree_impl()->animationRegistrar()-> | |
518 active_animation_controllers().empty(); | |
519 | |
520 if (PictureLayerImpl* twin = ActiveTwin()) { | |
521 float twin_raster_contents_scale = | |
522 twin->raster_page_scale_ * | |
523 twin->raster_device_scale_ * | |
524 twin->raster_source_scale_; | |
525 | |
526 min_acceptable_scale = std::min( | |
527 min_acceptable_scale, | |
528 std::min(twin->ideal_contents_scale_, twin_raster_contents_scale)); | |
529 } | |
530 | |
531 Region missing_region = rect; | |
532 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { | |
533 PictureLayerTiling* tiling = tilings_->tiling_at(i); | |
534 | |
535 if (tiling->contents_scale() < min_acceptable_scale) | |
536 continue; | |
537 | |
538 for (PictureLayerTiling::Iterator | |
539 iter(tiling, | |
540 contents_scale_x(), | |
541 rect, | |
542 PictureLayerTiling::LayerDeviceAlignmentUnknown); | |
543 iter; | |
544 ++iter) { | |
545 if (should_force_uploads && iter) | |
546 layer_tree_impl()->tile_manager()->ForceTileUploadToComplete(*iter); | |
547 // A null tile (i.e. no recording) is considered "ready". | |
548 if (!*iter || iter->drawing_info().IsReadyToDraw()) | |
549 missing_region.Subtract(iter.geometry_rect()); | |
550 } | |
551 } | |
552 | |
553 return missing_region.IsEmpty(); | |
554 } | |
555 | |
556 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { | |
557 DCHECK(contents_scale >= MinimumContentsScale()); | |
558 | |
559 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale); | |
560 | |
561 const Region& recorded = pile_->recorded_region(); | |
562 DCHECK(!recorded.IsEmpty()); | |
563 | |
564 for (Region::Iterator iter(recorded); iter.has_rect(); iter.next()) | |
565 tiling->CreateTilesFromLayerRect(iter.rect()); | |
566 | |
567 PictureLayerImpl* twin = | |
568 layer_tree_impl()->IsPendingTree() ? ActiveTwin() : PendingTwin(); | |
569 if (!twin) | |
570 return tiling; | |
571 | |
572 if (layer_tree_impl()->IsPendingTree()) | |
573 twin->SyncTiling(tiling, invalidation_); | |
574 else | |
575 twin->SyncTiling(tiling, twin->invalidation_); | |
576 | |
577 return tiling; | |
578 } | |
579 | |
580 void PictureLayerImpl::RemoveTiling(float contents_scale) { | |
581 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { | |
582 PictureLayerTiling* tiling = tilings_->tiling_at(i); | |
583 if (tiling->contents_scale() == contents_scale) { | |
584 tilings_->Remove(tiling); | |
585 break; | |
586 } | |
587 } | |
588 } | |
589 | |
590 namespace { | |
591 | |
592 inline float PositiveRatio(float float1, float float2) { | |
593 DCHECK(float1 > 0); | |
594 DCHECK(float2 > 0); | |
595 return float1 > float2 ? float1 / float2 : float2 / float1; | |
596 } | |
597 | |
598 inline bool IsCloserToThan( | |
599 PictureLayerTiling* layer1, | |
600 PictureLayerTiling* layer2, | |
601 float contents_scale) { | |
602 // Absolute value for ratios. | |
603 float ratio1 = PositiveRatio(layer1->contents_scale(), contents_scale); | |
604 float ratio2 = PositiveRatio(layer2->contents_scale(), contents_scale); | |
605 return ratio1 < ratio2; | |
606 } | |
607 | |
608 } // namespace | |
609 | |
610 void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) { | |
611 DCHECK(ideal_contents_scale_); | |
612 DCHECK(ideal_page_scale_); | |
613 DCHECK(ideal_device_scale_); | |
614 DCHECK(ideal_source_scale_); | |
615 | |
616 if (pile_->recorded_region().IsEmpty()) | |
617 return; | |
618 | |
619 bool is_active_layer = layer_tree_impl()->IsActiveTree(); | |
620 bool is_pinching = layer_tree_impl()->PinchGestureActive(); | |
621 | |
622 bool change_target_tiling = false; | |
623 | |
624 if (!raster_page_scale_ || !raster_device_scale_ || !raster_source_scale_) | |
625 change_target_tiling = true; | |
626 | |
627 // TODO(danakj): Adjust raster_source_scale_ closer to ideal_source_scale_ at | |
628 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending | |
629 // tree. This will allow CSS scale changes to get re-rastered at an | |
630 // appropriate rate. | |
631 | |
632 if (is_active_layer) { | |
633 if (raster_source_scale_was_animating_ && !animating_transform_to_screen) | |
634 change_target_tiling = true; | |
635 raster_source_scale_was_animating_ = animating_transform_to_screen; | |
636 } | |
637 | |
638 if (is_active_layer && is_pinching && raster_page_scale_) { | |
639 // If the page scale diverges too far during pinch, change raster target to | |
640 // the current page scale. | |
641 float ratio = PositiveRatio(ideal_page_scale_, raster_page_scale_); | |
642 if (ratio >= kMaxScaleRatioDuringPinch) | |
643 change_target_tiling = true; | |
644 } | |
645 | |
646 if (!is_pinching) { | |
647 // When not pinching, match the ideal page scale factor. | |
648 if (raster_page_scale_ != ideal_page_scale_) | |
649 change_target_tiling = true; | |
650 } | |
651 | |
652 // Always match the ideal device scale factor. | |
653 if (raster_device_scale_ != ideal_device_scale_) | |
654 change_target_tiling = true; | |
655 | |
656 if (!change_target_tiling) | |
657 return; | |
658 | |
659 raster_page_scale_ = ideal_page_scale_; | |
660 raster_device_scale_ = ideal_device_scale_; | |
661 raster_source_scale_ = ideal_source_scale_; | |
662 | |
663 float raster_contents_scale; | |
664 float low_res_raster_contents_scale; | |
665 CalculateRasterContentsScale(animating_transform_to_screen, | |
666 &raster_contents_scale, | |
667 &low_res_raster_contents_scale); | |
668 | |
669 PictureLayerTiling* high_res = NULL; | |
670 PictureLayerTiling* low_res = NULL; | |
671 | |
672 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { | |
673 PictureLayerTiling* tiling = tilings_->tiling_at(i); | |
674 if (tiling->contents_scale() == raster_contents_scale) | |
675 high_res = tiling; | |
676 if (tiling->contents_scale() == low_res_raster_contents_scale) | |
677 low_res = tiling; | |
678 | |
679 // Reset all tilings to non-ideal until the end of this function. | |
680 tiling->set_resolution(NON_IDEAL_RESOLUTION); | |
681 } | |
682 | |
683 if (!high_res) { | |
684 high_res = AddTiling(raster_contents_scale); | |
685 if (raster_contents_scale == low_res_raster_contents_scale) | |
686 low_res = high_res; | |
687 } | |
688 if (!low_res && low_res != high_res) | |
689 low_res = AddTiling(low_res_raster_contents_scale); | |
690 | |
691 if (high_res) | |
692 high_res->set_resolution(HIGH_RESOLUTION); | |
693 if (low_res && low_res != high_res) | |
694 low_res->set_resolution(LOW_RESOLUTION); | |
695 } | |
696 | |
697 void PictureLayerImpl::CalculateRasterContentsScale( | |
698 bool animating_transform_to_screen, | |
699 float* raster_contents_scale, | |
700 float* low_res_raster_contents_scale) { | |
701 *raster_contents_scale = ideal_contents_scale_; | |
702 | |
703 // Don't allow animating CSS scales to drop below 1. | |
704 if (animating_transform_to_screen) { | |
705 *raster_contents_scale = std::max( | |
706 *raster_contents_scale, 1.f * ideal_page_scale_ * ideal_device_scale_); | |
707 } | |
708 | |
709 float low_res_factor = | |
710 layer_tree_impl()->settings().lowResContentsScaleFactor; | |
711 *low_res_raster_contents_scale = std::max( | |
712 *raster_contents_scale * low_res_factor, | |
713 MinimumContentsScale()); | |
714 } | |
715 | |
716 void PictureLayerImpl::CleanUpTilingsOnActiveLayer( | |
717 std::vector<PictureLayerTiling*> used_tilings) { | |
718 DCHECK(layer_tree_impl()->IsActiveTree()); | |
719 | |
720 float raster_contents_scale = | |
721 raster_page_scale_ * raster_device_scale_ * raster_source_scale_; | |
722 | |
723 float min_acceptable_high_res_scale = std::min( | |
724 raster_contents_scale, ideal_contents_scale_); | |
725 float max_acceptable_high_res_scale = std::max( | |
726 raster_contents_scale, ideal_contents_scale_); | |
727 | |
728 PictureLayerImpl* twin = PendingTwin(); | |
729 if (twin) { | |
730 float twin_raster_contents_scale = | |
731 twin->raster_page_scale_ * | |
732 twin->raster_device_scale_ * | |
733 twin->raster_source_scale_; | |
734 | |
735 min_acceptable_high_res_scale = std::min( | |
736 min_acceptable_high_res_scale, | |
737 std::min(twin_raster_contents_scale, twin->ideal_contents_scale_)); | |
738 max_acceptable_high_res_scale = std::max( | |
739 max_acceptable_high_res_scale, | |
740 std::max(twin_raster_contents_scale, twin->ideal_contents_scale_)); | |
741 } | |
742 | |
743 float low_res_factor = | |
744 layer_tree_impl()->settings().lowResContentsScaleFactor; | |
745 | |
746 float min_acceptable_low_res_scale = | |
747 low_res_factor * min_acceptable_high_res_scale; | |
748 float max_acceptable_low_res_scale = | |
749 low_res_factor * max_acceptable_high_res_scale; | |
750 | |
751 std::vector<PictureLayerTiling*> to_remove; | |
752 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { | |
753 PictureLayerTiling* tiling = tilings_->tiling_at(i); | |
754 | |
755 if (tiling->contents_scale() >= min_acceptable_high_res_scale && | |
756 tiling->contents_scale() <= max_acceptable_high_res_scale) | |
757 continue; | |
758 | |
759 if (tiling->contents_scale() >= min_acceptable_low_res_scale && | |
760 tiling->contents_scale() <= max_acceptable_low_res_scale) | |
761 continue; | |
762 | |
763 // Don't remove tilings that are being used and expected to stay around. | |
764 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) != | |
765 used_tilings.end()) | |
766 continue; | |
767 | |
768 to_remove.push_back(tiling); | |
769 } | |
770 | |
771 for (size_t i = 0; i < to_remove.size(); ++i) { | |
772 if (twin) | |
773 twin->RemoveTiling(to_remove[i]->contents_scale()); | |
774 tilings_->Remove(to_remove[i]); | |
775 } | |
776 } | |
777 | |
778 PictureLayerImpl* PictureLayerImpl::PendingTwin() const { | |
779 DCHECK(layer_tree_impl()->IsActiveTree()); | |
780 | |
781 PictureLayerImpl* twin = static_cast<PictureLayerImpl*>( | |
782 layer_tree_impl()->FindPendingTreeLayerById(id())); | |
783 if (twin) | |
784 DCHECK_EQ(id(), twin->id()); | |
785 return twin; | |
786 } | |
787 | |
788 PictureLayerImpl* PictureLayerImpl::ActiveTwin() const { | |
789 DCHECK(layer_tree_impl()->IsPendingTree()); | |
790 | |
791 PictureLayerImpl* twin = static_cast<PictureLayerImpl*>( | |
792 layer_tree_impl()->FindActiveTreeLayerById(id())); | |
793 if (twin) | |
794 DCHECK_EQ(id(), twin->id()); | |
795 return twin; | |
796 } | |
797 | |
798 float PictureLayerImpl::MinimumContentsScale() const { | |
799 float setting_min = layer_tree_impl()->settings().minimumContentsScale; | |
800 | |
801 // If the contents scale is less than 1 / width (also for height), | |
802 // then it will end up having less than one pixel of content in that | |
803 // dimension. Bump the minimum contents scale up in this case to prevent | |
804 // this from happening. | |
805 int min_dimension = std::min(bounds().width(), bounds().height()); | |
806 if (!min_dimension) | |
807 return setting_min; | |
808 | |
809 return std::max(1.f / min_dimension, setting_min); | |
810 } | |
811 | |
812 void PictureLayerImpl::GetDebugBorderProperties( | |
813 SkColor* color, | |
814 float* width) const { | |
815 *color = DebugColors::TiledContentLayerBorderColor(); | |
816 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); | |
817 } | |
818 | |
819 scoped_ptr<base::Value> PictureLayerImpl::AsValue() const { | |
820 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
821 LayerImpl::AsValueInto(state.get()); | |
822 | |
823 state->SetDouble("ideal_contents_scale", ideal_contents_scale_); | |
824 state->Set("tilings", tilings_->AsValue().release()); | |
825 return state.PassAs<base::Value>(); | |
826 } | |
827 | |
828 } // namespace cc | |
OLD | NEW |