[Android] Add XXXHDPI assets
[chromium-blink-merge.git] / cc / layers / picture_layer_impl.cc
blob0d1e189b3edff3cc22c9e97a569d7acd2334fa80
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.
5 #include "cc/layers/picture_layer_impl.h"
7 #include <algorithm>
8 #include <limits>
9 #include <set>
11 #include "base/debug/trace_event_argument.h"
12 #include "base/time/time.h"
13 #include "cc/base/math_util.h"
14 #include "cc/base/util.h"
15 #include "cc/debug/debug_colors.h"
16 #include "cc/debug/micro_benchmark_impl.h"
17 #include "cc/debug/traced_value.h"
18 #include "cc/layers/append_quads_data.h"
19 #include "cc/layers/solid_color_layer_impl.h"
20 #include "cc/output/begin_frame_args.h"
21 #include "cc/quads/checkerboard_draw_quad.h"
22 #include "cc/quads/debug_border_draw_quad.h"
23 #include "cc/quads/picture_draw_quad.h"
24 #include "cc/quads/solid_color_draw_quad.h"
25 #include "cc/quads/tile_draw_quad.h"
26 #include "cc/resources/tile_manager.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "cc/trees/occlusion.h"
29 #include "ui/gfx/quad_f.h"
30 #include "ui/gfx/rect_conversions.h"
31 #include "ui/gfx/size_conversions.h"
33 namespace {
34 const float kMaxScaleRatioDuringPinch = 2.0f;
36 // When creating a new tiling during pinch, snap to an existing
37 // tiling's scale if the desired scale is within this ratio.
38 const float kSnapToExistingTilingRatio = 1.2f;
40 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
41 const float kCpuSkewportTargetTimeInFrames = 60.0f;
43 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
44 // TileManager::BinFromTilePriority).
45 const float kGpuSkewportTargetTimeInFrames = 0.0f;
47 // Even for really wide viewports, at some point GPU raster should use
48 // less than 4 tiles to fill the viewport. This is set to 256 as a
49 // sane minimum for now, but we might want to tune this for low-end.
50 const int kMinHeightForGpuRasteredTile = 256;
52 // When making odd-sized tiles, round them up to increase the chances
53 // of using the same tile size.
54 const int kTileRoundUp = 64;
56 } // namespace
58 namespace cc {
60 PictureLayerImpl::Pair::Pair() : active(nullptr), pending(nullptr) {
63 PictureLayerImpl::Pair::Pair(PictureLayerImpl* active_layer,
64 PictureLayerImpl* pending_layer)
65 : active(active_layer), pending(pending_layer) {
68 PictureLayerImpl::Pair::~Pair() {
71 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
72 : LayerImpl(tree_impl, id),
73 twin_layer_(nullptr),
74 pile_(PicturePileImpl::Create()),
75 ideal_page_scale_(0.f),
76 ideal_device_scale_(0.f),
77 ideal_source_scale_(0.f),
78 ideal_contents_scale_(0.f),
79 raster_page_scale_(0.f),
80 raster_device_scale_(0.f),
81 raster_source_scale_(0.f),
82 raster_contents_scale_(0.f),
83 low_res_raster_contents_scale_(0.f),
84 raster_source_scale_is_fixed_(false),
85 was_screen_space_transform_animating_(false),
86 needs_post_commit_initialization_(true),
87 should_update_tile_priorities_(false),
88 only_used_low_res_last_append_quads_(false) {
89 layer_tree_impl()->RegisterPictureLayerImpl(this);
92 PictureLayerImpl::~PictureLayerImpl() {
93 layer_tree_impl()->UnregisterPictureLayerImpl(this);
96 const char* PictureLayerImpl::LayerTypeAsString() const {
97 return "cc::PictureLayerImpl";
100 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
101 LayerTreeImpl* tree_impl) {
102 return PictureLayerImpl::Create(tree_impl, id());
105 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
106 // It's possible this layer was never drawn or updated (e.g. because it was
107 // a descendant of an opacity 0 layer).
108 DoPostCommitInitializationIfNeeded();
109 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
111 LayerImpl::PushPropertiesTo(base_layer);
113 // When the pending tree pushes to the active tree, the pending twin
114 // becomes recycled.
115 layer_impl->twin_layer_ = nullptr;
116 twin_layer_ = nullptr;
118 layer_impl->pile_ = pile_;
120 DCHECK(!pile_->is_solid_color() || !tilings_->num_tilings());
121 // Tilings would be expensive to push, so we swap.
122 layer_impl->tilings_.swap(tilings_);
123 layer_impl->tilings_->SetClient(layer_impl);
124 if (tilings_)
125 tilings_->SetClient(this);
127 // Ensure that the recycle tree doesn't have any unshared tiles.
128 if (tilings_ && pile_->is_solid_color())
129 tilings_->RemoveAllTilings();
131 // Remove invalidated tiles from what will become a recycle tree.
132 if (tilings_)
133 tilings_->RemoveTilesInRegion(invalidation_);
135 layer_impl->raster_page_scale_ = raster_page_scale_;
136 layer_impl->raster_device_scale_ = raster_device_scale_;
137 layer_impl->raster_source_scale_ = raster_source_scale_;
138 layer_impl->raster_contents_scale_ = raster_contents_scale_;
139 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
140 layer_impl->needs_post_commit_initialization_ = false;
142 // The invalidation on this soon-to-be-recycled layer must be cleared to
143 // mirror clearing the invalidation in PictureLayer's version of this function
144 // in case push properties is skipped.
145 layer_impl->invalidation_.Swap(&invalidation_);
146 invalidation_.Clear();
147 needs_post_commit_initialization_ = true;
149 // We always need to push properties.
150 // See http://crbug.com/303943
151 needs_push_properties_ = true;
154 void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
155 const Occlusion& occlusion_in_content_space,
156 AppendQuadsData* append_quads_data) {
157 DCHECK(!needs_post_commit_initialization_);
159 SharedQuadState* shared_quad_state =
160 render_pass->CreateAndAppendSharedQuadState();
162 if (pile_->is_solid_color()) {
163 PopulateSharedQuadState(shared_quad_state);
165 AppendDebugBorderQuad(
166 render_pass, content_bounds(), shared_quad_state, append_quads_data);
168 SolidColorLayerImpl::AppendSolidQuads(render_pass,
169 occlusion_in_content_space,
170 shared_quad_state,
171 content_bounds(),
172 pile_->solid_color(),
173 append_quads_data);
174 return;
177 float max_contents_scale = MaximumTilingContentsScale();
178 gfx::Transform scaled_draw_transform = draw_transform();
179 scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
180 SK_MScalar1 / max_contents_scale);
181 gfx::Size scaled_content_bounds =
182 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale));
183 gfx::Rect scaled_visible_content_rect =
184 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale);
185 scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
186 Occlusion scaled_occlusion =
187 occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
188 scaled_draw_transform);
190 shared_quad_state->SetAll(scaled_draw_transform,
191 scaled_content_bounds,
192 scaled_visible_content_rect,
193 draw_properties().clip_rect,
194 draw_properties().is_clipped,
195 draw_properties().opacity,
196 blend_mode(),
197 sorting_context_id_);
199 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
200 AppendDebugBorderQuad(
201 render_pass,
202 scaled_content_bounds,
203 shared_quad_state,
204 append_quads_data,
205 DebugColors::DirectPictureBorderColor(),
206 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
208 gfx::Rect geometry_rect = scaled_visible_content_rect;
209 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
210 gfx::Rect visible_geometry_rect =
211 scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
212 if (visible_geometry_rect.IsEmpty())
213 return;
215 gfx::Size texture_size = scaled_visible_content_rect.size();
216 gfx::RectF texture_rect = gfx::RectF(texture_size);
217 gfx::Rect quad_content_rect = scaled_visible_content_rect;
219 PictureDrawQuad* quad =
220 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
221 quad->SetNew(shared_quad_state,
222 geometry_rect,
223 opaque_rect,
224 visible_geometry_rect,
225 texture_rect,
226 texture_size,
227 RGBA_8888,
228 quad_content_rect,
229 max_contents_scale,
230 pile_);
231 return;
234 AppendDebugBorderQuad(
235 render_pass, scaled_content_bounds, shared_quad_state, append_quads_data);
237 if (ShowDebugBorders()) {
238 for (PictureLayerTilingSet::CoverageIterator iter(
239 tilings_.get(),
240 max_contents_scale,
241 scaled_visible_content_rect,
242 ideal_contents_scale_);
243 iter;
244 ++iter) {
245 SkColor color;
246 float width;
247 if (*iter && iter->IsReadyToDraw()) {
248 ManagedTileState::DrawInfo::Mode mode = iter->draw_info().mode();
249 if (mode == ManagedTileState::DrawInfo::SOLID_COLOR_MODE) {
250 color = DebugColors::SolidColorTileBorderColor();
251 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
252 } else if (mode == ManagedTileState::DrawInfo::PICTURE_PILE_MODE) {
253 color = DebugColors::PictureTileBorderColor();
254 width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
255 } else if (iter.resolution() == HIGH_RESOLUTION) {
256 color = DebugColors::HighResTileBorderColor();
257 width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
258 } else if (iter.resolution() == LOW_RESOLUTION) {
259 color = DebugColors::LowResTileBorderColor();
260 width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
261 } else if (iter->contents_scale() > max_contents_scale) {
262 color = DebugColors::ExtraHighResTileBorderColor();
263 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
264 } else {
265 color = DebugColors::ExtraLowResTileBorderColor();
266 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
268 } else {
269 color = DebugColors::MissingTileBorderColor();
270 width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
273 DebugBorderDrawQuad* debug_border_quad =
274 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
275 gfx::Rect geometry_rect = iter.geometry_rect();
276 gfx::Rect visible_geometry_rect = geometry_rect;
277 debug_border_quad->SetNew(shared_quad_state,
278 geometry_rect,
279 visible_geometry_rect,
280 color,
281 width);
285 // Keep track of the tilings that were used so that tilings that are
286 // unused can be considered for removal.
287 std::vector<PictureLayerTiling*> seen_tilings;
289 // Ignore missing tiles outside of viewport for tile priority. This is
290 // normally the same as draw viewport but can be independently overridden by
291 // embedders like Android WebView with SetExternalDrawConstraints.
292 gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect(
293 GetViewportForTilePriorityInContentSpace(), max_contents_scale);
295 size_t missing_tile_count = 0u;
296 size_t on_demand_missing_tile_count = 0u;
297 only_used_low_res_last_append_quads_ = true;
298 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
299 max_contents_scale,
300 scaled_visible_content_rect,
301 ideal_contents_scale_);
302 iter;
303 ++iter) {
304 gfx::Rect geometry_rect = iter.geometry_rect();
305 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
306 gfx::Rect visible_geometry_rect =
307 scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
308 if (visible_geometry_rect.IsEmpty())
309 continue;
311 append_quads_data->visible_content_area +=
312 visible_geometry_rect.width() * visible_geometry_rect.height();
314 bool has_draw_quad = false;
315 if (*iter && iter->IsReadyToDraw()) {
316 const ManagedTileState::DrawInfo& draw_info = iter->draw_info();
317 switch (draw_info.mode()) {
318 case ManagedTileState::DrawInfo::RESOURCE_MODE: {
319 gfx::RectF texture_rect = iter.texture_rect();
321 // The raster_contents_scale_ is the best scale that the layer is
322 // trying to produce, even though it may not be ideal. Since that's
323 // the best the layer can promise in the future, consider those as
324 // complete. But if a tile is ideal scale, we don't want to consider
325 // it incomplete and trying to replace it with a tile at a worse
326 // scale.
327 if (iter->contents_scale() != raster_contents_scale_ &&
328 iter->contents_scale() != ideal_contents_scale_ &&
329 geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
330 append_quads_data->num_incomplete_tiles++;
333 TileDrawQuad* quad =
334 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
335 quad->SetNew(shared_quad_state,
336 geometry_rect,
337 opaque_rect,
338 visible_geometry_rect,
339 draw_info.get_resource_id(),
340 texture_rect,
341 iter.texture_size(),
342 draw_info.contents_swizzled());
343 has_draw_quad = true;
344 break;
346 case ManagedTileState::DrawInfo::PICTURE_PILE_MODE: {
347 if (!layer_tree_impl()
348 ->GetRendererCapabilities()
349 .allow_rasterize_on_demand) {
350 ++on_demand_missing_tile_count;
351 break;
354 gfx::RectF texture_rect = iter.texture_rect();
356 ResourceProvider* resource_provider =
357 layer_tree_impl()->resource_provider();
358 ResourceFormat format =
359 resource_provider->memory_efficient_texture_format();
360 PictureDrawQuad* quad =
361 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
362 quad->SetNew(shared_quad_state,
363 geometry_rect,
364 opaque_rect,
365 visible_geometry_rect,
366 texture_rect,
367 iter.texture_size(),
368 format,
369 iter->content_rect(),
370 iter->contents_scale(),
371 pile_);
372 has_draw_quad = true;
373 break;
375 case ManagedTileState::DrawInfo::SOLID_COLOR_MODE: {
376 SolidColorDrawQuad* quad =
377 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
378 quad->SetNew(shared_quad_state,
379 geometry_rect,
380 visible_geometry_rect,
381 draw_info.get_solid_color(),
382 false);
383 has_draw_quad = true;
384 break;
389 if (!has_draw_quad) {
390 if (draw_checkerboard_for_missing_tiles()) {
391 CheckerboardDrawQuad* quad =
392 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
393 SkColor color = DebugColors::DefaultCheckerboardColor();
394 quad->SetNew(
395 shared_quad_state, geometry_rect, visible_geometry_rect, color);
396 } else {
397 SkColor color = SafeOpaqueBackgroundColor();
398 SolidColorDrawQuad* quad =
399 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
400 quad->SetNew(shared_quad_state,
401 geometry_rect,
402 visible_geometry_rect,
403 color,
404 false);
407 if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
408 append_quads_data->num_missing_tiles++;
409 ++missing_tile_count;
411 append_quads_data->approximated_visible_content_area +=
412 visible_geometry_rect.width() * visible_geometry_rect.height();
413 continue;
416 if (iter.resolution() != HIGH_RESOLUTION) {
417 append_quads_data->approximated_visible_content_area +=
418 visible_geometry_rect.width() * visible_geometry_rect.height();
421 // If we have a draw quad, but it's not low resolution, then
422 // mark that we've used something other than low res to draw.
423 if (iter.resolution() != LOW_RESOLUTION)
424 only_used_low_res_last_append_quads_ = false;
426 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
427 seen_tilings.push_back(iter.CurrentTiling());
430 if (missing_tile_count) {
431 TRACE_EVENT_INSTANT2("cc",
432 "PictureLayerImpl::AppendQuads checkerboard",
433 TRACE_EVENT_SCOPE_THREAD,
434 "missing_tile_count",
435 missing_tile_count,
436 "on_demand_missing_tile_count",
437 on_demand_missing_tile_count);
440 // Aggressively remove any tilings that are not seen to save memory. Note
441 // that this is at the expense of doing cause more frequent re-painting. A
442 // better scheme would be to maintain a tighter visible_content_rect for the
443 // finer tilings.
444 CleanUpTilingsOnActiveLayer(seen_tilings);
447 void PictureLayerImpl::UpdateTiles(const Occlusion& occlusion_in_content_space,
448 bool resourceless_software_draw) {
449 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
450 DCHECK_EQ(1.f, contents_scale_x());
451 DCHECK_EQ(1.f, contents_scale_y());
453 DoPostCommitInitializationIfNeeded();
455 if (!resourceless_software_draw) {
456 visible_rect_for_tile_priority_ = visible_content_rect();
459 if (!CanHaveTilings()) {
460 ideal_page_scale_ = 0.f;
461 ideal_device_scale_ = 0.f;
462 ideal_contents_scale_ = 0.f;
463 ideal_source_scale_ = 0.f;
464 SanityCheckTilingState();
465 return;
468 UpdateIdealScales();
470 DCHECK(tilings_->num_tilings() > 0 || raster_contents_scale_ == 0.f)
471 << "A layer with no tilings shouldn't have valid raster scales";
472 if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
473 RecalculateRasterScales();
474 AddTilingsForRasterScale();
477 DCHECK(raster_page_scale_);
478 DCHECK(raster_device_scale_);
479 DCHECK(raster_source_scale_);
480 DCHECK(raster_contents_scale_);
481 DCHECK(low_res_raster_contents_scale_);
483 was_screen_space_transform_animating_ =
484 draw_properties().screen_space_transform_is_animating;
486 should_update_tile_priorities_ = true;
488 UpdateTilePriorities(occlusion_in_content_space);
491 void PictureLayerImpl::UpdateTilePriorities(
492 const Occlusion& occlusion_in_content_space) {
493 DCHECK(!pile_->is_solid_color() || !tilings_->num_tilings());
495 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
497 double current_frame_time_in_seconds =
498 (layer_tree_impl()->CurrentBeginFrameArgs().frame_time -
499 base::TimeTicks()).InSecondsF();
501 bool tiling_needs_update = false;
502 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
503 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime(
504 current_frame_time_in_seconds)) {
505 tiling_needs_update = true;
506 break;
509 if (!tiling_needs_update)
510 return;
512 gfx::Rect viewport_rect_in_layer_space =
513 GetViewportForTilePriorityInContentSpace();
514 WhichTree tree =
515 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
516 bool can_require_tiles_for_activation =
517 !only_used_low_res_last_append_quads_ || RequiresHighResToDraw() ||
518 !layer_tree_impl()->SmoothnessTakesPriority();
519 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
520 PictureLayerTiling* tiling = tilings_->tiling_at(i);
522 tiling->set_can_require_tiles_for_activation(
523 can_require_tiles_for_activation);
525 // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
526 // they are the same space in picture layer, as contents scale is always 1.
527 tiling->ComputeTilePriorityRects(tree,
528 viewport_rect_in_layer_space,
529 ideal_contents_scale_,
530 current_frame_time_in_seconds,
531 occlusion_in_content_space);
534 // Tile priorities were modified.
535 // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
536 layer_tree_impl()->DidModifyTilePriorities();
539 gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
540 // If visible_rect_for_tile_priority_ is empty or
541 // viewport_rect_for_tile_priority is set to be different from the device
542 // viewport, try to inverse project the viewport into layer space and use
543 // that. Otherwise just use visible_rect_for_tile_priority_
544 gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_;
545 gfx::Rect viewport_rect_for_tile_priority =
546 layer_tree_impl()->ViewportRectForTilePriority();
548 if (visible_rect_in_content_space.IsEmpty() ||
549 layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority) {
550 gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
551 if (screen_space_transform().GetInverse(&view_to_layer)) {
552 // Transform from view space to content space.
553 visible_rect_in_content_space =
554 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
555 view_to_layer, viewport_rect_for_tile_priority));
558 return visible_rect_in_content_space;
561 PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() {
562 // TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
563 return static_cast<PictureLayerImpl*>(
564 layer_tree_impl()->FindRecycleTreeLayerById(id()));
567 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
568 if (layer_tree_impl()->IsActiveTree()) {
569 gfx::RectF layer_damage_rect =
570 gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale());
571 AddDamageRect(layer_damage_rect);
575 void PictureLayerImpl::DidBecomeActive() {
576 LayerImpl::DidBecomeActive();
577 // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
578 layer_tree_impl()->DidModifyTilePriorities();
581 void PictureLayerImpl::DidBeginTracing() {
582 pile_->DidBeginTracing();
585 void PictureLayerImpl::ReleaseResources() {
586 if (tilings_)
587 RemoveAllTilings();
589 ResetRasterScale();
591 // To avoid an edge case after lost context where the tree is up to date but
592 // the tilings have not been managed, request an update draw properties
593 // to force tilings to get managed.
594 layer_tree_impl()->set_needs_update_draw_properties();
597 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
598 return pile_->GetFlattenedPicture();
601 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
602 const gfx::Rect& content_rect) {
603 DCHECK(!pile_->is_solid_color());
604 if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
605 return scoped_refptr<Tile>();
607 int flags = 0;
609 // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as
610 // much savings on memory as we can. However, for some cases like ganesh or
611 // small layers, the amount of time we spend analyzing might not justify
612 // memory savings that we can get. Note that we don't handle solid color
613 // masks, so we shouldn't bother analyzing those.
614 // Bugs: crbug.com/397198, crbug.com/396908
615 if (!pile_->is_mask())
616 flags = Tile::USE_PICTURE_ANALYSIS;
618 return layer_tree_impl()->tile_manager()->CreateTile(
619 pile_.get(),
620 content_rect.size(),
621 content_rect,
622 tiling->contents_scale(),
623 id(),
624 layer_tree_impl()->source_frame_number(),
625 flags);
628 PicturePileImpl* PictureLayerImpl::GetPile() {
629 return pile_.get();
632 const Region* PictureLayerImpl::GetInvalidation() {
633 return &invalidation_;
636 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
637 const PictureLayerTiling* tiling) const {
638 if (!twin_layer_)
639 return nullptr;
640 return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale());
643 PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling(
644 const PictureLayerTiling* tiling) {
645 PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
646 if (!recycled_twin || !recycled_twin->tilings_)
647 return nullptr;
648 return recycled_twin->tilings_->TilingAtScale(tiling->contents_scale());
651 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
652 return layer_tree_impl()->settings().max_tiles_for_interest_area;
655 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
656 float skewport_target_time_in_frames =
657 layer_tree_impl()->use_gpu_rasterization()
658 ? kGpuSkewportTargetTimeInFrames
659 : kCpuSkewportTargetTimeInFrames;
660 return skewport_target_time_in_frames *
661 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
662 layer_tree_impl()->settings().skewport_target_time_multiplier;
665 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
666 return layer_tree_impl()
667 ->settings()
668 .skewport_extrapolation_limit_in_content_pixels;
671 bool PictureLayerImpl::RequiresHighResToDraw() const {
672 return layer_tree_impl()->RequiresHighResToDraw();
675 gfx::Size PictureLayerImpl::CalculateTileSize(
676 const gfx::Size& content_bounds) const {
677 int max_texture_size =
678 layer_tree_impl()->resource_provider()->max_texture_size();
680 if (pile_->is_mask()) {
681 // Masks are not tiled, so if we can't cover the whole mask with one tile,
682 // don't make any tiles at all. Returning an empty size signals this.
683 if (content_bounds.width() > max_texture_size ||
684 content_bounds.height() > max_texture_size)
685 return gfx::Size();
686 return content_bounds;
689 int default_tile_width = 0;
690 int default_tile_height = 0;
691 if (layer_tree_impl()->use_gpu_rasterization()) {
692 // For GPU rasterization, we pick an ideal tile size using the viewport
693 // so we don't need any settings. The current approach uses 4 tiles
694 // to cover the viewport vertically.
695 int viewport_width = layer_tree_impl()->device_viewport_size().width();
696 int viewport_height = layer_tree_impl()->device_viewport_size().height();
697 default_tile_width = viewport_width;
698 // Also, increase the height proportionally as the width decreases, and
699 // pad by our border texels to make the tiles exactly match the viewport.
700 int divisor = 4;
701 if (content_bounds.width() <= viewport_width / 2)
702 divisor = 2;
703 if (content_bounds.width() <= viewport_width / 4)
704 divisor = 1;
705 default_tile_height = RoundUp(viewport_height, divisor) / divisor;
706 default_tile_height += 2 * PictureLayerTiling::kBorderTexels;
707 default_tile_height =
708 std::max(default_tile_height, kMinHeightForGpuRasteredTile);
709 } else {
710 // For CPU rasterization we use tile-size settings.
711 const LayerTreeSettings& settings = layer_tree_impl()->settings();
712 int max_untiled_content_width = settings.max_untiled_layer_size.width();
713 int max_untiled_content_height = settings.max_untiled_layer_size.height();
714 default_tile_width = settings.default_tile_size.width();
715 default_tile_height = settings.default_tile_size.height();
717 // If the content width is small, increase tile size vertically.
718 // If the content height is small, increase tile size horizontally.
719 // If both are less than the untiled-size, use a single tile.
720 if (content_bounds.width() < default_tile_width)
721 default_tile_height = max_untiled_content_height;
722 if (content_bounds.height() < default_tile_height)
723 default_tile_width = max_untiled_content_width;
724 if (content_bounds.width() < max_untiled_content_width &&
725 content_bounds.height() < max_untiled_content_height) {
726 default_tile_height = max_untiled_content_height;
727 default_tile_width = max_untiled_content_width;
731 int tile_width = default_tile_width;
732 int tile_height = default_tile_height;
734 // Clamp the tile width/height to the content width/height to save space.
735 if (content_bounds.width() < default_tile_width) {
736 tile_width = std::min(tile_width, content_bounds.width());
737 tile_width = RoundUp(tile_width, kTileRoundUp);
738 tile_width = std::min(tile_width, default_tile_width);
740 if (content_bounds.height() < default_tile_height) {
741 tile_height = std::min(tile_height, content_bounds.height());
742 tile_height = RoundUp(tile_height, kTileRoundUp);
743 tile_height = std::min(tile_height, default_tile_height);
746 // Under no circumstance should we be larger than the max texture size.
747 tile_width = std::min(tile_width, max_texture_size);
748 tile_height = std::min(tile_height, max_texture_size);
749 return gfx::Size(tile_width, tile_height);
752 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
753 TRACE_EVENT0("cc", "SyncFromActiveLayer");
754 DCHECK(!other->needs_post_commit_initialization_);
755 DCHECK(other->tilings_);
757 if (!DrawsContent()) {
758 RemoveAllTilings();
759 return;
762 raster_page_scale_ = other->raster_page_scale_;
763 raster_device_scale_ = other->raster_device_scale_;
764 raster_source_scale_ = other->raster_source_scale_;
765 raster_contents_scale_ = other->raster_contents_scale_;
766 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
768 bool synced_high_res_tiling = false;
769 if (CanHaveTilings()) {
770 synced_high_res_tiling = tilings_->SyncTilings(
771 *other->tilings_, bounds(), invalidation_, MinimumContentsScale());
772 } else {
773 RemoveAllTilings();
776 // If our MinimumContentsScale has changed to prevent the twin's high res
777 // tiling from being synced, we should reset the raster scale and let it be
778 // recalculated (1) again. This can happen if our bounds shrink to the point
779 // where min contents scale grows.
780 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
781 // should refactor this code a little bit and actually recalculate this.
782 // However, this is a larger undertaking, so this will work for now.
783 if (!synced_high_res_tiling)
784 ResetRasterScale();
785 else
786 SanityCheckTilingState();
789 void PictureLayerImpl::SyncTiling(
790 const PictureLayerTiling* tiling) {
791 if (!CanHaveTilingWithScale(tiling->contents_scale()))
792 return;
793 tilings_->AddTiling(tiling->contents_scale());
795 // If this tree needs update draw properties, then the tiling will
796 // get updated prior to drawing or activation. If this tree does not
797 // need update draw properties, then its transforms are up to date and
798 // we can create tiles for this tiling immediately.
799 if (!layer_tree_impl()->needs_update_draw_properties() &&
800 should_update_tile_priorities_) {
801 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
802 // when we stop using the pending tree in the browser compositor. If we want
803 // to support occlusion tracking here, we need to dirty the draw properties
804 // or save occlusion as a draw property.
805 UpdateTilePriorities(Occlusion());
809 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
810 gfx::Rect content_rect(content_bounds());
811 PictureLayerTilingSet::CoverageIterator iter(
812 tilings_.get(), 1.f, content_rect, ideal_contents_scale_);
814 // Mask resource not ready yet.
815 if (!iter || !*iter)
816 return 0;
818 // Masks only supported if they fit on exactly one tile.
819 DCHECK(iter.geometry_rect() == content_rect)
820 << "iter rect " << iter.geometry_rect().ToString() << " content rect "
821 << content_rect.ToString();
823 const ManagedTileState::DrawInfo& draw_info = iter->draw_info();
824 if (!draw_info.IsReadyToDraw() ||
825 draw_info.mode() != ManagedTileState::DrawInfo::RESOURCE_MODE)
826 return 0;
828 return draw_info.get_resource_id();
831 void PictureLayerImpl::DoPostCommitInitialization() {
832 DCHECK(needs_post_commit_initialization_);
833 DCHECK(layer_tree_impl()->IsPendingTree());
835 if (!tilings_)
836 tilings_.reset(new PictureLayerTilingSet(this, bounds()));
838 DCHECK(!twin_layer_);
839 twin_layer_ = static_cast<PictureLayerImpl*>(
840 layer_tree_impl()->FindActiveTreeLayerById(id()));
841 if (twin_layer_) {
842 DCHECK(!twin_layer_->twin_layer_);
843 twin_layer_->twin_layer_ = this;
844 // If the twin has never been pushed to, do not sync from it.
845 // This can happen if this function is called during activation.
846 if (!twin_layer_->needs_post_commit_initialization_)
847 SyncFromActiveLayer(twin_layer_);
850 needs_post_commit_initialization_ = false;
853 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
854 DCHECK(CanHaveTilingWithScale(contents_scale)) <<
855 "contents_scale: " << contents_scale;
857 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
859 DCHECK(pile_->HasRecordings());
861 if (twin_layer_)
862 twin_layer_->SyncTiling(tiling);
864 return tiling;
867 void PictureLayerImpl::RemoveTiling(float contents_scale) {
868 if (!tilings_ || tilings_->num_tilings() == 0)
869 return;
871 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
872 PictureLayerTiling* tiling = tilings_->tiling_at(i);
873 if (tiling->contents_scale() == contents_scale) {
874 tilings_->Remove(tiling);
875 break;
878 if (tilings_->num_tilings() == 0)
879 ResetRasterScale();
880 SanityCheckTilingState();
883 void PictureLayerImpl::RemoveAllTilings() {
884 if (tilings_)
885 tilings_->RemoveAllTilings();
886 // If there are no tilings, then raster scales are no longer meaningful.
887 ResetRasterScale();
890 namespace {
892 inline float PositiveRatio(float float1, float float2) {
893 DCHECK_GT(float1, 0);
894 DCHECK_GT(float2, 0);
895 return float1 > float2 ? float1 / float2 : float2 / float1;
898 } // namespace
900 void PictureLayerImpl::AddTilingsForRasterScale() {
901 PictureLayerTiling* high_res = nullptr;
902 PictureLayerTiling* low_res = nullptr;
904 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
905 PictureLayerTiling* tiling = tilings_->tiling_at(i);
906 if (tiling->contents_scale() == raster_contents_scale_)
907 high_res = tiling;
908 if (tiling->contents_scale() == low_res_raster_contents_scale_)
909 low_res = tiling;
911 // Reset all tilings to non-ideal until the end of this function.
912 tiling->set_resolution(NON_IDEAL_RESOLUTION);
915 if (!high_res) {
916 high_res = AddTiling(raster_contents_scale_);
917 if (raster_contents_scale_ == low_res_raster_contents_scale_)
918 low_res = high_res;
921 // Only create new low res tilings when the transform is static. This
922 // prevents wastefully creating a paired low res tiling for every new high res
923 // tiling during a pinch or a CSS animation.
924 bool is_pinching = layer_tree_impl()->PinchGestureActive();
925 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching &&
926 !draw_properties().screen_space_transform_is_animating && !low_res &&
927 low_res != high_res)
928 low_res = AddTiling(low_res_raster_contents_scale_);
930 // Set low-res if we have one.
931 if (low_res && low_res != high_res)
932 low_res->set_resolution(LOW_RESOLUTION);
934 // Make sure we always have one high-res (even if high == low).
935 high_res->set_resolution(HIGH_RESOLUTION);
937 SanityCheckTilingState();
940 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
941 if (was_screen_space_transform_animating_ !=
942 draw_properties().screen_space_transform_is_animating)
943 return true;
945 if (draw_properties().screen_space_transform_is_animating &&
946 raster_contents_scale_ != ideal_contents_scale_ &&
947 ShouldAdjustRasterScaleDuringScaleAnimations())
948 return true;
950 bool is_pinching = layer_tree_impl()->PinchGestureActive();
951 if (is_pinching && raster_page_scale_) {
952 // We change our raster scale when it is:
953 // - Higher than ideal (need a lower-res tiling available)
954 // - Too far from ideal (need a higher-res tiling available)
955 float ratio = ideal_page_scale_ / raster_page_scale_;
956 if (raster_page_scale_ > ideal_page_scale_ ||
957 ratio > kMaxScaleRatioDuringPinch)
958 return true;
961 if (!is_pinching) {
962 // When not pinching, match the ideal page scale factor.
963 if (raster_page_scale_ != ideal_page_scale_)
964 return true;
967 // Always match the ideal device scale factor.
968 if (raster_device_scale_ != ideal_device_scale_)
969 return true;
971 // When the source scale changes we want to match it, but not when animating
972 // or when we've fixed the scale in place.
973 if (!draw_properties().screen_space_transform_is_animating &&
974 !raster_source_scale_is_fixed_ &&
975 raster_source_scale_ != ideal_source_scale_)
976 return true;
978 return false;
981 float PictureLayerImpl::SnappedContentsScale(float scale) {
982 // If a tiling exists within the max snapping ratio, snap to its scale.
983 float snapped_contents_scale = scale;
984 float snapped_ratio = kSnapToExistingTilingRatio;
985 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
986 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
987 float ratio = PositiveRatio(tiling_contents_scale, scale);
988 if (ratio < snapped_ratio) {
989 snapped_contents_scale = tiling_contents_scale;
990 snapped_ratio = ratio;
993 return snapped_contents_scale;
996 void PictureLayerImpl::RecalculateRasterScales() {
997 float old_raster_contents_scale = raster_contents_scale_;
998 float old_raster_page_scale = raster_page_scale_;
999 float old_raster_source_scale = raster_source_scale_;
1001 raster_device_scale_ = ideal_device_scale_;
1002 raster_page_scale_ = ideal_page_scale_;
1003 raster_source_scale_ = ideal_source_scale_;
1004 raster_contents_scale_ = ideal_contents_scale_;
1006 // If we're not animating, or leaving an animation, and the
1007 // ideal_source_scale_ changes, then things are unpredictable, and we fix
1008 // the raster_source_scale_ in place.
1009 if (old_raster_source_scale &&
1010 !draw_properties().screen_space_transform_is_animating &&
1011 !was_screen_space_transform_animating_ &&
1012 old_raster_source_scale != ideal_source_scale_)
1013 raster_source_scale_is_fixed_ = true;
1015 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1016 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1017 // tree. This will allow CSS scale changes to get re-rastered at an
1018 // appropriate rate. (crbug.com/413636)
1019 if (raster_source_scale_is_fixed_) {
1020 raster_contents_scale_ /= raster_source_scale_;
1021 raster_source_scale_ = 1.f;
1024 // During pinch we completely ignore the current ideal scale, and just use
1025 // a multiple of the previous scale.
1026 // TODO(danakj): This seems crazy, we should use the current ideal, no?
1027 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1028 if (is_pinching && old_raster_contents_scale) {
1029 // See ShouldAdjustRasterScale:
1030 // - When zooming out, preemptively create new tiling at lower resolution.
1031 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1032 bool zooming_out = old_raster_page_scale > ideal_page_scale_;
1033 float desired_contents_scale =
1034 zooming_out ? old_raster_contents_scale / kMaxScaleRatioDuringPinch
1035 : old_raster_contents_scale * kMaxScaleRatioDuringPinch;
1036 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
1037 raster_page_scale_ =
1038 raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
1041 raster_contents_scale_ =
1042 std::max(raster_contents_scale_, MinimumContentsScale());
1044 // If we're not re-rasterizing during animation, rasterize at the maximum
1045 // scale that will occur during the animation, if the maximum scale is
1046 // known. However we want to avoid excessive memory use. If the scale is
1047 // smaller than what we would choose otherwise, then it's always better off
1048 // for us memory-wise. But otherwise, we don't choose a scale at which this
1049 // layer's rastered content would become larger than the viewport.
1050 if (draw_properties().screen_space_transform_is_animating &&
1051 !ShouldAdjustRasterScaleDuringScaleAnimations()) {
1052 bool can_raster_at_maximum_scale = false;
1053 // TODO(ajuma): If we need to deal with scale-down animations starting right
1054 // as a layer gets promoted, then we'd want to have the
1055 // |starting_animation_contents_scale| passed in here as a separate draw
1056 // property so we could try use that when the max is too large.
1057 // See crbug.com/422341.
1058 float maximum_scale = draw_properties().maximum_animation_contents_scale;
1059 if (maximum_scale) {
1060 gfx::Size bounds_at_maximum_scale =
1061 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), maximum_scale));
1062 if (bounds_at_maximum_scale.GetArea() <=
1063 layer_tree_impl()->device_viewport_size().GetArea())
1064 can_raster_at_maximum_scale = true;
1066 // Use the computed scales for the raster scale directly, do not try to use
1067 // the ideal scale here. The current ideal scale may be way too large in the
1068 // case of an animation with scale, and will be constantly changing.
1069 if (can_raster_at_maximum_scale)
1070 raster_contents_scale_ = maximum_scale;
1071 else
1072 raster_contents_scale_ = 1.f * ideal_page_scale_ * ideal_device_scale_;
1075 // If this layer would create zero or one tiles at this content scale,
1076 // don't create a low res tiling.
1077 gfx::Size content_bounds =
1078 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
1079 gfx::Size tile_size = CalculateTileSize(content_bounds);
1080 bool tile_covers_bounds = tile_size.width() >= content_bounds.width() &&
1081 tile_size.height() >= content_bounds.height();
1082 if (tile_size.IsEmpty() || tile_covers_bounds) {
1083 low_res_raster_contents_scale_ = raster_contents_scale_;
1084 return;
1087 float low_res_factor =
1088 layer_tree_impl()->settings().low_res_contents_scale_factor;
1089 low_res_raster_contents_scale_ = std::max(
1090 raster_contents_scale_ * low_res_factor,
1091 MinimumContentsScale());
1094 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1095 std::vector<PictureLayerTiling*> used_tilings) {
1096 DCHECK(layer_tree_impl()->IsActiveTree());
1097 if (tilings_->num_tilings() == 0)
1098 return;
1100 float min_acceptable_high_res_scale = std::min(
1101 raster_contents_scale_, ideal_contents_scale_);
1102 float max_acceptable_high_res_scale = std::max(
1103 raster_contents_scale_, ideal_contents_scale_);
1104 float twin_low_res_scale = 0.f;
1106 PictureLayerImpl* twin = twin_layer_;
1107 if (twin && twin->CanHaveTilings()) {
1108 min_acceptable_high_res_scale = std::min(
1109 min_acceptable_high_res_scale,
1110 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1111 max_acceptable_high_res_scale = std::max(
1112 max_acceptable_high_res_scale,
1113 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1115 for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
1116 PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
1117 if (tiling->resolution() == LOW_RESOLUTION)
1118 twin_low_res_scale = tiling->contents_scale();
1122 std::vector<PictureLayerTiling*> to_remove;
1123 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1124 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1126 // Keep multiple high resolution tilings even if not used to help
1127 // activate earlier at non-ideal resolutions.
1128 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
1129 tiling->contents_scale() <= max_acceptable_high_res_scale)
1130 continue;
1132 // Keep low resolution tilings, if the layer should have them.
1133 if (layer_tree_impl()->create_low_res_tiling()) {
1134 if (tiling->resolution() == LOW_RESOLUTION ||
1135 tiling->contents_scale() == twin_low_res_scale)
1136 continue;
1139 // Don't remove tilings that are being used (and thus would cause a flash.)
1140 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
1141 used_tilings.end())
1142 continue;
1144 to_remove.push_back(tiling);
1147 if (to_remove.empty())
1148 return;
1150 PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
1151 // Remove tilings on this tree and the twin tree.
1152 for (size_t i = 0; i < to_remove.size(); ++i) {
1153 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
1154 // Only remove tilings from the twin layer if they have
1155 // NON_IDEAL_RESOLUTION.
1156 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
1157 twin->RemoveTiling(to_remove[i]->contents_scale());
1158 // Remove the tiling from the recycle tree. Note that we ignore resolution,
1159 // since we don't need to maintain high/low res on the recycle tree.
1160 if (recycled_twin)
1161 recycled_twin->RemoveTiling(to_remove[i]->contents_scale());
1162 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1163 CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution());
1164 tilings_->Remove(to_remove[i]);
1167 DCHECK_GT(tilings_->num_tilings(), 0u);
1168 SanityCheckTilingState();
1171 float PictureLayerImpl::MinimumContentsScale() const {
1172 float setting_min = layer_tree_impl()->settings().minimum_contents_scale;
1174 // If the contents scale is less than 1 / width (also for height),
1175 // then it will end up having less than one pixel of content in that
1176 // dimension. Bump the minimum contents scale up in this case to prevent
1177 // this from happening.
1178 int min_dimension = std::min(bounds().width(), bounds().height());
1179 if (!min_dimension)
1180 return setting_min;
1182 return std::max(1.f / min_dimension, setting_min);
1185 void PictureLayerImpl::ResetRasterScale() {
1186 raster_page_scale_ = 0.f;
1187 raster_device_scale_ = 0.f;
1188 raster_source_scale_ = 0.f;
1189 raster_contents_scale_ = 0.f;
1190 low_res_raster_contents_scale_ = 0.f;
1191 raster_source_scale_is_fixed_ = false;
1193 // When raster scales aren't valid, don't update tile priorities until
1194 // this layer has been updated via UpdateDrawProperties.
1195 should_update_tile_priorities_ = false;
1198 bool PictureLayerImpl::CanHaveTilings() const {
1199 if (pile_->is_solid_color())
1200 return false;
1201 if (!DrawsContent())
1202 return false;
1203 if (!pile_->HasRecordings())
1204 return false;
1205 return true;
1208 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const {
1209 if (!CanHaveTilings())
1210 return false;
1211 if (contents_scale < MinimumContentsScale())
1212 return false;
1213 return true;
1216 void PictureLayerImpl::SanityCheckTilingState() const {
1217 #if DCHECK_IS_ON
1218 // Recycle tree doesn't have any restrictions.
1219 if (layer_tree_impl()->IsRecycleTree())
1220 return;
1222 if (!CanHaveTilings()) {
1223 DCHECK_EQ(0u, tilings_->num_tilings());
1224 return;
1226 if (tilings_->num_tilings() == 0)
1227 return;
1229 // We should only have one high res tiling.
1230 DCHECK_EQ(1, tilings_->NumHighResTilings());
1231 #endif
1234 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const {
1235 if (!layer_tree_impl()->use_gpu_rasterization())
1236 return false;
1238 // Re-rastering text at different scales using GPU rasterization causes
1239 // texture uploads for glyphs at each scale (see crbug.com/366225). To
1240 // workaround this performance issue, we don't re-rasterize layers with
1241 // text during scale animations.
1242 // TODO(ajuma): Remove this workaround once text can be efficiently
1243 // re-rastered at different scales (e.g. by using distance-field fonts).
1244 if (pile_->has_text())
1245 return false;
1247 return true;
1250 float PictureLayerImpl::MaximumTilingContentsScale() const {
1251 float max_contents_scale = MinimumContentsScale();
1252 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1253 const PictureLayerTiling* tiling = tilings_->tiling_at(i);
1254 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
1256 return max_contents_scale;
1259 void PictureLayerImpl::UpdateIdealScales() {
1260 DCHECK(CanHaveTilings());
1262 float min_contents_scale = MinimumContentsScale();
1263 DCHECK_GT(min_contents_scale, 0.f);
1264 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
1265 DCHECK_GT(min_page_scale, 0.f);
1266 float min_device_scale = 1.f;
1267 float min_source_scale =
1268 min_contents_scale / min_page_scale / min_device_scale;
1270 float ideal_page_scale = draw_properties().page_scale_factor;
1271 float ideal_device_scale = draw_properties().device_scale_factor;
1272 float ideal_source_scale = draw_properties().ideal_contents_scale /
1273 ideal_page_scale / ideal_device_scale;
1274 ideal_contents_scale_ =
1275 std::max(draw_properties().ideal_contents_scale, min_contents_scale);
1276 ideal_page_scale_ = draw_properties().page_scale_factor;
1277 ideal_device_scale_ = draw_properties().device_scale_factor;
1278 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
1281 void PictureLayerImpl::GetDebugBorderProperties(
1282 SkColor* color,
1283 float* width) const {
1284 *color = DebugColors::TiledContentLayerBorderColor();
1285 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1288 void PictureLayerImpl::GetAllTilesForTracing(
1289 std::set<const Tile*>* tiles) const {
1290 if (!tilings_)
1291 return;
1293 for (size_t i = 0; i < tilings_->num_tilings(); ++i)
1294 tilings_->tiling_at(i)->GetAllTilesForTracing(tiles);
1297 void PictureLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
1298 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1299 LayerImpl::AsValueInto(state);
1300 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1301 state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1302 state->BeginArray("tilings");
1303 tilings_->AsValueInto(state);
1304 state->EndArray();
1306 state->BeginArray("tile_priority_rect");
1307 MathUtil::AddToTracedValue(GetViewportForTilePriorityInContentSpace(), state);
1308 state->EndArray();
1310 state->BeginArray("visible_rect");
1311 MathUtil::AddToTracedValue(visible_content_rect(), state);
1312 state->EndArray();
1314 state->BeginArray("pictures");
1315 pile_->AsValueInto(state);
1316 state->EndArray();
1318 state->BeginArray("invalidation");
1319 invalidation_.AsValueInto(state);
1320 state->EndArray();
1322 state->BeginArray("coverage_tiles");
1323 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
1324 1.f,
1325 gfx::Rect(content_bounds()),
1326 ideal_contents_scale_);
1327 iter;
1328 ++iter) {
1329 state->BeginDictionary();
1331 state->BeginArray("geometry_rect");
1332 MathUtil::AddToTracedValue(iter.geometry_rect(), state);
1333 state->EndArray();
1335 if (*iter)
1336 TracedValue::SetIDRef(*iter, state, "tile");
1338 state->EndDictionary();
1340 state->EndArray();
1343 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1344 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1345 return tilings_->GPUMemoryUsageInBytes();
1348 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1349 benchmark->RunOnLayer(this);
1352 WhichTree PictureLayerImpl::GetTree() const {
1353 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1356 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1357 return !layer_tree_impl()->IsRecycleTree();
1360 bool PictureLayerImpl::HasValidTilePriorities() const {
1361 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1364 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1365 TRACE_EVENT0("cc",
1366 "PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw");
1367 if (!layer_tree_impl()->IsPendingTree())
1368 return true;
1370 if (!HasValidTilePriorities())
1371 return true;
1373 if (!tilings_)
1374 return true;
1376 if (visible_rect_for_tile_priority_.IsEmpty())
1377 return true;
1379 gfx::Rect rect = GetViewportForTilePriorityInContentSpace();
1380 rect.Intersect(visible_rect_for_tile_priority_);
1382 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1383 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1384 if (tiling->resolution() != HIGH_RESOLUTION &&
1385 tiling->resolution() != LOW_RESOLUTION)
1386 continue;
1388 for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter;
1389 ++iter) {
1390 const Tile* tile = *iter;
1391 // A null tile (i.e. missing recording) can just be skipped.
1392 // TODO(vmpstr): Verify this is true if we create tiles in raster
1393 // iterators.
1394 if (!tile)
1395 continue;
1397 // We can't check tile->required_for_activation, because that value might
1398 // be out of date. It is updated in the raster/eviction iterators.
1399 // TODO(vmpstr): Remove the comment once you can't access this information
1400 // from the tile.
1401 if (tiling->IsTileRequiredForActivation(tile) && !tile->IsReadyToDraw()) {
1402 TRACE_EVENT_INSTANT0("cc",
1403 "PictureLayerImpl::"
1404 "AllTilesRequiredForActivationAreReadyToDraw not "
1405 "ready to activate",
1406 TRACE_EVENT_SCOPE_THREAD);
1407 return false;
1412 return true;
1415 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1416 : layer_(nullptr), current_stage_(arraysize(stages_)) {
1419 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1420 PictureLayerImpl* layer,
1421 bool prioritize_low_res)
1422 : layer_(layer), current_stage_(0) {
1423 DCHECK(layer_);
1425 // Early out if the layer has no tilings.
1426 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) {
1427 current_stage_ = arraysize(stages_);
1428 return;
1431 // Tiles without valid priority are treated as having lowest priority and
1432 // never considered for raster.
1433 if (!layer_->HasValidTilePriorities()) {
1434 current_stage_ = arraysize(stages_);
1435 return;
1438 // Find high and low res tilings and initialize the iterators.
1439 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1440 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1441 if (tiling->resolution() == HIGH_RESOLUTION) {
1442 iterators_[HIGH_RES] =
1443 PictureLayerTiling::TilingRasterTileIterator(tiling);
1446 if (tiling->resolution() == LOW_RESOLUTION) {
1447 iterators_[LOW_RES] =
1448 PictureLayerTiling::TilingRasterTileIterator(tiling);
1452 if (prioritize_low_res) {
1453 stages_[0].iterator_type = LOW_RES;
1454 stages_[0].tile_type = TilePriority::NOW;
1456 stages_[1].iterator_type = HIGH_RES;
1457 stages_[1].tile_type = TilePriority::NOW;
1458 } else {
1459 stages_[0].iterator_type = HIGH_RES;
1460 stages_[0].tile_type = TilePriority::NOW;
1462 stages_[1].iterator_type = LOW_RES;
1463 stages_[1].tile_type = TilePriority::NOW;
1466 stages_[2].iterator_type = HIGH_RES;
1467 stages_[2].tile_type = TilePriority::SOON;
1469 stages_[3].iterator_type = HIGH_RES;
1470 stages_[3].tile_type = TilePriority::EVENTUALLY;
1472 IteratorType index = stages_[current_stage_].iterator_type;
1473 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1474 if (!iterators_[index] || iterators_[index].get_type() != tile_type)
1475 AdvanceToNextStage();
1478 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1480 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1481 return current_stage_ < arraysize(stages_);
1484 PictureLayerImpl::LayerRasterTileIterator&
1485 PictureLayerImpl::LayerRasterTileIterator::
1486 operator++() {
1487 IteratorType index = stages_[current_stage_].iterator_type;
1488 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1490 // First advance the iterator.
1491 DCHECK(iterators_[index]);
1492 DCHECK(iterators_[index].get_type() == tile_type);
1493 ++iterators_[index];
1495 if (!iterators_[index] || iterators_[index].get_type() != tile_type)
1496 AdvanceToNextStage();
1498 return *this;
1501 Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1502 DCHECK(*this);
1504 IteratorType index = stages_[current_stage_].iterator_type;
1505 DCHECK(iterators_[index]);
1506 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1508 return *iterators_[index];
1511 const Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() const {
1512 DCHECK(*this);
1514 IteratorType index = stages_[current_stage_].iterator_type;
1515 DCHECK(iterators_[index]);
1516 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1518 return *iterators_[index];
1521 void PictureLayerImpl::LayerRasterTileIterator::AdvanceToNextStage() {
1522 DCHECK_LT(current_stage_, arraysize(stages_));
1523 ++current_stage_;
1524 while (current_stage_ < arraysize(stages_)) {
1525 IteratorType index = stages_[current_stage_].iterator_type;
1526 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1528 if (iterators_[index] && iterators_[index].get_type() == tile_type)
1529 break;
1530 ++current_stage_;
1534 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1535 : layer_(nullptr),
1536 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES),
1537 current_category_(PictureLayerTiling::EVENTUALLY),
1538 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
1539 current_tiling_(0u) {
1542 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1543 PictureLayerImpl* layer,
1544 TreePriority tree_priority)
1545 : layer_(layer),
1546 tree_priority_(tree_priority),
1547 current_category_(PictureLayerTiling::EVENTUALLY),
1548 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
1549 current_tiling_(CurrentTilingRange().start - 1u) {
1550 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1551 // that layers that don't have valid tile priorities have lowest priorities so
1552 // they evict their tiles first (crbug.com/381704)
1553 DCHECK(layer_->tilings_);
1554 do {
1555 if (!AdvanceToNextTiling())
1556 break;
1558 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
1559 layer_->tilings_->tiling_at(CurrentTilingIndex()),
1560 tree_priority,
1561 current_category_);
1562 } while (!current_iterator_);
1565 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {
1568 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1569 DCHECK(*this);
1570 return *current_iterator_;
1573 const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const {
1574 DCHECK(*this);
1575 return *current_iterator_;
1578 PictureLayerImpl::LayerEvictionTileIterator&
1579 PictureLayerImpl::LayerEvictionTileIterator::
1580 operator++() {
1581 DCHECK(*this);
1582 ++current_iterator_;
1583 while (!current_iterator_) {
1584 if (!AdvanceToNextTiling())
1585 break;
1587 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
1588 layer_->tilings_->tiling_at(CurrentTilingIndex()),
1589 tree_priority_,
1590 current_category_);
1592 return *this;
1595 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1596 return !!current_iterator_;
1599 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() {
1600 switch (current_category_) {
1601 case PictureLayerTiling::EVENTUALLY:
1602 current_category_ =
1603 PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION;
1604 return true;
1605 case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
1606 current_category_ = PictureLayerTiling::SOON;
1607 return true;
1608 case PictureLayerTiling::SOON:
1609 current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION;
1610 return true;
1611 case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION:
1612 current_category_ = PictureLayerTiling::NOW;
1613 return true;
1614 case PictureLayerTiling::NOW:
1615 current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION;
1616 return true;
1617 case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION:
1618 return false;
1620 NOTREACHED();
1621 return false;
1624 bool
1625 PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() {
1626 switch (current_tiling_range_type_) {
1627 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
1628 current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES;
1629 return true;
1630 case PictureLayerTilingSet::LOWER_THAN_LOW_RES:
1631 current_tiling_range_type_ =
1632 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES;
1633 return true;
1634 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
1635 current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES;
1636 return true;
1637 case PictureLayerTilingSet::LOW_RES:
1638 current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES;
1639 return true;
1640 case PictureLayerTilingSet::HIGH_RES:
1641 if (!AdvanceToNextCategory())
1642 return false;
1644 current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES;
1645 return true;
1647 NOTREACHED();
1648 return false;
1651 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() {
1652 DCHECK_NE(current_tiling_, CurrentTilingRange().end);
1653 ++current_tiling_;
1654 while (current_tiling_ == CurrentTilingRange().end) {
1655 if (!AdvanceToNextTilingRangeType())
1656 return false;
1658 current_tiling_ = CurrentTilingRange().start;
1660 return true;
1663 PictureLayerTilingSet::TilingRange
1664 PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const {
1665 return layer_->tilings_->GetTilingRange(current_tiling_range_type_);
1668 size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const {
1669 DCHECK_NE(current_tiling_, CurrentTilingRange().end);
1670 switch (current_tiling_range_type_) {
1671 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
1672 case PictureLayerTilingSet::LOW_RES:
1673 case PictureLayerTilingSet::HIGH_RES:
1674 return current_tiling_;
1675 // Tilings in the following ranges are accessed in reverse order.
1676 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
1677 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: {
1678 PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange();
1679 size_t current_tiling_range_offset = current_tiling_ - tiling_range.start;
1680 return tiling_range.end - 1 - current_tiling_range_offset;
1683 NOTREACHED();
1684 return 0;
1687 } // namespace cc