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"
10 #include "base/time/time.h"
11 #include "cc/base/math_util.h"
12 #include "cc/base/util.h"
13 #include "cc/debug/debug_colors.h"
14 #include "cc/debug/micro_benchmark_impl.h"
15 #include "cc/debug/traced_value.h"
16 #include "cc/layers/append_quads_data.h"
17 #include "cc/quads/checkerboard_draw_quad.h"
18 #include "cc/quads/debug_border_draw_quad.h"
19 #include "cc/quads/picture_draw_quad.h"
20 #include "cc/quads/solid_color_draw_quad.h"
21 #include "cc/quads/tile_draw_quad.h"
22 #include "cc/resources/tile_manager.h"
23 #include "cc/trees/layer_tree_impl.h"
24 #include "cc/trees/occlusion_tracker.h"
25 #include "ui/gfx/quad_f.h"
26 #include "ui/gfx/rect_conversions.h"
27 #include "ui/gfx/size_conversions.h"
30 const float kMaxScaleRatioDuringPinch
= 2.0f
;
32 // When creating a new tiling during pinch, snap to an existing
33 // tiling's scale if the desired scale is within this ratio.
34 const float kSnapToExistingTilingRatio
= 1.2f
;
36 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
37 const float kCpuSkewportTargetTimeInFrames
= 60.0f
;
39 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
40 // TileManager::BinFromTilePriority).
41 const float kGpuSkewportTargetTimeInFrames
= 0.0f
;
43 // Minimum width/height of a layer that would require analysis for tiles.
44 const int kMinDimensionsForAnalysis
= 256;
49 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
50 : LayerImpl(tree_impl
, id
),
52 pile_(PicturePileImpl::Create()),
54 ideal_page_scale_(0.f
),
55 ideal_device_scale_(0.f
),
56 ideal_source_scale_(0.f
),
57 ideal_contents_scale_(0.f
),
58 raster_page_scale_(0.f
),
59 raster_device_scale_(0.f
),
60 raster_source_scale_(0.f
),
61 raster_contents_scale_(0.f
),
62 low_res_raster_contents_scale_(0.f
),
63 raster_source_scale_is_fixed_(false),
64 was_screen_space_transform_animating_(false),
65 needs_post_commit_initialization_(true),
66 should_update_tile_priorities_(false) {
67 layer_tree_impl()->RegisterPictureLayerImpl(this);
70 PictureLayerImpl::~PictureLayerImpl() {
71 layer_tree_impl()->UnregisterPictureLayerImpl(this);
74 const char* PictureLayerImpl::LayerTypeAsString() const {
75 return "cc::PictureLayerImpl";
78 scoped_ptr
<LayerImpl
> PictureLayerImpl::CreateLayerImpl(
79 LayerTreeImpl
* tree_impl
) {
80 return PictureLayerImpl::Create(tree_impl
, id()).PassAs
<LayerImpl
>();
83 void PictureLayerImpl::PushPropertiesTo(LayerImpl
* base_layer
) {
84 // It's possible this layer was never drawn or updated (e.g. because it was
85 // a descendant of an opacity 0 layer).
86 DoPostCommitInitializationIfNeeded();
87 PictureLayerImpl
* layer_impl
= static_cast<PictureLayerImpl
*>(base_layer
);
89 // We have already synced the important bits from the the active layer, and
90 // we will soon swap out its tilings and use them for recycling. However,
91 // there are now tiles in this layer's tilings that were unref'd and replaced
92 // with new tiles (due to invalidation). This resets all active priorities on
93 // the to-be-recycled tiling to ensure replaced tiles don't linger and take
94 // memory (due to a stale 'active' priority).
95 if (layer_impl
->tilings_
)
96 layer_impl
->tilings_
->DidBecomeRecycled();
98 LayerImpl::PushPropertiesTo(base_layer
);
100 // When the pending tree pushes to the active tree, the pending twin
102 layer_impl
->twin_layer_
= NULL
;
105 layer_impl
->SetIsMask(is_mask_
);
106 layer_impl
->pile_
= pile_
;
108 // Tilings would be expensive to push, so we swap.
109 layer_impl
->tilings_
.swap(tilings_
);
111 // Ensure that we don't have any tiles that are out of date.
113 tilings_
->RemoveTilesInRegion(invalidation_
);
115 layer_impl
->tilings_
->SetClient(layer_impl
);
117 tilings_
->SetClient(this);
119 layer_impl
->raster_page_scale_
= raster_page_scale_
;
120 layer_impl
->raster_device_scale_
= raster_device_scale_
;
121 layer_impl
->raster_source_scale_
= raster_source_scale_
;
122 layer_impl
->raster_contents_scale_
= raster_contents_scale_
;
123 layer_impl
->low_res_raster_contents_scale_
= low_res_raster_contents_scale_
;
124 layer_impl
->needs_post_commit_initialization_
= false;
126 // The invalidation on this soon-to-be-recycled layer must be cleared to
127 // mirror clearing the invalidation in PictureLayer's version of this function
128 // in case push properties is skipped.
129 layer_impl
->invalidation_
.Swap(&invalidation_
);
130 invalidation_
.Clear();
131 needs_post_commit_initialization_
= true;
133 // We always need to push properties.
134 // See http://crbug.com/303943
135 needs_push_properties_
= true;
138 void PictureLayerImpl::AppendQuads(
139 RenderPass
* render_pass
,
140 const OcclusionTracker
<LayerImpl
>& occlusion_tracker
,
141 AppendQuadsData
* append_quads_data
) {
142 DCHECK(!needs_post_commit_initialization_
);
144 float max_contents_scale
= MaximumTilingContentsScale();
145 gfx::Transform scaled_draw_transform
= draw_transform();
146 scaled_draw_transform
.Scale(SK_MScalar1
/ max_contents_scale
,
147 SK_MScalar1
/ max_contents_scale
);
148 gfx::Size scaled_content_bounds
=
149 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale
));
151 gfx::Rect scaled_visible_content_rect
=
152 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale
);
153 scaled_visible_content_rect
.Intersect(gfx::Rect(scaled_content_bounds
));
155 SharedQuadState
* shared_quad_state
=
156 render_pass
->CreateAndAppendSharedQuadState();
157 PopulateSharedQuadState(shared_quad_state
);
158 shared_quad_state
->SetAll(scaled_draw_transform
,
159 scaled_content_bounds
,
160 scaled_visible_content_rect
,
161 draw_properties().clip_rect
,
162 draw_properties().is_clipped
,
163 draw_properties().opacity
,
165 sorting_context_id_
);
167 gfx::Rect rect
= scaled_visible_content_rect
;
169 if (current_draw_mode_
== DRAW_MODE_RESOURCELESS_SOFTWARE
) {
170 AppendDebugBorderQuad(
172 scaled_content_bounds
,
175 DebugColors::DirectPictureBorderColor(),
176 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
178 gfx::Rect geometry_rect
= rect
;
179 gfx::Rect opaque_rect
= contents_opaque() ? geometry_rect
: gfx::Rect();
180 gfx::Rect visible_geometry_rect
= occlusion_tracker
.UnoccludedContentRect(
181 geometry_rect
, scaled_draw_transform
);
182 if (visible_geometry_rect
.IsEmpty())
185 gfx::Size texture_size
= rect
.size();
186 gfx::RectF texture_rect
= gfx::RectF(texture_size
);
187 gfx::Rect quad_content_rect
= rect
;
189 PictureDrawQuad
* quad
=
190 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
191 quad
->SetNew(shared_quad_state
,
194 visible_geometry_rect
,
201 append_quads_data
->num_missing_tiles
++;
205 AppendDebugBorderQuad(
206 render_pass
, scaled_content_bounds
, shared_quad_state
, append_quads_data
);
208 if (ShowDebugBorders()) {
209 for (PictureLayerTilingSet::CoverageIterator
iter(
210 tilings_
.get(), max_contents_scale
, rect
, ideal_contents_scale_
);
215 if (*iter
&& iter
->IsReadyToDraw()) {
216 ManagedTileState::TileVersion::Mode mode
=
217 iter
->GetTileVersionForDrawing().mode();
218 if (mode
== ManagedTileState::TileVersion::SOLID_COLOR_MODE
) {
219 color
= DebugColors::SolidColorTileBorderColor();
220 width
= DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
221 } else if (mode
== ManagedTileState::TileVersion::PICTURE_PILE_MODE
) {
222 color
= DebugColors::PictureTileBorderColor();
223 width
= DebugColors::PictureTileBorderWidth(layer_tree_impl());
224 } else if (iter
->priority(ACTIVE_TREE
).resolution
== HIGH_RESOLUTION
) {
225 color
= DebugColors::HighResTileBorderColor();
226 width
= DebugColors::HighResTileBorderWidth(layer_tree_impl());
227 } else if (iter
->priority(ACTIVE_TREE
).resolution
== LOW_RESOLUTION
) {
228 color
= DebugColors::LowResTileBorderColor();
229 width
= DebugColors::LowResTileBorderWidth(layer_tree_impl());
230 } else if (iter
->contents_scale() > max_contents_scale
) {
231 color
= DebugColors::ExtraHighResTileBorderColor();
232 width
= DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
234 color
= DebugColors::ExtraLowResTileBorderColor();
235 width
= DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
238 color
= DebugColors::MissingTileBorderColor();
239 width
= DebugColors::MissingTileBorderWidth(layer_tree_impl());
242 DebugBorderDrawQuad
* debug_border_quad
=
243 render_pass
->CreateAndAppendDrawQuad
<DebugBorderDrawQuad
>();
244 gfx::Rect geometry_rect
= iter
.geometry_rect();
245 gfx::Rect visible_geometry_rect
= geometry_rect
;
246 debug_border_quad
->SetNew(shared_quad_state
,
248 visible_geometry_rect
,
254 // Keep track of the tilings that were used so that tilings that are
255 // unused can be considered for removal.
256 std::vector
<PictureLayerTiling
*> seen_tilings
;
258 size_t missing_tile_count
= 0u;
259 size_t on_demand_missing_tile_count
= 0u;
260 for (PictureLayerTilingSet::CoverageIterator
iter(
261 tilings_
.get(), max_contents_scale
, rect
, ideal_contents_scale_
);
264 gfx::Rect geometry_rect
= iter
.geometry_rect();
265 gfx::Rect visible_geometry_rect
= occlusion_tracker
.UnoccludedContentRect(
266 geometry_rect
, scaled_draw_transform
);
267 if (visible_geometry_rect
.IsEmpty())
270 append_quads_data
->visible_content_area
+=
271 visible_geometry_rect
.width() * visible_geometry_rect
.height();
273 if (*iter
&& iter
->IsReadyToDraw()) {
274 const ManagedTileState::TileVersion
& tile_version
=
275 iter
->GetTileVersionForDrawing();
276 switch (tile_version
.mode()) {
277 case ManagedTileState::TileVersion::RESOURCE_MODE
: {
278 gfx::RectF texture_rect
= iter
.texture_rect();
279 gfx::Rect opaque_rect
= iter
->opaque_rect();
280 opaque_rect
.Intersect(geometry_rect
);
282 if (iter
->contents_scale() != ideal_contents_scale_
)
283 append_quads_data
->had_incomplete_tile
= true;
286 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
287 quad
->SetNew(shared_quad_state
,
290 visible_geometry_rect
,
291 tile_version
.get_resource_id(),
294 tile_version
.contents_swizzled());
297 case ManagedTileState::TileVersion::PICTURE_PILE_MODE
: {
298 if (!layer_tree_impl()
299 ->GetRendererCapabilities()
300 .allow_rasterize_on_demand
) {
301 ++on_demand_missing_tile_count
;
305 gfx::RectF texture_rect
= iter
.texture_rect();
306 gfx::Rect opaque_rect
= iter
->opaque_rect();
307 opaque_rect
.Intersect(geometry_rect
);
309 ResourceProvider
* resource_provider
=
310 layer_tree_impl()->resource_provider();
311 ResourceFormat format
=
312 resource_provider
->memory_efficient_texture_format();
313 PictureDrawQuad
* quad
=
314 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
315 quad
->SetNew(shared_quad_state
,
318 visible_geometry_rect
,
322 iter
->content_rect(),
323 iter
->contents_scale(),
327 case ManagedTileState::TileVersion::SOLID_COLOR_MODE
: {
328 SolidColorDrawQuad
* quad
=
329 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
330 quad
->SetNew(shared_quad_state
,
332 visible_geometry_rect
,
333 tile_version
.get_solid_color(),
339 if (draw_checkerboard_for_missing_tiles()) {
340 CheckerboardDrawQuad
* quad
=
341 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
342 SkColor color
= DebugColors::DefaultCheckerboardColor();
344 shared_quad_state
, geometry_rect
, visible_geometry_rect
, color
);
346 SkColor color
= SafeOpaqueBackgroundColor();
347 SolidColorDrawQuad
* quad
=
348 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
349 quad
->SetNew(shared_quad_state
,
351 visible_geometry_rect
,
356 append_quads_data
->num_missing_tiles
++;
357 append_quads_data
->had_incomplete_tile
= true;
358 append_quads_data
->approximated_visible_content_area
+=
359 visible_geometry_rect
.width() * visible_geometry_rect
.height();
360 ++missing_tile_count
;
364 if (iter
->priority(ACTIVE_TREE
).resolution
!= HIGH_RESOLUTION
) {
365 append_quads_data
->approximated_visible_content_area
+=
366 visible_geometry_rect
.width() * visible_geometry_rect
.height();
369 if (seen_tilings
.empty() || seen_tilings
.back() != iter
.CurrentTiling())
370 seen_tilings
.push_back(iter
.CurrentTiling());
373 if (missing_tile_count
) {
374 TRACE_EVENT_INSTANT2("cc",
375 "PictureLayerImpl::AppendQuads checkerboard",
376 TRACE_EVENT_SCOPE_THREAD
,
377 "missing_tile_count",
379 "on_demand_missing_tile_count",
380 on_demand_missing_tile_count
);
383 // Aggressively remove any tilings that are not seen to save memory. Note
384 // that this is at the expense of doing cause more frequent re-painting. A
385 // better scheme would be to maintain a tighter visible_content_rect for the
387 CleanUpTilingsOnActiveLayer(seen_tilings
);
390 void PictureLayerImpl::UpdateTiles(
391 const OcclusionTracker
<LayerImpl
>* occlusion_tracker
) {
392 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
394 DoPostCommitInitializationIfNeeded();
396 // TODO(danakj): We should always get an occlusion tracker when we are using
397 // occlusion, so update this check when we don't use a pending tree in the
398 // browser compositor.
399 DCHECK(!occlusion_tracker
||
400 layer_tree_impl()->settings().use_occlusion_for_tile_prioritization
);
402 if (layer_tree_impl()->device_viewport_valid_for_tile_management()) {
403 visible_rect_for_tile_priority_
= visible_content_rect();
404 viewport_size_for_tile_priority_
= layer_tree_impl()->DrawViewportSize();
405 screen_space_transform_for_tile_priority_
= screen_space_transform();
408 if (!CanHaveTilings()) {
409 ideal_page_scale_
= 0.f
;
410 ideal_device_scale_
= 0.f
;
411 ideal_contents_scale_
= 0.f
;
412 ideal_source_scale_
= 0.f
;
413 SanityCheckTilingState();
419 DCHECK(tilings_
->num_tilings() > 0 || raster_contents_scale_
== 0.f
)
420 << "A layer with no tilings shouldn't have valid raster scales";
421 if (!raster_contents_scale_
|| ShouldAdjustRasterScale()) {
422 RecalculateRasterScales();
423 AddTilingsForRasterScale();
426 DCHECK(raster_page_scale_
);
427 DCHECK(raster_device_scale_
);
428 DCHECK(raster_source_scale_
);
429 DCHECK(raster_contents_scale_
);
430 DCHECK(low_res_raster_contents_scale_
);
432 was_screen_space_transform_animating_
=
433 draw_properties().screen_space_transform_is_animating
;
435 should_update_tile_priorities_
= true;
437 UpdateTilePriorities(occlusion_tracker
);
439 if (layer_tree_impl()->IsPendingTree())
440 MarkVisibleResourcesAsRequired();
443 void PictureLayerImpl::UpdateTilePriorities(
444 const OcclusionTracker
<LayerImpl
>* occlusion_tracker
) {
445 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
447 double current_frame_time_in_seconds
=
448 (layer_tree_impl()->CurrentFrameTimeTicks() -
449 base::TimeTicks()).InSecondsF();
451 bool tiling_needs_update
= false;
452 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
453 if (tilings_
->tiling_at(i
)->NeedsUpdateForFrameAtTime(
454 current_frame_time_in_seconds
)) {
455 tiling_needs_update
= true;
459 if (!tiling_needs_update
)
462 // Use visible_content_rect, unless it's empty. If it's empty, then
463 // try to inverse project the viewport into layer space and use that.
464 gfx::Rect visible_rect_in_content_space
= visible_rect_for_tile_priority_
;
465 if (visible_rect_in_content_space
.IsEmpty()) {
466 gfx::Transform
screen_to_layer(gfx::Transform::kSkipInitialization
);
467 if (screen_space_transform_for_tile_priority_
.GetInverse(
469 visible_rect_in_content_space
=
470 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
471 screen_to_layer
, gfx::Rect(viewport_size_for_tile_priority_
)));
472 visible_rect_in_content_space
.Intersect(gfx::Rect(content_bounds()));
476 gfx::Rect visible_layer_rect
= gfx::ScaleToEnclosingRect(
477 visible_rect_in_content_space
, 1.f
/ contents_scale_x());
479 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
480 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
481 tilings_
->tiling_at(i
)->UpdateTilePriorities(tree
,
483 ideal_contents_scale_
,
484 current_frame_time_in_seconds
,
490 // Tile priorities were modified.
491 layer_tree_impl()->DidModifyTilePriorities();
494 void PictureLayerImpl::NotifyTileStateChanged(const Tile
* tile
) {
495 if (layer_tree_impl()->IsActiveTree()) {
496 gfx::RectF layer_damage_rect
=
497 gfx::ScaleRect(tile
->content_rect(), 1.f
/ tile
->contents_scale());
498 AddDamageRect(layer_damage_rect
);
502 void PictureLayerImpl::DidBecomeActive() {
503 LayerImpl::DidBecomeActive();
504 tilings_
->DidBecomeActive();
505 layer_tree_impl()->DidModifyTilePriorities();
508 void PictureLayerImpl::DidBeginTracing() {
509 pile_
->DidBeginTracing();
512 void PictureLayerImpl::ReleaseResources() {
518 // To avoid an edge case after lost context where the tree is up to date but
519 // the tilings have not been managed, request an update draw properties
520 // to force tilings to get managed.
521 layer_tree_impl()->set_needs_update_draw_properties();
524 skia::RefPtr
<SkPicture
> PictureLayerImpl::GetPicture() {
525 return pile_
->GetFlattenedPicture();
528 scoped_refptr
<Tile
> PictureLayerImpl::CreateTile(PictureLayerTiling
* tiling
,
529 const gfx::Rect
& content_rect
) {
530 if (!pile_
->CanRaster(tiling
->contents_scale(), content_rect
))
531 return scoped_refptr
<Tile
>();
534 // We analyze picture before rasterization to detect solid-color tiles.
535 // If the tile is detected as such there is no need to raster or upload.
536 // It is drawn directly as a solid-color quad saving memory, raster and upload
537 // cost. The analysis step is however expensive and may not be justified when
538 // doing gpu rasterization which runs on the compositor thread and where there
540 // TODO(alokp): Revisit the decision to avoid analysis for gpu rasterization
541 // becuase it too can potentially benefit from memory savings.
542 if (!layer_tree_impl()->use_gpu_rasterization()) {
543 // Additionally, we do not want to do the analysis if the layer is too
544 // narrow, since more likely than not the tile would not be solid. Note that
545 // this last optimization is a heuristic that ensures that we don't spend
546 // too much time analyzing tiles on a multitude of small layers, as it is
547 // likely that these layers have some non-solid content.
548 int min_dimension
= std::min(bounds().width(), bounds().height());
549 if (min_dimension
>= kMinDimensionsForAnalysis
)
550 flags
|= Tile::USE_PICTURE_ANALYSIS
;
553 return layer_tree_impl()->tile_manager()->CreateTile(
557 contents_opaque() ? content_rect
: gfx::Rect(),
558 tiling
->contents_scale(),
560 layer_tree_impl()->source_frame_number(),
564 PicturePileImpl
* PictureLayerImpl::GetPile() {
568 const Region
* PictureLayerImpl::GetInvalidation() {
569 return &invalidation_
;
572 const PictureLayerTiling
* PictureLayerImpl::GetTwinTiling(
573 const PictureLayerTiling
* tiling
) const {
576 for (size_t i
= 0; i
< twin_layer_
->tilings_
->num_tilings(); ++i
)
577 if (twin_layer_
->tilings_
->tiling_at(i
)->contents_scale() ==
578 tiling
->contents_scale())
579 return twin_layer_
->tilings_
->tiling_at(i
);
583 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
584 return layer_tree_impl()->settings().max_tiles_for_interest_area
;
587 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
588 float skewport_target_time_in_frames
=
589 layer_tree_impl()->use_gpu_rasterization()
590 ? kGpuSkewportTargetTimeInFrames
591 : kCpuSkewportTargetTimeInFrames
;
592 return skewport_target_time_in_frames
*
593 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
594 layer_tree_impl()->settings().skewport_target_time_multiplier
;
597 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
598 return layer_tree_impl()
600 .skewport_extrapolation_limit_in_content_pixels
;
603 gfx::Size
PictureLayerImpl::CalculateTileSize(
604 const gfx::Size
& content_bounds
) const {
606 int max_size
= layer_tree_impl()->MaxTextureSize();
608 std::min(max_size
, content_bounds
.width()),
609 std::min(max_size
, content_bounds
.height()));
612 int max_texture_size
=
613 layer_tree_impl()->resource_provider()->max_texture_size();
615 gfx::Size default_tile_size
= layer_tree_impl()->settings().default_tile_size
;
616 if (layer_tree_impl()->use_gpu_rasterization()) {
617 // TODO(ernstm) crbug.com/365877: We need a unified way to override the
618 // default-tile-size.
620 gfx::Size(layer_tree_impl()->device_viewport_size().width(),
621 layer_tree_impl()->device_viewport_size().height() / 4);
623 default_tile_size
.SetToMin(gfx::Size(max_texture_size
, max_texture_size
));
625 gfx::Size max_untiled_content_size
=
626 layer_tree_impl()->settings().max_untiled_layer_size
;
627 max_untiled_content_size
.SetToMin(
628 gfx::Size(max_texture_size
, max_texture_size
));
630 bool any_dimension_too_large
=
631 content_bounds
.width() > max_untiled_content_size
.width() ||
632 content_bounds
.height() > max_untiled_content_size
.height();
634 bool any_dimension_one_tile
=
635 content_bounds
.width() <= default_tile_size
.width() ||
636 content_bounds
.height() <= default_tile_size
.height();
638 // If long and skinny, tile at the max untiled content size, and clamp
639 // the smaller dimension to the content size, e.g. 1000x12 layer with
640 // 500x500 max untiled size would get 500x12 tiles. Also do this
641 // if the layer is small.
642 if (any_dimension_one_tile
|| !any_dimension_too_large
) {
643 int width
= std::min(
644 std::max(max_untiled_content_size
.width(), default_tile_size
.width()),
645 content_bounds
.width());
646 int height
= std::min(
647 std::max(max_untiled_content_size
.height(), default_tile_size
.height()),
648 content_bounds
.height());
649 // Round up to the closest multiple of 64. This improves recycling and
650 // avoids odd texture sizes.
651 width
= RoundUp(width
, 64);
652 height
= RoundUp(height
, 64);
653 return gfx::Size(width
, height
);
656 return default_tile_size
;
659 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl
* other
) {
660 TRACE_EVENT0("cc", "SyncFromActiveLayer");
661 DCHECK(!other
->needs_post_commit_initialization_
);
662 DCHECK(other
->tilings_
);
664 if (!DrawsContent()) {
669 raster_page_scale_
= other
->raster_page_scale_
;
670 raster_device_scale_
= other
->raster_device_scale_
;
671 raster_source_scale_
= other
->raster_source_scale_
;
672 raster_contents_scale_
= other
->raster_contents_scale_
;
673 low_res_raster_contents_scale_
= other
->low_res_raster_contents_scale_
;
675 // Union in the other newly exposed regions as invalid.
676 Region difference_region
= Region(gfx::Rect(bounds()));
677 difference_region
.Subtract(gfx::Rect(other
->bounds()));
678 invalidation_
.Union(difference_region
);
680 bool synced_high_res_tiling
= false;
681 if (CanHaveTilings()) {
682 synced_high_res_tiling
= tilings_
->SyncTilings(
683 *other
->tilings_
, bounds(), invalidation_
, MinimumContentsScale());
688 // If our MinimumContentsScale has changed to prevent the twin's high res
689 // tiling from being synced, we should reset the raster scale and let it be
690 // recalculated (1) again. This can happen if our bounds shrink to the point
691 // where min contents scale grows.
692 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
693 // should refactor this code a little bit and actually recalculate this.
694 // However, this is a larger undertaking, so this will work for now.
695 if (!synced_high_res_tiling
)
698 SanityCheckTilingState();
701 void PictureLayerImpl::SyncTiling(
702 const PictureLayerTiling
* tiling
) {
703 if (!CanHaveTilingWithScale(tiling
->contents_scale()))
705 tilings_
->AddTiling(tiling
->contents_scale());
707 // If this tree needs update draw properties, then the tiling will
708 // get updated prior to drawing or activation. If this tree does not
709 // need update draw properties, then its transforms are up to date and
710 // we can create tiles for this tiling immediately.
711 if (!layer_tree_impl()->needs_update_draw_properties() &&
712 should_update_tile_priorities_
) {
713 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
714 // when we stop using the pending tree in the browser compositor. If we want
715 // to support occlusion tracking here, we need to dirty the draw properties
716 // or save occlusion as a draw property.
717 UpdateTilePriorities(NULL
);
721 void PictureLayerImpl::SetIsMask(bool is_mask
) {
722 if (is_mask_
== is_mask
)
726 tilings_
->RemoveAllTiles();
729 ResourceProvider::ResourceId
PictureLayerImpl::ContentsResourceId() const {
730 gfx::Rect
content_rect(content_bounds());
731 float scale
= MaximumTilingContentsScale();
732 PictureLayerTilingSet::CoverageIterator
iter(
733 tilings_
.get(), scale
, content_rect
, ideal_contents_scale_
);
735 // Mask resource not ready yet.
739 // Masks only supported if they fit on exactly one tile.
740 if (iter
.geometry_rect() != content_rect
)
743 const ManagedTileState::TileVersion
& tile_version
=
744 iter
->GetTileVersionForDrawing();
745 if (!tile_version
.IsReadyToDraw() ||
746 tile_version
.mode() != ManagedTileState::TileVersion::RESOURCE_MODE
)
749 return tile_version
.get_resource_id();
752 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
753 DCHECK(layer_tree_impl()->IsPendingTree());
754 DCHECK(ideal_contents_scale_
);
755 DCHECK_GT(tilings_
->num_tilings(), 0u);
757 // The goal of this function is to find the minimum set of tiles that need to
758 // be ready to draw in order to activate without flashing content from a
759 // higher res on the active tree to a lower res on the pending tree.
761 // First, early out for layers with no visible content.
762 if (visible_content_rect().IsEmpty())
765 gfx::Rect
rect(visible_content_rect());
767 float min_acceptable_scale
=
768 std::min(raster_contents_scale_
, ideal_contents_scale_
);
770 if (PictureLayerImpl
* twin
= twin_layer_
) {
771 float twin_min_acceptable_scale
=
772 std::min(twin
->ideal_contents_scale_
, twin
->raster_contents_scale_
);
773 // Ignore 0 scale in case CalculateContentsScale() has never been
774 // called for active twin.
775 if (twin_min_acceptable_scale
!= 0.0f
) {
776 min_acceptable_scale
=
777 std::min(min_acceptable_scale
, twin_min_acceptable_scale
);
781 PictureLayerTiling
* high_res
= NULL
;
782 PictureLayerTiling
* low_res
= NULL
;
784 // First pass: ready to draw tiles in acceptable but non-ideal tilings are
785 // marked as required for activation so that their textures are not thrown
786 // away; any non-ready tiles are not marked as required.
787 Region missing_region
= rect
;
788 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
789 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
790 DCHECK(tiling
->has_ever_been_updated());
792 if (tiling
->resolution() == LOW_RESOLUTION
) {
793 DCHECK(!low_res
) << "There can only be one low res tiling";
796 if (tiling
->contents_scale() < min_acceptable_scale
)
798 if (tiling
->resolution() == HIGH_RESOLUTION
) {
799 DCHECK(!high_res
) << "There can only be one high res tiling";
803 for (PictureLayerTiling::CoverageIterator
iter(tiling
,
808 if (!*iter
|| !iter
->IsReadyToDraw())
811 missing_region
.Subtract(iter
.geometry_rect());
812 iter
->MarkRequiredForActivation();
815 DCHECK(high_res
) << "There must be one high res tiling";
817 // If these pointers are null (because no twin, no matching tiling, or the
818 // simpification just below), then high res tiles will be required to fill any
819 // holes left by the first pass above. If the pointers are valid, then this
820 // layer is allowed to skip any tiles that are not ready on its twin.
821 const PictureLayerTiling
* twin_high_res
= NULL
;
822 const PictureLayerTiling
* twin_low_res
= NULL
;
825 // As a simplification, only allow activating to skip twin tiles that the
826 // active layer is also missing when both this layer and its twin have
827 // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
828 // res tiling. This avoids having to iterate/track coverage of non-ideal
829 // tilings during the last draw call on the active layer.
830 if (tilings_
->num_tilings() <= 2 &&
831 twin_layer_
->tilings_
->num_tilings() <= tilings_
->num_tilings()) {
832 twin_low_res
= low_res
? GetTwinTiling(low_res
) : NULL
;
833 twin_high_res
= high_res
? GetTwinTiling(high_res
) : NULL
;
836 // If this layer and its twin have different transforms, then don't compare
837 // them and only allow activating to high res tiles, since tiles on each
838 // layer will be in different places on screen.
839 if (twin_layer_
->layer_tree_impl()->RequiresHighResToDraw() ||
840 bounds() != twin_layer_
->bounds() ||
841 draw_properties().screen_space_transform
!=
842 twin_layer_
->draw_properties().screen_space_transform
) {
843 twin_high_res
= NULL
;
848 // As a second pass, mark as required any visible high res tiles not filled in
849 // by acceptable non-ideal tiles from the first pass.
850 if (MarkVisibleTilesAsRequired(
851 high_res
, twin_high_res
, contents_scale_x(), rect
, missing_region
)) {
852 // As an optional third pass, if a high res tile was skipped because its
853 // twin was also missing, then fall back to mark low res tiles as required
854 // in case the active twin is substituting those for missing high res
855 // content. Only suitable, when low res is enabled.
857 MarkVisibleTilesAsRequired(
858 low_res
, twin_low_res
, contents_scale_x(), rect
, missing_region
);
863 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
864 PictureLayerTiling
* tiling
,
865 const PictureLayerTiling
* optional_twin_tiling
,
866 float contents_scale
,
867 const gfx::Rect
& rect
,
868 const Region
& missing_region
) const {
869 bool twin_had_missing_tile
= false;
870 for (PictureLayerTiling::CoverageIterator
iter(tiling
,
876 // A null tile (i.e. missing recording) can just be skipped.
880 // If the tile is occluded, don't mark it as required for activation.
881 if (tile
->is_occluded(PENDING_TREE
))
884 // If the missing region doesn't cover it, this tile is fully
885 // covered by acceptable tiles at other scales.
886 if (!missing_region
.Intersects(iter
.geometry_rect()))
889 // If the twin tile doesn't exist (i.e. missing recording or so far away
890 // that it is outside the visible tile rect) or this tile is shared between
891 // with the twin, then this tile isn't required to prevent flashing.
892 if (optional_twin_tiling
) {
893 Tile
* twin_tile
= optional_twin_tiling
->TileAt(iter
.i(), iter
.j());
894 if (!twin_tile
|| twin_tile
== tile
) {
895 twin_had_missing_tile
= true;
900 tile
->MarkRequiredForActivation();
902 return twin_had_missing_tile
;
905 void PictureLayerImpl::DoPostCommitInitialization() {
906 DCHECK(needs_post_commit_initialization_
);
907 DCHECK(layer_tree_impl()->IsPendingTree());
910 tilings_
.reset(new PictureLayerTilingSet(this, bounds()));
912 DCHECK(!twin_layer_
);
913 twin_layer_
= static_cast<PictureLayerImpl
*>(
914 layer_tree_impl()->FindActiveTreeLayerById(id()));
916 DCHECK(!twin_layer_
->twin_layer_
);
917 twin_layer_
->twin_layer_
= this;
918 // If the twin has never been pushed to, do not sync from it.
919 // This can happen if this function is called during activation.
920 if (!twin_layer_
->needs_post_commit_initialization_
)
921 SyncFromActiveLayer(twin_layer_
);
924 needs_post_commit_initialization_
= false;
927 PictureLayerTiling
* PictureLayerImpl::AddTiling(float contents_scale
) {
928 DCHECK(CanHaveTilingWithScale(contents_scale
)) <<
929 "contents_scale: " << contents_scale
;
931 PictureLayerTiling
* tiling
= tilings_
->AddTiling(contents_scale
);
933 DCHECK(pile_
->HasRecordings());
936 twin_layer_
->SyncTiling(tiling
);
941 void PictureLayerImpl::RemoveTiling(float contents_scale
) {
942 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
943 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
944 if (tiling
->contents_scale() == contents_scale
) {
945 tilings_
->Remove(tiling
);
949 if (tilings_
->num_tilings() == 0)
951 SanityCheckTilingState();
954 void PictureLayerImpl::RemoveAllTilings() {
956 tilings_
->RemoveAllTilings();
957 // If there are no tilings, then raster scales are no longer meaningful.
963 inline float PositiveRatio(float float1
, float float2
) {
964 DCHECK_GT(float1
, 0);
965 DCHECK_GT(float2
, 0);
966 return float1
> float2
? float1
/ float2
: float2
/ float1
;
971 void PictureLayerImpl::AddTilingsForRasterScale() {
972 PictureLayerTiling
* high_res
= NULL
;
973 PictureLayerTiling
* low_res
= NULL
;
975 PictureLayerTiling
* previous_low_res
= NULL
;
976 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
977 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
978 if (tiling
->contents_scale() == raster_contents_scale_
)
980 if (tiling
->contents_scale() == low_res_raster_contents_scale_
)
982 if (tiling
->resolution() == LOW_RESOLUTION
)
983 previous_low_res
= tiling
;
985 // Reset all tilings to non-ideal until the end of this function.
986 tiling
->set_resolution(NON_IDEAL_RESOLUTION
);
990 high_res
= AddTiling(raster_contents_scale_
);
991 if (raster_contents_scale_
== low_res_raster_contents_scale_
)
995 // Only create new low res tilings when the transform is static. This
996 // prevents wastefully creating a paired low res tiling for every new high res
997 // tiling during a pinch or a CSS animation.
998 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
999 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching
&&
1000 !draw_properties().screen_space_transform_is_animating
&& !low_res
&&
1001 low_res
!= high_res
)
1002 low_res
= AddTiling(low_res_raster_contents_scale_
);
1004 // Set low-res if we have one.
1006 low_res
= previous_low_res
;
1007 if (low_res
&& low_res
!= high_res
)
1008 low_res
->set_resolution(LOW_RESOLUTION
);
1010 // Make sure we always have one high-res (even if high == low).
1011 high_res
->set_resolution(HIGH_RESOLUTION
);
1013 SanityCheckTilingState();
1016 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1017 if (was_screen_space_transform_animating_
!=
1018 draw_properties().screen_space_transform_is_animating
)
1021 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1022 if (is_pinching
&& raster_page_scale_
) {
1023 // We change our raster scale when it is:
1024 // - Higher than ideal (need a lower-res tiling available)
1025 // - Too far from ideal (need a higher-res tiling available)
1026 float ratio
= ideal_page_scale_
/ raster_page_scale_
;
1027 if (raster_page_scale_
> ideal_page_scale_
||
1028 ratio
> kMaxScaleRatioDuringPinch
)
1033 // When not pinching, match the ideal page scale factor.
1034 if (raster_page_scale_
!= ideal_page_scale_
)
1038 // Always match the ideal device scale factor.
1039 if (raster_device_scale_
!= ideal_device_scale_
)
1042 // When the source scale changes we want to match it, but not when animating
1043 // or when we've fixed the scale in place.
1044 if (!draw_properties().screen_space_transform_is_animating
&&
1045 !raster_source_scale_is_fixed_
&&
1046 raster_source_scale_
!= ideal_source_scale_
)
1052 float PictureLayerImpl::SnappedContentsScale(float scale
) {
1053 // If a tiling exists within the max snapping ratio, snap to its scale.
1054 float snapped_contents_scale
= scale
;
1055 float snapped_ratio
= kSnapToExistingTilingRatio
;
1056 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1057 float tiling_contents_scale
= tilings_
->tiling_at(i
)->contents_scale();
1058 float ratio
= PositiveRatio(tiling_contents_scale
, scale
);
1059 if (ratio
< snapped_ratio
) {
1060 snapped_contents_scale
= tiling_contents_scale
;
1061 snapped_ratio
= ratio
;
1064 return snapped_contents_scale
;
1067 void PictureLayerImpl::RecalculateRasterScales() {
1068 float old_raster_contents_scale
= raster_contents_scale_
;
1069 float old_raster_page_scale
= raster_page_scale_
;
1070 float old_raster_source_scale
= raster_source_scale_
;
1072 raster_device_scale_
= ideal_device_scale_
;
1073 raster_page_scale_
= ideal_page_scale_
;
1074 raster_source_scale_
= ideal_source_scale_
;
1075 raster_contents_scale_
= ideal_contents_scale_
;
1077 // If we're not animating, or leaving an animation, and the
1078 // ideal_source_scale_ changes, then things are unpredictable, and we fix
1079 // the raster_source_scale_ in place.
1080 if (old_raster_source_scale
&&
1081 !draw_properties().screen_space_transform_is_animating
&&
1082 !was_screen_space_transform_animating_
&&
1083 old_raster_source_scale
!= ideal_source_scale_
)
1084 raster_source_scale_is_fixed_
= true;
1086 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1087 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1088 // tree. This will allow CSS scale changes to get re-rastered at an
1089 // appropriate rate.
1090 if (raster_source_scale_is_fixed_
) {
1091 raster_contents_scale_
/= raster_source_scale_
;
1092 raster_source_scale_
= 1.f
;
1095 // During pinch we completely ignore the current ideal scale, and just use
1096 // a multiple of the previous scale.
1097 // TODO(danakj): This seems crazy, we should use the current ideal, no?
1098 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1099 if (is_pinching
&& old_raster_contents_scale
) {
1100 // See ShouldAdjustRasterScale:
1101 // - When zooming out, preemptively create new tiling at lower resolution.
1102 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1103 bool zooming_out
= old_raster_page_scale
> ideal_page_scale_
;
1104 float desired_contents_scale
=
1105 zooming_out
? old_raster_contents_scale
/ kMaxScaleRatioDuringPinch
1106 : old_raster_contents_scale
* kMaxScaleRatioDuringPinch
;
1107 raster_contents_scale_
= SnappedContentsScale(desired_contents_scale
);
1108 raster_page_scale_
=
1109 raster_contents_scale_
/ raster_device_scale_
/ raster_source_scale_
;
1112 raster_contents_scale_
=
1113 std::max(raster_contents_scale_
, MinimumContentsScale());
1115 // Since we're not re-rasterizing during animation, rasterize at the maximum
1116 // scale that will occur during the animation, if the maximum scale is
1118 if (draw_properties().screen_space_transform_is_animating
) {
1119 if (draw_properties().maximum_animation_contents_scale
> 0.f
) {
1120 raster_contents_scale_
=
1121 std::max(raster_contents_scale_
,
1122 draw_properties().maximum_animation_contents_scale
);
1124 raster_contents_scale_
=
1125 std::max(raster_contents_scale_
,
1126 1.f
* ideal_page_scale_
* ideal_device_scale_
);
1130 // If this layer would only create one tile at this content scale,
1131 // don't create a low res tiling.
1132 gfx::Size content_bounds
=
1133 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_
));
1134 gfx::Size tile_size
= CalculateTileSize(content_bounds
);
1135 if (tile_size
.width() >= content_bounds
.width() &&
1136 tile_size
.height() >= content_bounds
.height()) {
1137 low_res_raster_contents_scale_
= raster_contents_scale_
;
1141 float low_res_factor
=
1142 layer_tree_impl()->settings().low_res_contents_scale_factor
;
1143 low_res_raster_contents_scale_
= std::max(
1144 raster_contents_scale_
* low_res_factor
,
1145 MinimumContentsScale());
1148 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1149 std::vector
<PictureLayerTiling
*> used_tilings
) {
1150 DCHECK(layer_tree_impl()->IsActiveTree());
1151 if (tilings_
->num_tilings() == 0)
1154 float min_acceptable_high_res_scale
= std::min(
1155 raster_contents_scale_
, ideal_contents_scale_
);
1156 float max_acceptable_high_res_scale
= std::max(
1157 raster_contents_scale_
, ideal_contents_scale_
);
1158 float twin_low_res_scale
= 0.f
;
1160 PictureLayerImpl
* twin
= twin_layer_
;
1161 if (twin
&& twin
->CanHaveTilings()) {
1162 min_acceptable_high_res_scale
= std::min(
1163 min_acceptable_high_res_scale
,
1164 std::min(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1165 max_acceptable_high_res_scale
= std::max(
1166 max_acceptable_high_res_scale
,
1167 std::max(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1169 for (size_t i
= 0; i
< twin
->tilings_
->num_tilings(); ++i
) {
1170 PictureLayerTiling
* tiling
= twin
->tilings_
->tiling_at(i
);
1171 if (tiling
->resolution() == LOW_RESOLUTION
)
1172 twin_low_res_scale
= tiling
->contents_scale();
1176 std::vector
<PictureLayerTiling
*> to_remove
;
1177 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1178 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1180 // Keep multiple high resolution tilings even if not used to help
1181 // activate earlier at non-ideal resolutions.
1182 if (tiling
->contents_scale() >= min_acceptable_high_res_scale
&&
1183 tiling
->contents_scale() <= max_acceptable_high_res_scale
)
1186 // Keep low resolution tilings, if the layer should have them.
1187 if (layer_tree_impl()->create_low_res_tiling()) {
1188 if (tiling
->resolution() == LOW_RESOLUTION
||
1189 tiling
->contents_scale() == twin_low_res_scale
)
1193 // Don't remove tilings that are being used (and thus would cause a flash.)
1194 if (std::find(used_tilings
.begin(), used_tilings
.end(), tiling
) !=
1198 to_remove
.push_back(tiling
);
1201 for (size_t i
= 0; i
< to_remove
.size(); ++i
) {
1202 const PictureLayerTiling
* twin_tiling
= GetTwinTiling(to_remove
[i
]);
1203 // Only remove tilings from the twin layer if they have
1204 // NON_IDEAL_RESOLUTION.
1205 if (twin_tiling
&& twin_tiling
->resolution() == NON_IDEAL_RESOLUTION
)
1206 twin
->RemoveTiling(to_remove
[i
]->contents_scale());
1207 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1208 CHECK_NE(HIGH_RESOLUTION
, to_remove
[i
]->resolution());
1209 tilings_
->Remove(to_remove
[i
]);
1211 DCHECK_GT(tilings_
->num_tilings(), 0u);
1213 SanityCheckTilingState();
1216 float PictureLayerImpl::MinimumContentsScale() const {
1217 float setting_min
= layer_tree_impl()->settings().minimum_contents_scale
;
1219 // If the contents scale is less than 1 / width (also for height),
1220 // then it will end up having less than one pixel of content in that
1221 // dimension. Bump the minimum contents scale up in this case to prevent
1222 // this from happening.
1223 int min_dimension
= std::min(bounds().width(), bounds().height());
1227 return std::max(1.f
/ min_dimension
, setting_min
);
1230 void PictureLayerImpl::ResetRasterScale() {
1231 raster_page_scale_
= 0.f
;
1232 raster_device_scale_
= 0.f
;
1233 raster_source_scale_
= 0.f
;
1234 raster_contents_scale_
= 0.f
;
1235 low_res_raster_contents_scale_
= 0.f
;
1236 raster_source_scale_is_fixed_
= false;
1238 // When raster scales aren't valid, don't update tile priorities until
1239 // this layer has been updated via UpdateDrawProperties.
1240 should_update_tile_priorities_
= false;
1243 bool PictureLayerImpl::CanHaveTilings() const {
1244 if (!DrawsContent())
1246 if (!pile_
->HasRecordings())
1251 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale
) const {
1252 if (!CanHaveTilings())
1254 if (contents_scale
< MinimumContentsScale())
1259 void PictureLayerImpl::SanityCheckTilingState() const {
1261 if (!CanHaveTilings()) {
1262 DCHECK_EQ(0u, tilings_
->num_tilings());
1265 if (tilings_
->num_tilings() == 0)
1268 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1269 // tiling to mark its tiles as being required for activation.
1270 DCHECK_EQ(1, tilings_
->NumHighResTilings());
1274 float PictureLayerImpl::MaximumTilingContentsScale() const {
1275 float max_contents_scale
= MinimumContentsScale();
1276 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1277 const PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1278 max_contents_scale
= std::max(max_contents_scale
, tiling
->contents_scale());
1280 return max_contents_scale
;
1283 void PictureLayerImpl::UpdateIdealScales() {
1284 DCHECK(CanHaveTilings());
1286 float min_contents_scale
= MinimumContentsScale();
1287 DCHECK_GT(min_contents_scale
, 0.f
);
1288 float min_page_scale
= layer_tree_impl()->min_page_scale_factor();
1289 DCHECK_GT(min_page_scale
, 0.f
);
1290 float min_device_scale
= 1.f
;
1291 float min_source_scale
=
1292 min_contents_scale
/ min_page_scale
/ min_device_scale
;
1294 float ideal_page_scale
= draw_properties().page_scale_factor
;
1295 float ideal_device_scale
= draw_properties().device_scale_factor
;
1296 float ideal_source_scale
= draw_properties().ideal_contents_scale
/
1297 ideal_page_scale
/ ideal_device_scale
;
1298 ideal_contents_scale_
=
1299 std::max(draw_properties().ideal_contents_scale
, min_contents_scale
);
1300 ideal_page_scale_
= draw_properties().page_scale_factor
;
1301 ideal_device_scale_
= draw_properties().device_scale_factor
;
1302 ideal_source_scale_
= std::max(ideal_source_scale
, min_source_scale
);
1305 void PictureLayerImpl::GetDebugBorderProperties(
1307 float* width
) const {
1308 *color
= DebugColors::TiledContentLayerBorderColor();
1309 *width
= DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1312 void PictureLayerImpl::AsValueInto(base::DictionaryValue
* state
) const {
1313 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1314 LayerImpl::AsValueInto(state
);
1315 state
->SetDouble("ideal_contents_scale", ideal_contents_scale_
);
1316 state
->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1317 state
->Set("tilings", tilings_
->AsValue().release());
1318 state
->Set("pictures", pile_
->AsValue().release());
1319 state
->Set("invalidation", invalidation_
.AsValue().release());
1321 scoped_ptr
<base::ListValue
> coverage_tiles(new base::ListValue
);
1322 for (PictureLayerTilingSet::CoverageIterator
iter(tilings_
.get(),
1324 gfx::Rect(content_bounds()),
1325 ideal_contents_scale_
);
1328 scoped_ptr
<base::DictionaryValue
> tile_data(new base::DictionaryValue
);
1329 tile_data
->Set("geometry_rect",
1330 MathUtil::AsValue(iter
.geometry_rect()).release());
1332 tile_data
->Set("tile", TracedValue::CreateIDRef(*iter
).release());
1334 coverage_tiles
->Append(tile_data
.release());
1336 state
->Set("coverage_tiles", coverage_tiles
.release());
1339 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1340 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1341 return tilings_
->GPUMemoryUsageInBytes();
1344 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl
* benchmark
) {
1345 benchmark
->RunOnLayer(this);
1348 WhichTree
PictureLayerImpl::GetTree() const {
1349 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
1352 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1353 return !layer_tree_impl()->IsRecycleTree();
1356 bool PictureLayerImpl::HasValidTilePriorities() const {
1357 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1360 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1361 if (!layer_tree_impl()->IsPendingTree())
1364 if (!HasValidTilePriorities())
1370 if (visible_content_rect().IsEmpty())
1373 for (size_t i
= 0; i
< tilings_
->num_tilings(); ++i
) {
1374 PictureLayerTiling
* tiling
= tilings_
->tiling_at(i
);
1375 if (tiling
->resolution() != HIGH_RESOLUTION
&&
1376 tiling
->resolution() != LOW_RESOLUTION
)
1379 gfx::Rect
rect(visible_content_rect());
1380 for (PictureLayerTiling::CoverageIterator
iter(
1381 tiling
, contents_scale_x(), rect
);
1384 const Tile
* tile
= *iter
;
1385 // A null tile (i.e. missing recording) can just be skipped.
1389 if (tile
->required_for_activation() && !tile
->IsReadyToDraw())
1397 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1400 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1401 PictureLayerImpl
* layer
,
1402 bool prioritize_low_res
)
1403 : layer_(layer
), current_stage_(0) {
1406 // Early out if the layer has no tilings.
1407 if (!layer_
->tilings_
|| !layer_
->tilings_
->num_tilings()) {
1408 current_stage_
= arraysize(stages_
);
1412 // Tiles without valid priority are treated as having lowest priority and
1413 // never considered for raster.
1414 if (!layer_
->HasValidTilePriorities()) {
1415 current_stage_
= arraysize(stages_
);
1420 layer_
->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
1422 // Find high and low res tilings and initialize the iterators.
1423 for (size_t i
= 0; i
< layer_
->tilings_
->num_tilings(); ++i
) {
1424 PictureLayerTiling
* tiling
= layer_
->tilings_
->tiling_at(i
);
1425 if (tiling
->resolution() == HIGH_RESOLUTION
) {
1426 iterators_
[HIGH_RES
] =
1427 PictureLayerTiling::TilingRasterTileIterator(tiling
, tree
);
1430 if (tiling
->resolution() == LOW_RESOLUTION
) {
1431 iterators_
[LOW_RES
] =
1432 PictureLayerTiling::TilingRasterTileIterator(tiling
, tree
);
1436 if (prioritize_low_res
) {
1437 stages_
[0].iterator_type
= LOW_RES
;
1438 stages_
[0].tile_type
= TilePriority::NOW
;
1440 stages_
[1].iterator_type
= HIGH_RES
;
1441 stages_
[1].tile_type
= TilePriority::NOW
;
1443 stages_
[0].iterator_type
= HIGH_RES
;
1444 stages_
[0].tile_type
= TilePriority::NOW
;
1446 stages_
[1].iterator_type
= LOW_RES
;
1447 stages_
[1].tile_type
= TilePriority::NOW
;
1450 stages_
[2].iterator_type
= HIGH_RES
;
1451 stages_
[2].tile_type
= TilePriority::SOON
;
1453 stages_
[3].iterator_type
= HIGH_RES
;
1454 stages_
[3].tile_type
= TilePriority::EVENTUALLY
;
1456 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1457 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1458 if (!iterators_
[index
] || iterators_
[index
].get_type() != tile_type
||
1459 (*iterators_
[index
])->is_occluded(tree
))
1463 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1465 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1466 return layer_
&& static_cast<size_t>(current_stage_
) < arraysize(stages_
);
1469 PictureLayerImpl::LayerRasterTileIterator
&
1470 PictureLayerImpl::LayerRasterTileIterator::
1473 layer_
->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
1475 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1476 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1478 // First advance the iterator.
1479 if (iterators_
[index
])
1480 ++iterators_
[index
];
1482 while (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
&&
1483 (*iterators_
[index
])->is_occluded(tree
))
1484 ++iterators_
[index
];
1486 if (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
)
1489 // Next, advance the stage.
1490 int stage_count
= arraysize(stages_
);
1492 while (current_stage_
< stage_count
) {
1493 index
= stages_
[current_stage_
].iterator_type
;
1494 tile_type
= stages_
[current_stage_
].tile_type
;
1496 if (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
&&
1497 !(*iterators_
[index
])->is_occluded(tree
))
1504 Tile
* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1507 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1508 DCHECK(iterators_
[index
]);
1509 DCHECK(iterators_
[index
].get_type() == stages_
[current_stage_
].tile_type
);
1511 return *iterators_
[index
];
1514 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1515 : iterator_index_(0),
1516 iteration_stage_(TilePriority::EVENTUALLY
),
1517 required_for_activation_(false),
1520 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1521 PictureLayerImpl
* layer
,
1522 TreePriority tree_priority
)
1523 : iterator_index_(0),
1524 iteration_stage_(TilePriority::EVENTUALLY
),
1525 required_for_activation_(false),
1527 // Early out if the layer has no tilings.
1528 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1529 // that layers that don't have valid tile priorities have lowest priorities so
1530 // they evict their tiles first (crbug.com/381704)
1531 if (!layer_
->tilings_
|| !layer_
->tilings_
->num_tilings())
1534 size_t high_res_tiling_index
= layer_
->tilings_
->num_tilings();
1535 size_t low_res_tiling_index
= layer_
->tilings_
->num_tilings();
1536 for (size_t i
= 0; i
< layer_
->tilings_
->num_tilings(); ++i
) {
1537 PictureLayerTiling
* tiling
= layer_
->tilings_
->tiling_at(i
);
1538 if (tiling
->resolution() == HIGH_RESOLUTION
)
1539 high_res_tiling_index
= i
;
1540 else if (tiling
->resolution() == LOW_RESOLUTION
)
1541 low_res_tiling_index
= i
;
1544 iterators_
.reserve(layer_
->tilings_
->num_tilings());
1546 // Higher resolution non-ideal goes first.
1547 for (size_t i
= 0; i
< high_res_tiling_index
; ++i
) {
1548 iterators_
.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1549 layer_
->tilings_
->tiling_at(i
), tree_priority
));
1552 // Lower resolution non-ideal goes next.
1553 for (size_t i
= layer_
->tilings_
->num_tilings() - 1;
1554 i
> high_res_tiling_index
;
1556 PictureLayerTiling
* tiling
= layer_
->tilings_
->tiling_at(i
);
1557 if (tiling
->resolution() == LOW_RESOLUTION
)
1560 iterators_
.push_back(
1561 PictureLayerTiling::TilingEvictionTileIterator(tiling
, tree_priority
));
1564 // Now, put the low res tiling if we have one.
1565 if (low_res_tiling_index
< layer_
->tilings_
->num_tilings()) {
1566 iterators_
.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1567 layer_
->tilings_
->tiling_at(low_res_tiling_index
), tree_priority
));
1570 // Finally, put the high res tiling if we have one.
1571 if (high_res_tiling_index
< layer_
->tilings_
->num_tilings()) {
1572 iterators_
.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1573 layer_
->tilings_
->tiling_at(high_res_tiling_index
), tree_priority
));
1576 DCHECK_GT(iterators_
.size(), 0u);
1578 if (!iterators_
[iterator_index_
] ||
1579 !IsCorrectType(&iterators_
[iterator_index_
])) {
1580 AdvanceToNextIterator();
1584 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {}
1586 Tile
* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1588 return *iterators_
[iterator_index_
];
1591 PictureLayerImpl::LayerEvictionTileIterator
&
1592 PictureLayerImpl::LayerEvictionTileIterator::
1595 ++iterators_
[iterator_index_
];
1596 if (!iterators_
[iterator_index_
] ||
1597 !IsCorrectType(&iterators_
[iterator_index_
])) {
1598 AdvanceToNextIterator();
1603 void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() {
1607 while (iterator_index_
< iterators_
.size()) {
1608 if (iterators_
[iterator_index_
] &&
1609 IsCorrectType(&iterators_
[iterator_index_
])) {
1615 // If we're NOW and required_for_activation, then this was the last pass
1616 // through the iterators.
1617 if (iteration_stage_
== TilePriority::NOW
&& required_for_activation_
)
1620 if (!required_for_activation_
) {
1621 required_for_activation_
= true;
1623 required_for_activation_
= false;
1625 static_cast<TilePriority::PriorityBin
>(iteration_stage_
- 1);
1627 iterator_index_
= 0;
1631 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1632 return iterator_index_
< iterators_
.size();
1635 bool PictureLayerImpl::LayerEvictionTileIterator::IsCorrectType(
1636 PictureLayerTiling::TilingEvictionTileIterator
* it
) const {
1637 return it
->get_type() == iteration_stage_
&&
1638 (**it
)->required_for_activation() == required_for_activation_
;