Connect PPAPI IPC channels for non-SFI mode.
[chromium-blink-merge.git] / cc / layers / picture_layer_impl.cc
blobfc8647c06672435caf30524513c896e74b9ba2d7
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/layers/quad_sink.h"
18 #include "cc/quads/checkerboard_draw_quad.h"
19 #include "cc/quads/debug_border_draw_quad.h"
20 #include "cc/quads/picture_draw_quad.h"
21 #include "cc/quads/solid_color_draw_quad.h"
22 #include "cc/quads/tile_draw_quad.h"
23 #include "cc/resources/tile_manager.h"
24 #include "cc/trees/layer_tree_impl.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 = 0.2f;
37 namespace cc {
39 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
40 : LayerImpl(tree_impl, id),
41 twin_layer_(NULL),
42 pile_(PicturePileImpl::Create()),
43 is_mask_(false),
44 ideal_page_scale_(0.f),
45 ideal_device_scale_(0.f),
46 ideal_source_scale_(0.f),
47 ideal_contents_scale_(0.f),
48 raster_page_scale_(0.f),
49 raster_device_scale_(0.f),
50 raster_source_scale_(0.f),
51 raster_contents_scale_(0.f),
52 low_res_raster_contents_scale_(0.f),
53 raster_source_scale_was_animating_(false),
54 is_using_lcd_text_(tree_impl->settings().can_use_lcd_text),
55 needs_post_commit_initialization_(true),
56 should_update_tile_priorities_(false),
57 should_use_gpu_rasterization_(tree_impl->settings().gpu_rasterization) {}
59 PictureLayerImpl::~PictureLayerImpl() {}
61 const char* PictureLayerImpl::LayerTypeAsString() const {
62 return "cc::PictureLayerImpl";
65 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
66 LayerTreeImpl* tree_impl) {
67 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
70 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
71 // It's possible this layer was never drawn or updated (e.g. because it was
72 // a descendant of an opacity 0 layer).
73 DoPostCommitInitializationIfNeeded();
74 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
76 // We have already synced the important bits from the the active layer, and
77 // we will soon swap out its tilings and use them for recycling. However,
78 // there are now tiles in this layer's tilings that were unref'd and replaced
79 // with new tiles (due to invalidation). This resets all active priorities on
80 // the to-be-recycled tiling to ensure replaced tiles don't linger and take
81 // memory (due to a stale 'active' priority).
82 if (layer_impl->tilings_)
83 layer_impl->tilings_->DidBecomeRecycled();
85 LayerImpl::PushPropertiesTo(base_layer);
87 // When the pending tree pushes to the active tree, the pending twin
88 // disappears.
89 layer_impl->twin_layer_ = NULL;
90 twin_layer_ = NULL;
92 layer_impl->SetIsMask(is_mask_);
93 layer_impl->pile_ = pile_;
95 // Tilings would be expensive to push, so we swap. This optimization requires
96 // an extra invalidation in SyncFromActiveLayer.
97 layer_impl->tilings_.swap(tilings_);
98 layer_impl->tilings_->SetClient(layer_impl);
99 if (tilings_)
100 tilings_->SetClient(this);
102 layer_impl->raster_page_scale_ = raster_page_scale_;
103 layer_impl->raster_device_scale_ = raster_device_scale_;
104 layer_impl->raster_source_scale_ = raster_source_scale_;
105 layer_impl->raster_contents_scale_ = raster_contents_scale_;
106 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
108 layer_impl->UpdateLCDTextStatus(is_using_lcd_text_);
109 layer_impl->needs_post_commit_initialization_ = false;
111 // The invalidation on this soon-to-be-recycled layer must be cleared to
112 // mirror clearing the invalidation in PictureLayer's version of this function
113 // in case push properties is skipped.
114 layer_impl->invalidation_.Swap(&invalidation_);
115 invalidation_.Clear();
116 needs_post_commit_initialization_ = true;
118 // We always need to push properties.
119 // See http://crbug.com/303943
120 needs_push_properties_ = true;
123 void PictureLayerImpl::AppendQuads(QuadSink* quad_sink,
124 AppendQuadsData* append_quads_data) {
125 DCHECK(!needs_post_commit_initialization_);
126 gfx::Rect rect(visible_content_rect());
127 gfx::Rect content_rect(content_bounds());
129 SharedQuadState* shared_quad_state =
130 quad_sink->UseSharedQuadState(CreateSharedQuadState());
132 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
133 AppendDebugBorderQuad(
134 quad_sink,
135 shared_quad_state,
136 append_quads_data,
137 DebugColors::DirectPictureBorderColor(),
138 DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
140 gfx::Rect geometry_rect = rect;
141 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
142 gfx::Size texture_size = rect.size();
143 gfx::RectF texture_rect = gfx::RectF(texture_size);
144 gfx::Rect quad_content_rect = rect;
145 float contents_scale = contents_scale_x();
147 scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
148 quad->SetNew(shared_quad_state,
149 geometry_rect,
150 opaque_rect,
151 texture_rect,
152 texture_size,
153 RGBA_8888,
154 quad_content_rect,
155 contents_scale,
156 pile_);
157 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data))
158 append_quads_data->num_missing_tiles++;
159 return;
162 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
164 if (ShowDebugBorders()) {
165 for (PictureLayerTilingSet::CoverageIterator iter(
166 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_);
167 iter;
168 ++iter) {
169 SkColor color;
170 float width;
171 if (*iter && iter->IsReadyToDraw()) {
172 ManagedTileState::TileVersion::Mode mode =
173 iter->GetTileVersionForDrawing().mode();
174 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) {
175 color = DebugColors::SolidColorTileBorderColor();
176 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
177 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) {
178 color = DebugColors::PictureTileBorderColor();
179 width = DebugColors::PictureTileBorderWidth(layer_tree_impl());
180 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
181 color = DebugColors::HighResTileBorderColor();
182 width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
183 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
184 color = DebugColors::LowResTileBorderColor();
185 width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
186 } else if (iter->contents_scale() > contents_scale_x()) {
187 color = DebugColors::ExtraHighResTileBorderColor();
188 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
189 } else {
190 color = DebugColors::ExtraLowResTileBorderColor();
191 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
193 } else {
194 color = DebugColors::MissingTileBorderColor();
195 width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
198 scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
199 DebugBorderDrawQuad::Create();
200 gfx::Rect geometry_rect = iter.geometry_rect();
201 debug_border_quad->SetNew(shared_quad_state, geometry_rect, color, width);
202 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(),
203 append_quads_data);
207 // Keep track of the tilings that were used so that tilings that are
208 // unused can be considered for removal.
209 std::vector<PictureLayerTiling*> seen_tilings;
211 for (PictureLayerTilingSet::CoverageIterator iter(
212 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_);
213 iter;
214 ++iter) {
215 gfx::Rect geometry_rect = iter.geometry_rect();
216 if (!*iter || !iter->IsReadyToDraw()) {
217 if (DrawCheckerboardForMissingTiles()) {
218 // TODO(enne): Figure out how to show debug "invalidated checker" color
219 scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create();
220 SkColor color = DebugColors::DefaultCheckerboardColor();
221 quad->SetNew(shared_quad_state, geometry_rect, color);
222 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data))
223 append_quads_data->num_missing_tiles++;
224 } else {
225 SkColor color = SafeOpaqueBackgroundColor();
226 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
227 quad->SetNew(shared_quad_state, geometry_rect, color, false);
228 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data))
229 append_quads_data->num_missing_tiles++;
232 append_quads_data->had_incomplete_tile = true;
233 continue;
236 const ManagedTileState::TileVersion& tile_version =
237 iter->GetTileVersionForDrawing();
238 scoped_ptr<DrawQuad> draw_quad;
239 switch (tile_version.mode()) {
240 case ManagedTileState::TileVersion::RESOURCE_MODE: {
241 gfx::RectF texture_rect = iter.texture_rect();
242 gfx::Rect opaque_rect = iter->opaque_rect();
243 opaque_rect.Intersect(geometry_rect);
245 if (iter->contents_scale() != ideal_contents_scale_)
246 append_quads_data->had_incomplete_tile = true;
248 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
249 quad->SetNew(shared_quad_state,
250 geometry_rect,
251 opaque_rect,
252 tile_version.get_resource_id(),
253 texture_rect,
254 iter.texture_size(),
255 tile_version.contents_swizzled());
256 draw_quad = quad.PassAs<DrawQuad>();
257 break;
259 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: {
260 gfx::RectF texture_rect = iter.texture_rect();
261 gfx::Rect opaque_rect = iter->opaque_rect();
262 opaque_rect.Intersect(geometry_rect);
264 ResourceProvider* resource_provider =
265 layer_tree_impl()->resource_provider();
266 ResourceFormat format =
267 resource_provider->memory_efficient_texture_format();
268 scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create();
269 quad->SetNew(shared_quad_state,
270 geometry_rect,
271 opaque_rect,
272 texture_rect,
273 iter.texture_size(),
274 format,
275 iter->content_rect(),
276 iter->contents_scale(),
277 pile_);
278 draw_quad = quad.PassAs<DrawQuad>();
279 break;
281 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: {
282 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
283 quad->SetNew(shared_quad_state,
284 geometry_rect,
285 tile_version.get_solid_color(),
286 false);
287 draw_quad = quad.PassAs<DrawQuad>();
288 break;
292 DCHECK(draw_quad);
293 quad_sink->Append(draw_quad.Pass(), append_quads_data);
295 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling())
296 seen_tilings.push_back(iter.CurrentTiling());
299 // Aggressively remove any tilings that are not seen to save memory. Note
300 // that this is at the expense of doing cause more frequent re-painting. A
301 // better scheme would be to maintain a tighter visible_content_rect for the
302 // finer tilings.
303 CleanUpTilingsOnActiveLayer(seen_tilings);
306 void PictureLayerImpl::UpdateTilePriorities() {
307 DCHECK(!needs_post_commit_initialization_);
308 CHECK(should_update_tile_priorities_);
310 if (!layer_tree_impl()->device_viewport_valid_for_tile_management()) {
311 for (size_t i = 0; i < tilings_->num_tilings(); ++i)
312 DCHECK(tilings_->tiling_at(i)->has_ever_been_updated());
313 return;
316 if (!tilings_->num_tilings())
317 return;
319 double current_frame_time_in_seconds =
320 (layer_tree_impl()->CurrentFrameTimeTicks() -
321 base::TimeTicks()).InSecondsF();
323 bool tiling_needs_update = false;
324 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
325 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime(
326 current_frame_time_in_seconds)) {
327 tiling_needs_update = true;
328 break;
331 if (!tiling_needs_update)
332 return;
334 UpdateLCDTextStatus(can_use_lcd_text());
336 // Use visible_content_rect, unless it's empty. If it's empty, then
337 // try to inverse project the viewport into layer space and use that.
338 gfx::Rect visible_rect_in_content_space = visible_content_rect();
339 if (visible_rect_in_content_space.IsEmpty()) {
340 gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization);
341 if (screen_space_transform().GetInverse(&screen_to_layer)) {
342 gfx::Size viewport_size = layer_tree_impl()->DrawViewportSize();
343 visible_rect_in_content_space =
344 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
345 screen_to_layer, gfx::Rect(viewport_size)));
346 visible_rect_in_content_space.Intersect(gfx::Rect(content_bounds()));
350 WhichTree tree =
351 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
353 tilings_->UpdateTilePriorities(tree,
354 visible_rect_in_content_space,
355 contents_scale_x(),
356 current_frame_time_in_seconds);
358 if (layer_tree_impl()->IsPendingTree())
359 MarkVisibleResourcesAsRequired();
361 // Tile priorities were modified.
362 layer_tree_impl()->DidModifyTilePriorities();
365 void PictureLayerImpl::DidBecomeActive() {
366 LayerImpl::DidBecomeActive();
367 tilings_->DidBecomeActive();
368 layer_tree_impl()->DidModifyTilePriorities();
371 void PictureLayerImpl::DidBeginTracing() {
372 pile_->DidBeginTracing();
375 void PictureLayerImpl::ReleaseResources() {
376 if (tilings_)
377 RemoveAllTilings();
379 ResetRasterScale();
382 void PictureLayerImpl::CalculateContentsScale(
383 float ideal_contents_scale,
384 float device_scale_factor,
385 float page_scale_factor,
386 bool animating_transform_to_screen,
387 float* contents_scale_x,
388 float* contents_scale_y,
389 gfx::Size* content_bounds) {
390 DoPostCommitInitializationIfNeeded();
392 // This function sets valid raster scales and manages tilings, so tile
393 // priorities can now be updated.
394 should_update_tile_priorities_ = true;
396 if (!CanHaveTilings()) {
397 ideal_page_scale_ = page_scale_factor;
398 ideal_device_scale_ = device_scale_factor;
399 ideal_contents_scale_ = ideal_contents_scale;
400 ideal_source_scale_ =
401 ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_;
402 *contents_scale_x = ideal_contents_scale_;
403 *contents_scale_y = ideal_contents_scale_;
404 *content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(),
405 ideal_contents_scale_,
406 ideal_contents_scale_));
407 return;
410 float min_contents_scale = MinimumContentsScale();
411 DCHECK_GT(min_contents_scale, 0.f);
412 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
413 DCHECK_GT(min_page_scale, 0.f);
414 float min_device_scale = 1.f;
415 float min_source_scale =
416 min_contents_scale / min_page_scale / min_device_scale;
418 float ideal_page_scale = page_scale_factor;
419 float ideal_device_scale = device_scale_factor;
420 float ideal_source_scale =
421 ideal_contents_scale / ideal_page_scale / ideal_device_scale;
423 ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale);
424 ideal_page_scale_ = ideal_page_scale;
425 ideal_device_scale_ = ideal_device_scale;
426 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
428 ManageTilings(animating_transform_to_screen);
430 // The content scale and bounds for a PictureLayerImpl is somewhat fictitious.
431 // There are (usually) several tilings at different scales. However, the
432 // content bounds is the (integer!) space in which quads are generated.
433 // In order to guarantee that we can fill this integer space with any set of
434 // tilings (and then map back to floating point texture coordinates), the
435 // contents scale must be at least as large as the largest of the tilings.
436 float max_contents_scale = min_contents_scale;
437 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
438 const PictureLayerTiling* tiling = tilings_->tiling_at(i);
439 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
442 *contents_scale_x = max_contents_scale;
443 *contents_scale_y = max_contents_scale;
444 *content_bounds = gfx::ToCeiledSize(
445 gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale));
448 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
449 return pile_->GetFlattenedPicture();
452 void PictureLayerImpl::SetShouldUseGpuRasterization(
453 bool should_use_gpu_rasterization) {
454 if (should_use_gpu_rasterization != should_use_gpu_rasterization_) {
455 should_use_gpu_rasterization_ = should_use_gpu_rasterization;
456 RemoveAllTilings();
457 } else {
458 should_use_gpu_rasterization_ = should_use_gpu_rasterization;
462 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
463 const gfx::Rect& content_rect) {
464 if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
465 return scoped_refptr<Tile>();
467 int flags = 0;
468 if (is_using_lcd_text_)
469 flags |= Tile::USE_LCD_TEXT;
470 if (should_use_gpu_rasterization())
471 flags |= Tile::USE_GPU_RASTERIZATION;
472 return layer_tree_impl()->tile_manager()->CreateTile(
473 pile_.get(),
474 content_rect.size(),
475 content_rect,
476 contents_opaque() ? content_rect : gfx::Rect(),
477 tiling->contents_scale(),
478 id(),
479 layer_tree_impl()->source_frame_number(),
480 flags);
483 void PictureLayerImpl::UpdatePile(Tile* tile) {
484 tile->set_picture_pile(pile_);
487 const Region* PictureLayerImpl::GetInvalidation() {
488 return &invalidation_;
491 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
492 const PictureLayerTiling* tiling) const {
494 if (!twin_layer_ || twin_layer_->should_use_gpu_rasterization() !=
495 should_use_gpu_rasterization())
496 return NULL;
497 for (size_t i = 0; i < twin_layer_->tilings_->num_tilings(); ++i)
498 if (twin_layer_->tilings_->tiling_at(i)->contents_scale() ==
499 tiling->contents_scale())
500 return twin_layer_->tilings_->tiling_at(i);
501 return NULL;
504 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const {
505 return layer_tree_impl()->settings().max_tiles_for_interest_area;
508 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const {
509 return layer_tree_impl()->settings().skewport_target_time_in_seconds;
512 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const {
513 return layer_tree_impl()
514 ->settings()
515 .skewport_extrapolation_limit_in_content_pixels;
518 gfx::Size PictureLayerImpl::CalculateTileSize(
519 const gfx::Size& content_bounds) const {
520 if (is_mask_) {
521 int max_size = layer_tree_impl()->MaxTextureSize();
522 return gfx::Size(
523 std::min(max_size, content_bounds.width()),
524 std::min(max_size, content_bounds.height()));
527 int max_texture_size =
528 layer_tree_impl()->resource_provider()->max_texture_size();
530 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size;
531 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size));
533 gfx::Size max_untiled_content_size =
534 layer_tree_impl()->settings().max_untiled_layer_size;
535 max_untiled_content_size.SetToMin(
536 gfx::Size(max_texture_size, max_texture_size));
538 bool any_dimension_too_large =
539 content_bounds.width() > max_untiled_content_size.width() ||
540 content_bounds.height() > max_untiled_content_size.height();
542 bool any_dimension_one_tile =
543 content_bounds.width() <= default_tile_size.width() ||
544 content_bounds.height() <= default_tile_size.height();
546 // If long and skinny, tile at the max untiled content size, and clamp
547 // the smaller dimension to the content size, e.g. 1000x12 layer with
548 // 500x500 max untiled size would get 500x12 tiles. Also do this
549 // if the layer is small.
550 if (any_dimension_one_tile || !any_dimension_too_large) {
551 int width =
552 std::min(max_untiled_content_size.width(), content_bounds.width());
553 int height =
554 std::min(max_untiled_content_size.height(), content_bounds.height());
555 // Round width and height up to the closest multiple of 64, or 56 if
556 // we should avoid power-of-two textures. This helps reduce the number
557 // of different textures sizes to help recycling, and also keeps all
558 // textures multiple-of-eight, which is preferred on some drivers (IMG).
559 bool avoid_pow2 =
560 layer_tree_impl()->GetRendererCapabilities().avoid_pow2_textures;
561 int round_up_to = avoid_pow2 ? 56 : 64;
562 width = RoundUp(width, round_up_to);
563 height = RoundUp(height, round_up_to);
564 return gfx::Size(width, height);
567 return default_tile_size;
570 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
571 DCHECK(!other->needs_post_commit_initialization_);
572 DCHECK(other->tilings_);
574 UpdateLCDTextStatus(other->is_using_lcd_text_);
576 if (!DrawsContent()) {
577 RemoveAllTilings();
578 return;
581 raster_page_scale_ = other->raster_page_scale_;
582 raster_device_scale_ = other->raster_device_scale_;
583 raster_source_scale_ = other->raster_source_scale_;
584 raster_contents_scale_ = other->raster_contents_scale_;
585 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_;
587 // Add synthetic invalidations for any recordings that were dropped. As
588 // tiles are updated to point to this new pile, this will force the dropping
589 // of tiles that can no longer be rastered. This is not ideal, but is a
590 // trade-off for memory (use the same pile as much as possible, by switching
591 // during DidBecomeActive) and for time (don't bother checking every tile
592 // during activation to see if the new pile can still raster it).
593 for (int x = 0; x < pile_->num_tiles_x(); ++x) {
594 for (int y = 0; y < pile_->num_tiles_y(); ++y) {
595 bool previously_had = other->pile_->HasRecordingAt(x, y);
596 bool now_has = pile_->HasRecordingAt(x, y);
597 if (now_has || !previously_had)
598 continue;
599 gfx::Rect layer_rect = pile_->tile_bounds(x, y);
600 invalidation_.Union(layer_rect);
604 // Union in the other newly exposed regions as invalid.
605 Region difference_region = Region(gfx::Rect(bounds()));
606 difference_region.Subtract(gfx::Rect(other->bounds()));
607 invalidation_.Union(difference_region);
609 if (CanHaveTilings()) {
610 // The recycle tree's tiling set is two frames out of date, so it needs to
611 // have both this frame's invalidation and the previous frame's invalidation
612 // (stored on the active layer).
613 Region tiling_invalidation = other->invalidation_;
614 tiling_invalidation.Union(invalidation_);
615 tilings_->SyncTilings(*other->tilings_,
616 bounds(),
617 tiling_invalidation,
618 MinimumContentsScale());
619 } else {
620 RemoveAllTilings();
623 SanityCheckTilingState();
626 void PictureLayerImpl::SyncTiling(
627 const PictureLayerTiling* tiling) {
628 if (!CanHaveTilingWithScale(tiling->contents_scale()))
629 return;
630 tilings_->AddTiling(tiling->contents_scale());
632 // If this tree needs update draw properties, then the tiling will
633 // get updated prior to drawing or activation. If this tree does not
634 // need update draw properties, then its transforms are up to date and
635 // we can create tiles for this tiling immediately.
636 if (!layer_tree_impl()->needs_update_draw_properties() &&
637 should_update_tile_priorities_)
638 UpdateTilePriorities();
641 void PictureLayerImpl::SetIsMask(bool is_mask) {
642 if (is_mask_ == is_mask)
643 return;
644 is_mask_ = is_mask;
645 if (tilings_)
646 tilings_->RemoveAllTiles();
649 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
650 gfx::Rect content_rect(content_bounds());
651 float scale = contents_scale_x();
652 PictureLayerTilingSet::CoverageIterator iter(
653 tilings_.get(), scale, content_rect, ideal_contents_scale_);
655 // Mask resource not ready yet.
656 if (!iter || !*iter)
657 return 0;
659 // Masks only supported if they fit on exactly one tile.
660 if (iter.geometry_rect() != content_rect)
661 return 0;
663 const ManagedTileState::TileVersion& tile_version =
664 iter->GetTileVersionForDrawing();
665 if (!tile_version.IsReadyToDraw() ||
666 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE)
667 return 0;
669 return tile_version.get_resource_id();
672 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const {
673 DCHECK(layer_tree_impl()->IsPendingTree());
674 DCHECK(!layer_tree_impl()->needs_update_draw_properties());
675 DCHECK(ideal_contents_scale_);
676 DCHECK_GT(tilings_->num_tilings(), 0u);
678 // The goal of this function is to find the minimum set of tiles that need to
679 // be ready to draw in order to activate without flashing content from a
680 // higher res on the active tree to a lower res on the pending tree.
682 gfx::Rect rect(visible_content_rect());
684 float min_acceptable_scale =
685 std::min(raster_contents_scale_, ideal_contents_scale_);
687 if (PictureLayerImpl* twin = twin_layer_) {
688 float twin_min_acceptable_scale =
689 std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_);
690 // Ignore 0 scale in case CalculateContentsScale() has never been
691 // called for active twin.
692 if (twin_min_acceptable_scale != 0.0f) {
693 min_acceptable_scale =
694 std::min(min_acceptable_scale, twin_min_acceptable_scale);
698 PictureLayerTiling* high_res = NULL;
699 PictureLayerTiling* low_res = NULL;
701 // First pass: ready to draw tiles in acceptable but non-ideal tilings are
702 // marked as required for activation so that their textures are not thrown
703 // away; any non-ready tiles are not marked as required.
704 Region missing_region = rect;
705 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
706 PictureLayerTiling* tiling = tilings_->tiling_at(i);
707 DCHECK(tiling->has_ever_been_updated());
709 if (tiling->resolution() == LOW_RESOLUTION) {
710 DCHECK(!low_res) << "There can only be one low res tiling";
711 low_res = tiling;
713 if (tiling->contents_scale() < min_acceptable_scale)
714 continue;
715 if (tiling->resolution() == HIGH_RESOLUTION) {
716 DCHECK(!high_res) << "There can only be one high res tiling";
717 high_res = tiling;
718 continue;
720 for (PictureLayerTiling::CoverageIterator iter(tiling,
721 contents_scale_x(),
722 rect);
723 iter;
724 ++iter) {
725 if (!*iter || !iter->IsReadyToDraw())
726 continue;
728 missing_region.Subtract(iter.geometry_rect());
729 iter->MarkRequiredForActivation();
732 DCHECK(high_res) << "There must be one high res tiling";
734 // If these pointers are null (because no twin, no matching tiling, or the
735 // simpification just below), then high res tiles will be required to fill any
736 // holes left by the first pass above. If the pointers are valid, then this
737 // layer is allowed to skip any tiles that are not ready on its twin.
738 const PictureLayerTiling* twin_high_res = NULL;
739 const PictureLayerTiling* twin_low_res = NULL;
741 // As a simplification, only allow activating to skip twin tiles that the
742 // active layer is also missing when both this layer and its twin have 2
743 // tilings (high and low). This avoids having to iterate/track coverage of
744 // non-ideal tilings during the last draw call on the active layer.
745 if (high_res && low_res && tilings_->num_tilings() == 2 &&
746 twin_layer_ && twin_layer_->tilings_->num_tilings() == 2) {
747 twin_low_res = GetTwinTiling(low_res);
748 if (twin_low_res)
749 twin_high_res = GetTwinTiling(high_res);
751 // If this layer and its twin have different transforms, then don't compare
752 // them and only allow activating to high res tiles, since tiles on each layer
753 // will be in different places on screen.
754 if (!twin_high_res || !twin_low_res ||
755 twin_layer_->layer_tree_impl()->RequiresHighResToDraw() ||
756 draw_properties().screen_space_transform !=
757 twin_layer_->draw_properties().screen_space_transform) {
758 twin_high_res = NULL;
759 twin_low_res = NULL;
762 // As a second pass, mark as required any visible high res tiles not filled in
763 // by acceptable non-ideal tiles from the first pass.
764 if (MarkVisibleTilesAsRequired(
765 high_res, twin_high_res, contents_scale_x(), rect, missing_region)) {
766 // As an optional third pass, if a high res tile was skipped because its
767 // twin was also missing, then fall back to mark low res tiles as required
768 // in case the active twin is substituting those for missing high res
769 // content.
770 MarkVisibleTilesAsRequired(
771 low_res, twin_low_res, contents_scale_x(), rect, missing_region);
775 bool PictureLayerImpl::MarkVisibleTilesAsRequired(
776 PictureLayerTiling* tiling,
777 const PictureLayerTiling* optional_twin_tiling,
778 float contents_scale,
779 const gfx::Rect& rect,
780 const Region& missing_region) const {
781 bool twin_had_missing_tile = false;
782 for (PictureLayerTiling::CoverageIterator iter(tiling,
783 contents_scale,
784 rect);
785 iter;
786 ++iter) {
787 Tile* tile = *iter;
788 // A null tile (i.e. missing recording) can just be skipped.
789 if (!tile)
790 continue;
792 // If the missing region doesn't cover it, this tile is fully
793 // covered by acceptable tiles at other scales.
794 if (!missing_region.Intersects(iter.geometry_rect()))
795 continue;
797 // If the twin tile doesn't exist (i.e. missing recording or so far away
798 // that it is outside the visible tile rect) or this tile is shared between
799 // with the twin, then this tile isn't required to prevent flashing.
800 if (optional_twin_tiling) {
801 Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j());
802 if (!twin_tile || twin_tile == tile) {
803 twin_had_missing_tile = true;
804 continue;
808 tile->MarkRequiredForActivation();
810 return twin_had_missing_tile;
813 void PictureLayerImpl::DoPostCommitInitialization() {
814 DCHECK(needs_post_commit_initialization_);
815 DCHECK(layer_tree_impl()->IsPendingTree());
817 if (!tilings_)
818 tilings_.reset(new PictureLayerTilingSet(this, bounds()));
820 DCHECK(!twin_layer_);
821 twin_layer_ = static_cast<PictureLayerImpl*>(
822 layer_tree_impl()->FindActiveTreeLayerById(id()));
823 if (twin_layer_) {
824 DCHECK(!twin_layer_->twin_layer_);
825 twin_layer_->twin_layer_ = this;
826 // If the twin has never been pushed to, do not sync from it.
827 // This can happen if this function is called during activation.
828 if (!twin_layer_->needs_post_commit_initialization_)
829 SyncFromActiveLayer(twin_layer_);
832 needs_post_commit_initialization_ = false;
835 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
836 DCHECK(CanHaveTilingWithScale(contents_scale)) <<
837 "contents_scale: " << contents_scale;
839 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
841 const Region& recorded = pile_->recorded_region();
842 DCHECK(!recorded.IsEmpty());
844 if (twin_layer_ && twin_layer_->should_use_gpu_rasterization() ==
845 should_use_gpu_rasterization())
846 twin_layer_->SyncTiling(tiling);
848 return tiling;
851 void PictureLayerImpl::RemoveTiling(float contents_scale) {
852 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
853 PictureLayerTiling* tiling = tilings_->tiling_at(i);
854 if (tiling->contents_scale() == contents_scale) {
855 tilings_->Remove(tiling);
856 break;
859 if (tilings_->num_tilings() == 0)
860 ResetRasterScale();
861 SanityCheckTilingState();
864 void PictureLayerImpl::RemoveAllTilings() {
865 tilings_->RemoveAllTilings();
866 // If there are no tilings, then raster scales are no longer meaningful.
867 ResetRasterScale();
870 namespace {
872 inline float PositiveRatio(float float1, float float2) {
873 DCHECK_GT(float1, 0);
874 DCHECK_GT(float2, 0);
875 return float1 > float2 ? float1 / float2 : float2 / float1;
878 } // namespace
880 void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
881 DCHECK(ideal_contents_scale_);
882 DCHECK(ideal_page_scale_);
883 DCHECK(ideal_device_scale_);
884 DCHECK(ideal_source_scale_);
885 DCHECK(CanHaveTilings());
886 DCHECK(!needs_post_commit_initialization_);
888 bool change_target_tiling =
889 raster_page_scale_ == 0.f ||
890 raster_device_scale_ == 0.f ||
891 raster_source_scale_ == 0.f ||
892 raster_contents_scale_ == 0.f ||
893 low_res_raster_contents_scale_ == 0.f ||
894 ShouldAdjustRasterScale(animating_transform_to_screen);
896 if (tilings_->num_tilings() == 0) {
897 DCHECK(change_target_tiling)
898 << "A layer with no tilings shouldn't have valid raster scales";
901 // Store the value for the next time ShouldAdjustRasterScale is called.
902 raster_source_scale_was_animating_ = animating_transform_to_screen;
904 if (!change_target_tiling)
905 return;
907 if (!layer_tree_impl()->device_viewport_valid_for_tile_management())
908 return;
910 RecalculateRasterScales(animating_transform_to_screen);
912 PictureLayerTiling* high_res = NULL;
913 PictureLayerTiling* low_res = NULL;
915 PictureLayerTiling* previous_low_res = NULL;
916 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
917 PictureLayerTiling* tiling = tilings_->tiling_at(i);
918 if (tiling->contents_scale() == raster_contents_scale_)
919 high_res = tiling;
920 if (tiling->contents_scale() == low_res_raster_contents_scale_)
921 low_res = tiling;
922 if (tiling->resolution() == LOW_RESOLUTION)
923 previous_low_res = tiling;
925 // Reset all tilings to non-ideal until the end of this function.
926 tiling->set_resolution(NON_IDEAL_RESOLUTION);
929 if (!high_res) {
930 high_res = AddTiling(raster_contents_scale_);
931 if (raster_contents_scale_ == low_res_raster_contents_scale_)
932 low_res = high_res;
935 // Only create new low res tilings when the transform is static. This
936 // prevents wastefully creating a paired low res tiling for every new high res
937 // tiling during a pinch or a CSS animation.
938 bool is_pinching = layer_tree_impl()->PinchGestureActive();
939 if (ShouldHaveLowResTiling() && !is_pinching &&
940 !animating_transform_to_screen &&
941 !low_res && low_res != high_res)
942 low_res = AddTiling(low_res_raster_contents_scale_);
944 // Set low-res if we have one.
945 if (!low_res)
946 low_res = previous_low_res;
947 if (low_res && low_res != high_res)
948 low_res->set_resolution(LOW_RESOLUTION);
950 // Make sure we always have one high-res (even if high == low).
951 high_res->set_resolution(HIGH_RESOLUTION);
953 SanityCheckTilingState();
956 bool PictureLayerImpl::ShouldAdjustRasterScale(
957 bool animating_transform_to_screen) const {
958 // TODO(danakj): Adjust raster source scale closer to ideal source scale at
959 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
960 // tree. This will allow CSS scale changes to get re-rastered at an
961 // appropriate rate.
963 if (raster_source_scale_was_animating_ && !animating_transform_to_screen)
964 return true;
966 bool is_pinching = layer_tree_impl()->PinchGestureActive();
967 if (is_pinching && raster_page_scale_) {
968 // We change our raster scale when it is:
969 // - Higher than ideal (need a lower-res tiling available)
970 // - Too far from ideal (need a higher-res tiling available)
971 float ratio = ideal_page_scale_ / raster_page_scale_;
972 if (raster_page_scale_ > ideal_page_scale_ ||
973 ratio > kMaxScaleRatioDuringPinch)
974 return true;
977 if (!is_pinching) {
978 // When not pinching, match the ideal page scale factor.
979 if (raster_page_scale_ != ideal_page_scale_)
980 return true;
983 // Always match the ideal device scale factor.
984 if (raster_device_scale_ != ideal_device_scale_)
985 return true;
987 return false;
990 float PictureLayerImpl::SnappedContentsScale(float scale) {
991 // If a tiling exists within the max snapping ratio, snap to its scale.
992 float snapped_contents_scale = scale;
993 float snapped_ratio = kSnapToExistingTilingRatio;
994 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
995 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale();
996 float ratio = PositiveRatio(tiling_contents_scale, scale);
997 if (ratio < snapped_ratio) {
998 snapped_contents_scale = tiling_contents_scale;
999 snapped_ratio = ratio;
1002 return snapped_contents_scale;
1005 void PictureLayerImpl::RecalculateRasterScales(
1006 bool animating_transform_to_screen) {
1007 raster_device_scale_ = ideal_device_scale_;
1008 raster_source_scale_ = ideal_source_scale_;
1010 bool is_pinching = layer_tree_impl()->PinchGestureActive();
1011 if (!is_pinching || raster_contents_scale_ == 0.f) {
1012 // When not pinching or when we have no previous scale, we use ideal scale:
1013 raster_page_scale_ = ideal_page_scale_;
1014 raster_contents_scale_ = ideal_contents_scale_;
1015 } else {
1016 // See ShouldAdjustRasterScale:
1017 // - When zooming out, preemptively create new tiling at lower resolution.
1018 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
1019 bool zooming_out = raster_page_scale_ > ideal_page_scale_;
1020 float desired_contents_scale =
1021 zooming_out ? raster_contents_scale_ / kMaxScaleRatioDuringPinch
1022 : raster_contents_scale_ * kMaxScaleRatioDuringPinch;
1023 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale);
1024 raster_page_scale_ = raster_contents_scale_ / raster_device_scale_;
1027 raster_contents_scale_ =
1028 std::max(raster_contents_scale_, MinimumContentsScale());
1030 // Don't allow animating CSS scales to drop below 1. This is needed because
1031 // changes in raster source scale aren't handled. See the comment in
1032 // ShouldAdjustRasterScale.
1033 if (animating_transform_to_screen) {
1034 raster_contents_scale_ = std::max(
1035 raster_contents_scale_, 1.f * ideal_page_scale_ * ideal_device_scale_);
1038 // If this layer would only create one tile at this content scale,
1039 // don't create a low res tiling.
1040 gfx::Size content_bounds =
1041 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_));
1042 gfx::Size tile_size = CalculateTileSize(content_bounds);
1043 if (tile_size.width() >= content_bounds.width() &&
1044 tile_size.height() >= content_bounds.height()) {
1045 low_res_raster_contents_scale_ = raster_contents_scale_;
1046 return;
1049 float low_res_factor =
1050 layer_tree_impl()->settings().low_res_contents_scale_factor;
1051 low_res_raster_contents_scale_ = std::max(
1052 raster_contents_scale_ * low_res_factor,
1053 MinimumContentsScale());
1056 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
1057 std::vector<PictureLayerTiling*> used_tilings) {
1058 DCHECK(layer_tree_impl()->IsActiveTree());
1059 if (tilings_->num_tilings() == 0)
1060 return;
1062 float min_acceptable_high_res_scale = std::min(
1063 raster_contents_scale_, ideal_contents_scale_);
1064 float max_acceptable_high_res_scale = std::max(
1065 raster_contents_scale_, ideal_contents_scale_);
1067 PictureLayerImpl* twin = twin_layer_;
1068 if (twin) {
1069 min_acceptable_high_res_scale = std::min(
1070 min_acceptable_high_res_scale,
1071 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1072 max_acceptable_high_res_scale = std::max(
1073 max_acceptable_high_res_scale,
1074 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
1077 std::vector<PictureLayerTiling*> to_remove;
1078 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
1079 PictureLayerTiling* tiling = tilings_->tiling_at(i);
1081 // Keep multiple high resolution tilings even if not used to help
1082 // activate earlier at non-ideal resolutions.
1083 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
1084 tiling->contents_scale() <= max_acceptable_high_res_scale)
1085 continue;
1087 // Keep low resolution tilings, if the layer should have them.
1088 if (tiling->resolution() == LOW_RESOLUTION && ShouldHaveLowResTiling())
1089 continue;
1091 // Don't remove tilings that are being used (and thus would cause a flash.)
1092 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
1093 used_tilings.end())
1094 continue;
1096 to_remove.push_back(tiling);
1099 for (size_t i = 0; i < to_remove.size(); ++i) {
1100 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
1101 // Only remove tilings from the twin layer if they have
1102 // NON_IDEAL_RESOLUTION.
1103 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
1104 twin->RemoveTiling(to_remove[i]->contents_scale());
1105 tilings_->Remove(to_remove[i]);
1107 DCHECK_GT(tilings_->num_tilings(), 0u);
1109 SanityCheckTilingState();
1112 float PictureLayerImpl::MinimumContentsScale() const {
1113 float setting_min = layer_tree_impl()->settings().minimum_contents_scale;
1115 // If the contents scale is less than 1 / width (also for height),
1116 // then it will end up having less than one pixel of content in that
1117 // dimension. Bump the minimum contents scale up in this case to prevent
1118 // this from happening.
1119 int min_dimension = std::min(bounds().width(), bounds().height());
1120 if (!min_dimension)
1121 return setting_min;
1123 return std::max(1.f / min_dimension, setting_min);
1126 void PictureLayerImpl::UpdateLCDTextStatus(bool new_status) {
1127 // Once this layer is not using lcd text, don't switch back.
1128 if (!is_using_lcd_text_)
1129 return;
1131 if (is_using_lcd_text_ == new_status)
1132 return;
1134 is_using_lcd_text_ = new_status;
1135 tilings_->SetCanUseLCDText(is_using_lcd_text_);
1138 void PictureLayerImpl::ResetRasterScale() {
1139 raster_page_scale_ = 0.f;
1140 raster_device_scale_ = 0.f;
1141 raster_source_scale_ = 0.f;
1142 raster_contents_scale_ = 0.f;
1143 low_res_raster_contents_scale_ = 0.f;
1145 // When raster scales aren't valid, don't update tile priorities until
1146 // this layer has been updated via UpdateDrawProperties.
1147 should_update_tile_priorities_ = false;
1150 bool PictureLayerImpl::CanHaveTilings() const {
1151 if (!DrawsContent())
1152 return false;
1153 if (pile_->recorded_region().IsEmpty())
1154 return false;
1155 return true;
1158 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const {
1159 if (!CanHaveTilings())
1160 return false;
1161 if (contents_scale < MinimumContentsScale())
1162 return false;
1163 return true;
1166 void PictureLayerImpl::SanityCheckTilingState() const {
1167 if (!DCHECK_IS_ON())
1168 return;
1170 if (!CanHaveTilings()) {
1171 DCHECK_EQ(0u, tilings_->num_tilings());
1172 return;
1174 if (tilings_->num_tilings() == 0)
1175 return;
1177 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res
1178 // tiling to mark its tiles as being required for activation.
1179 DCHECK_EQ(1, tilings_->NumHighResTilings());
1182 void PictureLayerImpl::GetDebugBorderProperties(
1183 SkColor* color,
1184 float* width) const {
1185 *color = DebugColors::TiledContentLayerBorderColor();
1186 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
1189 void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
1190 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1191 LayerImpl::AsValueInto(state);
1192 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
1193 state->SetDouble("geometry_contents_scale", contents_scale_x());
1194 state->Set("tilings", tilings_->AsValue().release());
1195 state->Set("pictures", pile_->AsValue().release());
1196 state->Set("invalidation", invalidation_.AsValue().release());
1198 Region unrecorded_region(gfx::Rect(pile_->size()));
1199 unrecorded_region.Subtract(pile_->recorded_region());
1200 if (!unrecorded_region.IsEmpty())
1201 state->Set("unrecorded_region", unrecorded_region.AsValue().release());
1203 scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue);
1204 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
1205 contents_scale_x(),
1206 gfx::Rect(content_bounds()),
1207 ideal_contents_scale_);
1208 iter;
1209 ++iter) {
1210 scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue);
1211 tile_data->Set("geometry_rect",
1212 MathUtil::AsValue(iter.geometry_rect()).release());
1213 if (*iter)
1214 tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release());
1216 coverage_tiles->Append(tile_data.release());
1218 state->Set("coverage_tiles", coverage_tiles.release());
1219 state->SetBoolean("is_using_lcd_text", is_using_lcd_text_);
1222 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
1223 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
1224 return tilings_->GPUMemoryUsageInBytes();
1227 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1228 benchmark->RunOnLayer(this);
1231 } // namespace cc