Revert of cc: Don't consider tiles at the layers raster_contents_scale incomplete...
[chromium-blink-merge.git] / cc / layers / picture_layer_impl.cc
blob7e12ac4eec8c2a5cb361ffbd03c4ccc790faf749
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/picture_layer_impl.h"
7 #include <algorithm>
8 #include <limits>
10 #include "base/debug/trace_event_argument.h"
11 #include "base/time/time.h"
12 #include "cc/base/math_util.h"
13 #include "cc/base/util.h"
14 #include "cc/debug/debug_colors.h"
15 #include "cc/debug/micro_benchmark_impl.h"
16 #include "cc/debug/traced_value.h"
17 #include "cc/layers/append_quads_data.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "cc/quads/checkerboard_draw_quad.h"
20 #include "cc/quads/debug_border_draw_quad.h"
21 #include "cc/quads/picture_draw_quad.h"
22 #include "cc/quads/solid_color_draw_quad.h"
23 #include "cc/quads/tile_draw_quad.h"
24 #include "cc/resources/tile_manager.h"
25 #include "cc/trees/layer_tree_impl.h"
26 #include "cc/trees/occlusion_tracker.h"
27 #include "ui/gfx/quad_f.h"
28 #include "ui/gfx/rect_conversions.h"
29 #include "ui/gfx/size_conversions.h"
31 namespace {
32 const float kMaxScaleRatioDuringPinch = 2.0f;
34 // When creating a new tiling during pinch, snap to an existing
35 // tiling's scale if the desired scale is within this ratio.
36 const float kSnapToExistingTilingRatio = 1.2f;
38 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
39 const float kCpuSkewportTargetTimeInFrames = 60.0f;
41 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
42 // TileManager::BinFromTilePriority).
43 const float kGpuSkewportTargetTimeInFrames = 0.0f;
45 } // namespace
47 namespace cc {
49 PictureLayerImpl::Pair::Pair() : active(NULL), pending(NULL) {
52 PictureLayerImpl::Pair::Pair(PictureLayerImpl* active_layer,
53 PictureLayerImpl* pending_layer)
54 : active(active_layer), pending(pending_layer) {
57 PictureLayerImpl::Pair::~Pair() {
60 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
61 : LayerImpl(tree_impl, id),
62 twin_layer_(NULL),
63 pile_(PicturePileImpl::Create()),
64 is_mask_(false),
65 ideal_page_scale_(0.f),
66 ideal_device_scale_(0.f),
67 ideal_source_scale_(0.f),
68 ideal_contents_scale_(0.f),
69 raster_page_scale_(0.f),
70 raster_device_scale_(0.f),
71 raster_source_scale_(0.f),
72 raster_contents_scale_(0.f),
73 low_res_raster_contents_scale_(0.f),
74 raster_source_scale_is_fixed_(false),
75 was_screen_space_transform_animating_(false),
76 needs_post_commit_initialization_(true),
77 should_update_tile_priorities_(false) {
78 layer_tree_impl()->RegisterPictureLayerImpl(this);
81 PictureLayerImpl::~PictureLayerImpl() {
82 layer_tree_impl()->UnregisterPictureLayerImpl(this);
85 const char* PictureLayerImpl::LayerTypeAsString() const {
86 return "cc::PictureLayerImpl";
89 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
90 LayerTreeImpl* tree_impl) {
91 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
94 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
95 // It's possible this layer was never drawn or updated (e.g. because it was
96 // a descendant of an opacity 0 layer).
97 DoPostCommitInitializationIfNeeded();
98 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
100 // We have already synced the important bits from the the active layer, and
101 // we will soon swap out its tilings and use them for recycling. However,
102 // there are now tiles in this layer's tilings that were unref'd and replaced
103 // with new tiles (due to invalidation). This resets all active priorities on
104 // the to-be-recycled tiling to ensure replaced tiles don't linger and take
105 // memory (due to a stale 'active' priority).
106 if (layer_impl->tilings_)
107 layer_impl->tilings_->DidBecomeRecycled();
109 LayerImpl::PushPropertiesTo(base_layer);
111 // When the pending tree pushes to the active tree, the pending twin
112 // disappears.
113 layer_impl->twin_layer_ = NULL;
114 twin_layer_ = NULL;
116 layer_impl->SetIsMask(is_mask_);
117 layer_impl->pile_ = pile_;
119 // Tilings would be expensive to push, so we swap.
120 layer_impl->tilings_.swap(tilings_);
122 // Remove invalidated tiles from what will become a recycle tree.
123 if (tilings_)
124 tilings_->RemoveTilesInRegion(invalidation_);
126 layer_impl->tilings_->SetClient(layer_impl);
127 if (tilings_)
128 tilings_->SetClient(this);
130 layer_impl->raster_page_scale_ = raster_page_scale_;
131 layer_impl->raster_device_scale_ = raster_device_scale_;
132 layer_impl->raster_source_scale_ = raster_source_scale_;
133 layer_impl->raster_contents_scale_ = raster_contents_scale_;
134 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
135 layer_impl->needs_post_commit_initialization_ = false;
137 // The invalidation on this soon-to-be-recycled layer must be cleared to
138 // mirror clearing the invalidation in PictureLayer's version of this function
139 // in case push properties is skipped.
140 layer_impl->invalidation_.Swap(&invalidation_);
141 invalidation_.Clear();
142 needs_post_commit_initialization_ = true;
144 // We always need to push properties.
145 // See http://crbug.com/303943
146 needs_push_properties_ = true;
149 void PictureLayerImpl::AppendQuads(
150 RenderPass* render_pass,
151 const OcclusionTracker<LayerImpl>& occlusion_tracker,
152 AppendQuadsData* append_quads_data) {
153 DCHECK(!needs_post_commit_initialization_);
155 float max_contents_scale = MaximumTilingContentsScale();
156 gfx::Transform scaled_draw_transform = draw_transform();
157 scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
158 SK_MScalar1 / max_contents_scale);
159 gfx::Size scaled_content_bounds =
160 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale));
162 gfx::Rect scaled_visible_content_rect =
163 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale);
164 scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
166 SharedQuadState* shared_quad_state =
167 render_pass->CreateAndAppendSharedQuadState();
168 shared_quad_state->SetAll(scaled_draw_transform,
169 scaled_content_bounds,
170 scaled_visible_content_rect,
171 draw_properties().clip_rect,
172 draw_properties().is_clipped,
173 draw_properties().opacity,
174 blend_mode(),
175 sorting_context_id_);
177 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
178 AppendDebugBorderQuad(
179 render_pass,
180 scaled_content_bounds,
181 shared_quad_state,
182 append_quads_data,
183 DebugColors::DirectPictureBorderColor(),
184 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
186 gfx::Rect geometry_rect = scaled_visible_content_rect;
187 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
188 gfx::Rect visible_geometry_rect = occlusion_tracker.UnoccludedContentRect(
189 geometry_rect, scaled_draw_transform);
190 if (visible_geometry_rect.IsEmpty())
191 return;
193 gfx::Size texture_size = scaled_visible_content_rect.size();
194 gfx::RectF texture_rect = gfx::RectF(texture_size);
195 gfx::Rect quad_content_rect = scaled_visible_content_rect;
197 PictureDrawQuad* quad =
198 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
199 quad->SetNew(shared_quad_state,
200 geometry_rect,
201 opaque_rect,
202 visible_geometry_rect,
203 texture_rect,
204 texture_size,
205 RGBA_8888,
206 quad_content_rect,
207 max_contents_scale,
208 pile_);
209 return;
212 AppendDebugBorderQuad(
213 render_pass, scaled_content_bounds, shared_quad_state, append_quads_data);
215 if (ShowDebugBorders()) {
216 for (PictureLayerTilingSet::CoverageIterator iter(
217 tilings_.get(),
218 max_contents_scale,
219 scaled_visible_content_rect,
220 ideal_contents_scale_);
221 iter;
222 ++iter) {
223 SkColor color;
224 float width;
225 if (*iter && iter->IsReadyToDraw()) {
226 ManagedTileState::TileVersion::Mode mode =
227 iter->GetTileVersionForDrawing().mode();
228 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) {
229 color = DebugColors::SolidColorTileBorderColor();
230 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
231 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) {
232 color = DebugColors::PictureTileBorderColor();
233 width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
234 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
235 color = DebugColors::HighResTileBorderColor();
236 width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
237 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
238 color = DebugColors::LowResTileBorderColor();
239 width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
240 } else if (iter->contents_scale() > max_contents_scale) {
241 color = DebugColors::ExtraHighResTileBorderColor();
242 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
243 } else {
244 color = DebugColors::ExtraLowResTileBorderColor();
245 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
247 } else {
248 color = DebugColors::MissingTileBorderColor();
249 width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
252 DebugBorderDrawQuad* debug_border_quad =
253 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
254 gfx::Rect geometry_rect = iter.geometry_rect();
255 gfx::Rect visible_geometry_rect = geometry_rect;
256 debug_border_quad->SetNew(shared_quad_state,
257 geometry_rect,
258 visible_geometry_rect,
259 color,
260 width);
264 // Keep track of the tilings that were used so that tilings that are
265 // unused can be considered for removal.
266 std::vector<PictureLayerTiling*> seen_tilings;
268 // Ignore missing tiles outside of viewport for tile priority. This is
269 // normally the same as draw viewport but can be independently overridden by
270 // embedders like Android WebView with SetExternalDrawConstraints.
271 gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect(
272 GetViewportForTilePriorityInContentSpace(), max_contents_scale);
274 size_t missing_tile_count = 0u;
275 size_t on_demand_missing_tile_count = 0u;
276 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
277 max_contents_scale,
278 scaled_visible_content_rect,
279 ideal_contents_scale_);
280 iter;
281 ++iter) {
282 gfx::Rect geometry_rect = iter.geometry_rect();
283 gfx::Rect visible_geometry_rect = occlusion_tracker.UnoccludedContentRect(
284 geometry_rect, scaled_draw_transform);
285 if (visible_geometry_rect.IsEmpty())
286 continue;
288 append_quads_data->visible_content_area +=
289 visible_geometry_rect.width() * visible_geometry_rect.height();
291 bool has_draw_quad = false;
292 if (*iter && iter->IsReadyToDraw()) {
293 const ManagedTileState::TileVersion& tile_version =
294 iter->GetTileVersionForDrawing();
295 switch (tile_version.mode()) {
296 case ManagedTileState::TileVersion::RESOURCE_MODE: {
297 gfx::RectF texture_rect = iter.texture_rect();
298 gfx::Rect opaque_rect = iter->opaque_rect();
299 opaque_rect.Intersect(geometry_rect);
301 if (iter->contents_scale() != ideal_contents_scale_ &&
302 geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
303 append_quads_data->num_incomplete_tiles++;
306 TileDrawQuad* quad =
307 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
308 quad->SetNew(shared_quad_state,
309 geometry_rect,
310 opaque_rect,
311 visible_geometry_rect,
312 tile_version.get_resource_id(),
313 texture_rect,
314 iter.texture_size(),
315 tile_version.contents_swizzled());
316 has_draw_quad = true;
317 break;
319 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
320 if (!layer_tree_impl()
321 ->GetRendererCapabilities()
322 .allow_rasterize_on_demand) {
323 ++on_demand_missing_tile_count;
324 break;
327 gfx::RectF texture_rect = iter.texture_rect();
328 gfx::Rect opaque_rect = iter->opaque_rect();
329 opaque_rect.Intersect(geometry_rect);
331 ResourceProvider* resource_provider =
332 layer_tree_impl()->resource_provider();
333 ResourceFormat format =
334 resource_provider->memory_efficient_texture_format();
335 PictureDrawQuad* quad =
336 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
337 quad->SetNew(shared_quad_state,
338 geometry_rect,
339 opaque_rect,
340 visible_geometry_rect,
341 texture_rect,
342 iter.texture_size(),
343 format,
344 iter->content_rect(),
345 iter->contents_scale(),
346 pile_);
347 has_draw_quad = true;
348 break;
350 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: {
351 SolidColorDrawQuad* quad =
352 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
353 quad->SetNew(shared_quad_state,
354 geometry_rect,
355 visible_geometry_rect,
356 tile_version.get_solid_color(),
357 false);
358 has_draw_quad = true;
359 break;
364 if (!has_draw_quad) {
365 if (draw_checkerboard_for_missing_tiles()) {
366 CheckerboardDrawQuad* quad =
367 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
368 SkColor color = DebugColors::DefaultCheckerboardColor();
369 quad->SetNew(
370 shared_quad_state, geometry_rect, visible_geometry_rect, color);
371 } else {
372 SkColor color = SafeOpaqueBackgroundColor();
373 SolidColorDrawQuad* quad =
374 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
375 quad->SetNew(shared_quad_state,
376 geometry_rect,
377 visible_geometry_rect,
378 color,
379 false);
382 if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
383 append_quads_data->num_missing_tiles++;
384 ++missing_tile_count;
386 append_quads_data->approximated_visible_content_area +=
387 visible_geometry_rect.width() * visible_geometry_rect.height();
388 continue;
391 if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) {
392 append_quads_data->approximated_visible_content_area +=
393 visible_geometry_rect.width() * visible_geometry_rect.height();
396 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
397 seen_tilings.push_back(iter.CurrentTiling());
400 if (missing_tile_count) {
401 TRACE_EVENT_INSTANT2("cc",
402 "PictureLayerImpl::AppendQuads checkerboard",
403 TRACE_EVENT_SCOPE_THREAD,
404 "missing_tile_count",
405 missing_tile_count,
406 "on_demand_missing_tile_count",
407 on_demand_missing_tile_count);
410 // Aggressively remove any tilings that are not seen to save memory. Note
411 // that this is at the expense of doing cause more frequent re-painting. A
412 // better scheme would be to maintain a tighter visible_content_rect for the
413 // finer tilings.
414 CleanUpTilingsOnActiveLayer(seen_tilings);
417 void PictureLayerImpl::UpdateTiles(
418 const OcclusionTracker<LayerImpl>* occlusion_tracker) {
419 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
421 DoPostCommitInitializationIfNeeded();
423 // TODO(danakj): We should always get an occlusion tracker when we are using
424 // occlusion, so update this check when we don't use a pending tree in the
425 // browser compositor.
426 DCHECK(!occlusion_tracker ||
427 layer_tree_impl()->settings().use_occlusion_for_tile_prioritization);
429 // Transforms and viewport are invalid for tile management inside a
430 // resourceless software draw, so don't update them.
431 if (!layer_tree_impl()->resourceless_software_draw()) {
432 visible_rect_for_tile_priority_ = visible_content_rect();
433 viewport_rect_for_tile_priority_ =
434 layer_tree_impl()->ViewportRectForTilePriority();
435 screen_space_transform_for_tile_priority_ = screen_space_transform();
438 if (!CanHaveTilings()) {
439 ideal_page_scale_ = 0.f;
440 ideal_device_scale_ = 0.f;
441 ideal_contents_scale_ = 0.f;
442 ideal_source_scale_ = 0.f;
443 SanityCheckTilingState();
444 return;
447 UpdateIdealScales();
449 DCHECK(tilings_->num_tilings() > 0 || raster_contents_scale_ == 0.f)
450 << "A layer with no tilings shouldn't have valid raster scales";
451 if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
452 RecalculateRasterScales();
453 AddTilingsForRasterScale();
456 DCHECK(raster_page_scale_);
457 DCHECK(raster_device_scale_);
458 DCHECK(raster_source_scale_);
459 DCHECK(raster_contents_scale_);
460 DCHECK(low_res_raster_contents_scale_);
462 was_screen_space_transform_animating_ =
463 draw_properties().screen_space_transform_is_animating;
465 should_update_tile_priorities_ = true;
467 UpdateTilePriorities(occlusion_tracker);
469 if (layer_tree_impl()->IsPendingTree())
470 MarkVisibleResourcesAsRequired();
473 void PictureLayerImpl::UpdateTilePriorities(
474 const OcclusionTracker<LayerImpl>* occlusion_tracker) {
475 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
477 double current_frame_time_in_seconds =
478 (layer_tree_impl()->CurrentBeginFrameArgs().frame_time -
479 base::TimeTicks()).InSecondsF();
481 bool tiling_needs_update = false;
482 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
483 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime(
484 current_frame_time_in_seconds)) {
485 tiling_needs_update = true;
486 break;
489 if (!tiling_needs_update)
490 return;
492 gfx::Rect visible_rect_in_content_space(
493 GetViewportForTilePriorityInContentSpace());
494 visible_rect_in_content_space.Intersect(visible_content_rect());
495 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
496 visible_rect_in_content_space, 1.f / contents_scale_x());
497 WhichTree tree =
498 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
499 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
500 tilings_->tiling_at(i)->UpdateTilePriorities(tree,
501 visible_layer_rect,
502 ideal_contents_scale_,
503 current_frame_time_in_seconds,
504 occlusion_tracker,
505 render_target(),
506 draw_transform());
509 // Tile priorities were modified.
510 layer_tree_impl()->DidModifyTilePriorities();
513 gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
514 // If visible_rect_for_tile_priority_ is empty or
515 // viewport_rect_for_tile_priority_ is set to be different from the device
516 // viewport, try to inverse project the viewport into layer space and use
517 // that. Otherwise just use visible_rect_for_tile_priority_
518 gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_;
520 if (visible_rect_in_content_space.IsEmpty() ||
521 layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority_) {
522 gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
524 if (screen_space_transform_for_tile_priority_.GetInverse(&view_to_layer)) {
525 // Transform from view space to content space.
526 visible_rect_in_content_space =
527 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
528 view_to_layer, viewport_rect_for_tile_priority_));
530 visible_rect_in_content_space.Intersect(gfx::Rect(content_bounds()));
534 return visible_rect_in_content_space;
537 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
538 if (layer_tree_impl()->IsActiveTree()) {
539 gfx::RectF layer_damage_rect =
540 gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale());
541 AddDamageRect(layer_damage_rect);
545 void PictureLayerImpl::DidBecomeActive() {
546 LayerImpl::DidBecomeActive();
547 tilings_->DidBecomeActive();
548 layer_tree_impl()->DidModifyTilePriorities();
551 void PictureLayerImpl::DidBeginTracing() {
552 pile_->DidBeginTracing();
555 void PictureLayerImpl::ReleaseResources() {
556 if (tilings_)
557 RemoveAllTilings();
559 ResetRasterScale();
561 // To avoid an edge case after lost context where the tree is up to date but
562 // the tilings have not been managed, request an update draw properties
563 // to force tilings to get managed.
564 layer_tree_impl()->set_needs_update_draw_properties();
567 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
568 return pile_->GetFlattenedPicture();
571 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
572 const gfx::Rect& content_rect) {
573 if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
574 return scoped_refptr<Tile>();
576 // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as
577 // much savings on memory as we can. However, for some cases like ganesh or
578 // small layers, the amount of time we spend analyzing might not justify
579 // memory savings that we can get.
580 // Bugs: crbug.com/397198, crbug.com/396908
581 int flags = Tile::USE_PICTURE_ANALYSIS;
583 return layer_tree_impl()->tile_manager()->CreateTile(
584 pile_.get(),
585 content_rect.size(),
586 content_rect,
587 contents_opaque() ? content_rect : gfx::Rect(),
588 tiling->contents_scale(),
589 id(),
590 layer_tree_impl()->source_frame_number(),
591 flags);
594 PicturePileImpl* PictureLayerImpl::GetPile() {
595 return pile_.get();
598 const Region* PictureLayerImpl::GetInvalidation() {
599 return &invalidation_;
602 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
603 const PictureLayerTiling* tiling) const {
604 if (!twin_layer_)
605 return NULL;
606 return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale());
609 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
610 return layer_tree_impl()->settings().max_tiles_for_interest_area;
613 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
614 float skewport_target_time_in_frames =
615 layer_tree_impl()->use_gpu_rasterization()
616 ? kGpuSkewportTargetTimeInFrames
617 : kCpuSkewportTargetTimeInFrames;
618 return skewport_target_time_in_frames *
619 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
620 layer_tree_impl()->settings().skewport_target_time_multiplier;
623 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
624 return layer_tree_impl()
625 ->settings()
626 .skewport_extrapolation_limit_in_content_pixels;
629 gfx::Size PictureLayerImpl::CalculateTileSize(
630 const gfx::Size& content_bounds) const {
631 if (is_mask_) {
632 int max_size = layer_tree_impl()->MaxTextureSize();
633 return gfx::Size(
634 std::min(max_size, content_bounds.width()),
635 std::min(max_size, content_bounds.height()));
638 int max_texture_size =
639 layer_tree_impl()->resource_provider()->max_texture_size();
641 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size;
642 if (layer_tree_impl()->use_gpu_rasterization()) {
643 // TODO(ernstm) crbug.com/365877: We need a unified way to override the
644 // default-tile-size.
645 default_tile_size =
646 gfx::Size(layer_tree_impl()->device_viewport_size().width(),
647 layer_tree_impl()->device_viewport_size().height() / 4);
649 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
651 gfx::Size max_untiled_content_size =
652 layer_tree_impl()->settings().max_untiled_layer_size;
653 max_untiled_content_size.SetToMin(
654 gfx::Size(max_texture_size, max_texture_size));
656 bool any_dimension_too_large =
657 content_bounds.width() > max_untiled_content_size.width() ||
658 content_bounds.height() > max_untiled_content_size.height();
660 bool any_dimension_one_tile =
661 content_bounds.width() <= default_tile_size.width() ||
662 content_bounds.height() <= default_tile_size.height();
664 // If long and skinny, tile at the max untiled content size, and clamp
665 // the smaller dimension to the content size, e.g. 1000x12 layer with
666 // 500x500 max untiled size would get 500x12 tiles. Also do this
667 // if the layer is small.
668 if (any_dimension_one_tile || !any_dimension_too_large) {
669 int width = std::min(
670 std::max(max_untiled_content_size.width(), default_tile_size.width()),
671 content_bounds.width());
672 int height = std::min(
673 std::max(max_untiled_content_size.height(), default_tile_size.height()),
674 content_bounds.height());
675 // Round up to the closest multiple of 64. This improves recycling and
676 // avoids odd texture sizes.
677 width = RoundUp(width, 64);
678 height = RoundUp(height, 64);
679 return gfx::Size(width, height);
682 return default_tile_size;
685 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
686 TRACE_EVENT0("cc", "SyncFromActiveLayer");
687 DCHECK(!other->needs_post_commit_initialization_);
688 DCHECK(other->tilings_);
690 if (!DrawsContent()) {
691 RemoveAllTilings();
692 return;
695 raster_page_scale_ = other->raster_page_scale_;
696 raster_device_scale_ = other->raster_device_scale_;
697 raster_source_scale_ = other->raster_source_scale_;
698 raster_contents_scale_ = other->raster_contents_scale_;
699 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
701 bool synced_high_res_tiling = false;
702 if (CanHaveTilings()) {
703 synced_high_res_tiling = tilings_->SyncTilings(
704 *other->tilings_, bounds(), invalidation_, MinimumContentsScale());
705 } else {
706 RemoveAllTilings();
709 // If our MinimumContentsScale has changed to prevent the twin's high res
710 // tiling from being synced, we should reset the raster scale and let it be
711 // recalculated (1) again. This can happen if our bounds shrink to the point
712 // where min contents scale grows.
713 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
714 // should refactor this code a little bit and actually recalculate this.
715 // However, this is a larger undertaking, so this will work for now.
716 if (!synced_high_res_tiling)
717 ResetRasterScale();
718 else
719 SanityCheckTilingState();
722 void PictureLayerImpl::SyncTiling(
723 const PictureLayerTiling* tiling) {
724 if (!CanHaveTilingWithScale(tiling->contents_scale()))
725 return;
726 tilings_->AddTiling(tiling->contents_scale());
728 // If this tree needs update draw properties, then the tiling will
729 // get updated prior to drawing or activation. If this tree does not
730 // need update draw properties, then its transforms are up to date and
731 // we can create tiles for this tiling immediately.
732 if (!layer_tree_impl()->needs_update_draw_properties() &&
733 should_update_tile_priorities_) {
734 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
735 // when we stop using the pending tree in the browser compositor. If we want
736 // to support occlusion tracking here, we need to dirty the draw properties
737 // or save occlusion as a draw property.
738 UpdateTilePriorities(NULL);
742 void PictureLayerImpl::SetIsMask(bool is_mask) {
743 if (is_mask_ == is_mask)
744 return;
745 is_mask_ = is_mask;
746 if (tilings_)
747 tilings_->RemoveAllTiles();
750 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
751 gfx::Rect content_rect(content_bounds());
752 float scale = MaximumTilingContentsScale();
753 PictureLayerTilingSet::CoverageIterator iter(
754 tilings_.get(), scale, content_rect, ideal_contents_scale_);
756 // Mask resource not ready yet.
757 if (!iter || !*iter)
758 return 0;
760 // Masks only supported if they fit on exactly one tile.
761 if (iter.geometry_rect() != content_rect)
762 return 0;
764 const ManagedTileState::TileVersion& tile_version =
765 iter->GetTileVersionForDrawing();
766 if (!tile_version.IsReadyToDraw() ||
767 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE)
768 return 0;
770 return tile_version.get_resource_id();
773 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
774 DCHECK(layer_tree_impl()->IsPendingTree());
775 DCHECK(ideal_contents_scale_);
776 DCHECK_GT(tilings_->num_tilings(), 0u);
778 // The goal of this function is to find the minimum set of tiles that need to
779 // be ready to draw in order to activate without flashing content from a
780 // higher res on the active tree to a lower res on the pending tree.
782 // First, early out for layers with no visible content.
783 if (visible_content_rect().IsEmpty())
784 return;
786 gfx::Rect rect(visible_content_rect());
788 // Only mark tiles inside the viewport for tile priority as required for
789 // activation. This viewport is normally the same as the draw viewport but
790 // can be independently overridden by embedders like Android WebView with
791 // SetExternalDrawConstraints.
792 rect.Intersect(GetViewportForTilePriorityInContentSpace());
794 float min_acceptable_scale =
795 std::min(raster_contents_scale_, ideal_contents_scale_);
797 if (PictureLayerImpl* twin = twin_layer_) {
798 float twin_min_acceptable_scale =
799 std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_);
800 // Ignore 0 scale in case CalculateContentsScale() has never been
801 // called for active twin.
802 if (twin_min_acceptable_scale != 0.0f) {
803 min_acceptable_scale =
804 std::min(min_acceptable_scale, twin_min_acceptable_scale);
808 PictureLayerTiling* high_res = NULL;
809 PictureLayerTiling* low_res = NULL;
811 // First pass: ready to draw tiles in acceptable but non-ideal tilings are
812 // marked as required for activation so that their textures are not thrown
813 // away; any non-ready tiles are not marked as required.
814 Region missing_region = rect;
815 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
816 PictureLayerTiling* tiling = tilings_->tiling_at(i);
817 DCHECK(tiling->has_ever_been_updated());
819 if (tiling->resolution() == LOW_RESOLUTION) {
820 DCHECK(!low_res) << "There can only be one low res tiling";
821 low_res = tiling;
823 if (tiling->contents_scale() < min_acceptable_scale)
824 continue;
825 if (tiling->resolution() == HIGH_RESOLUTION) {
826 DCHECK(!high_res) << "There can only be one high res tiling";
827 high_res = tiling;
828 continue;
830 for (PictureLayerTiling::CoverageIterator iter(tiling,
831 contents_scale_x(),
832 rect);
833 iter;
834 ++iter) {
835 if (!*iter || !iter->IsReadyToDraw())
836 continue;
838 missing_region.Subtract(iter.geometry_rect());
839 iter->MarkRequiredForActivation();
842 DCHECK(high_res) << "There must be one high res tiling";
844 // If these pointers are null (because no twin, no matching tiling, or the
845 // simpification just below), then high res tiles will be required to fill any
846 // holes left by the first pass above. If the pointers are valid, then this
847 // layer is allowed to skip any tiles that are not ready on its twin.
848 const PictureLayerTiling* twin_high_res = NULL;
849 const PictureLayerTiling* twin_low_res = NULL;
851 if (twin_layer_) {
852 // As a simplification, only allow activating to skip twin tiles that the
853 // active layer is also missing when both this layer and its twin have
854 // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
855 // res tiling. This avoids having to iterate/track coverage of non-ideal
856 // tilings during the last draw call on the active layer.
857 if (tilings_->num_tilings() <= 2 &&
858 twin_layer_->tilings_->num_tilings() <= tilings_->num_tilings()) {
859 twin_low_res = low_res ? GetTwinTiling(low_res) : NULL;
860 twin_high_res = high_res ? GetTwinTiling(high_res) : NULL;
863 // If this layer and its twin have different transforms, then don't compare
864 // them and only allow activating to high res tiles, since tiles on each
865 // layer will be in different places on screen.
866 if (twin_layer_->layer_tree_impl()->RequiresHighResToDraw() ||
867 bounds() != twin_layer_->bounds() ||
868 draw_properties().screen_space_transform !=
869 twin_layer_->draw_properties().screen_space_transform) {
870 twin_high_res = NULL;
871 twin_low_res = NULL;
875 // As a second pass, mark as required any visible high res tiles not filled in
876 // by acceptable non-ideal tiles from the first pass.
877 if (MarkVisibleTilesAsRequired(
878 high_res, twin_high_res, contents_scale_x(), rect, missing_region)) {
879 // As an optional third pass, if a high res tile was skipped because its
880 // twin was also missing, then fall back to mark low res tiles as required
881 // in case the active twin is substituting those for missing high res
882 // content. Only suitable, when low res is enabled.
883 if (low_res) {
884 MarkVisibleTilesAsRequired(
885 low_res, twin_low_res, contents_scale_x(), rect, missing_region);
890 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
891 PictureLayerTiling* tiling,
892 const PictureLayerTiling* optional_twin_tiling,
893 float contents_scale,
894 const gfx::Rect& rect,
895 const Region& missing_region) const {
896 bool twin_had_missing_tile = false;
897 for (PictureLayerTiling::CoverageIterator iter(tiling,
898 contents_scale,
899 rect);
900 iter;
901 ++iter) {
902 Tile* tile = *iter;
903 // A null tile (i.e. missing recording) can just be skipped.
904 if (!tile)
905 continue;
907 // If the tile is occluded, don't mark it as required for activation.
908 if (tile->is_occluded(PENDING_TREE))
909 continue;
911 // If the missing region doesn't cover it, this tile is fully
912 // covered by acceptable tiles at other scales.
913 if (!missing_region.Intersects(iter.geometry_rect()))
914 continue;
916 // If the twin tile doesn't exist (i.e. missing recording or so far away
917 // that it is outside the visible tile rect) or this tile is shared between
918 // with the twin, then this tile isn't required to prevent flashing.
919 if (optional_twin_tiling) {
920 Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
921 if (!twin_tile || twin_tile == tile) {
922 twin_had_missing_tile = true;
923 continue;
927 tile->MarkRequiredForActivation();
929 return twin_had_missing_tile;
932 void PictureLayerImpl::DoPostCommitInitialization() {
933 DCHECK(needs_post_commit_initialization_);
934 DCHECK(layer_tree_impl()->IsPendingTree());
936 if (!tilings_)
937 tilings_.reset(new PictureLayerTilingSet(this, bounds()));
939 DCHECK(!twin_layer_);
940 twin_layer_ = static_cast<PictureLayerImpl*>(
941 layer_tree_impl()->FindActiveTreeLayerById(id()));
942 if (twin_layer_) {
943 DCHECK(!twin_layer_->twin_layer_);
944 twin_layer_->twin_layer_ = this;
945 // If the twin has never been pushed to, do not sync from it.
946 // This can happen if this function is called during activation.
947 if (!twin_layer_->needs_post_commit_initialization_)
948 SyncFromActiveLayer(twin_layer_);
951 needs_post_commit_initialization_ = false;
954 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
955 DCHECK(CanHaveTilingWithScale(contents_scale)) <<
956 "contents_scale: " << contents_scale;
958 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
960 DCHECK(pile_->HasRecordings());
962 if (twin_layer_)
963 twin_layer_->SyncTiling(tiling);
965 return tiling;
968 void PictureLayerImpl::RemoveTiling(float contents_scale) {
969 if (!tilings_ || tilings_->num_tilings() == 0)
970 return;
972 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
973 PictureLayerTiling* tiling = tilings_->tiling_at(i);
974 if (tiling->contents_scale() == contents_scale) {
975 tilings_->Remove(tiling);
976 break;
979 if (tilings_->num_tilings() == 0)
980 ResetRasterScale();
981 SanityCheckTilingState();
984 void PictureLayerImpl::RemoveAllTilings() {
985 if (tilings_)
986 tilings_->RemoveAllTilings();
987 // If there are no tilings, then raster scales are no longer meaningful.
988 ResetRasterScale();
991 namespace {
993 inline float PositiveRatio(float float1, float float2) {
994 DCHECK_GT(float1, 0);
995 DCHECK_GT(float2, 0);
996 return float1 > float2 ? float1 / float2 : float2 / float1;
999 } // namespace
1001 void PictureLayerImpl::AddTilingsForRasterScale() {
1002 PictureLayerTiling* high_res = NULL;
1003 PictureLayerTiling* low_res = NULL;
1005 PictureLayerTiling* previous_low_res = NULL;
1006 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1007 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1008 if (tiling->contents_scale() == raster_contents_scale_)
1009 high_res = tiling;
1010 if (tiling->contents_scale() == low_res_raster_contents_scale_)
1011 low_res = tiling;
1012 if (tiling->resolution() == LOW_RESOLUTION)
1013 previous_low_res = tiling;
1015 // Reset all tilings to non-ideal until the end of this function.
1016 tiling->set_resolution(NON_IDEAL_RESOLUTION);
1019 if (!high_res) {
1020 high_res = AddTiling(raster_contents_scale_);
1021 if (raster_contents_scale_ == low_res_raster_contents_scale_)
1022 low_res = high_res;
1025 // Only create new low res tilings when the transform is static. This
1026 // prevents wastefully creating a paired low res tiling for every new high res
1027 // tiling during a pinch or a CSS animation.
1028 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1029 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching &&
1030 !draw_properties().screen_space_transform_is_animating && !low_res &&
1031 low_res != high_res)
1032 low_res = AddTiling(low_res_raster_contents_scale_);
1034 // Set low-res if we have one.
1035 if (!low_res)
1036 low_res = previous_low_res;
1037 if (low_res && low_res != high_res)
1038 low_res->set_resolution(LOW_RESOLUTION);
1040 // Make sure we always have one high-res (even if high == low).
1041 high_res->set_resolution(HIGH_RESOLUTION);
1043 SanityCheckTilingState();
1046 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1047 if (was_screen_space_transform_animating_ !=
1048 draw_properties().screen_space_transform_is_animating)
1049 return true;
1051 if (draw_properties().screen_space_transform_is_animating &&
1052 raster_contents_scale_ != ideal_contents_scale_ &&
1053 ShouldAdjustRasterScaleDuringScaleAnimations())
1054 return true;
1056 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1057 if (is_pinching && raster_page_scale_) {
1058 // We change our raster scale when it is:
1059 // - Higher than ideal (need a lower-res tiling available)
1060 // - Too far from ideal (need a higher-res tiling available)
1061 float ratio = ideal_page_scale_ / raster_page_scale_;
1062 if (raster_page_scale_ > ideal_page_scale_ ||
1063 ratio > kMaxScaleRatioDuringPinch)
1064 return true;
1067 if (!is_pinching) {
1068 // When not pinching, match the ideal page scale factor.
1069 if (raster_page_scale_ != ideal_page_scale_)
1070 return true;
1073 // Always match the ideal device scale factor.
1074 if (raster_device_scale_ != ideal_device_scale_)
1075 return true;
1077 // When the source scale changes we want to match it, but not when animating
1078 // or when we've fixed the scale in place.
1079 if (!draw_properties().screen_space_transform_is_animating &&
1080 !raster_source_scale_is_fixed_ &&
1081 raster_source_scale_ != ideal_source_scale_)
1082 return true;
1084 return false;
1087 float PictureLayerImpl::SnappedContentsScale(float scale) {
1088 // If a tiling exists within the max snapping ratio, snap to its scale.
1089 float snapped_contents_scale = scale;
1090 float snapped_ratio = kSnapToExistingTilingRatio;
1091 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1092 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
1093 float ratio = PositiveRatio(tiling_contents_scale, scale);
1094 if (ratio < snapped_ratio) {
1095 snapped_contents_scale = tiling_contents_scale;
1096 snapped_ratio = ratio;
1099 return snapped_contents_scale;
1102 void PictureLayerImpl::RecalculateRasterScales() {
1103 float old_raster_contents_scale = raster_contents_scale_;
1104 float old_raster_page_scale = raster_page_scale_;
1105 float old_raster_source_scale = raster_source_scale_;
1107 raster_device_scale_ = ideal_device_scale_;
1108 raster_page_scale_ = ideal_page_scale_;
1109 raster_source_scale_ = ideal_source_scale_;
1110 raster_contents_scale_ = ideal_contents_scale_;
1112 // If we're not animating, or leaving an animation, and the
1113 // ideal_source_scale_ changes, then things are unpredictable, and we fix
1114 // the raster_source_scale_ in place.
1115 if (old_raster_source_scale &&
1116 !draw_properties().screen_space_transform_is_animating &&
1117 !was_screen_space_transform_animating_ &&
1118 old_raster_source_scale != ideal_source_scale_)
1119 raster_source_scale_is_fixed_ = true;
1121 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1122 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1123 // tree. This will allow CSS scale changes to get re-rastered at an
1124 // appropriate rate.
1125 if (raster_source_scale_is_fixed_) {
1126 raster_contents_scale_ /= raster_source_scale_;
1127 raster_source_scale_ = 1.f;
1130 // During pinch we completely ignore the current ideal scale, and just use
1131 // a multiple of the previous scale.
1132 // TODO(danakj): This seems crazy, we should use the current ideal, no?
1133 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1134 if (is_pinching && old_raster_contents_scale) {
1135 // See ShouldAdjustRasterScale:
1136 // - When zooming out, preemptively create new tiling at lower resolution.
1137 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1138 bool zooming_out = old_raster_page_scale > ideal_page_scale_;
1139 float desired_contents_scale =
1140 zooming_out ? old_raster_contents_scale / kMaxScaleRatioDuringPinch
1141 : old_raster_contents_scale * kMaxScaleRatioDuringPinch;
1142 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
1143 raster_page_scale_ =
1144 raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
1147 raster_contents_scale_ =
1148 std::max(raster_contents_scale_, MinimumContentsScale());
1150 // If we're not re-rasterizing during animation, rasterize at the maximum
1151 // scale that will occur during the animation, if the maximum scale is
1152 // known. However, to avoid excessive memory use, don't rasterize at a scale
1153 // at which this layer would become larger than the viewport.
1154 if (draw_properties().screen_space_transform_is_animating &&
1155 !ShouldAdjustRasterScaleDuringScaleAnimations()) {
1156 bool can_raster_at_maximum_scale = false;
1157 if (draw_properties().maximum_animation_contents_scale > 0.f) {
1158 gfx::Size bounds_at_maximum_scale = gfx::ToCeiledSize(gfx::ScaleSize(
1159 bounds(), draw_properties().maximum_animation_contents_scale));
1160 if (bounds_at_maximum_scale.GetArea() <=
1161 layer_tree_impl()->device_viewport_size().GetArea())
1162 can_raster_at_maximum_scale = true;
1164 if (can_raster_at_maximum_scale) {
1165 raster_contents_scale_ =
1166 std::max(raster_contents_scale_,
1167 draw_properties().maximum_animation_contents_scale);
1168 } else {
1169 raster_contents_scale_ =
1170 std::max(raster_contents_scale_,
1171 1.f * ideal_page_scale_ * ideal_device_scale_);
1175 // If this layer would only create one tile at this content scale,
1176 // don't create a low res tiling.
1177 gfx::Size content_bounds =
1178 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
1179 gfx::Size tile_size = CalculateTileSize(content_bounds);
1180 if (tile_size.width() >= content_bounds.width() &&
1181 tile_size.height() >= content_bounds.height()) {
1182 low_res_raster_contents_scale_ = raster_contents_scale_;
1183 return;
1186 float low_res_factor =
1187 layer_tree_impl()->settings().low_res_contents_scale_factor;
1188 low_res_raster_contents_scale_ = std::max(
1189 raster_contents_scale_ * low_res_factor,
1190 MinimumContentsScale());
1193 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1194 std::vector<PictureLayerTiling*> used_tilings) {
1195 DCHECK(layer_tree_impl()->IsActiveTree());
1196 if (tilings_->num_tilings() == 0)
1197 return;
1199 float min_acceptable_high_res_scale = std::min(
1200 raster_contents_scale_, ideal_contents_scale_);
1201 float max_acceptable_high_res_scale = std::max(
1202 raster_contents_scale_, ideal_contents_scale_);
1203 float twin_low_res_scale = 0.f;
1205 PictureLayerImpl* twin = twin_layer_;
1206 if (twin && twin->CanHaveTilings()) {
1207 min_acceptable_high_res_scale = std::min(
1208 min_acceptable_high_res_scale,
1209 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1210 max_acceptable_high_res_scale = std::max(
1211 max_acceptable_high_res_scale,
1212 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1214 for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
1215 PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
1216 if (tiling->resolution() == LOW_RESOLUTION)
1217 twin_low_res_scale = tiling->contents_scale();
1221 std::vector<PictureLayerTiling*> to_remove;
1222 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1223 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1225 // Keep multiple high resolution tilings even if not used to help
1226 // activate earlier at non-ideal resolutions.
1227 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
1228 tiling->contents_scale() <= max_acceptable_high_res_scale)
1229 continue;
1231 // Keep low resolution tilings, if the layer should have them.
1232 if (layer_tree_impl()->create_low_res_tiling()) {
1233 if (tiling->resolution() == LOW_RESOLUTION ||
1234 tiling->contents_scale() == twin_low_res_scale)
1235 continue;
1238 // Don't remove tilings that are being used (and thus would cause a flash.)
1239 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
1240 used_tilings.end())
1241 continue;
1243 to_remove.push_back(tiling);
1246 if (to_remove.empty())
1247 return;
1249 PictureLayerImpl* recycled_twin = static_cast<PictureLayerImpl*>(
1250 layer_tree_impl()->FindRecycleTreeLayerById(id()));
1251 // Remove tilings on this tree and the twin tree.
1252 for (size_t i = 0; i < to_remove.size(); ++i) {
1253 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
1254 // Only remove tilings from the twin layer if they have
1255 // NON_IDEAL_RESOLUTION.
1256 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
1257 twin->RemoveTiling(to_remove[i]->contents_scale());
1258 // Remove the tiling from the recycle tree. Note that we ignore resolution,
1259 // since we don't need to maintain high/low res on the recycle tree.
1260 if (recycled_twin)
1261 recycled_twin->RemoveTiling(to_remove[i]->contents_scale());
1262 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1263 CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution());
1264 tilings_->Remove(to_remove[i]);
1267 DCHECK_GT(tilings_->num_tilings(), 0u);
1268 SanityCheckTilingState();
1271 float PictureLayerImpl::MinimumContentsScale() const {
1272 float setting_min = layer_tree_impl()->settings().minimum_contents_scale;
1274 // If the contents scale is less than 1 / width (also for height),
1275 // then it will end up having less than one pixel of content in that
1276 // dimension. Bump the minimum contents scale up in this case to prevent
1277 // this from happening.
1278 int min_dimension = std::min(bounds().width(), bounds().height());
1279 if (!min_dimension)
1280 return setting_min;
1282 return std::max(1.f / min_dimension, setting_min);
1285 void PictureLayerImpl::ResetRasterScale() {
1286 raster_page_scale_ = 0.f;
1287 raster_device_scale_ = 0.f;
1288 raster_source_scale_ = 0.f;
1289 raster_contents_scale_ = 0.f;
1290 low_res_raster_contents_scale_ = 0.f;
1291 raster_source_scale_is_fixed_ = false;
1293 // When raster scales aren't valid, don't update tile priorities until
1294 // this layer has been updated via UpdateDrawProperties.
1295 should_update_tile_priorities_ = false;
1298 bool PictureLayerImpl::CanHaveTilings() const {
1299 if (!DrawsContent())
1300 return false;
1301 if (!pile_->HasRecordings())
1302 return false;
1303 return true;
1306 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const {
1307 if (!CanHaveTilings())
1308 return false;
1309 if (contents_scale < MinimumContentsScale())
1310 return false;
1311 return true;
1314 void PictureLayerImpl::SanityCheckTilingState() const {
1315 #if DCHECK_IS_ON
1316 // Recycle tree doesn't have any restrictions.
1317 if (layer_tree_impl()->IsRecycleTree())
1318 return;
1320 if (!CanHaveTilings()) {
1321 DCHECK_EQ(0u, tilings_->num_tilings());
1322 return;
1324 if (tilings_->num_tilings() == 0)
1325 return;
1327 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1328 // tiling to mark its tiles as being required for activation.
1329 DCHECK_EQ(1, tilings_->NumHighResTilings());
1330 #endif
1333 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const {
1334 if (!layer_tree_impl()->use_gpu_rasterization())
1335 return false;
1337 // Re-rastering text at different scales using GPU rasterization causes
1338 // texture uploads for glyphs at each scale (see crbug.com/366225). To
1339 // workaround this performance issue, we don't re-rasterize layers with
1340 // text during scale animations.
1341 // TODO(ajuma): Remove this workaround once text can be efficiently
1342 // re-rastered at different scales (e.g. by using distance-field fonts).
1343 if (pile_->has_text())
1344 return false;
1346 return true;
1349 float PictureLayerImpl::MaximumTilingContentsScale() const {
1350 float max_contents_scale = MinimumContentsScale();
1351 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1352 const PictureLayerTiling* tiling = tilings_->tiling_at(i);
1353 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
1355 return max_contents_scale;
1358 void PictureLayerImpl::UpdateIdealScales() {
1359 DCHECK(CanHaveTilings());
1361 float min_contents_scale = MinimumContentsScale();
1362 DCHECK_GT(min_contents_scale, 0.f);
1363 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
1364 DCHECK_GT(min_page_scale, 0.f);
1365 float min_device_scale = 1.f;
1366 float min_source_scale =
1367 min_contents_scale / min_page_scale / min_device_scale;
1369 float ideal_page_scale = draw_properties().page_scale_factor;
1370 float ideal_device_scale = draw_properties().device_scale_factor;
1371 float ideal_source_scale = draw_properties().ideal_contents_scale /
1372 ideal_page_scale / ideal_device_scale;
1373 ideal_contents_scale_ =
1374 std::max(draw_properties().ideal_contents_scale, min_contents_scale);
1375 ideal_page_scale_ = draw_properties().page_scale_factor;
1376 ideal_device_scale_ = draw_properties().device_scale_factor;
1377 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
1380 void PictureLayerImpl::GetDebugBorderProperties(
1381 SkColor* color,
1382 float* width) const {
1383 *color = DebugColors::TiledContentLayerBorderColor();
1384 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1387 void PictureLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
1388 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1389 LayerImpl::AsValueInto(state);
1390 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1391 state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1392 state->BeginArray("tilings");
1393 tilings_->AsValueInto(state);
1394 state->EndArray();
1396 state->BeginArray("pictures");
1397 pile_->AsValueInto(state);
1398 state->EndArray();
1400 state->BeginArray("invalidation");
1401 invalidation_.AsValueInto(state);
1402 state->EndArray();
1404 state->BeginArray("coverage_tiles");
1405 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
1406 contents_scale_x(),
1407 gfx::Rect(content_bounds()),
1408 ideal_contents_scale_);
1409 iter;
1410 ++iter) {
1411 state->BeginDictionary();
1413 state->BeginArray("geometry_rect");
1414 MathUtil::AddToTracedValue(iter.geometry_rect(), state);
1415 state->EndArray();
1417 if (*iter)
1418 TracedValue::SetIDRef(*iter, state, "tile");
1420 state->EndDictionary();
1422 state->EndArray();
1425 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1426 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1427 return tilings_->GPUMemoryUsageInBytes();
1430 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1431 benchmark->RunOnLayer(this);
1434 WhichTree PictureLayerImpl::GetTree() const {
1435 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1438 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1439 return !layer_tree_impl()->IsRecycleTree();
1442 bool PictureLayerImpl::HasValidTilePriorities() const {
1443 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1446 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1447 if (!layer_tree_impl()->IsPendingTree())
1448 return true;
1450 if (!HasValidTilePriorities())
1451 return true;
1453 if (!tilings_)
1454 return true;
1456 if (visible_content_rect().IsEmpty())
1457 return true;
1459 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1460 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1461 if (tiling->resolution() != HIGH_RESOLUTION &&
1462 tiling->resolution() != LOW_RESOLUTION)
1463 continue;
1465 gfx::Rect rect(visible_content_rect());
1466 for (PictureLayerTiling::CoverageIterator iter(
1467 tiling, contents_scale_x(), rect);
1468 iter;
1469 ++iter) {
1470 const Tile* tile = *iter;
1471 // A null tile (i.e. missing recording) can just be skipped.
1472 if (!tile)
1473 continue;
1475 if (tile->required_for_activation() && !tile->IsReadyToDraw())
1476 return false;
1480 return true;
1483 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1484 : layer_(NULL), current_stage_(arraysize(stages_)) {
1487 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1488 PictureLayerImpl* layer,
1489 bool prioritize_low_res)
1490 : layer_(layer), current_stage_(0) {
1491 DCHECK(layer_);
1493 // Early out if the layer has no tilings.
1494 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) {
1495 current_stage_ = arraysize(stages_);
1496 return;
1499 // Tiles without valid priority are treated as having lowest priority and
1500 // never considered for raster.
1501 if (!layer_->HasValidTilePriorities()) {
1502 current_stage_ = arraysize(stages_);
1503 return;
1506 WhichTree tree = layer_->GetTree();
1508 // Find high and low res tilings and initialize the iterators.
1509 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1510 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1511 if (tiling->resolution() == HIGH_RESOLUTION) {
1512 iterators_[HIGH_RES] =
1513 PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1516 if (tiling->resolution() == LOW_RESOLUTION) {
1517 iterators_[LOW_RES] =
1518 PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1522 if (prioritize_low_res) {
1523 stages_[0].iterator_type = LOW_RES;
1524 stages_[0].tile_type = TilePriority::NOW;
1526 stages_[1].iterator_type = HIGH_RES;
1527 stages_[1].tile_type = TilePriority::NOW;
1528 } else {
1529 stages_[0].iterator_type = HIGH_RES;
1530 stages_[0].tile_type = TilePriority::NOW;
1532 stages_[1].iterator_type = LOW_RES;
1533 stages_[1].tile_type = TilePriority::NOW;
1536 stages_[2].iterator_type = HIGH_RES;
1537 stages_[2].tile_type = TilePriority::SOON;
1539 stages_[3].iterator_type = HIGH_RES;
1540 stages_[3].tile_type = TilePriority::EVENTUALLY;
1542 IteratorType index = stages_[current_stage_].iterator_type;
1543 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1544 if (!iterators_[index] || iterators_[index].get_type() != tile_type)
1545 ++(*this);
1548 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1550 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1551 return current_stage_ < arraysize(stages_);
1554 PictureLayerImpl::LayerRasterTileIterator&
1555 PictureLayerImpl::LayerRasterTileIterator::
1556 operator++() {
1557 IteratorType index = stages_[current_stage_].iterator_type;
1558 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1560 // First advance the iterator.
1561 if (iterators_[index])
1562 ++iterators_[index];
1564 if (iterators_[index] && iterators_[index].get_type() == tile_type)
1565 return *this;
1567 // Next, advance the stage.
1568 ++current_stage_;
1569 while (current_stage_ < arraysize(stages_)) {
1570 index = stages_[current_stage_].iterator_type;
1571 tile_type = stages_[current_stage_].tile_type;
1573 if (iterators_[index] && iterators_[index].get_type() == tile_type)
1574 break;
1575 ++current_stage_;
1577 return *this;
1580 Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1581 DCHECK(*this);
1583 IteratorType index = stages_[current_stage_].iterator_type;
1584 DCHECK(iterators_[index]);
1585 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1587 return *iterators_[index];
1590 const Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() const {
1591 DCHECK(*this);
1593 IteratorType index = stages_[current_stage_].iterator_type;
1594 DCHECK(iterators_[index]);
1595 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1597 return *iterators_[index];
1600 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1601 : layer_(NULL),
1602 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES),
1603 current_category_(PictureLayerTiling::EVENTUALLY),
1604 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
1605 current_tiling_(0u) {
1608 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1609 PictureLayerImpl* layer,
1610 TreePriority tree_priority)
1611 : layer_(layer),
1612 tree_priority_(tree_priority),
1613 current_category_(PictureLayerTiling::EVENTUALLY),
1614 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES),
1615 current_tiling_(CurrentTilingRange().start - 1u) {
1616 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1617 // that layers that don't have valid tile priorities have lowest priorities so
1618 // they evict their tiles first (crbug.com/381704)
1619 DCHECK(layer_->tilings_);
1620 do {
1621 if (!AdvanceToNextTiling())
1622 break;
1624 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
1625 layer_->tilings_->tiling_at(CurrentTilingIndex()),
1626 tree_priority,
1627 current_category_);
1628 } while (!current_iterator_);
1631 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {
1634 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1635 DCHECK(*this);
1636 return *current_iterator_;
1639 const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const {
1640 DCHECK(*this);
1641 return *current_iterator_;
1644 PictureLayerImpl::LayerEvictionTileIterator&
1645 PictureLayerImpl::LayerEvictionTileIterator::
1646 operator++() {
1647 DCHECK(*this);
1648 ++current_iterator_;
1649 while (!current_iterator_) {
1650 if (!AdvanceToNextTiling())
1651 break;
1653 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator(
1654 layer_->tilings_->tiling_at(CurrentTilingIndex()),
1655 tree_priority_,
1656 current_category_);
1658 return *this;
1661 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1662 return !!current_iterator_;
1665 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() {
1666 switch (current_category_) {
1667 case PictureLayerTiling::EVENTUALLY:
1668 current_category_ =
1669 PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION;
1670 return true;
1671 case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION:
1672 current_category_ = PictureLayerTiling::SOON;
1673 return true;
1674 case PictureLayerTiling::SOON:
1675 current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION;
1676 return true;
1677 case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION:
1678 current_category_ = PictureLayerTiling::NOW;
1679 return true;
1680 case PictureLayerTiling::NOW:
1681 current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION;
1682 return true;
1683 case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION:
1684 return false;
1686 NOTREACHED();
1687 return false;
1690 bool
1691 PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() {
1692 switch (current_tiling_range_type_) {
1693 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
1694 current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES;
1695 return true;
1696 case PictureLayerTilingSet::LOWER_THAN_LOW_RES:
1697 current_tiling_range_type_ =
1698 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES;
1699 return true;
1700 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
1701 current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES;
1702 return true;
1703 case PictureLayerTilingSet::LOW_RES:
1704 current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES;
1705 return true;
1706 case PictureLayerTilingSet::HIGH_RES:
1707 if (!AdvanceToNextCategory())
1708 return false;
1710 current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES;
1711 return true;
1713 NOTREACHED();
1714 return false;
1717 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() {
1718 DCHECK_NE(current_tiling_, CurrentTilingRange().end);
1719 ++current_tiling_;
1720 while (current_tiling_ == CurrentTilingRange().end) {
1721 if (!AdvanceToNextTilingRangeType())
1722 return false;
1724 current_tiling_ = CurrentTilingRange().start;
1726 return true;
1729 PictureLayerTilingSet::TilingRange
1730 PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const {
1731 return layer_->tilings_->GetTilingRange(current_tiling_range_type_);
1734 size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const {
1735 DCHECK_NE(current_tiling_, CurrentTilingRange().end);
1736 switch (current_tiling_range_type_) {
1737 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES:
1738 case PictureLayerTilingSet::LOW_RES:
1739 case PictureLayerTilingSet::HIGH_RES:
1740 return current_tiling_;
1741 // Tilings in the following ranges are accessed in reverse order.
1742 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES:
1743 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: {
1744 PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange();
1745 size_t current_tiling_range_offset = current_tiling_ - tiling_range.start;
1746 return tiling_range.end - 1 - current_tiling_range_offset;
1749 NOTREACHED();
1750 return 0;
1753 } // namespace cc