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"
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/output/begin_frame_args.h"
20 #include "cc/quads/checkerboard_draw_quad.h"
21 #include "cc/quads/debug_border_draw_quad.h"
22 #include "cc/quads/picture_draw_quad.h"
23 #include "cc/quads/solid_color_draw_quad.h"
24 #include "cc/quads/tile_draw_quad.h"
25 #include "cc/resources/tile_manager.h"
26 #include "cc/trees/layer_tree_impl.h"
27 #include "cc/trees/occlusion_tracker.h"
28 #include "ui/gfx/quad_f.h"
29 #include "ui/gfx/rect_conversions.h"
30 #include "ui/gfx/size_conversions.h"
33 const float kMaxScaleRatioDuringPinch
= 2.0f
;
35 // When creating a new tiling during pinch, snap to an existing
36 // tiling's scale if the desired scale is within this ratio.
37 const float kSnapToExistingTilingRatio
= 1.2f
;
39 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
40 const float kCpuSkewportTargetTimeInFrames
= 60.0f
;
42 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
43 // TileManager::BinFromTilePriority).
44 const float kGpuSkewportTargetTimeInFrames
= 0.0f
;
50 PictureLayerImpl::Pair::Pair() : active(NULL
), pending(NULL
) {
53 PictureLayerImpl::Pair::Pair(PictureLayerImpl
* active_layer
,
54 PictureLayerImpl
* pending_layer
)
55 : active(active_layer
), pending(pending_layer
) {
58 PictureLayerImpl::Pair::~Pair() {
61 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
62 : LayerImpl(tree_impl
, id
),
64 pile_(PicturePileImpl::Create()),
66 ideal_page_scale_(0.f
),
67 ideal_device_scale_(0.f
),
68 ideal_source_scale_(0.f
),
69 ideal_contents_scale_(0.f
),
70 raster_page_scale_(0.f
),
71 raster_device_scale_(0.f
),
72 raster_source_scale_(0.f
),
73 raster_contents_scale_(0.f
),
74 low_res_raster_contents_scale_(0.f
),
75 raster_source_scale_is_fixed_(false),
76 was_screen_space_transform_animating_(false),
77 needs_post_commit_initialization_(true),
78 should_update_tile_priorities_(false) {
79 layer_tree_impl()->RegisterPictureLayerImpl(this);
82 PictureLayerImpl::~PictureLayerImpl() {
83 layer_tree_impl()->UnregisterPictureLayerImpl(this);
86 const char* PictureLayerImpl::LayerTypeAsString() const {
87 return "cc::PictureLayerImpl";
90 scoped_ptr
<LayerImpl
> PictureLayerImpl::CreateLayerImpl(
91 LayerTreeImpl
* tree_impl
) {
92 return PictureLayerImpl::Create(tree_impl
, id()).PassAs
<LayerImpl
>();
95 void PictureLayerImpl::PushPropertiesTo(LayerImpl
* base_layer
) {
96 // It's possible this layer was never drawn or updated (e.g. because it was
97 // a descendant of an opacity 0 layer).
98 DoPostCommitInitializationIfNeeded();
99 PictureLayerImpl
* layer_impl
= static_cast<PictureLayerImpl
*>(base_layer
);
101 // We have already synced the important bits from the the active layer, and
102 // we will soon swap out its tilings and use them for recycling. However,
103 // there are now tiles in this layer's tilings that were unref'd and replaced
104 // with new tiles (due to invalidation). This resets all active priorities on
105 // the to-be-recycled tiling to ensure replaced tiles don't linger and take
106 // memory (due to a stale 'active' priority).
107 if (layer_impl
->tilings_
)
108 layer_impl
->tilings_
->DidBecomeRecycled();
110 LayerImpl::PushPropertiesTo(base_layer
);
112 // When the pending tree pushes to the active tree, the pending twin
114 layer_impl
->twin_layer_
= NULL
;
117 layer_impl
->SetIsMask(is_mask_
);
118 layer_impl
->pile_
= pile_
;
120 // Tilings would be expensive to push, so we swap.
121 layer_impl
->tilings_
.swap(tilings_
);
122 layer_impl
->tilings_
->SetClient(layer_impl
);
124 tilings_
->SetClient(this);
126 // Remove invalidated tiles from what will become a recycle tree.
128 tilings_
->RemoveTilesInRegion(invalidation_
);
130 layer_impl
->raster_page_scale_
= raster_page_scale_
;
131 layer_impl
->raster_device_scale_
= raster_device_scale_
;
132 layer_impl
->raster_source_scale_
= raster_source_scale_
;
133 layer_impl
->raster_contents_scale_
= raster_contents_scale_
;
134 layer_impl
->low_res_raster_contents_scale_
= low_res_raster_contents_scale_
;
135 layer_impl
->needs_post_commit_initialization_
= false;
137 // The invalidation on this soon-to-be-recycled layer must be cleared to
138 // mirror clearing the invalidation in PictureLayer's version of this function
139 // in case push properties is skipped.
140 layer_impl
->invalidation_
.Swap(&invalidation_
);
141 invalidation_
.Clear();
142 needs_post_commit_initialization_
= true;
144 // We always need to push properties.
145 // See http://crbug.com/303943
146 needs_push_properties_
= true;
149 void PictureLayerImpl::AppendQuads(
150 RenderPass
* render_pass
,
151 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
152 AppendQuadsData
* append_quads_data
) {
153 DCHECK(!needs_post_commit_initialization_
);
155 float max_contents_scale
= MaximumTilingContentsScale();
156 gfx::Transform scaled_draw_transform
= draw_transform();
157 scaled_draw_transform
.Scale(SK_MScalar1
/ max_contents_scale
,
158 SK_MScalar1
/ max_contents_scale
);
159 gfx::Size scaled_content_bounds
=
160 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale
));
162 gfx::Rect scaled_visible_content_rect
=
163 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale
);
164 scaled_visible_content_rect
.Intersect(gfx::Rect(scaled_content_bounds
));
166 SharedQuadState
* shared_quad_state
=
167 render_pass
->CreateAndAppendSharedQuadState();
168 shared_quad_state
->SetAll(scaled_draw_transform
,
169 scaled_content_bounds
,
170 scaled_visible_content_rect
,
171 draw_properties().clip_rect
,
172 draw_properties().is_clipped
,
173 draw_properties().opacity
,
175 sorting_context_id_
);
177 if (current_draw_mode_
== DRAW_MODE_RESOURCELESS_SOFTWARE
) {
178 AppendDebugBorderQuad(
180 scaled_content_bounds
,
183 DebugColors::DirectPictureBorderColor(),
184 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
186 gfx::Rect geometry_rect
= scaled_visible_content_rect
;
187 gfx::Rect opaque_rect
= contents_opaque() ? geometry_rect
: gfx::Rect();
188 gfx::Rect visible_geometry_rect
= occlusion_tracker
.UnoccludedContentRect(
189 geometry_rect
, scaled_draw_transform
);
190 if (visible_geometry_rect
.IsEmpty())
193 gfx::Size texture_size
= scaled_visible_content_rect
.size();
194 gfx::RectF texture_rect
= gfx::RectF(texture_size
);
195 gfx::Rect quad_content_rect
= scaled_visible_content_rect
;
197 PictureDrawQuad
* quad
=
198 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
199 quad
->SetNew(shared_quad_state
,
202 visible_geometry_rect
,
212 AppendDebugBorderQuad(
213 render_pass
, scaled_content_bounds
, shared_quad_state
, append_quads_data
);
215 if (ShowDebugBorders()) {
216 for (PictureLayerTilingSet::CoverageIterator
iter(
219 scaled_visible_content_rect
,
220 ideal_contents_scale_
);
225 if (*iter
&& iter
->IsReadyToDraw()) {
226 ManagedTileState::TileVersion::Mode mode
=
227 iter
->GetTileVersionForDrawing().mode();
228 if (mode
== ManagedTileState::TileVersion::SOLID_COLOR_MODE
) {
229 color
= DebugColors::SolidColorTileBorderColor();
230 width
= DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
231 } else if (mode
== ManagedTileState::TileVersion::PICTURE_PILE_MODE
) {
232 color
= DebugColors::PictureTileBorderColor();
233 width
= DebugColors::PictureTileBorderWidth(layer_tree_impl());
234 } else if (iter
->priority(ACTIVE_TREE
).resolution
== HIGH_RESOLUTION
) {
235 color
= DebugColors::HighResTileBorderColor();
236 width
= DebugColors::HighResTileBorderWidth(layer_tree_impl());
237 } else if (iter
->priority(ACTIVE_TREE
).resolution
== LOW_RESOLUTION
) {
238 color
= DebugColors::LowResTileBorderColor();
239 width
= DebugColors::LowResTileBorderWidth(layer_tree_impl());
240 } else if (iter
->contents_scale() > max_contents_scale
) {
241 color
= DebugColors::ExtraHighResTileBorderColor();
242 width
= DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
244 color
= DebugColors::ExtraLowResTileBorderColor();
245 width
= DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
248 color
= DebugColors::MissingTileBorderColor();
249 width
= DebugColors::MissingTileBorderWidth(layer_tree_impl());
252 DebugBorderDrawQuad
* debug_border_quad
=
253 render_pass
->CreateAndAppendDrawQuad
<DebugBorderDrawQuad
>();
254 gfx::Rect geometry_rect
= iter
.geometry_rect();
255 gfx::Rect visible_geometry_rect
= geometry_rect
;
256 debug_border_quad
->SetNew(shared_quad_state
,
258 visible_geometry_rect
,
264 // Keep track of the tilings that were used so that tilings that are
265 // unused can be considered for removal.
266 std::vector
<PictureLayerTiling
*> seen_tilings
;
268 // Ignore missing tiles outside of viewport for tile priority. This is
269 // normally the same as draw viewport but can be independently overridden by
270 // embedders like Android WebView with SetExternalDrawConstraints.
271 gfx::Rect scaled_viewport_for_tile_priority
= gfx::ScaleToEnclosingRect(
272 GetViewportForTilePriorityInContentSpace(), max_contents_scale
);
274 size_t missing_tile_count
= 0u;
275 size_t on_demand_missing_tile_count
= 0u;
276 for (PictureLayerTilingSet::CoverageIterator
iter(tilings_
.get(),
278 scaled_visible_content_rect
,
279 ideal_contents_scale_
);
282 gfx::Rect geometry_rect
= iter
.geometry_rect();
283 gfx::Rect visible_geometry_rect
= occlusion_tracker
.UnoccludedContentRect(
284 geometry_rect
, scaled_draw_transform
);
285 if (visible_geometry_rect
.IsEmpty())
288 append_quads_data
->visible_content_area
+=
289 visible_geometry_rect
.width() * visible_geometry_rect
.height();
291 bool has_draw_quad
= false;
292 if (*iter
&& iter
->IsReadyToDraw()) {
293 const ManagedTileState::TileVersion
& tile_version
=
294 iter
->GetTileVersionForDrawing();
295 switch (tile_version
.mode()) {
296 case ManagedTileState::TileVersion::RESOURCE_MODE
: {
297 gfx::RectF texture_rect
= iter
.texture_rect();
298 gfx::Rect opaque_rect
= iter
->opaque_rect();
299 opaque_rect
.Intersect(geometry_rect
);
301 // The raster_contents_scale_ is the best scale that the layer is
302 // trying to produce, even though it may not be ideal. Since that's
303 // the best the layer can promise in the future, consider those as
304 // complete. But if a tile is ideal scale, we don't want to consider
305 // it incomplete and trying to replace it with a tile at a worse
307 if (iter
->contents_scale() != raster_contents_scale_
&&
308 iter
->contents_scale() != ideal_contents_scale_
&&
309 geometry_rect
.Intersects(scaled_viewport_for_tile_priority
)) {
310 append_quads_data
->num_incomplete_tiles
++;
314 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
315 quad
->SetNew(shared_quad_state
,
318 visible_geometry_rect
,
319 tile_version
.get_resource_id(),
322 tile_version
.contents_swizzled());
323 has_draw_quad
= true;
326 case ManagedTileState::TileVersion::PICTURE_PILE_MODE
: {
327 if (!layer_tree_impl()
328 ->GetRendererCapabilities()
329 .allow_rasterize_on_demand
) {
330 ++on_demand_missing_tile_count
;
334 gfx::RectF texture_rect
= iter
.texture_rect();
335 gfx::Rect opaque_rect
= iter
->opaque_rect();
336 opaque_rect
.Intersect(geometry_rect
);
338 ResourceProvider
* resource_provider
=
339 layer_tree_impl()->resource_provider();
340 ResourceFormat format
=
341 resource_provider
->memory_efficient_texture_format();
342 PictureDrawQuad
* quad
=
343 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
344 quad
->SetNew(shared_quad_state
,
347 visible_geometry_rect
,
351 iter
->content_rect(),
352 iter
->contents_scale(),
354 has_draw_quad
= true;
357 case ManagedTileState::TileVersion::SOLID_COLOR_MODE
: {
358 SolidColorDrawQuad
* quad
=
359 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
360 quad
->SetNew(shared_quad_state
,
362 visible_geometry_rect
,
363 tile_version
.get_solid_color(),
365 has_draw_quad
= true;
371 if (!has_draw_quad
) {
372 if (draw_checkerboard_for_missing_tiles()) {
373 CheckerboardDrawQuad
* quad
=
374 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
375 SkColor color
= DebugColors::DefaultCheckerboardColor();
377 shared_quad_state
, geometry_rect
, visible_geometry_rect
, color
);
379 SkColor color
= SafeOpaqueBackgroundColor();
380 SolidColorDrawQuad
* quad
=
381 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
382 quad
->SetNew(shared_quad_state
,
384 visible_geometry_rect
,
389 if (geometry_rect
.Intersects(scaled_viewport_for_tile_priority
)) {
390 append_quads_data
->num_missing_tiles
++;
391 ++missing_tile_count
;
393 append_quads_data
->approximated_visible_content_area
+=
394 visible_geometry_rect
.width() * visible_geometry_rect
.height();
398 if (iter
->priority(ACTIVE_TREE
).resolution
!= HIGH_RESOLUTION
) {
399 append_quads_data
->approximated_visible_content_area
+=
400 visible_geometry_rect
.width() * visible_geometry_rect
.height();
403 if (seen_tilings
.empty() || seen_tilings
.back() != iter
.CurrentTiling())
404 seen_tilings
.push_back(iter
.CurrentTiling());
407 if (missing_tile_count
) {
408 TRACE_EVENT_INSTANT2("cc",
409 "PictureLayerImpl::AppendQuads checkerboard",
410 TRACE_EVENT_SCOPE_THREAD
,
411 "missing_tile_count",
413 "on_demand_missing_tile_count",
414 on_demand_missing_tile_count
);
417 // Aggressively remove any tilings that are not seen to save memory. Note
418 // that this is at the expense of doing cause more frequent re-painting. A
419 // better scheme would be to maintain a tighter visible_content_rect for the
421 CleanUpTilingsOnActiveLayer(seen_tilings
);
424 void PictureLayerImpl::UpdateTiles(
425 const OcclusionTracker
<LayerImpl
>* occlusion_tracker
) {
426 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
428 DoPostCommitInitializationIfNeeded();
430 // TODO(danakj): We should always get an occlusion tracker when we are using
431 // occlusion, so update this check when we don't use a pending tree in the
432 // browser compositor.
433 DCHECK(!occlusion_tracker
||
434 layer_tree_impl()->settings().use_occlusion_for_tile_prioritization
);
436 visible_rect_for_tile_priority_
= visible_content_rect();
437 viewport_rect_for_tile_priority_
=
438 layer_tree_impl()->ViewportRectForTilePriority();
439 screen_space_transform_for_tile_priority_
= screen_space_transform();
441 if (!CanHaveTilings()) {
442 ideal_page_scale_
= 0.f
;
443 ideal_device_scale_
= 0.f
;
444 ideal_contents_scale_
= 0.f
;
445 ideal_source_scale_
= 0.f
;
446 SanityCheckTilingState();
452 DCHECK(tilings_
->num_tilings() > 0 || raster_contents_scale_
== 0.f
)
453 << "A layer with no tilings shouldn't have valid raster scales";
454 if (!raster_contents_scale_
|| ShouldAdjustRasterScale()) {
455 RecalculateRasterScales();
456 AddTilingsForRasterScale();
459 DCHECK(raster_page_scale_
);
460 DCHECK(raster_device_scale_
);
461 DCHECK(raster_source_scale_
);
462 DCHECK(raster_contents_scale_
);
463 DCHECK(low_res_raster_contents_scale_
);
465 was_screen_space_transform_animating_
=
466 draw_properties().screen_space_transform_is_animating
;
468 should_update_tile_priorities_
= true;
470 UpdateTilePriorities(occlusion_tracker
);
472 if (layer_tree_impl()->IsPendingTree())
473 MarkVisibleResourcesAsRequired();
476 void PictureLayerImpl::UpdateTilePriorities(
477 const OcclusionTracker
<LayerImpl
>* occlusion_tracker
) {
478 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
480 double current_frame_time_in_seconds
=
481 (layer_tree_impl()->CurrentBeginFrameArgs().frame_time
-
482 base::TimeTicks()).InSecondsF();
484 bool tiling_needs_update
= false;
485 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
486 if (tilings_
->tiling_at(i
)->NeedsUpdateForFrameAtTime(
487 current_frame_time_in_seconds
)) {
488 tiling_needs_update
= true;
492 if (!tiling_needs_update
)
495 gfx::Rect
visible_rect_in_content_space(
496 GetViewportForTilePriorityInContentSpace());
497 visible_rect_in_content_space
.Intersect(visible_content_rect());
498 gfx::Rect visible_layer_rect
= gfx::ScaleToEnclosingRect(
499 visible_rect_in_content_space
, 1.f
/ contents_scale_x());
501 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
502 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
503 tilings_
->tiling_at(i
)->UpdateTilePriorities(tree
,
505 ideal_contents_scale_
,
506 current_frame_time_in_seconds
,
512 // Tile priorities were modified.
513 layer_tree_impl()->DidModifyTilePriorities();
516 gfx::Rect
PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
517 // If visible_rect_for_tile_priority_ is empty or
518 // viewport_rect_for_tile_priority_ is set to be different from the device
519 // viewport, try to inverse project the viewport into layer space and use
520 // that. Otherwise just use visible_rect_for_tile_priority_
521 gfx::Rect visible_rect_in_content_space
= visible_rect_for_tile_priority_
;
523 if (visible_rect_in_content_space
.IsEmpty() ||
524 layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority_
) {
525 gfx::Transform
view_to_layer(gfx::Transform::kSkipInitialization
);
527 if (screen_space_transform_for_tile_priority_
.GetInverse(&view_to_layer
)) {
528 // Transform from view space to content space.
529 visible_rect_in_content_space
=
530 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
531 view_to_layer
, viewport_rect_for_tile_priority_
));
533 visible_rect_in_content_space
.Intersect(gfx::Rect(content_bounds()));
537 return visible_rect_in_content_space
;
540 PictureLayerImpl
* PictureLayerImpl::GetRecycledTwinLayer() {
541 // TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
542 return static_cast<PictureLayerImpl
*>(
543 layer_tree_impl()->FindRecycleTreeLayerById(id()));
546 void PictureLayerImpl::NotifyTileStateChanged(const Tile
* tile
) {
547 if (layer_tree_impl()->IsActiveTree()) {
548 gfx::RectF layer_damage_rect
=
549 gfx::ScaleRect(tile
->content_rect(), 1.f
/ tile
->contents_scale());
550 AddDamageRect(layer_damage_rect
);
554 void PictureLayerImpl::DidBecomeActive() {
555 LayerImpl::DidBecomeActive();
556 tilings_
->DidBecomeActive();
557 layer_tree_impl()->DidModifyTilePriorities();
560 void PictureLayerImpl::DidBeginTracing() {
561 pile_
->DidBeginTracing();
564 void PictureLayerImpl::ReleaseResources() {
570 // To avoid an edge case after lost context where the tree is up to date but
571 // the tilings have not been managed, request an update draw properties
572 // to force tilings to get managed.
573 layer_tree_impl()->set_needs_update_draw_properties();
576 skia::RefPtr
<SkPicture
> PictureLayerImpl::GetPicture() {
577 return pile_
->GetFlattenedPicture();
580 scoped_refptr
<Tile
> PictureLayerImpl::CreateTile(PictureLayerTiling
* tiling
,
581 const gfx::Rect
& content_rect
) {
582 if (!pile_
->CanRaster(tiling
->contents_scale(), content_rect
))
583 return scoped_refptr
<Tile
>();
587 // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as
588 // much savings on memory as we can. However, for some cases like ganesh or
589 // small layers, the amount of time we spend analyzing might not justify
590 // memory savings that we can get. Note that we don't handle solid color
591 // masks, so we shouldn't bother analyzing those.
592 // Bugs: crbug.com/397198, crbug.com/396908
594 flags
= Tile::USE_PICTURE_ANALYSIS
;
596 return layer_tree_impl()->tile_manager()->CreateTile(
600 contents_opaque() ? content_rect
: gfx::Rect(),
601 tiling
->contents_scale(),
603 layer_tree_impl()->source_frame_number(),
607 PicturePileImpl
* PictureLayerImpl::GetPile() {
611 const Region
* PictureLayerImpl::GetInvalidation() {
612 return &invalidation_
;
615 const PictureLayerTiling
* PictureLayerImpl::GetTwinTiling(
616 const PictureLayerTiling
* tiling
) const {
619 return twin_layer_
->tilings_
->TilingAtScale(tiling
->contents_scale());
622 PictureLayerTiling
* PictureLayerImpl::GetRecycledTwinTiling(
623 const PictureLayerTiling
* tiling
) {
624 PictureLayerImpl
* recycled_twin
= GetRecycledTwinLayer();
625 if (!recycled_twin
|| !recycled_twin
->tilings_
)
627 return recycled_twin
->tilings_
->TilingAtScale(tiling
->contents_scale());
630 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
631 return layer_tree_impl()->settings().max_tiles_for_interest_area
;
634 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
635 float skewport_target_time_in_frames
=
636 layer_tree_impl()->use_gpu_rasterization()
637 ? kGpuSkewportTargetTimeInFrames
638 : kCpuSkewportTargetTimeInFrames
;
639 return skewport_target_time_in_frames
*
640 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
641 layer_tree_impl()->settings().skewport_target_time_multiplier
;
644 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
645 return layer_tree_impl()
647 .skewport_extrapolation_limit_in_content_pixels
;
650 gfx::Size
PictureLayerImpl::CalculateTileSize(
651 const gfx::Size
& content_bounds
) const {
653 int max_size
= layer_tree_impl()->MaxTextureSize();
655 std::min(max_size
, content_bounds
.width()),
656 std::min(max_size
, content_bounds
.height()));
659 int max_texture_size
=
660 layer_tree_impl()->resource_provider()->max_texture_size();
662 gfx::Size default_tile_size
= layer_tree_impl()->settings().default_tile_size
;
663 if (layer_tree_impl()->use_gpu_rasterization()) {
664 // TODO(ernstm) crbug.com/365877: We need a unified way to override the
665 // default-tile-size.
667 gfx::Size(layer_tree_impl()->device_viewport_size().width(),
668 layer_tree_impl()->device_viewport_size().height() / 4);
670 default_tile_size
.SetToMin(gfx::Size(max_texture_size
, max_texture_size
));
672 gfx::Size max_untiled_content_size
=
673 layer_tree_impl()->settings().max_untiled_layer_size
;
674 max_untiled_content_size
.SetToMin(
675 gfx::Size(max_texture_size
, max_texture_size
));
677 bool any_dimension_too_large
=
678 content_bounds
.width() > max_untiled_content_size
.width() ||
679 content_bounds
.height() > max_untiled_content_size
.height();
681 bool any_dimension_one_tile
=
682 content_bounds
.width() <= default_tile_size
.width() ||
683 content_bounds
.height() <= default_tile_size
.height();
685 // If long and skinny, tile at the max untiled content size, and clamp
686 // the smaller dimension to the content size, e.g. 1000x12 layer with
687 // 500x500 max untiled size would get 500x12 tiles. Also do this
688 // if the layer is small.
689 if (any_dimension_one_tile
|| !any_dimension_too_large
) {
690 int width
= std::min(
691 std::max(max_untiled_content_size
.width(), default_tile_size
.width()),
692 content_bounds
.width());
693 int height
= std::min(
694 std::max(max_untiled_content_size
.height(), default_tile_size
.height()),
695 content_bounds
.height());
696 // Round up to the closest multiple of 64. This improves recycling and
697 // avoids odd texture sizes.
698 width
= RoundUp(width
, 64);
699 height
= RoundUp(height
, 64);
700 return gfx::Size(width
, height
);
703 return default_tile_size
;
706 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl
* other
) {
707 TRACE_EVENT0("cc", "SyncFromActiveLayer");
708 DCHECK(!other
->needs_post_commit_initialization_
);
709 DCHECK(other
->tilings_
);
711 if (!DrawsContent()) {
716 raster_page_scale_
= other
->raster_page_scale_
;
717 raster_device_scale_
= other
->raster_device_scale_
;
718 raster_source_scale_
= other
->raster_source_scale_
;
719 raster_contents_scale_
= other
->raster_contents_scale_
;
720 low_res_raster_contents_scale_
= other
->low_res_raster_contents_scale_
;
722 bool synced_high_res_tiling
= false;
723 if (CanHaveTilings()) {
724 synced_high_res_tiling
= tilings_
->SyncTilings(
725 *other
->tilings_
, bounds(), invalidation_
, MinimumContentsScale());
730 // If our MinimumContentsScale has changed to prevent the twin's high res
731 // tiling from being synced, we should reset the raster scale and let it be
732 // recalculated (1) again. This can happen if our bounds shrink to the point
733 // where min contents scale grows.
734 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
735 // should refactor this code a little bit and actually recalculate this.
736 // However, this is a larger undertaking, so this will work for now.
737 if (!synced_high_res_tiling
)
740 SanityCheckTilingState();
743 void PictureLayerImpl::SyncTiling(
744 const PictureLayerTiling
* tiling
) {
745 if (!CanHaveTilingWithScale(tiling
->contents_scale()))
747 tilings_
->AddTiling(tiling
->contents_scale());
749 // If this tree needs update draw properties, then the tiling will
750 // get updated prior to drawing or activation. If this tree does not
751 // need update draw properties, then its transforms are up to date and
752 // we can create tiles for this tiling immediately.
753 if (!layer_tree_impl()->needs_update_draw_properties() &&
754 should_update_tile_priorities_
) {
755 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
756 // when we stop using the pending tree in the browser compositor. If we want
757 // to support occlusion tracking here, we need to dirty the draw properties
758 // or save occlusion as a draw property.
759 UpdateTilePriorities(NULL
);
763 void PictureLayerImpl::SetIsMask(bool is_mask
) {
764 if (is_mask_
== is_mask
)
768 tilings_
->RemoveAllTiles();
771 ResourceProvider::ResourceId
PictureLayerImpl::ContentsResourceId() const {
772 gfx::Rect
content_rect(content_bounds());
773 float scale
= MaximumTilingContentsScale();
774 PictureLayerTilingSet::CoverageIterator
iter(
775 tilings_
.get(), scale
, content_rect
, ideal_contents_scale_
);
777 // Mask resource not ready yet.
781 // Masks only supported if they fit on exactly one tile.
782 if (iter
.geometry_rect() != content_rect
)
785 const ManagedTileState::TileVersion
& tile_version
=
786 iter
->GetTileVersionForDrawing();
787 if (!tile_version
.IsReadyToDraw() ||
788 tile_version
.mode() != ManagedTileState::TileVersion::RESOURCE_MODE
)
791 return tile_version
.get_resource_id();
794 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
795 DCHECK(layer_tree_impl()->IsPendingTree());
796 DCHECK(ideal_contents_scale_
);
797 DCHECK_GT(tilings_
->num_tilings(), 0u);
799 // The goal of this function is to find the minimum set of tiles that need to
800 // be ready to draw in order to activate without flashing content from a
801 // higher res on the active tree to a lower res on the pending tree.
803 // First, early out for layers with no visible content.
804 if (visible_content_rect().IsEmpty())
807 gfx::Rect
rect(visible_content_rect());
809 // Only mark tiles inside the viewport for tile priority as required for
810 // activation. This viewport is normally the same as the draw viewport but
811 // can be independently overridden by embedders like Android WebView with
812 // SetExternalDrawConstraints.
813 rect
.Intersect(GetViewportForTilePriorityInContentSpace());
815 float min_acceptable_scale
=
816 std::min(raster_contents_scale_
, ideal_contents_scale_
);
818 if (PictureLayerImpl
* twin
= twin_layer_
) {
819 float twin_min_acceptable_scale
=
820 std::min(twin
->ideal_contents_scale_
, twin
->raster_contents_scale_
);
821 // Ignore 0 scale in case CalculateContentsScale() has never been
822 // called for active twin.
823 if (twin_min_acceptable_scale
!= 0.0f
) {
824 min_acceptable_scale
=
825 std::min(min_acceptable_scale
, twin_min_acceptable_scale
);
829 PictureLayerTiling
* high_res
= NULL
;
830 PictureLayerTiling
* low_res
= NULL
;
832 // First pass: ready to draw tiles in acceptable but non-ideal tilings are
833 // marked as required for activation so that their textures are not thrown
834 // away; any non-ready tiles are not marked as required.
835 Region missing_region
= rect
;
836 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
837 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
838 DCHECK(tiling
->has_ever_been_updated());
840 if (tiling
->resolution() == LOW_RESOLUTION
) {
841 DCHECK(!low_res
) << "There can only be one low res tiling";
844 if (tiling
->contents_scale() < min_acceptable_scale
)
846 if (tiling
->resolution() == HIGH_RESOLUTION
) {
847 DCHECK(!high_res
) << "There can only be one high res tiling";
851 for (PictureLayerTiling::CoverageIterator
iter(tiling
,
856 if (!*iter
|| !iter
->IsReadyToDraw())
859 missing_region
.Subtract(iter
.geometry_rect());
860 iter
->MarkRequiredForActivation();
863 DCHECK(high_res
) << "There must be one high res tiling";
865 // If these pointers are null (because no twin, no matching tiling, or the
866 // simpification just below), then high res tiles will be required to fill any
867 // holes left by the first pass above. If the pointers are valid, then this
868 // layer is allowed to skip any tiles that are not ready on its twin.
869 const PictureLayerTiling
* twin_high_res
= NULL
;
870 const PictureLayerTiling
* twin_low_res
= NULL
;
873 // As a simplification, only allow activating to skip twin tiles that the
874 // active layer is also missing when both this layer and its twin have
875 // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
876 // res tiling. This avoids having to iterate/track coverage of non-ideal
877 // tilings during the last draw call on the active layer.
878 if (tilings_
->num_tilings() <= 2 &&
879 twin_layer_
->tilings_
->num_tilings() <= tilings_
->num_tilings()) {
880 twin_low_res
= low_res
? GetTwinTiling(low_res
) : NULL
;
881 twin_high_res
= high_res
? GetTwinTiling(high_res
) : NULL
;
884 // If this layer and its twin have different transforms, then don't compare
885 // them and only allow activating to high res tiles, since tiles on each
886 // layer will be in different places on screen.
887 if (twin_layer_
->layer_tree_impl()->RequiresHighResToDraw() ||
888 bounds() != twin_layer_
->bounds() ||
889 draw_properties().screen_space_transform
!=
890 twin_layer_
->draw_properties().screen_space_transform
) {
891 twin_high_res
= NULL
;
896 // As a second pass, mark as required any visible high res tiles not filled in
897 // by acceptable non-ideal tiles from the first pass.
898 if (MarkVisibleTilesAsRequired(
899 high_res
, twin_high_res
, contents_scale_x(), rect
, missing_region
)) {
900 // As an optional third pass, if a high res tile was skipped because its
901 // twin was also missing, then fall back to mark low res tiles as required
902 // in case the active twin is substituting those for missing high res
903 // content. Only suitable, when low res is enabled.
905 MarkVisibleTilesAsRequired(
906 low_res
, twin_low_res
, contents_scale_x(), rect
, missing_region
);
911 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
912 PictureLayerTiling
* tiling
,
913 const PictureLayerTiling
* optional_twin_tiling
,
914 float contents_scale
,
915 const gfx::Rect
& rect
,
916 const Region
& missing_region
) const {
917 bool twin_had_missing_tile
= false;
918 for (PictureLayerTiling::CoverageIterator
iter(tiling
,
924 // A null tile (i.e. missing recording) can just be skipped.
928 // If the tile is occluded, don't mark it as required for activation.
929 if (tile
->is_occluded(PENDING_TREE
))
932 // If the missing region doesn't cover it, this tile is fully
933 // covered by acceptable tiles at other scales.
934 if (!missing_region
.Intersects(iter
.geometry_rect()))
937 // If the twin tile doesn't exist (i.e. missing recording or so far away
938 // that it is outside the visible tile rect) or this tile is shared between
939 // with the twin, then this tile isn't required to prevent flashing.
940 if (optional_twin_tiling
) {
941 Tile
* twin_tile
= optional_twin_tiling
->TileAt(iter
.i(), iter
.j());
942 if (!twin_tile
|| twin_tile
== tile
) {
943 // However if the shared tile is being used on the active tree, then
944 // there's no missing content in this place, and low res is not needed.
945 if (!twin_tile
|| !twin_tile
->IsReadyToDraw())
946 twin_had_missing_tile
= true;
951 tile
->MarkRequiredForActivation();
953 return twin_had_missing_tile
;
956 void PictureLayerImpl::DoPostCommitInitialization() {
957 DCHECK(needs_post_commit_initialization_
);
958 DCHECK(layer_tree_impl()->IsPendingTree());
961 tilings_
.reset(new PictureLayerTilingSet(this, bounds()));
963 DCHECK(!twin_layer_
);
964 twin_layer_
= static_cast<PictureLayerImpl
*>(
965 layer_tree_impl()->FindActiveTreeLayerById(id()));
967 DCHECK(!twin_layer_
->twin_layer_
);
968 twin_layer_
->twin_layer_
= this;
969 // If the twin has never been pushed to, do not sync from it.
970 // This can happen if this function is called during activation.
971 if (!twin_layer_
->needs_post_commit_initialization_
)
972 SyncFromActiveLayer(twin_layer_
);
975 needs_post_commit_initialization_
= false;
978 PictureLayerTiling
* PictureLayerImpl::AddTiling(float contents_scale
) {
979 DCHECK(CanHaveTilingWithScale(contents_scale
)) <<
980 "contents_scale: " << contents_scale
;
982 PictureLayerTiling
* tiling
= tilings_
->AddTiling(contents_scale
);
984 DCHECK(pile_
->HasRecordings());
987 twin_layer_
->SyncTiling(tiling
);
992 void PictureLayerImpl::RemoveTiling(float contents_scale
) {
993 if (!tilings_
|| tilings_
->num_tilings() == 0)
996 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
997 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
998 if (tiling
->contents_scale() == contents_scale
) {
999 tilings_
->Remove(tiling
);
1003 if (tilings_
->num_tilings() == 0)
1005 SanityCheckTilingState();
1008 void PictureLayerImpl::RemoveAllTilings() {
1010 tilings_
->RemoveAllTilings();
1011 // If there are no tilings, then raster scales are no longer meaningful.
1017 inline float PositiveRatio(float float1
, float float2
) {
1018 DCHECK_GT(float1
, 0);
1019 DCHECK_GT(float2
, 0);
1020 return float1
> float2
? float1
/ float2
: float2
/ float1
;
1025 void PictureLayerImpl::AddTilingsForRasterScale() {
1026 PictureLayerTiling
* high_res
= NULL
;
1027 PictureLayerTiling
* low_res
= NULL
;
1029 PictureLayerTiling
* previous_low_res
= NULL
;
1030 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1031 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1032 if (tiling
->contents_scale() == raster_contents_scale_
)
1034 if (tiling
->contents_scale() == low_res_raster_contents_scale_
)
1036 if (tiling
->resolution() == LOW_RESOLUTION
)
1037 previous_low_res
= tiling
;
1039 // Reset all tilings to non-ideal until the end of this function.
1040 tiling
->set_resolution(NON_IDEAL_RESOLUTION
);
1044 high_res
= AddTiling(raster_contents_scale_
);
1045 if (raster_contents_scale_
== low_res_raster_contents_scale_
)
1049 // Only create new low res tilings when the transform is static. This
1050 // prevents wastefully creating a paired low res tiling for every new high res
1051 // tiling during a pinch or a CSS animation.
1052 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1053 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching
&&
1054 !draw_properties().screen_space_transform_is_animating
&& !low_res
&&
1055 low_res
!= high_res
)
1056 low_res
= AddTiling(low_res_raster_contents_scale_
);
1058 // Set low-res if we have one.
1060 low_res
= previous_low_res
;
1061 if (low_res
&& low_res
!= high_res
)
1062 low_res
->set_resolution(LOW_RESOLUTION
);
1064 // Make sure we always have one high-res (even if high == low).
1065 high_res
->set_resolution(HIGH_RESOLUTION
);
1067 SanityCheckTilingState();
1070 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1071 if (was_screen_space_transform_animating_
!=
1072 draw_properties().screen_space_transform_is_animating
)
1075 if (draw_properties().screen_space_transform_is_animating
&&
1076 raster_contents_scale_
!= ideal_contents_scale_
&&
1077 ShouldAdjustRasterScaleDuringScaleAnimations())
1080 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1081 if (is_pinching
&& raster_page_scale_
) {
1082 // We change our raster scale when it is:
1083 // - Higher than ideal (need a lower-res tiling available)
1084 // - Too far from ideal (need a higher-res tiling available)
1085 float ratio
= ideal_page_scale_
/ raster_page_scale_
;
1086 if (raster_page_scale_
> ideal_page_scale_
||
1087 ratio
> kMaxScaleRatioDuringPinch
)
1092 // When not pinching, match the ideal page scale factor.
1093 if (raster_page_scale_
!= ideal_page_scale_
)
1097 // Always match the ideal device scale factor.
1098 if (raster_device_scale_
!= ideal_device_scale_
)
1101 // When the source scale changes we want to match it, but not when animating
1102 // or when we've fixed the scale in place.
1103 if (!draw_properties().screen_space_transform_is_animating
&&
1104 !raster_source_scale_is_fixed_
&&
1105 raster_source_scale_
!= ideal_source_scale_
)
1111 float PictureLayerImpl::SnappedContentsScale(float scale
) {
1112 // If a tiling exists within the max snapping ratio, snap to its scale.
1113 float snapped_contents_scale
= scale
;
1114 float snapped_ratio
= kSnapToExistingTilingRatio
;
1115 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1116 float tiling_contents_scale
= tilings_
->tiling_at(i
)->contents_scale();
1117 float ratio
= PositiveRatio(tiling_contents_scale
, scale
);
1118 if (ratio
< snapped_ratio
) {
1119 snapped_contents_scale
= tiling_contents_scale
;
1120 snapped_ratio
= ratio
;
1123 return snapped_contents_scale
;
1126 void PictureLayerImpl::RecalculateRasterScales() {
1127 float old_raster_contents_scale
= raster_contents_scale_
;
1128 float old_raster_page_scale
= raster_page_scale_
;
1129 float old_raster_source_scale
= raster_source_scale_
;
1131 raster_device_scale_
= ideal_device_scale_
;
1132 raster_page_scale_
= ideal_page_scale_
;
1133 raster_source_scale_
= ideal_source_scale_
;
1134 raster_contents_scale_
= ideal_contents_scale_
;
1136 // If we're not animating, or leaving an animation, and the
1137 // ideal_source_scale_ changes, then things are unpredictable, and we fix
1138 // the raster_source_scale_ in place.
1139 if (old_raster_source_scale
&&
1140 !draw_properties().screen_space_transform_is_animating
&&
1141 !was_screen_space_transform_animating_
&&
1142 old_raster_source_scale
!= ideal_source_scale_
)
1143 raster_source_scale_is_fixed_
= true;
1145 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1146 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1147 // tree. This will allow CSS scale changes to get re-rastered at an
1148 // appropriate rate.
1149 if (raster_source_scale_is_fixed_
) {
1150 raster_contents_scale_
/= raster_source_scale_
;
1151 raster_source_scale_
= 1.f
;
1154 // During pinch we completely ignore the current ideal scale, and just use
1155 // a multiple of the previous scale.
1156 // TODO(danakj): This seems crazy, we should use the current ideal, no?
1157 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1158 if (is_pinching
&& old_raster_contents_scale
) {
1159 // See ShouldAdjustRasterScale:
1160 // - When zooming out, preemptively create new tiling at lower resolution.
1161 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1162 bool zooming_out
= old_raster_page_scale
> ideal_page_scale_
;
1163 float desired_contents_scale
=
1164 zooming_out
? old_raster_contents_scale
/ kMaxScaleRatioDuringPinch
1165 : old_raster_contents_scale
* kMaxScaleRatioDuringPinch
;
1166 raster_contents_scale_
= SnappedContentsScale(desired_contents_scale
);
1167 raster_page_scale_
=
1168 raster_contents_scale_
/ raster_device_scale_
/ raster_source_scale_
;
1171 raster_contents_scale_
=
1172 std::max(raster_contents_scale_
, MinimumContentsScale());
1174 // If we're not re-rasterizing during animation, rasterize at the maximum
1175 // scale that will occur during the animation, if the maximum scale is
1176 // known. However, to avoid excessive memory use, don't rasterize at a scale
1177 // at which this layer would become larger than the viewport.
1178 if (draw_properties().screen_space_transform_is_animating
&&
1179 !ShouldAdjustRasterScaleDuringScaleAnimations()) {
1180 bool can_raster_at_maximum_scale
= false;
1181 if (draw_properties().maximum_animation_contents_scale
> 0.f
) {
1182 gfx::Size bounds_at_maximum_scale
= gfx::ToCeiledSize(gfx::ScaleSize(
1183 bounds(), draw_properties().maximum_animation_contents_scale
));
1184 if (bounds_at_maximum_scale
.GetArea() <=
1185 layer_tree_impl()->device_viewport_size().GetArea())
1186 can_raster_at_maximum_scale
= true;
1188 if (can_raster_at_maximum_scale
) {
1189 raster_contents_scale_
=
1190 std::max(raster_contents_scale_
,
1191 draw_properties().maximum_animation_contents_scale
);
1193 raster_contents_scale_
=
1194 std::max(raster_contents_scale_
,
1195 1.f
* ideal_page_scale_
* ideal_device_scale_
);
1199 // If this layer would only create one tile at this content scale,
1200 // don't create a low res tiling.
1201 gfx::Size content_bounds
=
1202 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_
));
1203 gfx::Size tile_size
= CalculateTileSize(content_bounds
);
1204 if (tile_size
.width() >= content_bounds
.width() &&
1205 tile_size
.height() >= content_bounds
.height()) {
1206 low_res_raster_contents_scale_
= raster_contents_scale_
;
1210 float low_res_factor
=
1211 layer_tree_impl()->settings().low_res_contents_scale_factor
;
1212 low_res_raster_contents_scale_
= std::max(
1213 raster_contents_scale_
* low_res_factor
,
1214 MinimumContentsScale());
1217 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1218 std::vector
<PictureLayerTiling
*> used_tilings
) {
1219 DCHECK(layer_tree_impl()->IsActiveTree());
1220 if (tilings_
->num_tilings() == 0)
1223 float min_acceptable_high_res_scale
= std::min(
1224 raster_contents_scale_
, ideal_contents_scale_
);
1225 float max_acceptable_high_res_scale
= std::max(
1226 raster_contents_scale_
, ideal_contents_scale_
);
1227 float twin_low_res_scale
= 0.f
;
1229 PictureLayerImpl
* twin
= twin_layer_
;
1230 if (twin
&& twin
->CanHaveTilings()) {
1231 min_acceptable_high_res_scale
= std::min(
1232 min_acceptable_high_res_scale
,
1233 std::min(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1234 max_acceptable_high_res_scale
= std::max(
1235 max_acceptable_high_res_scale
,
1236 std::max(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1238 for (size_t i
= 0; i
< twin
->tilings_
->num_tilings(); ++i
) {
1239 PictureLayerTiling
* tiling
= twin
->tilings_
->tiling_at(i
);
1240 if (tiling
->resolution() == LOW_RESOLUTION
)
1241 twin_low_res_scale
= tiling
->contents_scale();
1245 std::vector
<PictureLayerTiling
*> to_remove
;
1246 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1247 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1249 // Keep multiple high resolution tilings even if not used to help
1250 // activate earlier at non-ideal resolutions.
1251 if (tiling
->contents_scale() >= min_acceptable_high_res_scale
&&
1252 tiling
->contents_scale() <= max_acceptable_high_res_scale
)
1255 // Keep low resolution tilings, if the layer should have them.
1256 if (layer_tree_impl()->create_low_res_tiling()) {
1257 if (tiling
->resolution() == LOW_RESOLUTION
||
1258 tiling
->contents_scale() == twin_low_res_scale
)
1262 // Don't remove tilings that are being used (and thus would cause a flash.)
1263 if (std::find(used_tilings
.begin(), used_tilings
.end(), tiling
) !=
1267 to_remove
.push_back(tiling
);
1270 if (to_remove
.empty())
1273 PictureLayerImpl
* recycled_twin
= GetRecycledTwinLayer();
1274 // Remove tilings on this tree and the twin tree.
1275 for (size_t i
= 0; i
< to_remove
.size(); ++i
) {
1276 const PictureLayerTiling
* twin_tiling
= GetTwinTiling(to_remove
[i
]);
1277 // Only remove tilings from the twin layer if they have
1278 // NON_IDEAL_RESOLUTION.
1279 if (twin_tiling
&& twin_tiling
->resolution() == NON_IDEAL_RESOLUTION
)
1280 twin
->RemoveTiling(to_remove
[i
]->contents_scale());
1281 // Remove the tiling from the recycle tree. Note that we ignore resolution,
1282 // since we don't need to maintain high/low res on the recycle tree.
1284 recycled_twin
->RemoveTiling(to_remove
[i
]->contents_scale());
1285 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1286 CHECK_NE(HIGH_RESOLUTION
, to_remove
[i
]->resolution());
1287 tilings_
->Remove(to_remove
[i
]);
1290 DCHECK_GT(tilings_
->num_tilings(), 0u);
1291 SanityCheckTilingState();
1294 float PictureLayerImpl::MinimumContentsScale() const {
1295 float setting_min
= layer_tree_impl()->settings().minimum_contents_scale
;
1297 // If the contents scale is less than 1 / width (also for height),
1298 // then it will end up having less than one pixel of content in that
1299 // dimension. Bump the minimum contents scale up in this case to prevent
1300 // this from happening.
1301 int min_dimension
= std::min(bounds().width(), bounds().height());
1305 return std::max(1.f
/ min_dimension
, setting_min
);
1308 void PictureLayerImpl::ResetRasterScale() {
1309 raster_page_scale_
= 0.f
;
1310 raster_device_scale_
= 0.f
;
1311 raster_source_scale_
= 0.f
;
1312 raster_contents_scale_
= 0.f
;
1313 low_res_raster_contents_scale_
= 0.f
;
1314 raster_source_scale_is_fixed_
= false;
1316 // When raster scales aren't valid, don't update tile priorities until
1317 // this layer has been updated via UpdateDrawProperties.
1318 should_update_tile_priorities_
= false;
1321 bool PictureLayerImpl::CanHaveTilings() const {
1322 if (!DrawsContent())
1324 if (!pile_
->HasRecordings())
1329 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale
) const {
1330 if (!CanHaveTilings())
1332 if (contents_scale
< MinimumContentsScale())
1337 void PictureLayerImpl::SanityCheckTilingState() const {
1339 // Recycle tree doesn't have any restrictions.
1340 if (layer_tree_impl()->IsRecycleTree())
1343 if (!CanHaveTilings()) {
1344 DCHECK_EQ(0u, tilings_
->num_tilings());
1347 if (tilings_
->num_tilings() == 0)
1350 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1351 // tiling to mark its tiles as being required for activation.
1352 DCHECK_EQ(1, tilings_
->NumHighResTilings());
1356 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const {
1357 if (!layer_tree_impl()->use_gpu_rasterization())
1360 // Re-rastering text at different scales using GPU rasterization causes
1361 // texture uploads for glyphs at each scale (see crbug.com/366225). To
1362 // workaround this performance issue, we don't re-rasterize layers with
1363 // text during scale animations.
1364 // TODO(ajuma): Remove this workaround once text can be efficiently
1365 // re-rastered at different scales (e.g. by using distance-field fonts).
1366 if (pile_
->has_text())
1372 float PictureLayerImpl::MaximumTilingContentsScale() const {
1373 float max_contents_scale
= MinimumContentsScale();
1374 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1375 const PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1376 max_contents_scale
= std::max(max_contents_scale
, tiling
->contents_scale());
1378 return max_contents_scale
;
1381 void PictureLayerImpl::UpdateIdealScales() {
1382 DCHECK(CanHaveTilings());
1384 float min_contents_scale
= MinimumContentsScale();
1385 DCHECK_GT(min_contents_scale
, 0.f
);
1386 float min_page_scale
= layer_tree_impl()->min_page_scale_factor();
1387 DCHECK_GT(min_page_scale
, 0.f
);
1388 float min_device_scale
= 1.f
;
1389 float min_source_scale
=
1390 min_contents_scale
/ min_page_scale
/ min_device_scale
;
1392 float ideal_page_scale
= draw_properties().page_scale_factor
;
1393 float ideal_device_scale
= draw_properties().device_scale_factor
;
1394 float ideal_source_scale
= draw_properties().ideal_contents_scale
/
1395 ideal_page_scale
/ ideal_device_scale
;
1396 ideal_contents_scale_
=
1397 std::max(draw_properties().ideal_contents_scale
, min_contents_scale
);
1398 ideal_page_scale_
= draw_properties().page_scale_factor
;
1399 ideal_device_scale_
= draw_properties().device_scale_factor
;
1400 ideal_source_scale_
= std::max(ideal_source_scale
, min_source_scale
);
1403 void PictureLayerImpl::GetDebugBorderProperties(
1405 float* width
) const {
1406 *color
= DebugColors::TiledContentLayerBorderColor();
1407 *width
= DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1410 void PictureLayerImpl::GetAllTilesForTracing(
1411 std::set
<const Tile
*>* tiles
) const {
1415 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
)
1416 tilings_
->tiling_at(i
)->GetAllTilesForTracing(tiles
);
1419 void PictureLayerImpl::AsValueInto(base::debug::TracedValue
* state
) const {
1420 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1421 LayerImpl::AsValueInto(state
);
1422 state
->SetDouble("ideal_contents_scale", ideal_contents_scale_
);
1423 state
->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1424 state
->BeginArray("tilings");
1425 tilings_
->AsValueInto(state
);
1428 state
->BeginArray("pictures");
1429 pile_
->AsValueInto(state
);
1432 state
->BeginArray("invalidation");
1433 invalidation_
.AsValueInto(state
);
1436 state
->BeginArray("coverage_tiles");
1437 for (PictureLayerTilingSet::CoverageIterator
iter(tilings_
.get(),
1439 gfx::Rect(content_bounds()),
1440 ideal_contents_scale_
);
1443 state
->BeginDictionary();
1445 state
->BeginArray("geometry_rect");
1446 MathUtil::AddToTracedValue(iter
.geometry_rect(), state
);
1450 TracedValue::SetIDRef(*iter
, state
, "tile");
1452 state
->EndDictionary();
1457 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1458 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1459 return tilings_
->GPUMemoryUsageInBytes();
1462 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl
* benchmark
) {
1463 benchmark
->RunOnLayer(this);
1466 WhichTree
PictureLayerImpl::GetTree() const {
1467 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
1470 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1471 return !layer_tree_impl()->IsRecycleTree();
1474 bool PictureLayerImpl::HasValidTilePriorities() const {
1475 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1478 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1479 if (!layer_tree_impl()->IsPendingTree())
1482 if (!HasValidTilePriorities())
1488 if (visible_content_rect().IsEmpty())
1491 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1492 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1493 if (tiling
->resolution() != HIGH_RESOLUTION
&&
1494 tiling
->resolution() != LOW_RESOLUTION
)
1497 gfx::Rect
rect(visible_content_rect());
1498 for (PictureLayerTiling::CoverageIterator
iter(
1499 tiling
, contents_scale_x(), rect
);
1502 const Tile
* tile
= *iter
;
1503 // A null tile (i.e. missing recording) can just be skipped.
1507 if (tile
->required_for_activation() && !tile
->IsReadyToDraw())
1515 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1516 : layer_(NULL
), current_stage_(arraysize(stages_
)) {
1519 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1520 PictureLayerImpl
* layer
,
1521 bool prioritize_low_res
)
1522 : layer_(layer
), current_stage_(0) {
1525 // Early out if the layer has no tilings.
1526 if (!layer_
->tilings_
|| !layer_
->tilings_
->num_tilings()) {
1527 current_stage_
= arraysize(stages_
);
1531 // Tiles without valid priority are treated as having lowest priority and
1532 // never considered for raster.
1533 if (!layer_
->HasValidTilePriorities()) {
1534 current_stage_
= arraysize(stages_
);
1538 WhichTree tree
= layer_
->GetTree();
1540 // Find high and low res tilings and initialize the iterators.
1541 for (size_t i
= 0; i
< layer_
->tilings_
->num_tilings(); ++i
) {
1542 PictureLayerTiling
* tiling
= layer_
->tilings_
->tiling_at(i
);
1543 if (tiling
->resolution() == HIGH_RESOLUTION
) {
1544 iterators_
[HIGH_RES
] =
1545 PictureLayerTiling::TilingRasterTileIterator(tiling
, tree
);
1548 if (tiling
->resolution() == LOW_RESOLUTION
) {
1549 iterators_
[LOW_RES
] =
1550 PictureLayerTiling::TilingRasterTileIterator(tiling
, tree
);
1554 if (prioritize_low_res
) {
1555 stages_
[0].iterator_type
= LOW_RES
;
1556 stages_
[0].tile_type
= TilePriority::NOW
;
1558 stages_
[1].iterator_type
= HIGH_RES
;
1559 stages_
[1].tile_type
= TilePriority::NOW
;
1561 stages_
[0].iterator_type
= HIGH_RES
;
1562 stages_
[0].tile_type
= TilePriority::NOW
;
1564 stages_
[1].iterator_type
= LOW_RES
;
1565 stages_
[1].tile_type
= TilePriority::NOW
;
1568 stages_
[2].iterator_type
= HIGH_RES
;
1569 stages_
[2].tile_type
= TilePriority::SOON
;
1571 stages_
[3].iterator_type
= HIGH_RES
;
1572 stages_
[3].tile_type
= TilePriority::EVENTUALLY
;
1574 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1575 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1576 if (!iterators_
[index
] || iterators_
[index
].get_type() != tile_type
)
1580 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1582 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1583 return current_stage_
< arraysize(stages_
);
1586 PictureLayerImpl::LayerRasterTileIterator
&
1587 PictureLayerImpl::LayerRasterTileIterator::
1589 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1590 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1592 // First advance the iterator.
1593 if (iterators_
[index
])
1594 ++iterators_
[index
];
1596 if (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
)
1599 // Next, advance the stage.
1601 while (current_stage_
< arraysize(stages_
)) {
1602 index
= stages_
[current_stage_
].iterator_type
;
1603 tile_type
= stages_
[current_stage_
].tile_type
;
1605 if (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
)
1612 Tile
* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1615 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1616 DCHECK(iterators_
[index
]);
1617 DCHECK(iterators_
[index
].get_type() == stages_
[current_stage_
].tile_type
);
1619 return *iterators_
[index
];
1622 const Tile
* PictureLayerImpl::LayerRasterTileIterator::operator*() const {
1625 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1626 DCHECK(iterators_
[index
]);
1627 DCHECK(iterators_
[index
].get_type() == stages_
[current_stage_
].tile_type
);
1629 return *iterators_
[index
];
1632 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1634 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES
),
1635 current_category_(PictureLayerTiling::EVENTUALLY
),
1636 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
),
1637 current_tiling_(0u) {
1640 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1641 PictureLayerImpl
* layer
,
1642 TreePriority tree_priority
)
1644 tree_priority_(tree_priority
),
1645 current_category_(PictureLayerTiling::EVENTUALLY
),
1646 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
),
1647 current_tiling_(CurrentTilingRange().start
- 1u) {
1648 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1649 // that layers that don't have valid tile priorities have lowest priorities so
1650 // they evict their tiles first (crbug.com/381704)
1651 DCHECK(layer_
->tilings_
);
1653 if (!AdvanceToNextTiling())
1656 current_iterator_
= PictureLayerTiling::TilingEvictionTileIterator(
1657 layer_
->tilings_
->tiling_at(CurrentTilingIndex()),
1660 } while (!current_iterator_
);
1663 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {
1666 Tile
* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1668 return *current_iterator_
;
1671 const Tile
* PictureLayerImpl::LayerEvictionTileIterator::operator*() const {
1673 return *current_iterator_
;
1676 PictureLayerImpl::LayerEvictionTileIterator
&
1677 PictureLayerImpl::LayerEvictionTileIterator::
1680 ++current_iterator_
;
1681 while (!current_iterator_
) {
1682 if (!AdvanceToNextTiling())
1685 current_iterator_
= PictureLayerTiling::TilingEvictionTileIterator(
1686 layer_
->tilings_
->tiling_at(CurrentTilingIndex()),
1693 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1694 return !!current_iterator_
;
1697 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() {
1698 switch (current_category_
) {
1699 case PictureLayerTiling::EVENTUALLY
:
1701 PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION
;
1703 case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION
:
1704 current_category_
= PictureLayerTiling::SOON
;
1706 case PictureLayerTiling::SOON
:
1707 current_category_
= PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION
;
1709 case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION
:
1710 current_category_
= PictureLayerTiling::NOW
;
1712 case PictureLayerTiling::NOW
:
1713 current_category_
= PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION
;
1715 case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION
:
1723 PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() {
1724 switch (current_tiling_range_type_
) {
1725 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
:
1726 current_tiling_range_type_
= PictureLayerTilingSet::LOWER_THAN_LOW_RES
;
1728 case PictureLayerTilingSet::LOWER_THAN_LOW_RES
:
1729 current_tiling_range_type_
=
1730 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
;
1732 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
:
1733 current_tiling_range_type_
= PictureLayerTilingSet::LOW_RES
;
1735 case PictureLayerTilingSet::LOW_RES
:
1736 current_tiling_range_type_
= PictureLayerTilingSet::HIGH_RES
;
1738 case PictureLayerTilingSet::HIGH_RES
:
1739 if (!AdvanceToNextCategory())
1742 current_tiling_range_type_
= PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
;
1749 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() {
1750 DCHECK_NE(current_tiling_
, CurrentTilingRange().end
);
1752 while (current_tiling_
== CurrentTilingRange().end
) {
1753 if (!AdvanceToNextTilingRangeType())
1756 current_tiling_
= CurrentTilingRange().start
;
1761 PictureLayerTilingSet::TilingRange
1762 PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const {
1763 return layer_
->tilings_
->GetTilingRange(current_tiling_range_type_
);
1766 size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const {
1767 DCHECK_NE(current_tiling_
, CurrentTilingRange().end
);
1768 switch (current_tiling_range_type_
) {
1769 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
:
1770 case PictureLayerTilingSet::LOW_RES
:
1771 case PictureLayerTilingSet::HIGH_RES
:
1772 return current_tiling_
;
1773 // Tilings in the following ranges are accessed in reverse order.
1774 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
:
1775 case PictureLayerTilingSet::LOWER_THAN_LOW_RES
: {
1776 PictureLayerTilingSet::TilingRange tiling_range
= CurrentTilingRange();
1777 size_t current_tiling_range_offset
= current_tiling_
- tiling_range
.start
;
1778 return tiling_range
.end
- 1 - current_tiling_range_offset
;