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/layers/solid_color_layer_impl.h"
20 #include "cc/output/begin_frame_args.h"
21 #include "cc/quads/checkerboard_draw_quad.h"
22 #include "cc/quads/debug_border_draw_quad.h"
23 #include "cc/quads/picture_draw_quad.h"
24 #include "cc/quads/solid_color_draw_quad.h"
25 #include "cc/quads/tile_draw_quad.h"
26 #include "cc/resources/tile_manager.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "cc/trees/occlusion.h"
29 #include "ui/gfx/geometry/quad_f.h"
30 #include "ui/gfx/geometry/rect_conversions.h"
31 #include "ui/gfx/geometry/size_conversions.h"
34 // This must be > 1 as we multiply or divide by this to find a new raster
35 // scale during pinch.
36 const float kMaxScaleRatioDuringPinch
= 2.0f
;
38 // When creating a new tiling during pinch, snap to an existing
39 // tiling's scale if the desired scale is within this ratio.
40 const float kSnapToExistingTilingRatio
= 1.2f
;
42 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
43 const float kCpuSkewportTargetTimeInFrames
= 60.0f
;
45 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
46 // TileManager::BinFromTilePriority).
47 const float kGpuSkewportTargetTimeInFrames
= 0.0f
;
49 // Even for really wide viewports, at some point GPU raster should use
50 // less than 4 tiles to fill the viewport. This is set to 256 as a
51 // sane minimum for now, but we might want to tune this for low-end.
52 const int kMinHeightForGpuRasteredTile
= 256;
54 // When making odd-sized tiles, round them up to increase the chances
55 // of using the same tile size.
56 const int kTileRoundUp
= 64;
62 PictureLayerImpl::Pair::Pair() : active(nullptr), pending(nullptr) {
65 PictureLayerImpl::Pair::Pair(PictureLayerImpl
* active_layer
,
66 PictureLayerImpl
* pending_layer
)
67 : active(active_layer
), pending(pending_layer
) {
70 PictureLayerImpl::Pair::~Pair() {
73 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
74 : LayerImpl(tree_impl
, id
),
76 raster_source_(PicturePileImpl::Create()),
77 ideal_page_scale_(0.f
),
78 ideal_device_scale_(0.f
),
79 ideal_source_scale_(0.f
),
80 ideal_contents_scale_(0.f
),
81 raster_page_scale_(0.f
),
82 raster_device_scale_(0.f
),
83 raster_source_scale_(0.f
),
84 raster_contents_scale_(0.f
),
85 low_res_raster_contents_scale_(0.f
),
86 raster_source_scale_is_fixed_(false),
87 was_screen_space_transform_animating_(false),
88 needs_post_commit_initialization_(true),
89 should_update_tile_priorities_(false),
90 only_used_low_res_last_append_quads_(false),
92 layer_tree_impl()->RegisterPictureLayerImpl(this);
95 PictureLayerImpl::~PictureLayerImpl() {
97 twin_layer_
->twin_layer_
= nullptr;
98 layer_tree_impl()->UnregisterPictureLayerImpl(this);
101 const char* PictureLayerImpl::LayerTypeAsString() const {
102 return "cc::PictureLayerImpl";
105 scoped_ptr
<LayerImpl
> PictureLayerImpl::CreateLayerImpl(
106 LayerTreeImpl
* tree_impl
) {
107 return PictureLayerImpl::Create(tree_impl
, id());
110 void PictureLayerImpl::PushPropertiesTo(LayerImpl
* base_layer
) {
111 // It's possible this layer was never drawn or updated (e.g. because it was
112 // a descendant of an opacity 0 layer).
113 DoPostCommitInitializationIfNeeded();
114 PictureLayerImpl
* layer_impl
= static_cast<PictureLayerImpl
*>(base_layer
);
116 LayerImpl::PushPropertiesTo(base_layer
);
118 // Twin relationships should never change once established.
119 DCHECK_IMPLIES(twin_layer_
, twin_layer_
== layer_impl
);
120 DCHECK_IMPLIES(twin_layer_
, layer_impl
->twin_layer_
== this);
121 // The twin relationship does not need to exist before the first
122 // PushPropertiesTo from pending to active layer since before that the active
123 // layer can not have a pile or tilings, it has only been created and inserted
124 // into the tree at that point.
125 twin_layer_
= layer_impl
;
126 layer_impl
->twin_layer_
= this;
128 layer_impl
->UpdateRasterSource(raster_source_
);
130 DCHECK_IMPLIES(raster_source_
->IsSolidColor(), tilings_
->num_tilings() == 0);
131 // Tilings would be expensive to push, so we swap.
132 layer_impl
->tilings_
.swap(tilings_
);
133 layer_impl
->tilings_
->SetClient(layer_impl
);
135 tilings_
->SetClient(this);
137 // Ensure that the recycle tree doesn't have any unshared tiles.
138 if (tilings_
&& raster_source_
->IsSolidColor())
139 tilings_
->RemoveAllTilings();
141 // Remove invalidated tiles from what will become a recycle tree.
143 tilings_
->RemoveTilesInRegion(invalidation_
);
145 layer_impl
->raster_page_scale_
= raster_page_scale_
;
146 layer_impl
->raster_device_scale_
= raster_device_scale_
;
147 layer_impl
->raster_source_scale_
= raster_source_scale_
;
148 layer_impl
->raster_contents_scale_
= raster_contents_scale_
;
149 layer_impl
->low_res_raster_contents_scale_
= low_res_raster_contents_scale_
;
150 layer_impl
->needs_post_commit_initialization_
= false;
152 // The invalidation on this soon-to-be-recycled layer must be cleared to
153 // mirror clearing the invalidation in PictureLayer's version of this function
154 // in case push properties is skipped.
155 layer_impl
->invalidation_
.Swap(&invalidation_
);
156 invalidation_
.Clear();
157 needs_post_commit_initialization_
= true;
159 // We always need to push properties.
160 // See http://crbug.com/303943
161 needs_push_properties_
= true;
164 void PictureLayerImpl::UpdateRasterSource(
165 scoped_refptr
<RasterSource
> raster_source
) {
166 bool could_have_tilings
= CanHaveTilings();
167 raster_source_
.swap(raster_source
);
169 // Need to call UpdateTiles again if CanHaveTilings changed.
170 if (could_have_tilings
!= CanHaveTilings()) {
171 layer_tree_impl()->set_needs_update_draw_properties();
175 void PictureLayerImpl::AppendQuads(RenderPass
* render_pass
,
176 const Occlusion
& occlusion_in_content_space
,
177 AppendQuadsData
* append_quads_data
) {
178 DCHECK(!needs_post_commit_initialization_
);
179 // The bounds and the pile size may differ if the pile wasn't updated (ie.
180 // PictureLayer::Update didn't happen). In that case the pile will be empty.
181 DCHECK_IMPLIES(!raster_source_
->GetSize().IsEmpty(),
182 bounds() == raster_source_
->GetSize())
183 << " bounds " << bounds().ToString() << " pile "
184 << raster_source_
->GetSize().ToString();
186 SharedQuadState
* shared_quad_state
=
187 render_pass
->CreateAndAppendSharedQuadState();
189 if (raster_source_
->IsSolidColor()) {
190 PopulateSharedQuadState(shared_quad_state
);
192 AppendDebugBorderQuad(
193 render_pass
, bounds(), shared_quad_state
, append_quads_data
);
195 SolidColorLayerImpl::AppendSolidQuads(
196 render_pass
, occlusion_in_content_space
, shared_quad_state
,
197 visible_content_rect(), raster_source_
->GetSolidColor(),
202 float max_contents_scale
= MaximumTilingContentsScale();
203 gfx::Transform scaled_draw_transform
= draw_transform();
204 scaled_draw_transform
.Scale(SK_MScalar1
/ max_contents_scale
,
205 SK_MScalar1
/ max_contents_scale
);
206 gfx::Size scaled_content_bounds
=
207 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), max_contents_scale
));
208 gfx::Rect scaled_visible_content_rect
=
209 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale
);
210 scaled_visible_content_rect
.Intersect(gfx::Rect(scaled_content_bounds
));
211 Occlusion scaled_occlusion
=
212 occlusion_in_content_space
.GetOcclusionWithGivenDrawTransform(
213 scaled_draw_transform
);
215 shared_quad_state
->SetAll(
216 scaled_draw_transform
, scaled_content_bounds
, scaled_visible_content_rect
,
217 draw_properties().clip_rect
, draw_properties().is_clipped
,
218 draw_properties().opacity
, draw_properties().blend_mode
,
219 sorting_context_id_
);
221 if (current_draw_mode_
== DRAW_MODE_RESOURCELESS_SOFTWARE
) {
222 AppendDebugBorderQuad(
224 scaled_content_bounds
,
227 DebugColors::DirectPictureBorderColor(),
228 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
230 gfx::Rect geometry_rect
= scaled_visible_content_rect
;
231 gfx::Rect opaque_rect
= contents_opaque() ? geometry_rect
: gfx::Rect();
232 gfx::Rect visible_geometry_rect
=
233 scaled_occlusion
.GetUnoccludedContentRect(geometry_rect
);
234 if (visible_geometry_rect
.IsEmpty())
237 gfx::Size texture_size
= scaled_visible_content_rect
.size();
238 gfx::RectF texture_rect
= gfx::RectF(texture_size
);
239 gfx::Rect quad_content_rect
= scaled_visible_content_rect
;
241 PictureDrawQuad
* quad
=
242 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
243 quad
->SetNew(shared_quad_state
, geometry_rect
, opaque_rect
,
244 visible_geometry_rect
, texture_rect
, texture_size
, RGBA_8888
,
245 quad_content_rect
, max_contents_scale
, raster_source_
);
249 AppendDebugBorderQuad(
250 render_pass
, scaled_content_bounds
, shared_quad_state
, append_quads_data
);
252 if (ShowDebugBorders()) {
253 for (PictureLayerTilingSet::CoverageIterator
iter(
256 scaled_visible_content_rect
,
257 ideal_contents_scale_
);
262 if (*iter
&& iter
->IsReadyToDraw()) {
263 ManagedTileState::DrawInfo::Mode mode
= iter
->draw_info().mode();
264 if (mode
== ManagedTileState::DrawInfo::SOLID_COLOR_MODE
) {
265 color
= DebugColors::SolidColorTileBorderColor();
266 width
= DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
267 } else if (mode
== ManagedTileState::DrawInfo::PICTURE_PILE_MODE
) {
268 color
= DebugColors::PictureTileBorderColor();
269 width
= DebugColors::PictureTileBorderWidth(layer_tree_impl());
270 } else if (iter
.resolution() == HIGH_RESOLUTION
) {
271 color
= DebugColors::HighResTileBorderColor();
272 width
= DebugColors::HighResTileBorderWidth(layer_tree_impl());
273 } else if (iter
.resolution() == LOW_RESOLUTION
) {
274 color
= DebugColors::LowResTileBorderColor();
275 width
= DebugColors::LowResTileBorderWidth(layer_tree_impl());
276 } else if (iter
->contents_scale() > max_contents_scale
) {
277 color
= DebugColors::ExtraHighResTileBorderColor();
278 width
= DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
280 color
= DebugColors::ExtraLowResTileBorderColor();
281 width
= DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
284 color
= DebugColors::MissingTileBorderColor();
285 width
= DebugColors::MissingTileBorderWidth(layer_tree_impl());
288 DebugBorderDrawQuad
* debug_border_quad
=
289 render_pass
->CreateAndAppendDrawQuad
<DebugBorderDrawQuad
>();
290 gfx::Rect geometry_rect
= iter
.geometry_rect();
291 gfx::Rect visible_geometry_rect
= geometry_rect
;
292 debug_border_quad
->SetNew(shared_quad_state
,
294 visible_geometry_rect
,
300 // Keep track of the tilings that were used so that tilings that are
301 // unused can be considered for removal.
302 std::vector
<PictureLayerTiling
*> seen_tilings
;
304 // Ignore missing tiles outside of viewport for tile priority. This is
305 // normally the same as draw viewport but can be independently overridden by
306 // embedders like Android WebView with SetExternalDrawConstraints.
307 gfx::Rect scaled_viewport_for_tile_priority
= gfx::ScaleToEnclosingRect(
308 GetViewportForTilePriorityInContentSpace(), max_contents_scale
);
310 size_t missing_tile_count
= 0u;
311 size_t on_demand_missing_tile_count
= 0u;
312 only_used_low_res_last_append_quads_
= true;
313 for (PictureLayerTilingSet::CoverageIterator
iter(tilings_
.get(),
315 scaled_visible_content_rect
,
316 ideal_contents_scale_
);
319 gfx::Rect geometry_rect
= iter
.geometry_rect();
320 gfx::Rect opaque_rect
= contents_opaque() ? geometry_rect
: gfx::Rect();
321 gfx::Rect visible_geometry_rect
=
322 scaled_occlusion
.GetUnoccludedContentRect(geometry_rect
);
323 if (visible_geometry_rect
.IsEmpty())
326 append_quads_data
->visible_content_area
+=
327 visible_geometry_rect
.width() * visible_geometry_rect
.height();
329 bool has_draw_quad
= false;
330 if (*iter
&& iter
->IsReadyToDraw()) {
331 const ManagedTileState::DrawInfo
& draw_info
= iter
->draw_info();
332 switch (draw_info
.mode()) {
333 case ManagedTileState::DrawInfo::RESOURCE_MODE
: {
334 gfx::RectF texture_rect
= iter
.texture_rect();
336 // The raster_contents_scale_ is the best scale that the layer is
337 // trying to produce, even though it may not be ideal. Since that's
338 // the best the layer can promise in the future, consider those as
339 // complete. But if a tile is ideal scale, we don't want to consider
340 // it incomplete and trying to replace it with a tile at a worse
342 if (iter
->contents_scale() != raster_contents_scale_
&&
343 iter
->contents_scale() != ideal_contents_scale_
&&
344 geometry_rect
.Intersects(scaled_viewport_for_tile_priority
)) {
345 append_quads_data
->num_incomplete_tiles
++;
349 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
350 quad
->SetNew(shared_quad_state
,
353 visible_geometry_rect
,
354 draw_info
.get_resource_id(),
357 draw_info
.contents_swizzled());
358 has_draw_quad
= true;
361 case ManagedTileState::DrawInfo::PICTURE_PILE_MODE
: {
362 if (!layer_tree_impl()
363 ->GetRendererCapabilities()
364 .allow_rasterize_on_demand
) {
365 ++on_demand_missing_tile_count
;
369 gfx::RectF texture_rect
= iter
.texture_rect();
371 ResourceProvider
* resource_provider
=
372 layer_tree_impl()->resource_provider();
373 ResourceFormat format
=
374 resource_provider
->memory_efficient_texture_format();
375 PictureDrawQuad
* quad
=
376 render_pass
->CreateAndAppendDrawQuad
<PictureDrawQuad
>();
377 quad
->SetNew(shared_quad_state
, geometry_rect
, opaque_rect
,
378 visible_geometry_rect
, texture_rect
, iter
.texture_size(),
379 format
, iter
->content_rect(), iter
->contents_scale(),
381 has_draw_quad
= true;
384 case ManagedTileState::DrawInfo::SOLID_COLOR_MODE
: {
385 SolidColorDrawQuad
* quad
=
386 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
387 quad
->SetNew(shared_quad_state
,
389 visible_geometry_rect
,
390 draw_info
.get_solid_color(),
392 has_draw_quad
= true;
398 if (!has_draw_quad
) {
399 if (draw_checkerboard_for_missing_tiles()) {
400 CheckerboardDrawQuad
* quad
=
401 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
402 SkColor color
= DebugColors::DefaultCheckerboardColor();
404 shared_quad_state
, geometry_rect
, visible_geometry_rect
, color
);
406 SkColor color
= SafeOpaqueBackgroundColor();
407 SolidColorDrawQuad
* quad
=
408 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
409 quad
->SetNew(shared_quad_state
,
411 visible_geometry_rect
,
416 if (geometry_rect
.Intersects(scaled_viewport_for_tile_priority
)) {
417 append_quads_data
->num_missing_tiles
++;
418 ++missing_tile_count
;
420 append_quads_data
->approximated_visible_content_area
+=
421 visible_geometry_rect
.width() * visible_geometry_rect
.height();
425 if (iter
.resolution() != HIGH_RESOLUTION
) {
426 append_quads_data
->approximated_visible_content_area
+=
427 visible_geometry_rect
.width() * visible_geometry_rect
.height();
430 // If we have a draw quad, but it's not low resolution, then
431 // mark that we've used something other than low res to draw.
432 if (iter
.resolution() != LOW_RESOLUTION
)
433 only_used_low_res_last_append_quads_
= false;
435 if (seen_tilings
.empty() || seen_tilings
.back() != iter
.CurrentTiling())
436 seen_tilings
.push_back(iter
.CurrentTiling());
439 if (missing_tile_count
) {
440 TRACE_EVENT_INSTANT2("cc",
441 "PictureLayerImpl::AppendQuads checkerboard",
442 TRACE_EVENT_SCOPE_THREAD
,
443 "missing_tile_count",
445 "on_demand_missing_tile_count",
446 on_demand_missing_tile_count
);
449 // Aggressively remove any tilings that are not seen to save memory. Note
450 // that this is at the expense of doing cause more frequent re-painting. A
451 // better scheme would be to maintain a tighter visible_content_rect for the
453 CleanUpTilingsOnActiveLayer(seen_tilings
);
456 void PictureLayerImpl::UpdateTiles(const Occlusion
& occlusion_in_content_space
,
457 bool resourceless_software_draw
) {
458 DCHECK_EQ(1.f
, contents_scale_x());
459 DCHECK_EQ(1.f
, contents_scale_y());
461 DoPostCommitInitializationIfNeeded();
463 if (!resourceless_software_draw
) {
464 visible_rect_for_tile_priority_
= visible_content_rect();
467 if (!CanHaveTilings()) {
468 ideal_page_scale_
= 0.f
;
469 ideal_device_scale_
= 0.f
;
470 ideal_contents_scale_
= 0.f
;
471 ideal_source_scale_
= 0.f
;
472 SanityCheckTilingState();
478 DCHECK_IMPLIES(tilings_
->num_tilings() == 0, raster_contents_scale_
== 0.f
)
479 << "A layer with no tilings shouldn't have valid raster scales";
480 if (!raster_contents_scale_
|| ShouldAdjustRasterScale()) {
481 RecalculateRasterScales();
482 AddTilingsForRasterScale();
485 DCHECK(raster_page_scale_
);
486 DCHECK(raster_device_scale_
);
487 DCHECK(raster_source_scale_
);
488 DCHECK(raster_contents_scale_
);
489 DCHECK(low_res_raster_contents_scale_
);
491 was_screen_space_transform_animating_
=
492 draw_properties().screen_space_transform_is_animating
;
494 if (draw_transform_is_animating())
495 raster_source_
->SetShouldAttemptToUseDistanceFieldText();
497 should_update_tile_priorities_
= true;
499 UpdateTilePriorities(occlusion_in_content_space
);
502 void PictureLayerImpl::UpdateTilePriorities(
503 const Occlusion
& occlusion_in_content_space
) {
504 DCHECK_IMPLIES(raster_source_
->IsSolidColor(), tilings_
->num_tilings() == 0);
506 double current_frame_time_in_seconds
=
507 (layer_tree_impl()->CurrentBeginFrameArgs().frame_time
-
508 base::TimeTicks()).InSecondsF();
509 gfx::Rect viewport_rect_in_layer_space
=
510 GetViewportForTilePriorityInContentSpace();
512 // The tiling set can require tiles for activation any of the following
513 // conditions are true:
514 // - This layer produced a high-res or non-ideal-res tile last frame.
515 // - We're in requires high res to draw mode.
516 // - We're not in smoothness takes priority mode.
517 // To put different, the tiling set can't require tiles for activation if
518 // we're in smoothness mode and only used low-res or checkerboard to draw last
519 // frame and we don't need high res to draw.
521 // The reason for this is that we should be able to activate sooner and get a
522 // more up to date recording, so we don't run out of recording on the active
524 bool can_require_tiles_for_activation
=
525 !only_used_low_res_last_append_quads_
|| RequiresHighResToDraw() ||
526 !layer_tree_impl()->SmoothnessTakesPriority();
528 // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
529 // they are the same space in picture layer, as contents scale is always 1.
530 bool updated
= tilings_
->UpdateTilePriorities(
531 viewport_rect_in_layer_space
, ideal_contents_scale_
,
532 current_frame_time_in_seconds
, occlusion_in_content_space
,
533 can_require_tiles_for_activation
);
535 // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
537 layer_tree_impl()->DidModifyTilePriorities();
540 gfx::Rect
PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
541 // If visible_rect_for_tile_priority_ is empty or
542 // viewport_rect_for_tile_priority is set to be different from the device
543 // viewport, try to inverse project the viewport into layer space and use
544 // that. Otherwise just use visible_rect_for_tile_priority_
545 gfx::Rect visible_rect_in_content_space
= visible_rect_for_tile_priority_
;
546 gfx::Rect viewport_rect_for_tile_priority
=
547 layer_tree_impl()->ViewportRectForTilePriority();
549 if (visible_rect_in_content_space
.IsEmpty() ||
550 layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority
) {
551 gfx::Transform
view_to_layer(gfx::Transform::kSkipInitialization
);
552 if (screen_space_transform().GetInverse(&view_to_layer
)) {
553 // Transform from view space to content space.
554 visible_rect_in_content_space
=
555 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
556 view_to_layer
, viewport_rect_for_tile_priority
));
559 return visible_rect_in_content_space
;
562 PictureLayerImpl
* PictureLayerImpl::GetPendingOrActiveTwinLayer() const {
563 if (!twin_layer_
|| !twin_layer_
->IsOnActiveOrPendingTree())
568 PictureLayerImpl
* PictureLayerImpl::GetRecycledTwinLayer() const {
569 if (!twin_layer_
|| twin_layer_
->IsOnActiveOrPendingTree())
574 void PictureLayerImpl::NotifyTileStateChanged(const Tile
* tile
) {
575 if (layer_tree_impl()->IsActiveTree()) {
576 gfx::RectF layer_damage_rect
=
577 gfx::ScaleRect(tile
->content_rect(), 1.f
/ tile
->contents_scale());
578 AddDamageRect(layer_damage_rect
);
582 void PictureLayerImpl::DidBecomeActive() {
583 LayerImpl::DidBecomeActive();
584 // TODO(vmpstr): See if this can be removed in favour of calling it from LTHI
585 layer_tree_impl()->DidModifyTilePriorities();
588 void PictureLayerImpl::DidBeginTracing() {
589 raster_source_
->DidBeginTracing();
592 void PictureLayerImpl::ReleaseResources() {
598 // To avoid an edge case after lost context where the tree is up to date but
599 // the tilings have not been managed, request an update draw properties
600 // to force tilings to get managed.
601 layer_tree_impl()->set_needs_update_draw_properties();
604 skia::RefPtr
<SkPicture
> PictureLayerImpl::GetPicture() {
605 return raster_source_
->GetFlattenedPicture();
608 scoped_refptr
<Tile
> PictureLayerImpl::CreateTile(PictureLayerTiling
* tiling
,
609 const gfx::Rect
& content_rect
) {
610 DCHECK(!raster_source_
->IsSolidColor());
611 if (!raster_source_
->CoversRect(content_rect
, tiling
->contents_scale()))
612 return scoped_refptr
<Tile
>();
616 // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as
617 // much savings on memory as we can. However, for some cases like ganesh or
618 // small layers, the amount of time we spend analyzing might not justify
619 // memory savings that we can get. Note that we don't handle solid color
620 // masks, so we shouldn't bother analyzing those.
621 // Bugs: crbug.com/397198, crbug.com/396908
623 flags
= Tile::USE_PICTURE_ANALYSIS
;
625 return layer_tree_impl()->tile_manager()->CreateTile(
626 raster_source_
.get(), content_rect
.size(), content_rect
,
627 tiling
->contents_scale(), id(), layer_tree_impl()->source_frame_number(),
631 const Region
* PictureLayerImpl::GetPendingInvalidation() {
632 if (layer_tree_impl()->IsPendingTree())
633 return &invalidation_
;
634 DCHECK(layer_tree_impl()->IsActiveTree());
635 if (PictureLayerImpl
* twin_layer
= GetPendingOrActiveTwinLayer())
636 return &twin_layer
->invalidation_
;
640 const PictureLayerTiling
* PictureLayerImpl::GetPendingOrActiveTwinTiling(
641 const PictureLayerTiling
* tiling
) const {
642 PictureLayerImpl
* twin_layer
= GetPendingOrActiveTwinLayer();
645 // TODO(danakj): Remove this when no longer swapping tilings.
646 if (!twin_layer
->tilings_
)
648 return twin_layer
->tilings_
->FindTilingWithScale(tiling
->contents_scale());
651 PictureLayerTiling
* PictureLayerImpl::GetRecycledTwinTiling(
652 const PictureLayerTiling
* tiling
) {
653 PictureLayerImpl
* recycled_twin
= GetRecycledTwinLayer();
654 if (!recycled_twin
|| !recycled_twin
->tilings_
)
656 return recycled_twin
->tilings_
->FindTilingWithScale(tiling
->contents_scale());
659 TilePriority::PriorityBin
PictureLayerImpl::GetMaxTilePriorityBin() const {
660 if (!HasValidTilePriorities())
661 return TilePriority::EVENTUALLY
;
662 return TilePriority::NOW
;
665 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
666 return layer_tree_impl()->settings().max_tiles_for_interest_area
;
669 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
670 float skewport_target_time_in_frames
=
671 layer_tree_impl()->use_gpu_rasterization()
672 ? kGpuSkewportTargetTimeInFrames
673 : kCpuSkewportTargetTimeInFrames
;
674 return skewport_target_time_in_frames
*
675 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
676 layer_tree_impl()->settings().skewport_target_time_multiplier
;
679 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
680 return layer_tree_impl()
682 .skewport_extrapolation_limit_in_content_pixels
;
685 bool PictureLayerImpl::RequiresHighResToDraw() const {
686 return layer_tree_impl()->RequiresHighResToDraw();
689 gfx::Size
PictureLayerImpl::CalculateTileSize(
690 const gfx::Size
& content_bounds
) const {
691 int max_texture_size
=
692 layer_tree_impl()->resource_provider()->max_texture_size();
695 // Masks are not tiled, so if we can't cover the whole mask with one tile,
696 // don't make any tiles at all. Returning an empty size signals this.
697 if (content_bounds
.width() > max_texture_size
||
698 content_bounds
.height() > max_texture_size
)
700 return content_bounds
;
703 int default_tile_width
= 0;
704 int default_tile_height
= 0;
705 if (layer_tree_impl()->use_gpu_rasterization()) {
706 // For GPU rasterization, we pick an ideal tile size using the viewport
707 // so we don't need any settings. The current approach uses 4 tiles
708 // to cover the viewport vertically.
709 int viewport_width
= layer_tree_impl()->device_viewport_size().width();
710 int viewport_height
= layer_tree_impl()->device_viewport_size().height();
711 default_tile_width
= viewport_width
;
712 // Also, increase the height proportionally as the width decreases, and
713 // pad by our border texels to make the tiles exactly match the viewport.
715 if (content_bounds
.width() <= viewport_width
/ 2)
717 if (content_bounds
.width() <= viewport_width
/ 4)
719 default_tile_height
= RoundUp(viewport_height
, divisor
) / divisor
;
720 default_tile_height
+= 2 * PictureLayerTiling::kBorderTexels
;
721 default_tile_height
=
722 std::max(default_tile_height
, kMinHeightForGpuRasteredTile
);
724 // For CPU rasterization we use tile-size settings.
725 const LayerTreeSettings
& settings
= layer_tree_impl()->settings();
726 int max_untiled_content_width
= settings
.max_untiled_layer_size
.width();
727 int max_untiled_content_height
= settings
.max_untiled_layer_size
.height();
728 default_tile_width
= settings
.default_tile_size
.width();
729 default_tile_height
= settings
.default_tile_size
.height();
731 // If the content width is small, increase tile size vertically.
732 // If the content height is small, increase tile size horizontally.
733 // If both are less than the untiled-size, use a single tile.
734 if (content_bounds
.width() < default_tile_width
)
735 default_tile_height
= max_untiled_content_height
;
736 if (content_bounds
.height() < default_tile_height
)
737 default_tile_width
= max_untiled_content_width
;
738 if (content_bounds
.width() < max_untiled_content_width
&&
739 content_bounds
.height() < max_untiled_content_height
) {
740 default_tile_height
= max_untiled_content_height
;
741 default_tile_width
= max_untiled_content_width
;
745 int tile_width
= default_tile_width
;
746 int tile_height
= default_tile_height
;
748 // Clamp the tile width/height to the content width/height to save space.
749 if (content_bounds
.width() < default_tile_width
) {
750 tile_width
= std::min(tile_width
, content_bounds
.width());
751 tile_width
= RoundUp(tile_width
, kTileRoundUp
);
752 tile_width
= std::min(tile_width
, default_tile_width
);
754 if (content_bounds
.height() < default_tile_height
) {
755 tile_height
= std::min(tile_height
, content_bounds
.height());
756 tile_height
= RoundUp(tile_height
, kTileRoundUp
);
757 tile_height
= std::min(tile_height
, default_tile_height
);
760 // Under no circumstance should we be larger than the max texture size.
761 tile_width
= std::min(tile_width
, max_texture_size
);
762 tile_height
= std::min(tile_height
, max_texture_size
);
763 return gfx::Size(tile_width
, tile_height
);
766 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl
* other
) {
767 DCHECK(!other
->needs_post_commit_initialization_
);
768 DCHECK(other
->tilings_
);
770 if (!DrawsContent()) {
775 raster_page_scale_
= other
->raster_page_scale_
;
776 raster_device_scale_
= other
->raster_device_scale_
;
777 raster_source_scale_
= other
->raster_source_scale_
;
778 raster_contents_scale_
= other
->raster_contents_scale_
;
779 low_res_raster_contents_scale_
= other
->low_res_raster_contents_scale_
;
781 bool synced_high_res_tiling
= false;
782 if (CanHaveTilings()) {
783 synced_high_res_tiling
= tilings_
->SyncTilings(
784 *other
->tilings_
, raster_source_
->GetSize(), invalidation_
,
785 MinimumContentsScale(), raster_source_
.get());
790 // If our MinimumContentsScale has changed to prevent the twin's high res
791 // tiling from being synced, we should reset the raster scale and let it be
792 // recalculated (1) again. This can happen if our bounds shrink to the point
793 // where min contents scale grows.
794 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
795 // should refactor this code a little bit and actually recalculate this.
796 // However, this is a larger undertaking, so this will work for now.
797 if (!synced_high_res_tiling
)
800 SanityCheckTilingState();
803 void PictureLayerImpl::SyncTiling(
804 const PictureLayerTiling
* tiling
) {
807 if (!CanHaveTilingWithScale(tiling
->contents_scale()))
809 tilings_
->AddTiling(tiling
->contents_scale(), raster_source_
->GetSize());
811 // If this tree needs update draw properties, then the tiling will
812 // get updated prior to drawing or activation. If this tree does not
813 // need update draw properties, then its transforms are up to date and
814 // we can create tiles for this tiling immediately.
815 if (!layer_tree_impl()->needs_update_draw_properties() &&
816 should_update_tile_priorities_
) {
817 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
818 // when we stop using the pending tree in the browser compositor. If we want
819 // to support occlusion tracking here, we need to dirty the draw properties
820 // or save occlusion as a draw property.
821 UpdateTilePriorities(Occlusion());
825 void PictureLayerImpl::GetContentsResourceId(
826 ResourceProvider::ResourceId
* resource_id
,
827 gfx::Size
* resource_size
) const {
828 DCHECK_EQ(bounds().ToString(), raster_source_
->GetSize().ToString());
829 gfx::Rect
content_rect(bounds());
830 PictureLayerTilingSet::CoverageIterator
iter(
831 tilings_
.get(), 1.f
, content_rect
, ideal_contents_scale_
);
833 // Mask resource not ready yet.
834 if (!iter
|| !*iter
) {
839 // Masks only supported if they fit on exactly one tile.
840 DCHECK(iter
.geometry_rect() == content_rect
)
841 << "iter rect " << iter
.geometry_rect().ToString() << " content rect "
842 << content_rect
.ToString();
844 const ManagedTileState::DrawInfo
& draw_info
= iter
->draw_info();
845 if (!draw_info
.IsReadyToDraw() ||
846 draw_info
.mode() != ManagedTileState::DrawInfo::RESOURCE_MODE
) {
851 *resource_id
= draw_info
.get_resource_id();
852 *resource_size
= iter
.texture_size();
855 void PictureLayerImpl::DoPostCommitInitialization() {
856 DCHECK(needs_post_commit_initialization_
);
857 DCHECK(layer_tree_impl()->IsPendingTree());
860 tilings_
= PictureLayerTilingSet::Create(this);
862 PictureLayerImpl
* twin_layer
= GetPendingOrActiveTwinLayer();
864 // If the twin has never been pushed to, do not sync from it.
865 // This can happen if this function is called during activation.
866 if (!twin_layer
->needs_post_commit_initialization_
)
867 SyncFromActiveLayer(twin_layer
);
870 needs_post_commit_initialization_
= false;
873 PictureLayerTiling
* PictureLayerImpl::AddTiling(float contents_scale
) {
874 DCHECK(CanHaveTilingWithScale(contents_scale
)) <<
875 "contents_scale: " << contents_scale
;
877 PictureLayerTiling
* tiling
=
878 tilings_
->AddTiling(contents_scale
, raster_source_
->GetSize());
880 DCHECK(raster_source_
->HasRecordings());
882 if (PictureLayerImpl
* twin_layer
= GetPendingOrActiveTwinLayer())
883 twin_layer
->SyncTiling(tiling
);
888 void PictureLayerImpl::RemoveAllTilings() {
890 tilings_
->RemoveAllTilings();
891 // If there are no tilings, then raster scales are no longer meaningful.
895 void PictureLayerImpl::AddTilingsForRasterScale() {
896 // Reset all resolution enums on tilings, we'll be setting new values in this
898 tilings_
->MarkAllTilingsNonIdeal();
900 PictureLayerTiling
* high_res
=
901 tilings_
->FindTilingWithScale(raster_contents_scale_
);
902 // We always need a high res tiling, so create one if it doesn't exist.
904 high_res
= AddTiling(raster_contents_scale_
);
906 // Try and find a low res tiling.
907 PictureLayerTiling
* low_res
= nullptr;
908 if (raster_contents_scale_
== low_res_raster_contents_scale_
)
911 low_res
= tilings_
->FindTilingWithScale(low_res_raster_contents_scale_
);
913 // Only create new low res tilings when the transform is static. This
914 // prevents wastefully creating a paired low res tiling for every new high res
915 // tiling during a pinch or a CSS animation.
916 bool can_have_low_res
= layer_tree_impl()->create_low_res_tiling();
917 bool needs_low_res
= !low_res
;
918 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
919 bool is_animating
= draw_properties().screen_space_transform_is_animating
;
920 if (can_have_low_res
&& needs_low_res
&& !is_pinching
&& !is_animating
)
921 low_res
= AddTiling(low_res_raster_contents_scale_
);
923 // Set low-res if we have one.
924 if (low_res
&& low_res
!= high_res
)
925 low_res
->set_resolution(LOW_RESOLUTION
);
927 // Make sure we always have one high-res (even if high == low).
928 high_res
->set_resolution(HIGH_RESOLUTION
);
930 SanityCheckTilingState();
933 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
934 if (was_screen_space_transform_animating_
!=
935 draw_properties().screen_space_transform_is_animating
)
938 if (draw_properties().screen_space_transform_is_animating
&&
939 raster_contents_scale_
!= ideal_contents_scale_
&&
940 ShouldAdjustRasterScaleDuringScaleAnimations())
943 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
944 if (is_pinching
&& raster_page_scale_
) {
945 // We change our raster scale when it is:
946 // - Higher than ideal (need a lower-res tiling available)
947 // - Too far from ideal (need a higher-res tiling available)
948 float ratio
= ideal_page_scale_
/ raster_page_scale_
;
949 if (raster_page_scale_
> ideal_page_scale_
||
950 ratio
> kMaxScaleRatioDuringPinch
)
955 // When not pinching, match the ideal page scale factor.
956 if (raster_page_scale_
!= ideal_page_scale_
)
960 // Always match the ideal device scale factor.
961 if (raster_device_scale_
!= ideal_device_scale_
)
964 // When the source scale changes we want to match it, but not when animating
965 // or when we've fixed the scale in place.
966 if (!draw_properties().screen_space_transform_is_animating
&&
967 !raster_source_scale_is_fixed_
&&
968 raster_source_scale_
!= ideal_source_scale_
)
974 void PictureLayerImpl::RecalculateRasterScales() {
975 float old_raster_contents_scale
= raster_contents_scale_
;
976 float old_raster_page_scale
= raster_page_scale_
;
977 float old_raster_source_scale
= raster_source_scale_
;
979 raster_device_scale_
= ideal_device_scale_
;
980 raster_page_scale_
= ideal_page_scale_
;
981 raster_source_scale_
= ideal_source_scale_
;
982 raster_contents_scale_
= ideal_contents_scale_
;
984 // If we're not animating, or leaving an animation, and the
985 // ideal_source_scale_ changes, then things are unpredictable, and we fix
986 // the raster_source_scale_ in place.
987 if (old_raster_source_scale
&&
988 !draw_properties().screen_space_transform_is_animating
&&
989 !was_screen_space_transform_animating_
&&
990 old_raster_source_scale
!= ideal_source_scale_
)
991 raster_source_scale_is_fixed_
= true;
993 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
994 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
995 // tree. This will allow CSS scale changes to get re-rastered at an
996 // appropriate rate. (crbug.com/413636)
997 if (raster_source_scale_is_fixed_
) {
998 raster_contents_scale_
/= raster_source_scale_
;
999 raster_source_scale_
= 1.f
;
1002 // During pinch we completely ignore the current ideal scale, and just use
1003 // a multiple of the previous scale.
1004 bool is_pinching
= layer_tree_impl()->PinchGestureActive();
1005 if (is_pinching
&& old_raster_contents_scale
) {
1006 // See ShouldAdjustRasterScale:
1007 // - When zooming out, preemptively create new tiling at lower resolution.
1008 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1009 bool zooming_out
= old_raster_page_scale
> ideal_page_scale_
;
1010 float desired_contents_scale
= old_raster_contents_scale
;
1012 while (desired_contents_scale
> ideal_contents_scale_
)
1013 desired_contents_scale
/= kMaxScaleRatioDuringPinch
;
1015 while (desired_contents_scale
< ideal_contents_scale_
)
1016 desired_contents_scale
*= kMaxScaleRatioDuringPinch
;
1018 raster_contents_scale_
= tilings_
->GetSnappedContentsScale(
1019 desired_contents_scale
, kSnapToExistingTilingRatio
);
1020 raster_page_scale_
=
1021 raster_contents_scale_
/ raster_device_scale_
/ raster_source_scale_
;
1024 // If we're not re-rasterizing during animation, rasterize at the maximum
1025 // scale that will occur during the animation, if the maximum scale is
1026 // known. However we want to avoid excessive memory use. If the scale is
1027 // smaller than what we would choose otherwise, then it's always better off
1028 // for us memory-wise. But otherwise, we don't choose a scale at which this
1029 // layer's rastered content would become larger than the viewport.
1030 if (draw_properties().screen_space_transform_is_animating
&&
1031 !ShouldAdjustRasterScaleDuringScaleAnimations()) {
1032 bool can_raster_at_maximum_scale
= false;
1033 // TODO(ajuma): If we need to deal with scale-down animations starting right
1034 // as a layer gets promoted, then we'd want to have the
1035 // |starting_animation_contents_scale| passed in here as a separate draw
1036 // property so we could try use that when the max is too large.
1037 // See crbug.com/422341.
1038 float maximum_scale
= draw_properties().maximum_animation_contents_scale
;
1039 if (maximum_scale
) {
1040 gfx::Size bounds_at_maximum_scale
= gfx::ToCeiledSize(
1041 gfx::ScaleSize(raster_source_
->GetSize(), maximum_scale
));
1042 if (bounds_at_maximum_scale
.GetArea() <=
1043 layer_tree_impl()->device_viewport_size().GetArea())
1044 can_raster_at_maximum_scale
= true;
1046 // Use the computed scales for the raster scale directly, do not try to use
1047 // the ideal scale here. The current ideal scale may be way too large in the
1048 // case of an animation with scale, and will be constantly changing.
1049 if (can_raster_at_maximum_scale
)
1050 raster_contents_scale_
= maximum_scale
;
1052 raster_contents_scale_
= 1.f
* ideal_page_scale_
* ideal_device_scale_
;
1055 raster_contents_scale_
=
1056 std::max(raster_contents_scale_
, MinimumContentsScale());
1058 // If this layer would create zero or one tiles at this content scale,
1059 // don't create a low res tiling.
1060 gfx::Size raster_bounds
= gfx::ToCeiledSize(
1061 gfx::ScaleSize(raster_source_
->GetSize(), raster_contents_scale_
));
1062 gfx::Size tile_size
= CalculateTileSize(raster_bounds
);
1063 bool tile_covers_bounds
= tile_size
.width() >= raster_bounds
.width() &&
1064 tile_size
.height() >= raster_bounds
.height();
1065 if (tile_size
.IsEmpty() || tile_covers_bounds
) {
1066 low_res_raster_contents_scale_
= raster_contents_scale_
;
1070 float low_res_factor
=
1071 layer_tree_impl()->settings().low_res_contents_scale_factor
;
1072 low_res_raster_contents_scale_
= std::max(
1073 raster_contents_scale_
* low_res_factor
,
1074 MinimumContentsScale());
1075 DCHECK_LE(low_res_raster_contents_scale_
, raster_contents_scale_
);
1076 DCHECK_GE(low_res_raster_contents_scale_
, MinimumContentsScale());
1079 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1080 std::vector
<PictureLayerTiling
*> used_tilings
) {
1081 DCHECK(layer_tree_impl()->IsActiveTree());
1082 if (tilings_
->num_tilings() == 0)
1085 float min_acceptable_high_res_scale
= std::min(
1086 raster_contents_scale_
, ideal_contents_scale_
);
1087 float max_acceptable_high_res_scale
= std::max(
1088 raster_contents_scale_
, ideal_contents_scale_
);
1090 PictureLayerImpl
* twin
= GetPendingOrActiveTwinLayer();
1091 if (twin
&& twin
->CanHaveTilings()) {
1092 min_acceptable_high_res_scale
= std::min(
1093 min_acceptable_high_res_scale
,
1094 std::min(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1095 max_acceptable_high_res_scale
= std::max(
1096 max_acceptable_high_res_scale
,
1097 std::max(twin
->raster_contents_scale_
, twin
->ideal_contents_scale_
));
1100 PictureLayerTilingSet
* twin_set
= twin
? twin
->tilings_
.get() : nullptr;
1101 PictureLayerImpl
* recycled_twin
= GetRecycledTwinLayer();
1102 PictureLayerTilingSet
* recycled_twin_set
=
1103 recycled_twin
? recycled_twin
->tilings_
.get() : nullptr;
1105 tilings_
->CleanUpTilings(min_acceptable_high_res_scale
,
1106 max_acceptable_high_res_scale
, used_tilings
,
1107 layer_tree_impl()->create_low_res_tiling(), twin_set
,
1110 if (twin_set
&& twin_set
->num_tilings() == 0)
1111 twin
->ResetRasterScale();
1113 if (recycled_twin_set
&& recycled_twin_set
->num_tilings() == 0)
1114 recycled_twin
->ResetRasterScale();
1116 DCHECK_GT(tilings_
->num_tilings(), 0u);
1117 SanityCheckTilingState();
1120 float PictureLayerImpl::MinimumContentsScale() const {
1121 float setting_min
= layer_tree_impl()->settings().minimum_contents_scale
;
1123 // If the contents scale is less than 1 / width (also for height),
1124 // then it will end up having less than one pixel of content in that
1125 // dimension. Bump the minimum contents scale up in this case to prevent
1126 // this from happening.
1127 int min_dimension
= std::min(raster_source_
->GetSize().width(),
1128 raster_source_
->GetSize().height());
1132 return std::max(1.f
/ min_dimension
, setting_min
);
1135 void PictureLayerImpl::ResetRasterScale() {
1136 raster_page_scale_
= 0.f
;
1137 raster_device_scale_
= 0.f
;
1138 raster_source_scale_
= 0.f
;
1139 raster_contents_scale_
= 0.f
;
1140 low_res_raster_contents_scale_
= 0.f
;
1141 raster_source_scale_is_fixed_
= false;
1143 // When raster scales aren't valid, don't update tile priorities until
1144 // this layer has been updated via UpdateDrawProperties.
1145 should_update_tile_priorities_
= false;
1148 bool PictureLayerImpl::CanHaveTilings() const {
1149 if (raster_source_
->IsSolidColor())
1151 if (!DrawsContent())
1153 if (!raster_source_
->HasRecordings())
1158 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale
) const {
1159 if (!CanHaveTilings())
1161 if (contents_scale
< MinimumContentsScale())
1166 void PictureLayerImpl::SanityCheckTilingState() const {
1168 // Recycle tree doesn't have any restrictions.
1169 if (layer_tree_impl()->IsRecycleTree())
1172 if (!CanHaveTilings()) {
1173 DCHECK_EQ(0u, tilings_
->num_tilings());
1176 if (tilings_
->num_tilings() == 0)
1179 // We should only have one high res tiling.
1180 DCHECK_EQ(1, tilings_
->NumHighResTilings());
1184 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const {
1185 return layer_tree_impl()->use_gpu_rasterization();
1188 float PictureLayerImpl::MaximumTilingContentsScale() const {
1189 float max_contents_scale
= tilings_
->GetMaximumContentsScale();
1190 return std::max(max_contents_scale
, MinimumContentsScale());
1193 void PictureLayerImpl::UpdateIdealScales() {
1194 DCHECK(CanHaveTilings());
1196 float min_contents_scale
= MinimumContentsScale();
1197 DCHECK_GT(min_contents_scale
, 0.f
);
1198 float min_page_scale
= layer_tree_impl()->min_page_scale_factor();
1199 DCHECK_GT(min_page_scale
, 0.f
);
1200 float min_device_scale
= 1.f
;
1201 float min_source_scale
=
1202 min_contents_scale
/ min_page_scale
/ min_device_scale
;
1204 float ideal_page_scale
= draw_properties().page_scale_factor
;
1205 float ideal_device_scale
= draw_properties().device_scale_factor
;
1206 float ideal_source_scale
= draw_properties().ideal_contents_scale
/
1207 ideal_page_scale
/ ideal_device_scale
;
1208 ideal_contents_scale_
=
1209 std::max(draw_properties().ideal_contents_scale
, min_contents_scale
);
1210 ideal_page_scale_
= draw_properties().page_scale_factor
;
1211 ideal_device_scale_
= draw_properties().device_scale_factor
;
1212 ideal_source_scale_
= std::max(ideal_source_scale
, min_source_scale
);
1215 void PictureLayerImpl::GetDebugBorderProperties(
1217 float* width
) const {
1218 *color
= DebugColors::TiledContentLayerBorderColor();
1219 *width
= DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1222 void PictureLayerImpl::GetAllTilesForTracing(
1223 std::set
<const Tile
*>* tiles
) const {
1226 tilings_
->GetAllTilesForTracing(tiles
);
1229 void PictureLayerImpl::AsValueInto(base::debug::TracedValue
* state
) const {
1230 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1231 LayerImpl::AsValueInto(state
);
1232 state
->SetDouble("ideal_contents_scale", ideal_contents_scale_
);
1233 state
->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1234 state
->BeginArray("tilings");
1235 tilings_
->AsValueInto(state
);
1238 state
->BeginArray("tile_priority_rect");
1239 MathUtil::AddToTracedValue(GetViewportForTilePriorityInContentSpace(), state
);
1242 state
->BeginArray("visible_rect");
1243 MathUtil::AddToTracedValue(visible_content_rect(), state
);
1246 state
->BeginArray("pictures");
1247 raster_source_
->AsValueInto(state
);
1250 state
->BeginArray("invalidation");
1251 invalidation_
.AsValueInto(state
);
1254 state
->BeginArray("coverage_tiles");
1255 for (PictureLayerTilingSet::CoverageIterator
iter(
1256 tilings_
.get(), 1.f
, gfx::Rect(raster_source_
->GetSize()),
1257 ideal_contents_scale_
);
1259 state
->BeginDictionary();
1261 state
->BeginArray("geometry_rect");
1262 MathUtil::AddToTracedValue(iter
.geometry_rect(), state
);
1266 TracedValue::SetIDRef(*iter
, state
, "tile");
1268 state
->EndDictionary();
1273 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1274 const_cast<PictureLayerImpl
*>(this)->DoPostCommitInitializationIfNeeded();
1275 return tilings_
->GPUMemoryUsageInBytes();
1278 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl
* benchmark
) {
1279 benchmark
->RunOnLayer(this);
1282 WhichTree
PictureLayerImpl::GetTree() const {
1283 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE
: PENDING_TREE
;
1286 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1287 return !layer_tree_impl()->IsRecycleTree();
1290 bool PictureLayerImpl::HasValidTilePriorities() const {
1291 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1294 bool PictureLayerImpl::AllTilesRequiredAreReadyToDraw(
1295 TileRequirementCheck is_tile_required_callback
) const {
1296 if (!HasValidTilePriorities())
1302 if (visible_rect_for_tile_priority_
.IsEmpty())
1305 gfx::Rect rect
= GetViewportForTilePriorityInContentSpace();
1306 rect
.Intersect(visible_rect_for_tile_priority_
);
1308 // The high resolution tiling is the only tiling that can mark tiles as
1309 // requiring either draw or activation. There is an explicit check in those
1310 // callbacks to return false if they are not high resolution tilings. This
1311 // check needs to remain since there are other callers of that function that
1312 // rely on it. However, for the purposes of this function, we don't have to
1313 // check other tilings.
1314 PictureLayerTiling
* tiling
=
1315 tilings_
->FindTilingWithResolution(HIGH_RESOLUTION
);
1319 for (PictureLayerTiling::CoverageIterator
iter(tiling
, 1.f
, rect
); iter
;
1321 const Tile
* tile
= *iter
;
1322 // A null tile (i.e. missing recording) can just be skipped.
1323 // TODO(vmpstr): Verify this is true if we create tiles in raster
1328 // We can't check tile->required_for_activation, because that value might
1329 // be out of date. It is updated in the raster/eviction iterators.
1330 // TODO(vmpstr): Remove the comment once you can't access this information
1332 if ((tiling
->*is_tile_required_callback
)(tile
) && !tile
->IsReadyToDraw()) {
1333 TRACE_EVENT_INSTANT0("cc", "Tile required, but not ready to draw.",
1334 TRACE_EVENT_SCOPE_THREAD
);
1342 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1343 if (!layer_tree_impl()->IsPendingTree())
1346 return AllTilesRequiredAreReadyToDraw(
1347 &PictureLayerTiling::IsTileRequiredForActivationIfVisible
);
1350 bool PictureLayerImpl::AllTilesRequiredForDrawAreReadyToDraw() const {
1351 if (!layer_tree_impl()->IsActiveTree())
1354 return AllTilesRequiredAreReadyToDraw(
1355 &PictureLayerTiling::IsTileRequiredForDrawIfVisible
);
1358 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1359 : layer_(nullptr), current_stage_(arraysize(stages_
)) {
1362 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1363 PictureLayerImpl
* layer
,
1364 bool prioritize_low_res
)
1365 : layer_(layer
), current_stage_(0) {
1368 // Early out if the layer has no tilings.
1369 if (!layer_
->tilings_
|| !layer_
->tilings_
->num_tilings()) {
1370 current_stage_
= arraysize(stages_
);
1374 // Tiles without valid priority are treated as having lowest priority and
1375 // never considered for raster.
1376 if (!layer_
->HasValidTilePriorities()) {
1377 current_stage_
= arraysize(stages_
);
1381 // Find high and low res tilings and initialize the iterators.
1382 for (size_t i
= 0; i
< layer_
->tilings_
->num_tilings(); ++i
) {
1383 PictureLayerTiling
* tiling
= layer_
->tilings_
->tiling_at(i
);
1384 if (tiling
->resolution() == HIGH_RESOLUTION
) {
1385 iterators_
[HIGH_RES
] =
1386 PictureLayerTiling::TilingRasterTileIterator(tiling
);
1389 if (prioritize_low_res
&& tiling
->resolution() == LOW_RESOLUTION
) {
1390 iterators_
[LOW_RES
] =
1391 PictureLayerTiling::TilingRasterTileIterator(tiling
);
1395 if (prioritize_low_res
) {
1396 stages_
[0].iterator_type
= LOW_RES
;
1397 stages_
[0].tile_type
= TilePriority::NOW
;
1399 stages_
[1].iterator_type
= HIGH_RES
;
1400 stages_
[1].tile_type
= TilePriority::NOW
;
1402 stages_
[0].iterator_type
= HIGH_RES
;
1403 stages_
[0].tile_type
= TilePriority::NOW
;
1405 stages_
[1].iterator_type
= LOW_RES
;
1406 stages_
[1].tile_type
= TilePriority::NOW
;
1409 stages_
[2].iterator_type
= HIGH_RES
;
1410 stages_
[2].tile_type
= TilePriority::SOON
;
1412 stages_
[3].iterator_type
= HIGH_RES
;
1413 stages_
[3].tile_type
= TilePriority::EVENTUALLY
;
1415 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1416 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1417 if (!iterators_
[index
] || iterators_
[index
].get_type() != tile_type
)
1418 AdvanceToNextStage();
1421 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1423 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1424 return current_stage_
< arraysize(stages_
);
1427 PictureLayerImpl::LayerRasterTileIterator
&
1428 PictureLayerImpl::LayerRasterTileIterator::
1430 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1431 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1433 // First advance the iterator.
1434 DCHECK(iterators_
[index
]);
1435 DCHECK(iterators_
[index
].get_type() == tile_type
);
1436 ++iterators_
[index
];
1438 if (!iterators_
[index
] || iterators_
[index
].get_type() != tile_type
)
1439 AdvanceToNextStage();
1444 Tile
* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1447 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1448 DCHECK(iterators_
[index
]);
1449 DCHECK(iterators_
[index
].get_type() == stages_
[current_stage_
].tile_type
);
1451 return *iterators_
[index
];
1454 const Tile
* PictureLayerImpl::LayerRasterTileIterator::operator*() const {
1457 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1458 DCHECK(iterators_
[index
]);
1459 DCHECK(iterators_
[index
].get_type() == stages_
[current_stage_
].tile_type
);
1461 return *iterators_
[index
];
1464 void PictureLayerImpl::LayerRasterTileIterator::AdvanceToNextStage() {
1465 DCHECK_LT(current_stage_
, arraysize(stages_
));
1467 while (current_stage_
< arraysize(stages_
)) {
1468 IteratorType index
= stages_
[current_stage_
].iterator_type
;
1469 TilePriority::PriorityBin tile_type
= stages_
[current_stage_
].tile_type
;
1471 if (iterators_
[index
] && iterators_
[index
].get_type() == tile_type
)
1477 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1479 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES
),
1480 current_category_(PictureLayerTiling::EVENTUALLY
),
1481 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
),
1482 current_tiling_(0u) {
1485 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1486 PictureLayerImpl
* layer
,
1487 TreePriority tree_priority
)
1489 tree_priority_(tree_priority
),
1490 current_category_(PictureLayerTiling::EVENTUALLY
),
1491 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
),
1492 current_tiling_(0u) {
1493 // Early out if the layer has no tilings.
1494 if (!layer_
->tilings_
|| !layer_
->tilings_
->num_tilings())
1497 current_tiling_
= CurrentTilingRange().start
- 1u;
1499 if (!AdvanceToNextTiling())
1502 current_iterator_
= PictureLayerTiling::TilingEvictionTileIterator(
1503 layer_
->tilings_
->tiling_at(CurrentTilingIndex()),
1506 } while (!current_iterator_
);
1509 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {
1512 Tile
* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1514 return *current_iterator_
;
1517 const Tile
* PictureLayerImpl::LayerEvictionTileIterator::operator*() const {
1519 return *current_iterator_
;
1522 PictureLayerImpl::LayerEvictionTileIterator
&
1523 PictureLayerImpl::LayerEvictionTileIterator::
1526 ++current_iterator_
;
1527 while (!current_iterator_
) {
1528 if (!AdvanceToNextTiling())
1531 current_iterator_
= PictureLayerTiling::TilingEvictionTileIterator(
1532 layer_
->tilings_
->tiling_at(CurrentTilingIndex()),
1539 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1540 return !!current_iterator_
;
1543 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() {
1544 switch (current_category_
) {
1545 case PictureLayerTiling::EVENTUALLY
:
1547 PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION
;
1549 case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION
:
1550 current_category_
= PictureLayerTiling::SOON
;
1552 case PictureLayerTiling::SOON
:
1553 current_category_
= PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION
;
1555 case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION
:
1556 current_category_
= PictureLayerTiling::NOW
;
1558 case PictureLayerTiling::NOW
:
1559 current_category_
= PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION
;
1561 case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION
:
1569 PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() {
1570 switch (current_tiling_range_type_
) {
1571 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
:
1572 current_tiling_range_type_
= PictureLayerTilingSet::LOWER_THAN_LOW_RES
;
1574 case PictureLayerTilingSet::LOWER_THAN_LOW_RES
:
1575 current_tiling_range_type_
=
1576 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
;
1578 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
:
1579 current_tiling_range_type_
= PictureLayerTilingSet::LOW_RES
;
1581 case PictureLayerTilingSet::LOW_RES
:
1582 current_tiling_range_type_
= PictureLayerTilingSet::HIGH_RES
;
1584 case PictureLayerTilingSet::HIGH_RES
:
1585 if (!AdvanceToNextCategory())
1588 current_tiling_range_type_
= PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
;
1595 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() {
1596 DCHECK_NE(current_tiling_
, CurrentTilingRange().end
);
1598 while (current_tiling_
== CurrentTilingRange().end
) {
1599 if (!AdvanceToNextTilingRangeType())
1602 current_tiling_
= CurrentTilingRange().start
;
1607 PictureLayerTilingSet::TilingRange
1608 PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const {
1609 return layer_
->tilings_
->GetTilingRange(current_tiling_range_type_
);
1612 size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const {
1613 DCHECK_NE(current_tiling_
, CurrentTilingRange().end
);
1614 switch (current_tiling_range_type_
) {
1615 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES
:
1616 case PictureLayerTilingSet::LOW_RES
:
1617 case PictureLayerTilingSet::HIGH_RES
:
1618 return current_tiling_
;
1619 // Tilings in the following ranges are accessed in reverse order.
1620 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES
:
1621 case PictureLayerTilingSet::LOWER_THAN_LOW_RES
: {
1622 PictureLayerTilingSet::TilingRange tiling_range
= CurrentTilingRange();
1623 size_t current_tiling_range_offset
= current_tiling_
- tiling_range
.start
;
1624 return tiling_range
.end
- 1 - current_tiling_range_offset
;