Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(346)

Side by Side Diff: cc/picture_layer_impl.cc

Issue 12603013: Part 10 of cc/ directory shuffles: layers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/picture_layer_impl.h ('k') | cc/picture_layer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/picture_layer_impl.h"
6
7 #include "base/time.h"
8 #include "cc/append_quads_data.h"
9 #include "cc/base/math_util.h"
10 #include "cc/base/util.h"
11 #include "cc/debug/debug_colors.h"
12 #include "cc/quad_sink.h"
13 #include "cc/quads/checkerboard_draw_quad.h"
14 #include "cc/quads/debug_border_draw_quad.h"
15 #include "cc/quads/solid_color_draw_quad.h"
16 #include "cc/quads/tile_draw_quad.h"
17 #include "cc/trees/layer_tree_impl.h"
18 #include "ui/gfx/quad_f.h"
19 #include "ui/gfx/rect_conversions.h"
20 #include "ui/gfx/size_conversions.h"
21
22 namespace {
23 const float kMaxScaleRatioDuringPinch = 2.0f;
24 }
25
26 namespace cc {
27
28 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
29 : LayerImpl(tree_impl, id),
30 pile_(PicturePileImpl::Create()),
31 last_content_scale_(0),
32 ideal_contents_scale_(0),
33 is_mask_(false),
34 ideal_page_scale_(0.f),
35 ideal_device_scale_(0.f),
36 ideal_source_scale_(0.f),
37 raster_page_scale_(0.f),
38 raster_device_scale_(0.f),
39 raster_source_scale_(0.f),
40 raster_source_scale_was_animating_(false) {
41 }
42
43 PictureLayerImpl::~PictureLayerImpl() {
44 }
45
46 const char* PictureLayerImpl::LayerTypeAsString() const {
47 return "PictureLayer";
48 }
49
50 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
51 LayerTreeImpl* tree_impl) {
52 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
53 }
54
55 void PictureLayerImpl::CreateTilingSet() {
56 DCHECK(layer_tree_impl()->IsPendingTree());
57 DCHECK(!tilings_);
58 tilings_.reset(new PictureLayerTilingSet(this));
59 tilings_->SetLayerBounds(bounds());
60 }
61
62 void PictureLayerImpl::TransferTilingSet(
63 scoped_ptr<PictureLayerTilingSet> tilings) {
64 DCHECK(layer_tree_impl()->IsActiveTree());
65 tilings->SetClient(this);
66 tilings_ = tilings.Pass();
67 }
68
69 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
70 LayerImpl::PushPropertiesTo(base_layer);
71
72 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
73
74 layer_impl->SetIsMask(is_mask_);
75 layer_impl->TransferTilingSet(tilings_.Pass());
76 layer_impl->pile_ = pile_;
77 pile_ = PicturePileImpl::Create();
78
79 layer_impl->raster_page_scale_ = raster_page_scale_;
80 layer_impl->raster_device_scale_ = raster_device_scale_;
81 layer_impl->raster_source_scale_ = raster_source_scale_;
82 }
83
84
85 void PictureLayerImpl::AppendQuads(QuadSink* quadSink,
86 AppendQuadsData* appendQuadsData) {
87 const gfx::Rect& rect = visible_content_rect();
88 gfx::Rect content_rect(content_bounds());
89
90 SharedQuadState* sharedQuadState =
91 quadSink->UseSharedQuadState(CreateSharedQuadState());
92 AppendDebugBorderQuad(quadSink, sharedQuadState, appendQuadsData);
93
94 bool clipped = false;
95 gfx::QuadF target_quad = MathUtil::MapQuad(
96 draw_transform(),
97 gfx::QuadF(rect),
98 &clipped);
99 bool is_axis_aligned_in_target = !clipped && target_quad.IsRectilinear();
100
101 bool is_pixel_aligned = is_axis_aligned_in_target &&
102 draw_transform().IsIdentityOrIntegerTranslation();
103 PictureLayerTiling::LayerDeviceAlignment layerDeviceAlignment =
104 is_pixel_aligned ? PictureLayerTiling::LayerAlignedToDevice
105 : PictureLayerTiling::LayerNotAlignedToDevice;
106
107 if (ShowDebugBorders()) {
108 for (PictureLayerTilingSet::Iterator iter(tilings_.get(),
109 contents_scale_x(),
110 rect,
111 ideal_contents_scale_,
112 layerDeviceAlignment);
113 iter;
114 ++iter) {
115 SkColor color;
116 float width;
117 if (*iter && iter->drawing_info().IsReadyToDraw()) {
118 ManagedTileState::DrawingInfo::Mode mode = iter->drawing_info().mode();
119 if (mode == ManagedTileState::DrawingInfo::SOLID_COLOR_MODE ||
120 mode == ManagedTileState::DrawingInfo::TRANSPARENT_MODE) {
121 color = DebugColors::SolidColorTileBorderColor();
122 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl());
123 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) {
124 color = DebugColors::HighResTileBorderColor();
125 width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
126 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) {
127 color = DebugColors::LowResTileBorderColor();
128 width = DebugColors::LowResTileBorderWidth(layer_tree_impl());
129 } else if (iter->contents_scale() > contents_scale_x()) {
130 color = DebugColors::ExtraHighResTileBorderColor();
131 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl());
132 } else {
133 color = DebugColors::ExtraLowResTileBorderColor();
134 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl());
135 }
136 } else {
137 color = DebugColors::MissingTileBorderColor();
138 width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
139 }
140
141 scoped_ptr<DebugBorderDrawQuad> debugBorderQuad =
142 DebugBorderDrawQuad::Create();
143 gfx::Rect geometry_rect = iter.geometry_rect();
144 debugBorderQuad->SetNew(sharedQuadState, geometry_rect, color, width);
145 quadSink->Append(debugBorderQuad.PassAs<DrawQuad>(), appendQuadsData);
146 }
147 }
148
149 // Keep track of the tilings that were used so that tilings that are
150 // unused can be considered for removal.
151 std::vector<PictureLayerTiling*> seen_tilings;
152
153 for (PictureLayerTilingSet::Iterator iter(tilings_.get(),
154 contents_scale_x(),
155 rect,
156 ideal_contents_scale_,
157 layerDeviceAlignment);
158 iter;
159 ++iter) {
160
161 gfx::Rect geometry_rect = iter.geometry_rect();
162 if (!*iter || !iter->drawing_info().IsReadyToDraw()) {
163 if (DrawCheckerboardForMissingTiles()) {
164 // TODO(enne): Figure out how to show debug "invalidated checker" color
165 scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create();
166 SkColor color = DebugColors::DefaultCheckerboardColor();
167 quad->SetNew(sharedQuadState, geometry_rect, color);
168 if (quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData))
169 appendQuadsData->numMissingTiles++;
170 } else {
171 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
172 quad->SetNew(sharedQuadState, geometry_rect, background_color());
173 if (quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData))
174 appendQuadsData->numMissingTiles++;
175 }
176
177 appendQuadsData->hadIncompleteTile = true;
178 continue;
179 }
180
181 const ManagedTileState::DrawingInfo& drawing_info = iter->drawing_info();
182 switch (drawing_info.mode()) {
183 case ManagedTileState::DrawingInfo::TEXTURE_MODE: {
184 if (iter->contents_scale() != ideal_contents_scale_)
185 appendQuadsData->hadIncompleteTile = true;
186
187 gfx::RectF texture_rect = iter.texture_rect();
188 gfx::Rect opaque_rect = iter->opaque_rect();
189 opaque_rect.Intersect(content_rect);
190
191 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
192 quad->SetNew(sharedQuadState,
193 geometry_rect,
194 opaque_rect,
195 drawing_info.get_resource_id(),
196 texture_rect,
197 iter.texture_size(),
198 drawing_info.contents_swizzled());
199 quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData);
200 break;
201 }
202 case ManagedTileState::DrawingInfo::SOLID_COLOR_MODE: {
203 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
204 quad->SetNew(sharedQuadState,
205 geometry_rect,
206 drawing_info.get_solid_color());
207 quadSink->Append(quad.PassAs<DrawQuad>(), appendQuadsData);
208 break;
209 }
210 case ManagedTileState::DrawingInfo::TRANSPARENT_MODE:
211 break;
212 case ManagedTileState::DrawingInfo::PICTURE_PILE_MODE:
213 // TODO: crbug.com/173011 would fill this part in.
214 default:
215 NOTREACHED();
216 }
217
218 if (!seen_tilings.size() || seen_tilings.back() != iter.CurrentTiling())
219 seen_tilings.push_back(iter.CurrentTiling());
220 }
221
222 // Aggressively remove any tilings that are not seen to save memory. Note
223 // that this is at the expense of doing cause more frequent re-painting. A
224 // better scheme would be to maintain a tighter visibleContentRect for the
225 // finer tilings.
226 CleanUpTilingsOnActiveLayer(seen_tilings);
227 }
228
229 void PictureLayerImpl::DumpLayerProperties(std::string*, int indent) const {
230 // TODO(enne): implement me
231 }
232
233 void PictureLayerImpl::UpdateTilePriorities() {
234 int current_source_frame_number = layer_tree_impl()->source_frame_number();
235 double current_frame_time =
236 (layer_tree_impl()->CurrentFrameTime() - base::TimeTicks()).InSecondsF();
237
238 gfx::Transform current_screen_space_transform = screen_space_transform();
239
240 gfx::Rect viewport_in_content_space;
241 gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization);
242 if (screen_space_transform().GetInverse(&screen_to_layer)) {
243 gfx::Rect device_viewport(layer_tree_impl()->device_viewport_size());
244 viewport_in_content_space = gfx::ToEnclosingRect(
245 MathUtil::ProjectClippedRect(screen_to_layer, device_viewport));
246 }
247
248 WhichTree tree =
249 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE;
250 bool store_screen_space_quads_on_tiles =
251 layer_tree_impl()->debug_state().traceAllRenderedFrames;
252 tilings_->UpdateTilePriorities(
253 tree,
254 layer_tree_impl()->device_viewport_size(),
255 viewport_in_content_space,
256 last_bounds_,
257 bounds(),
258 last_content_scale_,
259 contents_scale_x(),
260 last_screen_space_transform_,
261 current_screen_space_transform,
262 current_source_frame_number,
263 current_frame_time,
264 store_screen_space_quads_on_tiles);
265
266 last_screen_space_transform_ = current_screen_space_transform;
267 last_bounds_ = bounds();
268 last_content_scale_ = contents_scale_x();
269 }
270
271 void PictureLayerImpl::DidBecomeActive() {
272 LayerImpl::DidBecomeActive();
273 tilings_->DidBecomeActive();
274 }
275
276 void PictureLayerImpl::DidLoseOutputSurface() {
277 if (tilings_)
278 tilings_->RemoveAllTilings();
279 }
280
281 void PictureLayerImpl::CalculateContentsScale(
282 float ideal_contents_scale,
283 bool animating_transform_to_screen,
284 float* contents_scale_x,
285 float* contents_scale_y,
286 gfx::Size* content_bounds) {
287 if (!DrawsContent()) {
288 DCHECK(!tilings_->num_tilings());
289 return;
290 }
291
292 float min_contents_scale = MinimumContentsScale();
293 float min_page_scale = layer_tree_impl()->min_page_scale_factor();
294 float min_device_scale = 1.f;
295 float min_source_scale =
296 min_contents_scale / min_page_scale / min_device_scale;
297
298 float ideal_page_scale = layer_tree_impl()->total_page_scale_factor();
299 float ideal_device_scale = layer_tree_impl()->device_scale_factor();
300 float ideal_source_scale =
301 ideal_contents_scale / ideal_page_scale / ideal_device_scale;
302
303 ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale);
304 ideal_page_scale_ = ideal_page_scale;
305 ideal_device_scale_ = ideal_device_scale;
306 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale);
307
308 ManageTilings(animating_transform_to_screen);
309
310 // The content scale and bounds for a PictureLayerImpl is somewhat fictitious.
311 // There are (usually) several tilings at different scales. However, the
312 // content bounds is the (integer!) space in which quads are generated.
313 // In order to guarantee that we can fill this integer space with any set of
314 // tilings (and then map back to floating point texture coordinates), the
315 // contents scale must be at least as large as the largest of the tilings.
316 float max_contents_scale = min_contents_scale;
317 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
318 const PictureLayerTiling* tiling = tilings_->tiling_at(i);
319 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale());
320 }
321
322 *contents_scale_x = max_contents_scale;
323 *contents_scale_y = max_contents_scale;
324 *content_bounds = gfx::ToCeiledSize(
325 gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale));
326 }
327
328 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
329 return pile_->GetFlattenedPicture();
330 }
331
332 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
333 gfx::Rect content_rect) {
334 if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
335 return scoped_refptr<Tile>();
336
337 return make_scoped_refptr(new Tile(
338 layer_tree_impl()->tile_manager(),
339 pile_.get(),
340 content_rect.size(),
341 GL_RGBA,
342 content_rect,
343 contents_opaque() ? content_rect : gfx::Rect(),
344 tiling->contents_scale(),
345 id()));
346 }
347
348 void PictureLayerImpl::UpdatePile(Tile* tile) {
349 tile->set_picture_pile(pile_);
350 }
351
352 gfx::Size PictureLayerImpl::CalculateTileSize(
353 gfx::Size current_tile_size,
354 gfx::Size content_bounds) {
355 if (is_mask_) {
356 int max_size = layer_tree_impl()->MaxTextureSize();
357 return gfx::Size(
358 std::min(max_size, content_bounds.width()),
359 std::min(max_size, content_bounds.height()));
360 }
361
362 gfx::Size default_tile_size = layer_tree_impl()->settings().defaultTileSize;
363 gfx::Size max_untiled_content_size =
364 layer_tree_impl()->settings().maxUntiledLayerSize;
365
366 bool any_dimension_too_large =
367 content_bounds.width() > max_untiled_content_size.width() ||
368 content_bounds.height() > max_untiled_content_size.height();
369
370 bool any_dimension_one_tile =
371 content_bounds.width() <= default_tile_size.width() ||
372 content_bounds.height() <= default_tile_size.height();
373
374 // If long and skinny, tile at the max untiled content size, and clamp
375 // the smaller dimension to the content size, e.g. 1000x12 layer with
376 // 500x500 max untiled size would get 500x12 tiles. Also do this
377 // if the layer is small.
378 if (any_dimension_one_tile || !any_dimension_too_large) {
379 int width =
380 std::min(max_untiled_content_size.width(), content_bounds.width());
381 int height =
382 std::min(max_untiled_content_size.height(), content_bounds.height());
383 // Round width and height up to the closest multiple of 64, or 56 if
384 // we should avoid power-of-two textures. This helps reduce the number
385 // of different textures sizes to help recycling, and also keeps all
386 // textures multiple-of-eight, which is preferred on some drivers (IMG).
387 bool avoid_pow2 =
388 layer_tree_impl()->rendererCapabilities().avoid_pow2_textures;
389 int round_up_to = avoid_pow2 ? 56 : 64;
390 width = RoundUp(width, round_up_to);
391 height = RoundUp(height, round_up_to);
392 return gfx::Size(width, height);
393 }
394
395 return default_tile_size;
396 }
397
398 void PictureLayerImpl::SyncFromActiveLayer() {
399 DCHECK(layer_tree_impl()->IsPendingTree());
400
401 if (!DrawsContent()) {
402 raster_page_scale_ = 0;
403 raster_device_scale_ = 0;
404 raster_source_scale_ = 0;
405 return;
406 }
407
408 // If there is an active tree version of this layer, get a copy of its
409 // tiles. This needs to be done last, after setting invalidation and the
410 // pile.
411 if (PictureLayerImpl* active_twin = ActiveTwin())
412 SyncFromActiveLayer(active_twin);
413 }
414
415 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
416 raster_page_scale_ = other->raster_page_scale_;
417 raster_device_scale_ = other->raster_device_scale_;
418 raster_source_scale_ = other->raster_source_scale_;
419
420 // Add synthetic invalidations for any recordings that were dropped. As
421 // tiles are updated to point to this new pile, this will force the dropping
422 // of tiles that can no longer be rastered. This is not ideal, but is a
423 // trade-off for memory (use the same pile as much as possible, by switching
424 // during DidBecomeActive) and for time (don't bother checking every tile
425 // during activation to see if the new pile can still raster it).
426 //
427 // TODO(enne): Clean up this double loop.
428 for (int x = 0; x < pile_->num_tiles_x(); ++x) {
429 for (int y = 0; y < pile_->num_tiles_y(); ++y) {
430 bool previously_had = other->pile_->HasRecordingAt(x, y);
431 bool now_has = pile_->HasRecordingAt(x, y);
432 if (now_has || !previously_had)
433 continue;
434 gfx::Rect layer_rect = pile_->tile_bounds(x, y);
435 invalidation_.Union(layer_rect);
436 }
437 }
438
439 tilings_->CloneAll(*other->tilings_, invalidation_, MinimumContentsScale());
440 DCHECK(bounds() == tilings_->LayerBounds());
441
442 // It's a sad but unfortunate fact that PicturePile tiling edges do not line
443 // up with PictureLayerTiling edges. Tiles can only be added if they are
444 // entirely covered by recordings (that may come from multiple PicturePile
445 // tiles). This check happens in this class's CreateTile() call.
446 for (int x = 0; x < pile_->num_tiles_x(); ++x) {
447 for (int y = 0; y < pile_->num_tiles_y(); ++y) {
448 bool previously_had = other->pile_->HasRecordingAt(x, y);
449 bool now_has = pile_->HasRecordingAt(x, y);
450 if (!now_has || previously_had)
451 continue;
452 gfx::Rect layer_rect = pile_->tile_bounds(x, y);
453 tilings_->CreateTilesFromLayerRect(layer_rect);
454 }
455 }
456 }
457
458 void PictureLayerImpl::SyncTiling(
459 const PictureLayerTiling* tiling,
460 const Region& pending_layer_invalidation) {
461 if (!DrawsContent() || tiling->contents_scale() < MinimumContentsScale())
462 return;
463 tilings_->Clone(tiling, pending_layer_invalidation);
464 }
465
466 void PictureLayerImpl::SetIsMask(bool is_mask) {
467 if (is_mask_ == is_mask)
468 return;
469 is_mask_ = is_mask;
470 if (tilings_)
471 tilings_->RemoveAllTiles();
472 }
473
474 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const {
475 gfx::Rect content_rect(content_bounds());
476 float scale = contents_scale_x();
477 for (PictureLayerTilingSet::Iterator
478 iter(tilings_.get(),
479 scale,
480 content_rect,
481 ideal_contents_scale_,
482 PictureLayerTiling::LayerDeviceAlignmentUnknown);
483 iter;
484 ++iter) {
485 // Mask resource not ready yet.
486 if (!*iter ||
487 iter->drawing_info().mode() !=
488 ManagedTileState::DrawingInfo::TEXTURE_MODE ||
489 !iter->drawing_info().IsReadyToDraw())
490 return 0;
491 // Masks only supported if they fit on exactly one tile.
492 if (iter.geometry_rect() != content_rect)
493 return 0;
494 return iter->drawing_info().get_resource_id();
495 }
496 return 0;
497 }
498
499 bool PictureLayerImpl::AreVisibleResourcesReady() const {
500 DCHECK(layer_tree_impl()->IsPendingTree());
501 DCHECK(ideal_contents_scale_);
502
503 const gfx::Rect& rect = visible_content_rect();
504
505 float raster_contents_scale =
506 raster_page_scale_ *
507 raster_device_scale_ *
508 raster_source_scale_;
509
510 float min_acceptable_scale =
511 std::min(raster_contents_scale, ideal_contents_scale_);
512
513 TreePriority tree_priority =
514 layer_tree_impl()->tile_manager()->GlobalState().tree_priority;
515 bool should_force_uploads =
516 tree_priority != SMOOTHNESS_TAKES_PRIORITY &&
517 layer_tree_impl()->animationRegistrar()->
518 active_animation_controllers().empty();
519
520 if (PictureLayerImpl* twin = ActiveTwin()) {
521 float twin_raster_contents_scale =
522 twin->raster_page_scale_ *
523 twin->raster_device_scale_ *
524 twin->raster_source_scale_;
525
526 min_acceptable_scale = std::min(
527 min_acceptable_scale,
528 std::min(twin->ideal_contents_scale_, twin_raster_contents_scale));
529 }
530
531 Region missing_region = rect;
532 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
533 PictureLayerTiling* tiling = tilings_->tiling_at(i);
534
535 if (tiling->contents_scale() < min_acceptable_scale)
536 continue;
537
538 for (PictureLayerTiling::Iterator
539 iter(tiling,
540 contents_scale_x(),
541 rect,
542 PictureLayerTiling::LayerDeviceAlignmentUnknown);
543 iter;
544 ++iter) {
545 if (should_force_uploads && iter)
546 layer_tree_impl()->tile_manager()->ForceTileUploadToComplete(*iter);
547 // A null tile (i.e. no recording) is considered "ready".
548 if (!*iter || iter->drawing_info().IsReadyToDraw())
549 missing_region.Subtract(iter.geometry_rect());
550 }
551 }
552
553 return missing_region.IsEmpty();
554 }
555
556 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
557 DCHECK(contents_scale >= MinimumContentsScale());
558
559 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale);
560
561 const Region& recorded = pile_->recorded_region();
562 DCHECK(!recorded.IsEmpty());
563
564 for (Region::Iterator iter(recorded); iter.has_rect(); iter.next())
565 tiling->CreateTilesFromLayerRect(iter.rect());
566
567 PictureLayerImpl* twin =
568 layer_tree_impl()->IsPendingTree() ? ActiveTwin() : PendingTwin();
569 if (!twin)
570 return tiling;
571
572 if (layer_tree_impl()->IsPendingTree())
573 twin->SyncTiling(tiling, invalidation_);
574 else
575 twin->SyncTiling(tiling, twin->invalidation_);
576
577 return tiling;
578 }
579
580 void PictureLayerImpl::RemoveTiling(float contents_scale) {
581 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
582 PictureLayerTiling* tiling = tilings_->tiling_at(i);
583 if (tiling->contents_scale() == contents_scale) {
584 tilings_->Remove(tiling);
585 break;
586 }
587 }
588 }
589
590 namespace {
591
592 inline float PositiveRatio(float float1, float float2) {
593 DCHECK(float1 > 0);
594 DCHECK(float2 > 0);
595 return float1 > float2 ? float1 / float2 : float2 / float1;
596 }
597
598 inline bool IsCloserToThan(
599 PictureLayerTiling* layer1,
600 PictureLayerTiling* layer2,
601 float contents_scale) {
602 // Absolute value for ratios.
603 float ratio1 = PositiveRatio(layer1->contents_scale(), contents_scale);
604 float ratio2 = PositiveRatio(layer2->contents_scale(), contents_scale);
605 return ratio1 < ratio2;
606 }
607
608 } // namespace
609
610 void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) {
611 DCHECK(ideal_contents_scale_);
612 DCHECK(ideal_page_scale_);
613 DCHECK(ideal_device_scale_);
614 DCHECK(ideal_source_scale_);
615
616 if (pile_->recorded_region().IsEmpty())
617 return;
618
619 bool is_active_layer = layer_tree_impl()->IsActiveTree();
620 bool is_pinching = layer_tree_impl()->PinchGestureActive();
621
622 bool change_target_tiling = false;
623
624 if (!raster_page_scale_ || !raster_device_scale_ || !raster_source_scale_)
625 change_target_tiling = true;
626
627 // TODO(danakj): Adjust raster_source_scale_ closer to ideal_source_scale_ at
628 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending
629 // tree. This will allow CSS scale changes to get re-rastered at an
630 // appropriate rate.
631
632 if (is_active_layer) {
633 if (raster_source_scale_was_animating_ && !animating_transform_to_screen)
634 change_target_tiling = true;
635 raster_source_scale_was_animating_ = animating_transform_to_screen;
636 }
637
638 if (is_active_layer && is_pinching && raster_page_scale_) {
639 // If the page scale diverges too far during pinch, change raster target to
640 // the current page scale.
641 float ratio = PositiveRatio(ideal_page_scale_, raster_page_scale_);
642 if (ratio >= kMaxScaleRatioDuringPinch)
643 change_target_tiling = true;
644 }
645
646 if (!is_pinching) {
647 // When not pinching, match the ideal page scale factor.
648 if (raster_page_scale_ != ideal_page_scale_)
649 change_target_tiling = true;
650 }
651
652 // Always match the ideal device scale factor.
653 if (raster_device_scale_ != ideal_device_scale_)
654 change_target_tiling = true;
655
656 if (!change_target_tiling)
657 return;
658
659 raster_page_scale_ = ideal_page_scale_;
660 raster_device_scale_ = ideal_device_scale_;
661 raster_source_scale_ = ideal_source_scale_;
662
663 float raster_contents_scale;
664 float low_res_raster_contents_scale;
665 CalculateRasterContentsScale(animating_transform_to_screen,
666 &raster_contents_scale,
667 &low_res_raster_contents_scale);
668
669 PictureLayerTiling* high_res = NULL;
670 PictureLayerTiling* low_res = NULL;
671
672 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
673 PictureLayerTiling* tiling = tilings_->tiling_at(i);
674 if (tiling->contents_scale() == raster_contents_scale)
675 high_res = tiling;
676 if (tiling->contents_scale() == low_res_raster_contents_scale)
677 low_res = tiling;
678
679 // Reset all tilings to non-ideal until the end of this function.
680 tiling->set_resolution(NON_IDEAL_RESOLUTION);
681 }
682
683 if (!high_res) {
684 high_res = AddTiling(raster_contents_scale);
685 if (raster_contents_scale == low_res_raster_contents_scale)
686 low_res = high_res;
687 }
688 if (!low_res && low_res != high_res)
689 low_res = AddTiling(low_res_raster_contents_scale);
690
691 if (high_res)
692 high_res->set_resolution(HIGH_RESOLUTION);
693 if (low_res && low_res != high_res)
694 low_res->set_resolution(LOW_RESOLUTION);
695 }
696
697 void PictureLayerImpl::CalculateRasterContentsScale(
698 bool animating_transform_to_screen,
699 float* raster_contents_scale,
700 float* low_res_raster_contents_scale) {
701 *raster_contents_scale = ideal_contents_scale_;
702
703 // Don't allow animating CSS scales to drop below 1.
704 if (animating_transform_to_screen) {
705 *raster_contents_scale = std::max(
706 *raster_contents_scale, 1.f * ideal_page_scale_ * ideal_device_scale_);
707 }
708
709 float low_res_factor =
710 layer_tree_impl()->settings().lowResContentsScaleFactor;
711 *low_res_raster_contents_scale = std::max(
712 *raster_contents_scale * low_res_factor,
713 MinimumContentsScale());
714 }
715
716 void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
717 std::vector<PictureLayerTiling*> used_tilings) {
718 DCHECK(layer_tree_impl()->IsActiveTree());
719
720 float raster_contents_scale =
721 raster_page_scale_ * raster_device_scale_ * raster_source_scale_;
722
723 float min_acceptable_high_res_scale = std::min(
724 raster_contents_scale, ideal_contents_scale_);
725 float max_acceptable_high_res_scale = std::max(
726 raster_contents_scale, ideal_contents_scale_);
727
728 PictureLayerImpl* twin = PendingTwin();
729 if (twin) {
730 float twin_raster_contents_scale =
731 twin->raster_page_scale_ *
732 twin->raster_device_scale_ *
733 twin->raster_source_scale_;
734
735 min_acceptable_high_res_scale = std::min(
736 min_acceptable_high_res_scale,
737 std::min(twin_raster_contents_scale, twin->ideal_contents_scale_));
738 max_acceptable_high_res_scale = std::max(
739 max_acceptable_high_res_scale,
740 std::max(twin_raster_contents_scale, twin->ideal_contents_scale_));
741 }
742
743 float low_res_factor =
744 layer_tree_impl()->settings().lowResContentsScaleFactor;
745
746 float min_acceptable_low_res_scale =
747 low_res_factor * min_acceptable_high_res_scale;
748 float max_acceptable_low_res_scale =
749 low_res_factor * max_acceptable_high_res_scale;
750
751 std::vector<PictureLayerTiling*> to_remove;
752 for (size_t i = 0; i < tilings_->num_tilings(); ++i) {
753 PictureLayerTiling* tiling = tilings_->tiling_at(i);
754
755 if (tiling->contents_scale() >= min_acceptable_high_res_scale &&
756 tiling->contents_scale() <= max_acceptable_high_res_scale)
757 continue;
758
759 if (tiling->contents_scale() >= min_acceptable_low_res_scale &&
760 tiling->contents_scale() <= max_acceptable_low_res_scale)
761 continue;
762
763 // Don't remove tilings that are being used and expected to stay around.
764 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) !=
765 used_tilings.end())
766 continue;
767
768 to_remove.push_back(tiling);
769 }
770
771 for (size_t i = 0; i < to_remove.size(); ++i) {
772 if (twin)
773 twin->RemoveTiling(to_remove[i]->contents_scale());
774 tilings_->Remove(to_remove[i]);
775 }
776 }
777
778 PictureLayerImpl* PictureLayerImpl::PendingTwin() const {
779 DCHECK(layer_tree_impl()->IsActiveTree());
780
781 PictureLayerImpl* twin = static_cast<PictureLayerImpl*>(
782 layer_tree_impl()->FindPendingTreeLayerById(id()));
783 if (twin)
784 DCHECK_EQ(id(), twin->id());
785 return twin;
786 }
787
788 PictureLayerImpl* PictureLayerImpl::ActiveTwin() const {
789 DCHECK(layer_tree_impl()->IsPendingTree());
790
791 PictureLayerImpl* twin = static_cast<PictureLayerImpl*>(
792 layer_tree_impl()->FindActiveTreeLayerById(id()));
793 if (twin)
794 DCHECK_EQ(id(), twin->id());
795 return twin;
796 }
797
798 float PictureLayerImpl::MinimumContentsScale() const {
799 float setting_min = layer_tree_impl()->settings().minimumContentsScale;
800
801 // If the contents scale is less than 1 / width (also for height),
802 // then it will end up having less than one pixel of content in that
803 // dimension. Bump the minimum contents scale up in this case to prevent
804 // this from happening.
805 int min_dimension = std::min(bounds().width(), bounds().height());
806 if (!min_dimension)
807 return setting_min;
808
809 return std::max(1.f / min_dimension, setting_min);
810 }
811
812 void PictureLayerImpl::GetDebugBorderProperties(
813 SkColor* color,
814 float* width) const {
815 *color = DebugColors::TiledContentLayerBorderColor();
816 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
817 }
818
819 scoped_ptr<base::Value> PictureLayerImpl::AsValue() const {
820 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
821 LayerImpl::AsValueInto(state.get());
822
823 state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
824 state->Set("tilings", tilings_->AsValue().release());
825 return state.PassAs<base::Value>();
826 }
827
828 } // namespace cc
OLDNEW
« no previous file with comments | « cc/picture_layer_impl.h ('k') | cc/picture_layer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698