Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / cc / layers / picture_layer_impl.cc
blob094cd4f2f08e9eaa6cfdb9733dd281a9b85931d4
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/time/time.h"
11 #include "cc/base/math_util.h"
12 #include "cc/base/util.h"
13 #include "cc/debug/debug_colors.h"
14 #include "cc/debug/micro_benchmark_impl.h"
15 #include "cc/debug/traced_value.h"
16 #include "cc/layers/append_quads_data.h"
17 #include "cc/quads/checkerboard_draw_quad.h"
18 #include "cc/quads/debug_border_draw_quad.h"
19 #include "cc/quads/picture_draw_quad.h"
20 #include "cc/quads/solid_color_draw_quad.h"
21 #include "cc/quads/tile_draw_quad.h"
22 #include "cc/resources/tile_manager.h"
23 #include "cc/trees/layer_tree_impl.h"
24 #include "cc/trees/occlusion_tracker.h"
25 #include "ui/gfx/quad_f.h"
26 #include "ui/gfx/rect_conversions.h"
27 #include "ui/gfx/size_conversions.h"
29 namespace {
30 const float kMaxScaleRatioDuringPinch = 2.0f;
32 // When creating a new tiling during pinch, snap to an existing
33 // tiling's scale if the desired scale is within this ratio.
34 const float kSnapToExistingTilingRatio = 1.2f;
36 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU.
37 const float kCpuSkewportTargetTimeInFrames = 60.0f;
39 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in
40 // TileManager::BinFromTilePriority).
41 const float kGpuSkewportTargetTimeInFrames = 0.0f;
43 // Minimum width/height of a layer that would require analysis for tiles.
44 const int kMinDimensionsForAnalysis = 256;
45 } // namespace
47 namespace cc {
49 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
50 : LayerImpl(tree_impl, id),
51 twin_layer_(NULL),
52 pile_(PicturePileImpl::Create()),
53 is_mask_(false),
54 ideal_page_scale_(0.f),
55 ideal_device_scale_(0.f),
56 ideal_source_scale_(0.f),
57 ideal_contents_scale_(0.f),
58 raster_page_scale_(0.f),
59 raster_device_scale_(0.f),
60 raster_source_scale_(0.f),
61 raster_contents_scale_(0.f),
62 low_res_raster_contents_scale_(0.f),
63 raster_source_scale_is_fixed_(false),
64 was_screen_space_transform_animating_(false),
65 needs_post_commit_initialization_(true),
66 should_update_tile_priorities_(false) {
67 layer_tree_impl()->RegisterPictureLayerImpl(this);
70 PictureLayerImpl::~PictureLayerImpl() {
71 layer_tree_impl()->UnregisterPictureLayerImpl(this);
74 const char* PictureLayerImpl::LayerTypeAsString() const {
75 return "cc::PictureLayerImpl";
78 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
79 LayerTreeImpl* tree_impl) {
80 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
83 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
84 // It's possible this layer was never drawn or updated (e.g. because it was
85 // a descendant of an opacity 0 layer).
86 DoPostCommitInitializationIfNeeded();
87 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
89 // We have already synced the important bits from the the active layer, and
90 // we will soon swap out its tilings and use them for recycling. However,
91 // there are now tiles in this layer's tilings that were unref'd and replaced
92 // with new tiles (due to invalidation). This resets all active priorities on
93 // the to-be-recycled tiling to ensure replaced tiles don't linger and take
94 // memory (due to a stale 'active' priority).
95 if (layer_impl->tilings_)
96 layer_impl->tilings_->DidBecomeRecycled();
98 LayerImpl::PushPropertiesTo(base_layer);
100 // When the pending tree pushes to the active tree, the pending twin
101 // disappears.
102 layer_impl->twin_layer_ = NULL;
103 twin_layer_ = NULL;
105 layer_impl->SetIsMask(is_mask_);
106 layer_impl->pile_ = pile_;
108 // Tilings would be expensive to push, so we swap.
109 layer_impl->tilings_.swap(tilings_);
111 // Ensure that we don't have any tiles that are out of date.
112 if (tilings_)
113 tilings_->RemoveTilesInRegion(invalidation_);
115 layer_impl->tilings_->SetClient(layer_impl);
116 if (tilings_)
117 tilings_->SetClient(this);
119 layer_impl->raster_page_scale_ = raster_page_scale_;
120 layer_impl->raster_device_scale_ = raster_device_scale_;
121 layer_impl->raster_source_scale_ = raster_source_scale_;
122 layer_impl->raster_contents_scale_ = raster_contents_scale_;
123 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
124 layer_impl->needs_post_commit_initialization_ = false;
126 // The invalidation on this soon-to-be-recycled layer must be cleared to
127 // mirror clearing the invalidation in PictureLayer's version of this function
128 // in case push properties is skipped.
129 layer_impl->invalidation_.Swap(&invalidation_);
130 invalidation_.Clear();
131 needs_post_commit_initialization_ = true;
133 // We always need to push properties.
134 // See http://crbug.com/303943
135 needs_push_properties_ = true;
138 void PictureLayerImpl::AppendQuads(
139 RenderPass* render_pass,
140 const OcclusionTracker<LayerImpl>& occlusion_tracker,
141 AppendQuadsData* append_quads_data) {
142 DCHECK(!needs_post_commit_initialization_);
144 float max_contents_scale = MaximumTilingContentsScale();
145 gfx::Transform scaled_draw_transform = draw_transform();
146 scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
147 SK_MScalar1 / max_contents_scale);
148 gfx::Size scaled_content_bounds =
149 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale));
151 gfx::Rect scaled_visible_content_rect =
152 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale);
153 scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
155 SharedQuadState* shared_quad_state =
156 render_pass->CreateAndAppendSharedQuadState();
157 shared_quad_state->SetAll(scaled_draw_transform,
158 scaled_content_bounds,
159 scaled_visible_content_rect,
160 draw_properties().clip_rect,
161 draw_properties().is_clipped,
162 draw_properties().opacity,
163 blend_mode(),
164 sorting_context_id_);
166 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
167 AppendDebugBorderQuad(
168 render_pass,
169 scaled_content_bounds,
170 shared_quad_state,
171 append_quads_data,
172 DebugColors::DirectPictureBorderColor(),
173 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
175 gfx::Rect geometry_rect = scaled_visible_content_rect;
176 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
177 gfx::Rect visible_geometry_rect = occlusion_tracker.UnoccludedContentRect(
178 geometry_rect, scaled_draw_transform);
179 if (visible_geometry_rect.IsEmpty())
180 return;
182 gfx::Size texture_size = scaled_visible_content_rect.size();
183 gfx::RectF texture_rect = gfx::RectF(texture_size);
184 gfx::Rect quad_content_rect = scaled_visible_content_rect;
186 PictureDrawQuad* quad =
187 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
188 quad->SetNew(shared_quad_state,
189 geometry_rect,
190 opaque_rect,
191 visible_geometry_rect,
192 texture_rect,
193 texture_size,
194 RGBA_8888,
195 quad_content_rect,
196 max_contents_scale,
197 pile_);
198 append_quads_data->num_missing_tiles++;
199 return;
202 AppendDebugBorderQuad(
203 render_pass, scaled_content_bounds, shared_quad_state, append_quads_data);
205 if (ShowDebugBorders()) {
206 for (PictureLayerTilingSet::CoverageIterator iter(
207 tilings_.get(),
208 max_contents_scale,
209 scaled_visible_content_rect,
210 ideal_contents_scale_);
211 iter;
212 ++iter) {
213 SkColor color;
214 float width;
215 if (*iter && iter->IsReadyToDraw()) {
216 ManagedTileState::TileVersion::Mode mode =
217 iter->GetTileVersionForDrawing().mode();
218 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) {
219 color = DebugColors::SolidColorTileBorderColor();
220 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
221 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) {
222 color = DebugColors::PictureTileBorderColor();
223 width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
224 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
225 color = DebugColors::HighResTileBorderColor();
226 width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
227 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
228 color = DebugColors::LowResTileBorderColor();
229 width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
230 } else if (iter->contents_scale() > max_contents_scale) {
231 color = DebugColors::ExtraHighResTileBorderColor();
232 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
233 } else {
234 color = DebugColors::ExtraLowResTileBorderColor();
235 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
237 } else {
238 color = DebugColors::MissingTileBorderColor();
239 width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
242 DebugBorderDrawQuad* debug_border_quad =
243 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
244 gfx::Rect geometry_rect = iter.geometry_rect();
245 gfx::Rect visible_geometry_rect = geometry_rect;
246 debug_border_quad->SetNew(shared_quad_state,
247 geometry_rect,
248 visible_geometry_rect,
249 color,
250 width);
254 // Keep track of the tilings that were used so that tilings that are
255 // unused can be considered for removal.
256 std::vector<PictureLayerTiling*> seen_tilings;
258 size_t missing_tile_count = 0u;
259 size_t on_demand_missing_tile_count = 0u;
260 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
261 max_contents_scale,
262 scaled_visible_content_rect,
263 ideal_contents_scale_);
264 iter;
265 ++iter) {
266 gfx::Rect geometry_rect = iter.geometry_rect();
267 gfx::Rect visible_geometry_rect = occlusion_tracker.UnoccludedContentRect(
268 geometry_rect, scaled_draw_transform);
269 if (visible_geometry_rect.IsEmpty())
270 continue;
272 append_quads_data->visible_content_area +=
273 visible_geometry_rect.width() * visible_geometry_rect.height();
275 if (*iter && iter->IsReadyToDraw()) {
276 const ManagedTileState::TileVersion& tile_version =
277 iter->GetTileVersionForDrawing();
278 switch (tile_version.mode()) {
279 case ManagedTileState::TileVersion::RESOURCE_MODE: {
280 gfx::RectF texture_rect = iter.texture_rect();
281 gfx::Rect opaque_rect = iter->opaque_rect();
282 opaque_rect.Intersect(geometry_rect);
284 if (iter->contents_scale() != ideal_contents_scale_)
285 append_quads_data->had_incomplete_tile = true;
287 TileDrawQuad* quad =
288 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
289 quad->SetNew(shared_quad_state,
290 geometry_rect,
291 opaque_rect,
292 visible_geometry_rect,
293 tile_version.get_resource_id(),
294 texture_rect,
295 iter.texture_size(),
296 tile_version.contents_swizzled());
297 break;
299 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
300 if (!layer_tree_impl()
301 ->GetRendererCapabilities()
302 .allow_rasterize_on_demand) {
303 ++on_demand_missing_tile_count;
304 break;
307 gfx::RectF texture_rect = iter.texture_rect();
308 gfx::Rect opaque_rect = iter->opaque_rect();
309 opaque_rect.Intersect(geometry_rect);
311 ResourceProvider* resource_provider =
312 layer_tree_impl()->resource_provider();
313 ResourceFormat format =
314 resource_provider->memory_efficient_texture_format();
315 PictureDrawQuad* quad =
316 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
317 quad->SetNew(shared_quad_state,
318 geometry_rect,
319 opaque_rect,
320 visible_geometry_rect,
321 texture_rect,
322 iter.texture_size(),
323 format,
324 iter->content_rect(),
325 iter->contents_scale(),
326 pile_);
327 break;
329 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: {
330 SolidColorDrawQuad* quad =
331 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
332 quad->SetNew(shared_quad_state,
333 geometry_rect,
334 visible_geometry_rect,
335 tile_version.get_solid_color(),
336 false);
337 break;
340 } else {
341 if (draw_checkerboard_for_missing_tiles()) {
342 CheckerboardDrawQuad* quad =
343 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
344 SkColor color = DebugColors::DefaultCheckerboardColor();
345 quad->SetNew(
346 shared_quad_state, geometry_rect, visible_geometry_rect, color);
347 } else {
348 SkColor color = SafeOpaqueBackgroundColor();
349 SolidColorDrawQuad* quad =
350 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
351 quad->SetNew(shared_quad_state,
352 geometry_rect,
353 visible_geometry_rect,
354 color,
355 false);
358 append_quads_data->num_missing_tiles++;
359 append_quads_data->had_incomplete_tile = true;
360 append_quads_data->approximated_visible_content_area +=
361 visible_geometry_rect.width() * visible_geometry_rect.height();
362 ++missing_tile_count;
363 continue;
366 if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) {
367 append_quads_data->approximated_visible_content_area +=
368 visible_geometry_rect.width() * visible_geometry_rect.height();
371 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
372 seen_tilings.push_back(iter.CurrentTiling());
375 if (missing_tile_count) {
376 TRACE_EVENT_INSTANT2("cc",
377 "PictureLayerImpl::AppendQuads checkerboard",
378 TRACE_EVENT_SCOPE_THREAD,
379 "missing_tile_count",
380 missing_tile_count,
381 "on_demand_missing_tile_count",
382 on_demand_missing_tile_count);
385 // Aggressively remove any tilings that are not seen to save memory. Note
386 // that this is at the expense of doing cause more frequent re-painting. A
387 // better scheme would be to maintain a tighter visible_content_rect for the
388 // finer tilings.
389 CleanUpTilingsOnActiveLayer(seen_tilings);
392 void PictureLayerImpl::UpdateTiles(
393 const OcclusionTracker<LayerImpl>* occlusion_tracker) {
394 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
396 DoPostCommitInitializationIfNeeded();
398 // TODO(danakj): We should always get an occlusion tracker when we are using
399 // occlusion, so update this check when we don't use a pending tree in the
400 // browser compositor.
401 DCHECK(!occlusion_tracker ||
402 layer_tree_impl()->settings().use_occlusion_for_tile_prioritization);
404 // Transforms and viewport are invalid for tile management inside a
405 // resourceless software draw, so don't update them.
406 if (!layer_tree_impl()->resourceless_software_draw()) {
407 visible_rect_for_tile_priority_ = visible_content_rect();
408 viewport_size_for_tile_priority_ = layer_tree_impl()->DrawViewportSize();
409 screen_space_transform_for_tile_priority_ = screen_space_transform();
412 if (!CanHaveTilings()) {
413 ideal_page_scale_ = 0.f;
414 ideal_device_scale_ = 0.f;
415 ideal_contents_scale_ = 0.f;
416 ideal_source_scale_ = 0.f;
417 SanityCheckTilingState();
418 return;
421 UpdateIdealScales();
423 DCHECK(tilings_->num_tilings() > 0 || raster_contents_scale_ == 0.f)
424 << "A layer with no tilings shouldn't have valid raster scales";
425 if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
426 RecalculateRasterScales();
427 AddTilingsForRasterScale();
430 DCHECK(raster_page_scale_);
431 DCHECK(raster_device_scale_);
432 DCHECK(raster_source_scale_);
433 DCHECK(raster_contents_scale_);
434 DCHECK(low_res_raster_contents_scale_);
436 was_screen_space_transform_animating_ =
437 draw_properties().screen_space_transform_is_animating;
439 should_update_tile_priorities_ = true;
441 UpdateTilePriorities(occlusion_tracker);
443 if (layer_tree_impl()->IsPendingTree())
444 MarkVisibleResourcesAsRequired();
447 void PictureLayerImpl::UpdateTilePriorities(
448 const OcclusionTracker<LayerImpl>* occlusion_tracker) {
449 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
451 double current_frame_time_in_seconds =
452 (layer_tree_impl()->CurrentFrameTimeTicks() -
453 base::TimeTicks()).InSecondsF();
455 bool tiling_needs_update = false;
456 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
457 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime(
458 current_frame_time_in_seconds)) {
459 tiling_needs_update = true;
460 break;
463 if (!tiling_needs_update)
464 return;
466 // Use visible_content_rect, unless it's empty. If it's empty, then
467 // try to inverse project the viewport into layer space and use that.
468 gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_;
469 if (visible_rect_in_content_space.IsEmpty()) {
470 gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization);
471 if (screen_space_transform_for_tile_priority_.GetInverse(
472 &screen_to_layer)) {
473 visible_rect_in_content_space =
474 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
475 screen_to_layer, gfx::Rect(viewport_size_for_tile_priority_)));
476 visible_rect_in_content_space.Intersect(gfx::Rect(content_bounds()));
480 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect(
481 visible_rect_in_content_space, 1.f / contents_scale_x());
482 WhichTree tree =
483 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
484 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
485 tilings_->tiling_at(i)->UpdateTilePriorities(tree,
486 visible_layer_rect,
487 ideal_contents_scale_,
488 current_frame_time_in_seconds,
489 occlusion_tracker,
490 render_target(),
491 draw_transform());
494 // Tile priorities were modified.
495 layer_tree_impl()->DidModifyTilePriorities();
498 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
499 if (layer_tree_impl()->IsActiveTree()) {
500 gfx::RectF layer_damage_rect =
501 gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale());
502 AddDamageRect(layer_damage_rect);
506 void PictureLayerImpl::DidBecomeActive() {
507 LayerImpl::DidBecomeActive();
508 tilings_->DidBecomeActive();
509 layer_tree_impl()->DidModifyTilePriorities();
512 void PictureLayerImpl::DidBeginTracing() {
513 pile_->DidBeginTracing();
516 void PictureLayerImpl::ReleaseResources() {
517 if (tilings_)
518 RemoveAllTilings();
520 ResetRasterScale();
522 // To avoid an edge case after lost context where the tree is up to date but
523 // the tilings have not been managed, request an update draw properties
524 // to force tilings to get managed.
525 layer_tree_impl()->set_needs_update_draw_properties();
528 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
529 return pile_->GetFlattenedPicture();
532 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
533 const gfx::Rect& content_rect) {
534 if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
535 return scoped_refptr<Tile>();
537 int flags = 0;
538 // We analyze picture before rasterization to detect solid-color tiles.
539 // If the tile is detected as such there is no need to raster or upload.
540 // It is drawn directly as a solid-color quad saving memory, raster and upload
541 // cost. The analysis step is however expensive and may not be justified when
542 // doing gpu rasterization which runs on the compositor thread and where there
543 // is no upload.
544 // TODO(alokp): Revisit the decision to avoid analysis for gpu rasterization
545 // becuase it too can potentially benefit from memory savings.
546 if (!layer_tree_impl()->use_gpu_rasterization()) {
547 // Additionally, we do not want to do the analysis if the layer is too
548 // narrow, since more likely than not the tile would not be solid. Note that
549 // this last optimization is a heuristic that ensures that we don't spend
550 // too much time analyzing tiles on a multitude of small layers, as it is
551 // likely that these layers have some non-solid content.
552 int min_dimension = std::min(bounds().width(), bounds().height());
553 if (min_dimension >= kMinDimensionsForAnalysis)
554 flags |= Tile::USE_PICTURE_ANALYSIS;
557 return layer_tree_impl()->tile_manager()->CreateTile(
558 pile_.get(),
559 content_rect.size(),
560 content_rect,
561 contents_opaque() ? content_rect : gfx::Rect(),
562 tiling->contents_scale(),
563 id(),
564 layer_tree_impl()->source_frame_number(),
565 flags);
568 PicturePileImpl* PictureLayerImpl::GetPile() {
569 return pile_.get();
572 const Region* PictureLayerImpl::GetInvalidation() {
573 return &invalidation_;
576 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
577 const PictureLayerTiling* tiling) const {
578 if (!twin_layer_)
579 return NULL;
580 for (size_t i = 0; i < twin_layer_->tilings_->num_tilings(); ++i)
581 if (twin_layer_->tilings_->tiling_at(i)->contents_scale() ==
582 tiling->contents_scale())
583 return twin_layer_->tilings_->tiling_at(i);
584 return NULL;
587 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
588 return layer_tree_impl()->settings().max_tiles_for_interest_area;
591 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
592 float skewport_target_time_in_frames =
593 layer_tree_impl()->use_gpu_rasterization()
594 ? kGpuSkewportTargetTimeInFrames
595 : kCpuSkewportTargetTimeInFrames;
596 return skewport_target_time_in_frames *
597 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() *
598 layer_tree_impl()->settings().skewport_target_time_multiplier;
601 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
602 return layer_tree_impl()
603 ->settings()
604 .skewport_extrapolation_limit_in_content_pixels;
607 gfx::Size PictureLayerImpl::CalculateTileSize(
608 const gfx::Size& content_bounds) const {
609 if (is_mask_) {
610 int max_size = layer_tree_impl()->MaxTextureSize();
611 return gfx::Size(
612 std::min(max_size, content_bounds.width()),
613 std::min(max_size, content_bounds.height()));
616 int max_texture_size =
617 layer_tree_impl()->resource_provider()->max_texture_size();
619 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size;
620 if (layer_tree_impl()->use_gpu_rasterization()) {
621 // TODO(ernstm) crbug.com/365877: We need a unified way to override the
622 // default-tile-size.
623 default_tile_size =
624 gfx::Size(layer_tree_impl()->device_viewport_size().width(),
625 layer_tree_impl()->device_viewport_size().height() / 4);
627 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
629 gfx::Size max_untiled_content_size =
630 layer_tree_impl()->settings().max_untiled_layer_size;
631 max_untiled_content_size.SetToMin(
632 gfx::Size(max_texture_size, max_texture_size));
634 bool any_dimension_too_large =
635 content_bounds.width() > max_untiled_content_size.width() ||
636 content_bounds.height() > max_untiled_content_size.height();
638 bool any_dimension_one_tile =
639 content_bounds.width() <= default_tile_size.width() ||
640 content_bounds.height() <= default_tile_size.height();
642 // If long and skinny, tile at the max untiled content size, and clamp
643 // the smaller dimension to the content size, e.g. 1000x12 layer with
644 // 500x500 max untiled size would get 500x12 tiles. Also do this
645 // if the layer is small.
646 if (any_dimension_one_tile || !any_dimension_too_large) {
647 int width = std::min(
648 std::max(max_untiled_content_size.width(), default_tile_size.width()),
649 content_bounds.width());
650 int height = std::min(
651 std::max(max_untiled_content_size.height(), default_tile_size.height()),
652 content_bounds.height());
653 // Round up to the closest multiple of 64. This improves recycling and
654 // avoids odd texture sizes.
655 width = RoundUp(width, 64);
656 height = RoundUp(height, 64);
657 return gfx::Size(width, height);
660 return default_tile_size;
663 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
664 TRACE_EVENT0("cc", "SyncFromActiveLayer");
665 DCHECK(!other->needs_post_commit_initialization_);
666 DCHECK(other->tilings_);
668 if (!DrawsContent()) {
669 RemoveAllTilings();
670 return;
673 raster_page_scale_ = other->raster_page_scale_;
674 raster_device_scale_ = other->raster_device_scale_;
675 raster_source_scale_ = other->raster_source_scale_;
676 raster_contents_scale_ = other->raster_contents_scale_;
677 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
679 // Union in the other newly exposed regions as invalid.
680 Region difference_region = Region(gfx::Rect(bounds()));
681 difference_region.Subtract(gfx::Rect(other->bounds()));
682 invalidation_.Union(difference_region);
684 bool synced_high_res_tiling = false;
685 if (CanHaveTilings()) {
686 synced_high_res_tiling = tilings_->SyncTilings(
687 *other->tilings_, bounds(), invalidation_, MinimumContentsScale());
688 } else {
689 RemoveAllTilings();
692 // If our MinimumContentsScale has changed to prevent the twin's high res
693 // tiling from being synced, we should reset the raster scale and let it be
694 // recalculated (1) again. This can happen if our bounds shrink to the point
695 // where min contents scale grows.
696 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we
697 // should refactor this code a little bit and actually recalculate this.
698 // However, this is a larger undertaking, so this will work for now.
699 if (!synced_high_res_tiling)
700 ResetRasterScale();
701 else
702 SanityCheckTilingState();
705 void PictureLayerImpl::SyncTiling(
706 const PictureLayerTiling* tiling) {
707 if (!CanHaveTilingWithScale(tiling->contents_scale()))
708 return;
709 tilings_->AddTiling(tiling->contents_scale());
711 // If this tree needs update draw properties, then the tiling will
712 // get updated prior to drawing or activation. If this tree does not
713 // need update draw properties, then its transforms are up to date and
714 // we can create tiles for this tiling immediately.
715 if (!layer_tree_impl()->needs_update_draw_properties() &&
716 should_update_tile_priorities_) {
717 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking
718 // when we stop using the pending tree in the browser compositor. If we want
719 // to support occlusion tracking here, we need to dirty the draw properties
720 // or save occlusion as a draw property.
721 UpdateTilePriorities(NULL);
725 void PictureLayerImpl::SetIsMask(bool is_mask) {
726 if (is_mask_ == is_mask)
727 return;
728 is_mask_ = is_mask;
729 if (tilings_)
730 tilings_->RemoveAllTiles();
733 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
734 gfx::Rect content_rect(content_bounds());
735 float scale = MaximumTilingContentsScale();
736 PictureLayerTilingSet::CoverageIterator iter(
737 tilings_.get(), scale, content_rect, ideal_contents_scale_);
739 // Mask resource not ready yet.
740 if (!iter || !*iter)
741 return 0;
743 // Masks only supported if they fit on exactly one tile.
744 if (iter.geometry_rect() != content_rect)
745 return 0;
747 const ManagedTileState::TileVersion& tile_version =
748 iter->GetTileVersionForDrawing();
749 if (!tile_version.IsReadyToDraw() ||
750 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE)
751 return 0;
753 return tile_version.get_resource_id();
756 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
757 DCHECK(layer_tree_impl()->IsPendingTree());
758 DCHECK(ideal_contents_scale_);
759 DCHECK_GT(tilings_->num_tilings(), 0u);
761 // The goal of this function is to find the minimum set of tiles that need to
762 // be ready to draw in order to activate without flashing content from a
763 // higher res on the active tree to a lower res on the pending tree.
765 // First, early out for layers with no visible content.
766 if (visible_content_rect().IsEmpty())
767 return;
769 gfx::Rect rect(visible_content_rect());
771 float min_acceptable_scale =
772 std::min(raster_contents_scale_, ideal_contents_scale_);
774 if (PictureLayerImpl* twin = twin_layer_) {
775 float twin_min_acceptable_scale =
776 std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_);
777 // Ignore 0 scale in case CalculateContentsScale() has never been
778 // called for active twin.
779 if (twin_min_acceptable_scale != 0.0f) {
780 min_acceptable_scale =
781 std::min(min_acceptable_scale, twin_min_acceptable_scale);
785 PictureLayerTiling* high_res = NULL;
786 PictureLayerTiling* low_res = NULL;
788 // First pass: ready to draw tiles in acceptable but non-ideal tilings are
789 // marked as required for activation so that their textures are not thrown
790 // away; any non-ready tiles are not marked as required.
791 Region missing_region = rect;
792 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
793 PictureLayerTiling* tiling = tilings_->tiling_at(i);
794 DCHECK(tiling->has_ever_been_updated());
796 if (tiling->resolution() == LOW_RESOLUTION) {
797 DCHECK(!low_res) << "There can only be one low res tiling";
798 low_res = tiling;
800 if (tiling->contents_scale() < min_acceptable_scale)
801 continue;
802 if (tiling->resolution() == HIGH_RESOLUTION) {
803 DCHECK(!high_res) << "There can only be one high res tiling";
804 high_res = tiling;
805 continue;
807 for (PictureLayerTiling::CoverageIterator iter(tiling,
808 contents_scale_x(),
809 rect);
810 iter;
811 ++iter) {
812 if (!*iter || !iter->IsReadyToDraw())
813 continue;
815 missing_region.Subtract(iter.geometry_rect());
816 iter->MarkRequiredForActivation();
819 DCHECK(high_res) << "There must be one high res tiling";
821 // If these pointers are null (because no twin, no matching tiling, or the
822 // simpification just below), then high res tiles will be required to fill any
823 // holes left by the first pass above. If the pointers are valid, then this
824 // layer is allowed to skip any tiles that are not ready on its twin.
825 const PictureLayerTiling* twin_high_res = NULL;
826 const PictureLayerTiling* twin_low_res = NULL;
828 if (twin_layer_) {
829 // As a simplification, only allow activating to skip twin tiles that the
830 // active layer is also missing when both this layer and its twin have
831 // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high
832 // res tiling. This avoids having to iterate/track coverage of non-ideal
833 // tilings during the last draw call on the active layer.
834 if (tilings_->num_tilings() <= 2 &&
835 twin_layer_->tilings_->num_tilings() <= tilings_->num_tilings()) {
836 twin_low_res = low_res ? GetTwinTiling(low_res) : NULL;
837 twin_high_res = high_res ? GetTwinTiling(high_res) : NULL;
840 // If this layer and its twin have different transforms, then don't compare
841 // them and only allow activating to high res tiles, since tiles on each
842 // layer will be in different places on screen.
843 if (twin_layer_->layer_tree_impl()->RequiresHighResToDraw() ||
844 bounds() != twin_layer_->bounds() ||
845 draw_properties().screen_space_transform !=
846 twin_layer_->draw_properties().screen_space_transform) {
847 twin_high_res = NULL;
848 twin_low_res = NULL;
852 // As a second pass, mark as required any visible high res tiles not filled in
853 // by acceptable non-ideal tiles from the first pass.
854 if (MarkVisibleTilesAsRequired(
855 high_res, twin_high_res, contents_scale_x(), rect, missing_region)) {
856 // As an optional third pass, if a high res tile was skipped because its
857 // twin was also missing, then fall back to mark low res tiles as required
858 // in case the active twin is substituting those for missing high res
859 // content. Only suitable, when low res is enabled.
860 if (low_res) {
861 MarkVisibleTilesAsRequired(
862 low_res, twin_low_res, contents_scale_x(), rect, missing_region);
867 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
868 PictureLayerTiling* tiling,
869 const PictureLayerTiling* optional_twin_tiling,
870 float contents_scale,
871 const gfx::Rect& rect,
872 const Region& missing_region) const {
873 bool twin_had_missing_tile = false;
874 for (PictureLayerTiling::CoverageIterator iter(tiling,
875 contents_scale,
876 rect);
877 iter;
878 ++iter) {
879 Tile* tile = *iter;
880 // A null tile (i.e. missing recording) can just be skipped.
881 if (!tile)
882 continue;
884 // If the tile is occluded, don't mark it as required for activation.
885 if (tile->is_occluded(PENDING_TREE))
886 continue;
888 // If the missing region doesn't cover it, this tile is fully
889 // covered by acceptable tiles at other scales.
890 if (!missing_region.Intersects(iter.geometry_rect()))
891 continue;
893 // If the twin tile doesn't exist (i.e. missing recording or so far away
894 // that it is outside the visible tile rect) or this tile is shared between
895 // with the twin, then this tile isn't required to prevent flashing.
896 if (optional_twin_tiling) {
897 Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
898 if (!twin_tile || twin_tile == tile) {
899 twin_had_missing_tile = true;
900 continue;
904 tile->MarkRequiredForActivation();
906 return twin_had_missing_tile;
909 void PictureLayerImpl::DoPostCommitInitialization() {
910 DCHECK(needs_post_commit_initialization_);
911 DCHECK(layer_tree_impl()->IsPendingTree());
913 if (!tilings_)
914 tilings_.reset(new PictureLayerTilingSet(this, bounds()));
916 DCHECK(!twin_layer_);
917 twin_layer_ = static_cast<PictureLayerImpl*>(
918 layer_tree_impl()->FindActiveTreeLayerById(id()));
919 if (twin_layer_) {
920 DCHECK(!twin_layer_->twin_layer_);
921 twin_layer_->twin_layer_ = this;
922 // If the twin has never been pushed to, do not sync from it.
923 // This can happen if this function is called during activation.
924 if (!twin_layer_->needs_post_commit_initialization_)
925 SyncFromActiveLayer(twin_layer_);
928 needs_post_commit_initialization_ = false;
931 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
932 DCHECK(CanHaveTilingWithScale(contents_scale)) <<
933 "contents_scale: " << contents_scale;
935 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
937 DCHECK(pile_->HasRecordings());
939 if (twin_layer_)
940 twin_layer_->SyncTiling(tiling);
942 return tiling;
945 void PictureLayerImpl::RemoveTiling(float contents_scale) {
946 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
947 PictureLayerTiling* tiling = tilings_->tiling_at(i);
948 if (tiling->contents_scale() == contents_scale) {
949 tilings_->Remove(tiling);
950 break;
953 if (tilings_->num_tilings() == 0)
954 ResetRasterScale();
955 SanityCheckTilingState();
958 void PictureLayerImpl::RemoveAllTilings() {
959 if (tilings_)
960 tilings_->RemoveAllTilings();
961 // If there are no tilings, then raster scales are no longer meaningful.
962 ResetRasterScale();
965 namespace {
967 inline float PositiveRatio(float float1, float float2) {
968 DCHECK_GT(float1, 0);
969 DCHECK_GT(float2, 0);
970 return float1 > float2 ? float1 / float2 : float2 / float1;
973 } // namespace
975 void PictureLayerImpl::AddTilingsForRasterScale() {
976 PictureLayerTiling* high_res = NULL;
977 PictureLayerTiling* low_res = NULL;
979 PictureLayerTiling* previous_low_res = NULL;
980 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
981 PictureLayerTiling* tiling = tilings_->tiling_at(i);
982 if (tiling->contents_scale() == raster_contents_scale_)
983 high_res = tiling;
984 if (tiling->contents_scale() == low_res_raster_contents_scale_)
985 low_res = tiling;
986 if (tiling->resolution() == LOW_RESOLUTION)
987 previous_low_res = tiling;
989 // Reset all tilings to non-ideal until the end of this function.
990 tiling->set_resolution(NON_IDEAL_RESOLUTION);
993 if (!high_res) {
994 high_res = AddTiling(raster_contents_scale_);
995 if (raster_contents_scale_ == low_res_raster_contents_scale_)
996 low_res = high_res;
999 // Only create new low res tilings when the transform is static. This
1000 // prevents wastefully creating a paired low res tiling for every new high res
1001 // tiling during a pinch or a CSS animation.
1002 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1003 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching &&
1004 !draw_properties().screen_space_transform_is_animating && !low_res &&
1005 low_res != high_res)
1006 low_res = AddTiling(low_res_raster_contents_scale_);
1008 // Set low-res if we have one.
1009 if (!low_res)
1010 low_res = previous_low_res;
1011 if (low_res && low_res != high_res)
1012 low_res->set_resolution(LOW_RESOLUTION);
1014 // Make sure we always have one high-res (even if high == low).
1015 high_res->set_resolution(HIGH_RESOLUTION);
1017 SanityCheckTilingState();
1020 bool PictureLayerImpl::ShouldAdjustRasterScale() const {
1021 if (was_screen_space_transform_animating_ !=
1022 draw_properties().screen_space_transform_is_animating)
1023 return true;
1025 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1026 if (is_pinching && raster_page_scale_) {
1027 // We change our raster scale when it is:
1028 // - Higher than ideal (need a lower-res tiling available)
1029 // - Too far from ideal (need a higher-res tiling available)
1030 float ratio = ideal_page_scale_ / raster_page_scale_;
1031 if (raster_page_scale_ > ideal_page_scale_ ||
1032 ratio > kMaxScaleRatioDuringPinch)
1033 return true;
1036 if (!is_pinching) {
1037 // When not pinching, match the ideal page scale factor.
1038 if (raster_page_scale_ != ideal_page_scale_)
1039 return true;
1042 // Always match the ideal device scale factor.
1043 if (raster_device_scale_ != ideal_device_scale_)
1044 return true;
1046 // When the source scale changes we want to match it, but not when animating
1047 // or when we've fixed the scale in place.
1048 if (!draw_properties().screen_space_transform_is_animating &&
1049 !raster_source_scale_is_fixed_ &&
1050 raster_source_scale_ != ideal_source_scale_)
1051 return true;
1053 return false;
1056 float PictureLayerImpl::SnappedContentsScale(float scale) {
1057 // If a tiling exists within the max snapping ratio, snap to its scale.
1058 float snapped_contents_scale = scale;
1059 float snapped_ratio = kSnapToExistingTilingRatio;
1060 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1061 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
1062 float ratio = PositiveRatio(tiling_contents_scale, scale);
1063 if (ratio < snapped_ratio) {
1064 snapped_contents_scale = tiling_contents_scale;
1065 snapped_ratio = ratio;
1068 return snapped_contents_scale;
1071 void PictureLayerImpl::RecalculateRasterScales() {
1072 float old_raster_contents_scale = raster_contents_scale_;
1073 float old_raster_page_scale = raster_page_scale_;
1074 float old_raster_source_scale = raster_source_scale_;
1076 raster_device_scale_ = ideal_device_scale_;
1077 raster_page_scale_ = ideal_page_scale_;
1078 raster_source_scale_ = ideal_source_scale_;
1079 raster_contents_scale_ = ideal_contents_scale_;
1081 // If we're not animating, or leaving an animation, and the
1082 // ideal_source_scale_ changes, then things are unpredictable, and we fix
1083 // the raster_source_scale_ in place.
1084 if (old_raster_source_scale &&
1085 !draw_properties().screen_space_transform_is_animating &&
1086 !was_screen_space_transform_animating_ &&
1087 old_raster_source_scale != ideal_source_scale_)
1088 raster_source_scale_is_fixed_ = true;
1090 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
1091 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
1092 // tree. This will allow CSS scale changes to get re-rastered at an
1093 // appropriate rate.
1094 if (raster_source_scale_is_fixed_) {
1095 raster_contents_scale_ /= raster_source_scale_;
1096 raster_source_scale_ = 1.f;
1099 // During pinch we completely ignore the current ideal scale, and just use
1100 // a multiple of the previous scale.
1101 // TODO(danakj): This seems crazy, we should use the current ideal, no?
1102 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1103 if (is_pinching && old_raster_contents_scale) {
1104 // See ShouldAdjustRasterScale:
1105 // - When zooming out, preemptively create new tiling at lower resolution.
1106 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1107 bool zooming_out = old_raster_page_scale > ideal_page_scale_;
1108 float desired_contents_scale =
1109 zooming_out ? old_raster_contents_scale / kMaxScaleRatioDuringPinch
1110 : old_raster_contents_scale * kMaxScaleRatioDuringPinch;
1111 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
1112 raster_page_scale_ =
1113 raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
1116 raster_contents_scale_ =
1117 std::max(raster_contents_scale_, MinimumContentsScale());
1119 // Since we're not re-rasterizing during animation, rasterize at the maximum
1120 // scale that will occur during the animation, if the maximum scale is
1121 // known.
1122 if (draw_properties().screen_space_transform_is_animating) {
1123 if (draw_properties().maximum_animation_contents_scale > 0.f) {
1124 raster_contents_scale_ =
1125 std::max(raster_contents_scale_,
1126 draw_properties().maximum_animation_contents_scale);
1127 } else {
1128 raster_contents_scale_ =
1129 std::max(raster_contents_scale_,
1130 1.f * ideal_page_scale_ * ideal_device_scale_);
1134 // If this layer would only create one tile at this content scale,
1135 // don't create a low res tiling.
1136 gfx::Size content_bounds =
1137 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
1138 gfx::Size tile_size = CalculateTileSize(content_bounds);
1139 if (tile_size.width() >= content_bounds.width() &&
1140 tile_size.height() >= content_bounds.height()) {
1141 low_res_raster_contents_scale_ = raster_contents_scale_;
1142 return;
1145 float low_res_factor =
1146 layer_tree_impl()->settings().low_res_contents_scale_factor;
1147 low_res_raster_contents_scale_ = std::max(
1148 raster_contents_scale_ * low_res_factor,
1149 MinimumContentsScale());
1152 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1153 std::vector<PictureLayerTiling*> used_tilings) {
1154 DCHECK(layer_tree_impl()->IsActiveTree());
1155 if (tilings_->num_tilings() == 0)
1156 return;
1158 float min_acceptable_high_res_scale = std::min(
1159 raster_contents_scale_, ideal_contents_scale_);
1160 float max_acceptable_high_res_scale = std::max(
1161 raster_contents_scale_, ideal_contents_scale_);
1162 float twin_low_res_scale = 0.f;
1164 PictureLayerImpl* twin = twin_layer_;
1165 if (twin && twin->CanHaveTilings()) {
1166 min_acceptable_high_res_scale = std::min(
1167 min_acceptable_high_res_scale,
1168 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1169 max_acceptable_high_res_scale = std::max(
1170 max_acceptable_high_res_scale,
1171 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1173 for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
1174 PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
1175 if (tiling->resolution() == LOW_RESOLUTION)
1176 twin_low_res_scale = tiling->contents_scale();
1180 std::vector<PictureLayerTiling*> to_remove;
1181 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1182 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1184 // Keep multiple high resolution tilings even if not used to help
1185 // activate earlier at non-ideal resolutions.
1186 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
1187 tiling->contents_scale() <= max_acceptable_high_res_scale)
1188 continue;
1190 // Keep low resolution tilings, if the layer should have them.
1191 if (layer_tree_impl()->create_low_res_tiling()) {
1192 if (tiling->resolution() == LOW_RESOLUTION ||
1193 tiling->contents_scale() == twin_low_res_scale)
1194 continue;
1197 // Don't remove tilings that are being used (and thus would cause a flash.)
1198 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
1199 used_tilings.end())
1200 continue;
1202 to_remove.push_back(tiling);
1205 for (size_t i = 0; i < to_remove.size(); ++i) {
1206 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
1207 // Only remove tilings from the twin layer if they have
1208 // NON_IDEAL_RESOLUTION.
1209 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
1210 twin->RemoveTiling(to_remove[i]->contents_scale());
1211 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350
1212 CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution());
1213 tilings_->Remove(to_remove[i]);
1215 DCHECK_GT(tilings_->num_tilings(), 0u);
1217 SanityCheckTilingState();
1220 float PictureLayerImpl::MinimumContentsScale() const {
1221 float setting_min = layer_tree_impl()->settings().minimum_contents_scale;
1223 // If the contents scale is less than 1 / width (also for height),
1224 // then it will end up having less than one pixel of content in that
1225 // dimension. Bump the minimum contents scale up in this case to prevent
1226 // this from happening.
1227 int min_dimension = std::min(bounds().width(), bounds().height());
1228 if (!min_dimension)
1229 return setting_min;
1231 return std::max(1.f / min_dimension, setting_min);
1234 void PictureLayerImpl::ResetRasterScale() {
1235 raster_page_scale_ = 0.f;
1236 raster_device_scale_ = 0.f;
1237 raster_source_scale_ = 0.f;
1238 raster_contents_scale_ = 0.f;
1239 low_res_raster_contents_scale_ = 0.f;
1240 raster_source_scale_is_fixed_ = false;
1242 // When raster scales aren't valid, don't update tile priorities until
1243 // this layer has been updated via UpdateDrawProperties.
1244 should_update_tile_priorities_ = false;
1247 bool PictureLayerImpl::CanHaveTilings() const {
1248 if (!DrawsContent())
1249 return false;
1250 if (!pile_->HasRecordings())
1251 return false;
1252 return true;
1255 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const {
1256 if (!CanHaveTilings())
1257 return false;
1258 if (contents_scale < MinimumContentsScale())
1259 return false;
1260 return true;
1263 void PictureLayerImpl::SanityCheckTilingState() const {
1264 #if DCHECK_IS_ON
1265 if (!CanHaveTilings()) {
1266 DCHECK_EQ(0u, tilings_->num_tilings());
1267 return;
1269 if (tilings_->num_tilings() == 0)
1270 return;
1272 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1273 // tiling to mark its tiles as being required for activation.
1274 DCHECK_EQ(1, tilings_->NumHighResTilings());
1275 #endif
1278 float PictureLayerImpl::MaximumTilingContentsScale() const {
1279 float max_contents_scale = MinimumContentsScale();
1280 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1281 const PictureLayerTiling* tiling = tilings_->tiling_at(i);
1282 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
1284 return max_contents_scale;
1287 void PictureLayerImpl::UpdateIdealScales() {
1288 DCHECK(CanHaveTilings());
1290 float min_contents_scale = MinimumContentsScale();
1291 DCHECK_GT(min_contents_scale, 0.f);
1292 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
1293 DCHECK_GT(min_page_scale, 0.f);
1294 float min_device_scale = 1.f;
1295 float min_source_scale =
1296 min_contents_scale / min_page_scale / min_device_scale;
1298 float ideal_page_scale = draw_properties().page_scale_factor;
1299 float ideal_device_scale = draw_properties().device_scale_factor;
1300 float ideal_source_scale = draw_properties().ideal_contents_scale /
1301 ideal_page_scale / ideal_device_scale;
1302 ideal_contents_scale_ =
1303 std::max(draw_properties().ideal_contents_scale, min_contents_scale);
1304 ideal_page_scale_ = draw_properties().page_scale_factor;
1305 ideal_device_scale_ = draw_properties().device_scale_factor;
1306 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
1309 void PictureLayerImpl::GetDebugBorderProperties(
1310 SkColor* color,
1311 float* width) const {
1312 *color = DebugColors::TiledContentLayerBorderColor();
1313 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1316 void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
1317 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1318 LayerImpl::AsValueInto(state);
1319 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1320 state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
1321 state->Set("tilings", tilings_->AsValue().release());
1322 state->Set("pictures", pile_->AsValue().release());
1323 state->Set("invalidation", invalidation_.AsValue().release());
1325 scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue);
1326 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
1327 contents_scale_x(),
1328 gfx::Rect(content_bounds()),
1329 ideal_contents_scale_);
1330 iter;
1331 ++iter) {
1332 scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue);
1333 tile_data->Set("geometry_rect",
1334 MathUtil::AsValue(iter.geometry_rect()).release());
1335 if (*iter)
1336 tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release());
1338 coverage_tiles->Append(tile_data.release());
1340 state->Set("coverage_tiles", coverage_tiles.release());
1343 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1344 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1345 return tilings_->GPUMemoryUsageInBytes();
1348 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1349 benchmark->RunOnLayer(this);
1352 WhichTree PictureLayerImpl::GetTree() const {
1353 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1356 bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
1357 return !layer_tree_impl()->IsRecycleTree();
1360 bool PictureLayerImpl::HasValidTilePriorities() const {
1361 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember();
1364 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const {
1365 if (!layer_tree_impl()->IsPendingTree())
1366 return true;
1368 if (!HasValidTilePriorities())
1369 return true;
1371 if (!tilings_)
1372 return true;
1374 if (visible_content_rect().IsEmpty())
1375 return true;
1377 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1378 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1379 if (tiling->resolution() != HIGH_RESOLUTION &&
1380 tiling->resolution() != LOW_RESOLUTION)
1381 continue;
1383 gfx::Rect rect(visible_content_rect());
1384 for (PictureLayerTiling::CoverageIterator iter(
1385 tiling, contents_scale_x(), rect);
1386 iter;
1387 ++iter) {
1388 const Tile* tile = *iter;
1389 // A null tile (i.e. missing recording) can just be skipped.
1390 if (!tile)
1391 continue;
1393 if (tile->required_for_activation() && !tile->IsReadyToDraw())
1394 return false;
1398 return true;
1401 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator()
1402 : layer_(NULL) {}
1404 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator(
1405 PictureLayerImpl* layer,
1406 bool prioritize_low_res)
1407 : layer_(layer), current_stage_(0) {
1408 DCHECK(layer_);
1410 // Early out if the layer has no tilings.
1411 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) {
1412 current_stage_ = arraysize(stages_);
1413 return;
1416 // Tiles without valid priority are treated as having lowest priority and
1417 // never considered for raster.
1418 if (!layer_->HasValidTilePriorities()) {
1419 current_stage_ = arraysize(stages_);
1420 return;
1423 WhichTree tree =
1424 layer_->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1426 // Find high and low res tilings and initialize the iterators.
1427 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1428 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1429 if (tiling->resolution() == HIGH_RESOLUTION) {
1430 iterators_[HIGH_RES] =
1431 PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1434 if (tiling->resolution() == LOW_RESOLUTION) {
1435 iterators_[LOW_RES] =
1436 PictureLayerTiling::TilingRasterTileIterator(tiling, tree);
1440 if (prioritize_low_res) {
1441 stages_[0].iterator_type = LOW_RES;
1442 stages_[0].tile_type = TilePriority::NOW;
1444 stages_[1].iterator_type = HIGH_RES;
1445 stages_[1].tile_type = TilePriority::NOW;
1446 } else {
1447 stages_[0].iterator_type = HIGH_RES;
1448 stages_[0].tile_type = TilePriority::NOW;
1450 stages_[1].iterator_type = LOW_RES;
1451 stages_[1].tile_type = TilePriority::NOW;
1454 stages_[2].iterator_type = HIGH_RES;
1455 stages_[2].tile_type = TilePriority::SOON;
1457 stages_[3].iterator_type = HIGH_RES;
1458 stages_[3].tile_type = TilePriority::EVENTUALLY;
1460 IteratorType index = stages_[current_stage_].iterator_type;
1461 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1462 if (!iterators_[index] || iterators_[index].get_type() != tile_type ||
1463 (*iterators_[index])->is_occluded(tree))
1464 ++(*this);
1467 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {}
1469 PictureLayerImpl::LayerRasterTileIterator::operator bool() const {
1470 return layer_ && static_cast<size_t>(current_stage_) < arraysize(stages_);
1473 PictureLayerImpl::LayerRasterTileIterator&
1474 PictureLayerImpl::LayerRasterTileIterator::
1475 operator++() {
1476 WhichTree tree =
1477 layer_->layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
1479 IteratorType index = stages_[current_stage_].iterator_type;
1480 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
1482 // First advance the iterator.
1483 if (iterators_[index])
1484 ++iterators_[index];
1486 while (iterators_[index] && iterators_[index].get_type() == tile_type &&
1487 (*iterators_[index])->is_occluded(tree))
1488 ++iterators_[index];
1490 if (iterators_[index] && iterators_[index].get_type() == tile_type)
1491 return *this;
1493 // Next, advance the stage.
1494 int stage_count = arraysize(stages_);
1495 ++current_stage_;
1496 while (current_stage_ < stage_count) {
1497 index = stages_[current_stage_].iterator_type;
1498 tile_type = stages_[current_stage_].tile_type;
1500 if (iterators_[index] && iterators_[index].get_type() == tile_type &&
1501 !(*iterators_[index])->is_occluded(tree))
1502 break;
1503 ++current_stage_;
1505 return *this;
1508 Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() {
1509 DCHECK(*this);
1511 IteratorType index = stages_[current_stage_].iterator_type;
1512 DCHECK(iterators_[index]);
1513 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type);
1515 return *iterators_[index];
1518 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator()
1519 : iterator_index_(0),
1520 iteration_stage_(TilePriority::EVENTUALLY),
1521 required_for_activation_(false),
1522 layer_(NULL) {}
1524 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator(
1525 PictureLayerImpl* layer,
1526 TreePriority tree_priority)
1527 : iterator_index_(0),
1528 iteration_stage_(TilePriority::EVENTUALLY),
1529 required_for_activation_(false),
1530 layer_(layer) {
1531 // Early out if the layer has no tilings.
1532 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure
1533 // that layers that don't have valid tile priorities have lowest priorities so
1534 // they evict their tiles first (crbug.com/381704)
1535 if (!layer_->tilings_ || !layer_->tilings_->num_tilings())
1536 return;
1538 size_t high_res_tiling_index = layer_->tilings_->num_tilings();
1539 size_t low_res_tiling_index = layer_->tilings_->num_tilings();
1540 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) {
1541 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1542 if (tiling->resolution() == HIGH_RESOLUTION)
1543 high_res_tiling_index = i;
1544 else if (tiling->resolution() == LOW_RESOLUTION)
1545 low_res_tiling_index = i;
1548 iterators_.reserve(layer_->tilings_->num_tilings());
1550 // Higher resolution non-ideal goes first.
1551 for (size_t i = 0; i < high_res_tiling_index; ++i) {
1552 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1553 layer_->tilings_->tiling_at(i), tree_priority));
1556 // Lower resolution non-ideal goes next.
1557 for (size_t i = layer_->tilings_->num_tilings() - 1;
1558 i > high_res_tiling_index;
1559 --i) {
1560 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i);
1561 if (tiling->resolution() == LOW_RESOLUTION)
1562 continue;
1564 iterators_.push_back(
1565 PictureLayerTiling::TilingEvictionTileIterator(tiling, tree_priority));
1568 // Now, put the low res tiling if we have one.
1569 if (low_res_tiling_index < layer_->tilings_->num_tilings()) {
1570 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1571 layer_->tilings_->tiling_at(low_res_tiling_index), tree_priority));
1574 // Finally, put the high res tiling if we have one.
1575 if (high_res_tiling_index < layer_->tilings_->num_tilings()) {
1576 iterators_.push_back(PictureLayerTiling::TilingEvictionTileIterator(
1577 layer_->tilings_->tiling_at(high_res_tiling_index), tree_priority));
1580 DCHECK_GT(iterators_.size(), 0u);
1582 if (!iterators_[iterator_index_] ||
1583 !IsCorrectType(&iterators_[iterator_index_])) {
1584 AdvanceToNextIterator();
1588 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() {}
1590 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() {
1591 DCHECK(*this);
1592 return *iterators_[iterator_index_];
1595 PictureLayerImpl::LayerEvictionTileIterator&
1596 PictureLayerImpl::LayerEvictionTileIterator::
1597 operator++() {
1598 DCHECK(*this);
1599 ++iterators_[iterator_index_];
1600 if (!iterators_[iterator_index_] ||
1601 !IsCorrectType(&iterators_[iterator_index_])) {
1602 AdvanceToNextIterator();
1604 return *this;
1607 void PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextIterator() {
1608 ++iterator_index_;
1610 while (true) {
1611 while (iterator_index_ < iterators_.size()) {
1612 if (iterators_[iterator_index_] &&
1613 IsCorrectType(&iterators_[iterator_index_])) {
1614 return;
1616 ++iterator_index_;
1619 // If we're NOW and required_for_activation, then this was the last pass
1620 // through the iterators.
1621 if (iteration_stage_ == TilePriority::NOW && required_for_activation_)
1622 break;
1624 if (!required_for_activation_) {
1625 required_for_activation_ = true;
1626 } else {
1627 required_for_activation_ = false;
1628 iteration_stage_ =
1629 static_cast<TilePriority::PriorityBin>(iteration_stage_ - 1);
1631 iterator_index_ = 0;
1635 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const {
1636 return iterator_index_ < iterators_.size();
1639 bool PictureLayerImpl::LayerEvictionTileIterator::IsCorrectType(
1640 PictureLayerTiling::TilingEvictionTileIterator* it) const {
1641 return it->get_type() == iteration_stage_ &&
1642 (**it)->required_for_activation() == required_for_activation_;
1645 } // namespace cc