layer_impl.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright 2011 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/layers/layer_impl.h" 6 7#include "base/debug/trace_event.h" 8#include "base/strings/stringprintf.h" 9#include "cc/animation/animation_registrar.h" 10#include "cc/animation/scrollbar_animation_controller.h" 11#include "cc/animation/scrollbar_animation_controller_linear_fade.h" 12#include "cc/animation/scrollbar_animation_controller_thinning.h" 13#include "cc/base/math_util.h" 14#include "cc/debug/debug_colors.h" 15#include "cc/debug/layer_tree_debug_state.h" 16#include "cc/debug/traced_value.h" 17#include "cc/input/layer_scroll_offset_delegate.h" 18#include "cc/layers/painted_scrollbar_layer_impl.h" 19#include "cc/layers/quad_sink.h" 20#include "cc/output/copy_output_request.h" 21#include "cc/quads/debug_border_draw_quad.h" 22#include "cc/trees/layer_tree_impl.h" 23#include "cc/trees/layer_tree_settings.h" 24#include "cc/trees/proxy.h" 25#include "ui/gfx/point_conversions.h" 26#include "ui/gfx/quad_f.h" 27#include "ui/gfx/rect_conversions.h" 28 29namespace cc { 30 31LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) 32 : parent_(NULL), 33 scroll_parent_(NULL), 34 clip_parent_(NULL), 35 mask_layer_id_(-1), 36 replica_layer_id_(-1), 37 layer_id_(id), 38 layer_tree_impl_(tree_impl), 39 anchor_point_(0.5f, 0.5f), 40 anchor_point_z_(0.f), 41 scroll_offset_delegate_(NULL), 42 scrollable_(false), 43 should_scroll_on_main_thread_(false), 44 have_wheel_event_handlers_(false), 45 background_color_(0), 46 stacking_order_changed_(false), 47 double_sided_(true), 48 layer_property_changed_(false), 49 layer_surface_property_changed_(false), 50 masks_to_bounds_(false), 51 contents_opaque_(false), 52 opacity_(1.0), 53 preserves_3d_(false), 54 use_parent_backface_visibility_(false), 55 draw_checkerboard_for_missing_tiles_(false), 56 draws_content_(false), 57 hide_layer_and_subtree_(false), 58 force_render_surface_(false), 59 is_container_for_fixed_position_layers_(false), 60 draw_depth_(0.f), 61 compositing_reasons_(kCompositingReasonUnknown), 62 current_draw_mode_(DRAW_MODE_NONE), 63 horizontal_scrollbar_layer_(NULL), 64 vertical_scrollbar_layer_(NULL) { 65 DCHECK_GT(layer_id_, 0); 66 DCHECK(layer_tree_impl_); 67 layer_tree_impl_->RegisterLayer(this); 68 AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar(); 69 layer_animation_controller_ = 70 registrar->GetAnimationControllerForId(layer_id_); 71 layer_animation_controller_->AddValueObserver(this); 72} 73 74LayerImpl::~LayerImpl() { 75 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_); 76 77 layer_tree_impl_->UnregisterLayer(this); 78 layer_animation_controller_->RemoveValueObserver(this); 79 80 if (scroll_children_) { 81 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin(); 82 it != scroll_children_->end(); ++it) 83 (*it)->scroll_parent_ = NULL; 84 } 85 86 if (scroll_parent_) 87 scroll_parent_->RemoveScrollChild(this); 88 89 if (clip_children_) { 90 for (std::set<LayerImpl*>::iterator it = clip_children_->begin(); 91 it != clip_children_->end(); ++it) 92 (*it)->clip_parent_ = NULL; 93 } 94 95 if (clip_parent_) 96 clip_parent_->RemoveClipChild(this); 97} 98 99void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) { 100 child->set_parent(this); 101 DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl()); 102 children_.push_back(child.Pass()); 103 layer_tree_impl()->set_needs_update_draw_properties(); 104} 105 106scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) { 107 for (OwnedLayerImplList::iterator it = children_.begin(); 108 it != children_.end(); 109 ++it) { 110 if (*it == child) { 111 scoped_ptr<LayerImpl> ret = children_.take(it); 112 children_.erase(it); 113 layer_tree_impl()->set_needs_update_draw_properties(); 114 return ret.Pass(); 115 } 116 } 117 return scoped_ptr<LayerImpl>(); 118} 119 120void LayerImpl::ClearChildList() { 121 if (children_.empty()) 122 return; 123 124 children_.clear(); 125 layer_tree_impl()->set_needs_update_draw_properties(); 126} 127 128bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const { 129 if (!ancestor) 130 return false; 131 132 for (const LayerImpl* layer = this; layer; layer = layer->parent()) { 133 if (layer == ancestor) 134 return true; 135 } 136 137 return false; 138} 139 140void LayerImpl::SetScrollParent(LayerImpl* parent) { 141 if (scroll_parent_ == parent) 142 return; 143 144 // Having both a scroll parent and a scroll offset delegate is unsupported. 145 DCHECK(!scroll_offset_delegate_); 146 147 if (scroll_parent_) 148 scroll_parent_->RemoveScrollChild(this); 149 150 scroll_parent_ = parent; 151} 152 153void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) { 154 if (scroll_children_.get() == children) 155 return; 156 scroll_children_.reset(children); 157} 158 159void LayerImpl::RemoveScrollChild(LayerImpl* child) { 160 DCHECK(scroll_children_); 161 scroll_children_->erase(child); 162 if (scroll_children_->empty()) 163 scroll_children_.reset(); 164} 165 166void LayerImpl::SetClipParent(LayerImpl* ancestor) { 167 if (clip_parent_ == ancestor) 168 return; 169 170 if (clip_parent_) 171 clip_parent_->RemoveClipChild(this); 172 173 clip_parent_ = ancestor; 174} 175 176void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) { 177 if (clip_children_.get() == children) 178 return; 179 clip_children_.reset(children); 180} 181 182void LayerImpl::RemoveClipChild(LayerImpl* child) { 183 DCHECK(clip_children_); 184 clip_children_->erase(child); 185 if (clip_children_->empty()) 186 clip_children_.reset(); 187} 188 189void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) { 190 if (requests->empty()) 191 return; 192 193 bool was_empty = copy_requests_.empty(); 194 copy_requests_.insert_and_take(copy_requests_.end(), *requests); 195 requests->clear(); 196 197 if (was_empty && layer_tree_impl()->IsActiveTree()) 198 layer_tree_impl()->AddLayerWithCopyOutputRequest(this); 199 NoteLayerPropertyChangedForSubtree(); 200} 201 202void LayerImpl::TakeCopyRequestsAndTransformToTarget( 203 ScopedPtrVector<CopyOutputRequest>* requests) { 204 if (copy_requests_.empty()) 205 return; 206 207 size_t first_inserted_request = requests->size(); 208 requests->insert_and_take(requests->end(), copy_requests_); 209 copy_requests_.clear(); 210 211 for (size_t i = first_inserted_request; i < requests->size(); ++i) { 212 CopyOutputRequest* request = requests->at(i); 213 if (!request->has_area()) 214 continue; 215 216 gfx::Rect request_in_layer_space = request->area(); 217 gfx::Rect request_in_content_space = 218 LayerRectToContentRect(request_in_layer_space); 219 request->set_area( 220 MathUtil::MapClippedRect(draw_properties_.target_space_transform, 221 request_in_content_space)); 222 } 223 224 if (layer_tree_impl()->IsActiveTree()) 225 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); 226} 227 228void LayerImpl::CreateRenderSurface() { 229 DCHECK(!draw_properties_.render_surface); 230 draw_properties_.render_surface = 231 make_scoped_ptr(new RenderSurfaceImpl(this)); 232 draw_properties_.render_target = this; 233} 234 235void LayerImpl::ClearRenderSurface() { 236 draw_properties_.render_surface.reset(); 237} 238 239scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const { 240 scoped_ptr<SharedQuadState> state = SharedQuadState::Create(); 241 state->SetAll(draw_properties_.target_space_transform, 242 draw_properties_.content_bounds, 243 draw_properties_.visible_content_rect, 244 draw_properties_.clip_rect, 245 draw_properties_.is_clipped, 246 draw_properties_.opacity); 247 return state.Pass(); 248} 249 250bool LayerImpl::WillDraw(DrawMode draw_mode, 251 ResourceProvider* resource_provider) { 252 // WillDraw/DidDraw must be matched. 253 DCHECK_NE(DRAW_MODE_NONE, draw_mode); 254 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_); 255 current_draw_mode_ = draw_mode; 256 return true; 257} 258 259void LayerImpl::DidDraw(ResourceProvider* resource_provider) { 260 DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_); 261 current_draw_mode_ = DRAW_MODE_NONE; 262} 263 264bool LayerImpl::ShowDebugBorders() const { 265 return layer_tree_impl()->debug_state().show_debug_borders; 266} 267 268void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { 269 if (draws_content_) { 270 *color = DebugColors::ContentLayerBorderColor(); 271 *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl()); 272 return; 273 } 274 275 if (masks_to_bounds_) { 276 *color = DebugColors::MaskingLayerBorderColor(); 277 *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl()); 278 return; 279 } 280 281 *color = DebugColors::ContainerLayerBorderColor(); 282 *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl()); 283} 284 285void LayerImpl::AppendDebugBorderQuad( 286 QuadSink* quad_sink, 287 const SharedQuadState* shared_quad_state, 288 AppendQuadsData* append_quads_data) const { 289 SkColor color; 290 float width; 291 GetDebugBorderProperties(&color, &width); 292 AppendDebugBorderQuad( 293 quad_sink, shared_quad_state, append_quads_data, color, width); 294} 295 296void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink, 297 const SharedQuadState* shared_quad_state, 298 AppendQuadsData* append_quads_data, 299 SkColor color, 300 float width) const { 301 if (!ShowDebugBorders()) 302 return; 303 304 gfx::Rect content_rect(content_bounds()); 305 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = 306 DebugBorderDrawQuad::Create(); 307 debug_border_quad->SetNew(shared_quad_state, content_rect, color, width); 308 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data); 309} 310 311bool LayerImpl::HasDelegatedContent() const { 312 return false; 313} 314 315bool LayerImpl::HasContributingDelegatedRenderPasses() const { 316 return false; 317} 318 319RenderPass::Id LayerImpl::FirstContributingRenderPassId() const { 320 return RenderPass::Id(0, 0); 321} 322 323RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id) 324 const { 325 return RenderPass::Id(0, 0); 326} 327 328ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const { 329 NOTREACHED(); 330 return 0; 331} 332 333void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) { 334 // Pending tree never has sent scroll deltas 335 DCHECK(layer_tree_impl()->IsActiveTree()); 336 337 if (sent_scroll_delta_ == sent_scroll_delta) 338 return; 339 340 sent_scroll_delta_ = sent_scroll_delta; 341} 342 343gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) { 344 DCHECK(scrollable()); 345 346 gfx::Vector2dF min_delta = -scroll_offset_; 347 gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_; 348 // Clamp new_delta so that position + delta stays within scroll bounds. 349 gfx::Vector2dF new_delta = (ScrollDelta() + scroll); 350 new_delta.SetToMax(min_delta); 351 new_delta.SetToMin(max_delta); 352 gfx::Vector2dF unscrolled = ScrollDelta() + scroll - new_delta; 353 SetScrollDelta(new_delta); 354 return unscrolled; 355} 356 357void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() { 358 // Pending tree never has sent scroll deltas 359 DCHECK(layer_tree_impl()->IsActiveTree()); 360 361 // Apply sent scroll deltas to scroll position / scroll delta as if the 362 // main thread had applied them and then committed those values. 363 // 364 // This function should not change the total scroll offset; it just shifts 365 // some of the scroll delta to the scroll offset. Therefore, adjust these 366 // variables directly rather than calling the scroll offset delegate to 367 // avoid sending it multiple spurious calls. 368 // 369 // Because of the way scroll delta is calculated with a delegate, this will 370 // leave the total scroll offset unchanged on this layer regardless of 371 // whether a delegate is being used. 372 scroll_offset_ += sent_scroll_delta_; 373 scroll_delta_ -= sent_scroll_delta_; 374 sent_scroll_delta_ = gfx::Vector2d(); 375} 376 377void LayerImpl::ApplyScrollDeltasSinceBeginFrame() { 378 // Only the pending tree can have missing scrolls. 379 DCHECK(layer_tree_impl()->IsPendingTree()); 380 if (!scrollable()) 381 return; 382 383 // Pending tree should never have sent scroll deltas. 384 DCHECK(sent_scroll_delta().IsZero()); 385 386 LayerImpl* active_twin = layer_tree_impl()->FindActiveTreeLayerById(id()); 387 if (active_twin) { 388 // Scrolls that happens after begin frame (where the sent scroll delta 389 // comes from) and commit need to be applied to the pending tree 390 // so that it is up to date with the total scroll. 391 SetScrollDelta(active_twin->ScrollDelta() - 392 active_twin->sent_scroll_delta()); 393 } 394} 395 396InputHandler::ScrollStatus LayerImpl::TryScroll( 397 gfx::PointF screen_space_point, 398 InputHandler::ScrollInputType type) const { 399 if (should_scroll_on_main_thread()) { 400 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread"); 401 return InputHandler::ScrollOnMainThread; 402 } 403 404 if (!screen_space_transform().IsInvertible()) { 405 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform"); 406 return InputHandler::ScrollIgnored; 407 } 408 409 if (!non_fast_scrollable_region().IsEmpty()) { 410 bool clipped = false; 411 gfx::Transform inverse_screen_space_transform( 412 gfx::Transform::kSkipInitialization); 413 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) { 414 // TODO(shawnsingh): We shouldn't be applying a projection if screen space 415 // transform is uninvertible here. Perhaps we should be returning 416 // ScrollOnMainThread in this case? 417 } 418 419 gfx::PointF hit_test_point_in_content_space = 420 MathUtil::ProjectPoint(inverse_screen_space_transform, 421 screen_space_point, 422 &clipped); 423 gfx::PointF hit_test_point_in_layer_space = 424 gfx::ScalePoint(hit_test_point_in_content_space, 425 1.f / contents_scale_x(), 426 1.f / contents_scale_y()); 427 if (!clipped && 428 non_fast_scrollable_region().Contains( 429 gfx::ToRoundedPoint(hit_test_point_in_layer_space))) { 430 TRACE_EVENT0("cc", 431 "LayerImpl::tryScroll: Failed NonFastScrollableRegion"); 432 return InputHandler::ScrollOnMainThread; 433 } 434 } 435 436 if (type == InputHandler::Wheel && have_wheel_event_handlers()) { 437 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers"); 438 return InputHandler::ScrollOnMainThread; 439 } 440 441 if (!scrollable()) { 442 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); 443 return InputHandler::ScrollIgnored; 444 } 445 446 if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) { 447 TRACE_EVENT0("cc", 448 "LayerImpl::tryScroll: Ignored. Technically scrollable," 449 " but has no affordance in either direction."); 450 return InputHandler::ScrollIgnored; 451 } 452 453 return InputHandler::ScrollStarted; 454} 455 456bool LayerImpl::DrawCheckerboardForMissingTiles() const { 457 return draw_checkerboard_for_missing_tiles_ && 458 !layer_tree_impl()->settings().background_color_instead_of_checkerboard; 459} 460 461gfx::Rect LayerImpl::LayerRectToContentRect( 462 const gfx::RectF& layer_rect) const { 463 gfx::RectF content_rect = 464 gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y()); 465 // Intersect with content rect to avoid the extra pixel because for some 466 // values x and y, ceil((x / y) * y) may be x + 1. 467 content_rect.Intersect(gfx::Rect(content_bounds())); 468 return gfx::ToEnclosingRect(content_rect); 469} 470 471skia::RefPtr<SkPicture> LayerImpl::GetPicture() { 472 return skia::RefPtr<SkPicture>(); 473} 474 475bool LayerImpl::CanClipSelf() const { 476 return false; 477} 478 479bool LayerImpl::AreVisibleResourcesReady() const { 480 return true; 481} 482 483scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { 484 return LayerImpl::Create(tree_impl, layer_id_); 485} 486 487void LayerImpl::PushPropertiesTo(LayerImpl* layer) { 488 layer->SetAnchorPoint(anchor_point_); 489 layer->SetAnchorPointZ(anchor_point_z_); 490 layer->SetBackgroundColor(background_color_); 491 layer->SetBounds(bounds_); 492 layer->SetContentBounds(content_bounds()); 493 layer->SetContentsScale(contents_scale_x(), contents_scale_y()); 494 layer->SetDebugName(debug_name_); 495 layer->SetCompositingReasons(compositing_reasons_); 496 layer->SetDoubleSided(double_sided_); 497 layer->SetDrawCheckerboardForMissingTiles( 498 draw_checkerboard_for_missing_tiles_); 499 layer->SetForceRenderSurface(force_render_surface_); 500 layer->SetDrawsContent(DrawsContent()); 501 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); 502 layer->SetFilters(filters()); 503 layer->SetFilter(filter()); 504 layer->SetBackgroundFilters(background_filters()); 505 layer->SetMasksToBounds(masks_to_bounds_); 506 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); 507 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_); 508 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); 509 layer->SetTouchEventHandlerRegion(touch_event_handler_region_); 510 layer->SetContentsOpaque(contents_opaque_); 511 layer->SetOpacity(opacity_); 512 layer->SetPosition(position_); 513 layer->SetIsContainerForFixedPositionLayers( 514 is_container_for_fixed_position_layers_); 515 layer->SetFixedContainerSizeDelta(fixed_container_size_delta_); 516 layer->SetPositionConstraint(position_constraint_); 517 layer->SetPreserves3d(preserves_3d()); 518 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); 519 layer->SetSublayerTransform(sublayer_transform_); 520 layer->SetTransform(transform_); 521 522 layer->SetScrollable(scrollable_); 523 layer->SetScrollOffsetAndDelta( 524 scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta()); 525 layer->SetSentScrollDelta(gfx::Vector2d()); 526 527 layer->SetMaxScrollOffset(max_scroll_offset_); 528 529 LayerImpl* scroll_parent = NULL; 530 if (scroll_parent_) 531 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id()); 532 533 layer->SetScrollParent(scroll_parent); 534 if (scroll_children_) { 535 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>; 536 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin(); 537 it != scroll_children_->end(); ++it) 538 scroll_children->insert(layer->layer_tree_impl()->LayerById((*it)->id())); 539 layer->SetScrollChildren(scroll_children); 540 } 541 542 LayerImpl* clip_parent = NULL; 543 if (clip_parent_) { 544 clip_parent = layer->layer_tree_impl()->LayerById( 545 clip_parent_->id()); 546 } 547 548 layer->SetClipParent(clip_parent); 549 if (clip_children_) { 550 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>; 551 for (std::set<LayerImpl*>::iterator it = clip_children_->begin(); 552 it != clip_children_->end(); ++it) 553 clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id())); 554 layer->SetClipChildren(clip_children); 555 } 556 557 layer->PassCopyRequests(©_requests_); 558 559 // If the main thread commits multiple times before the impl thread actually 560 // draws, then damage tracking will become incorrect if we simply clobber the 561 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. 562 // union) any update changes that have occurred on the main thread. 563 update_rect_.Union(layer->update_rect()); 564 layer->set_update_rect(update_rect_); 565 566 layer->SetStackingOrderChanged(stacking_order_changed_); 567 568 // Reset any state that should be cleared for the next update. 569 stacking_order_changed_ = false; 570 update_rect_ = gfx::RectF(); 571} 572 573base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { 574 base::DictionaryValue* result = new base::DictionaryValue; 575 result->SetString("LayerType", LayerTypeAsString()); 576 577 base::ListValue* list = new base::ListValue; 578 list->AppendInteger(bounds().width()); 579 list->AppendInteger(bounds().height()); 580 result->Set("Bounds", list); 581 582 list = new base::ListValue; 583 list->AppendDouble(position_.x()); 584 list->AppendDouble(position_.y()); 585 result->Set("Position", list); 586 587 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform; 588 double transform[16]; 589 gfx_transform.matrix().asColMajord(transform); 590 list = new base::ListValue; 591 for (int i = 0; i < 16; ++i) 592 list->AppendDouble(transform[i]); 593 result->Set("DrawTransform", list); 594 595 result->SetBoolean("DrawsContent", draws_content_); 596 result->SetDouble("Opacity", opacity()); 597 result->SetBoolean("ContentsOpaque", contents_opaque_); 598 599 if (scrollable_) 600 result->SetBoolean("Scrollable", scrollable_); 601 602 list = new base::ListValue; 603 for (size_t i = 0; i < children_.size(); ++i) 604 list->Append(children_[i]->LayerTreeAsJson()); 605 result->Set("Children", list); 606 607 return result; 608} 609 610void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) { 611 if (stacking_order_changed) { 612 stacking_order_changed_ = true; 613 NoteLayerPropertyChangedForSubtree(); 614 } 615} 616 617bool LayerImpl::LayerSurfacePropertyChanged() const { 618 if (layer_surface_property_changed_) 619 return true; 620 621 // If this layer's surface property hasn't changed, we want to see if 622 // some layer above us has changed this property. This is done for the 623 // case when such parent layer does not draw content, and therefore will 624 // not be traversed by the damage tracker. We need to make sure that 625 // property change on such layer will be caught by its descendants. 626 LayerImpl* current = this->parent_; 627 while (current && !current->draw_properties_.render_surface) { 628 if (current->layer_surface_property_changed_) 629 return true; 630 current = current->parent_; 631 } 632 633 return false; 634} 635 636void LayerImpl::NoteLayerSurfacePropertyChanged() { 637 layer_surface_property_changed_ = true; 638 layer_tree_impl()->set_needs_update_draw_properties(); 639} 640 641void LayerImpl::NoteLayerPropertyChanged() { 642 layer_property_changed_ = true; 643 layer_tree_impl()->set_needs_update_draw_properties(); 644} 645 646void LayerImpl::NoteLayerPropertyChangedForSubtree() { 647 NoteLayerPropertyChanged(); 648 NoteLayerPropertyChangedForDescendants(); 649} 650 651void LayerImpl::NoteLayerPropertyChangedForDescendants() { 652 layer_tree_impl()->set_needs_update_draw_properties(); 653 for (size_t i = 0; i < children_.size(); ++i) 654 children_[i]->NoteLayerPropertyChangedForSubtree(); 655} 656 657const char* LayerImpl::LayerTypeAsString() const { 658 return "cc::LayerImpl"; 659} 660 661void LayerImpl::ResetAllChangeTrackingForSubtree() { 662 layer_property_changed_ = false; 663 layer_surface_property_changed_ = false; 664 665 update_rect_ = gfx::RectF(); 666 667 if (draw_properties_.render_surface) 668 draw_properties_.render_surface->ResetPropertyChangedFlag(); 669 670 if (mask_layer_) 671 mask_layer_->ResetAllChangeTrackingForSubtree(); 672 673 if (replica_layer_) { 674 // This also resets the replica mask, if it exists. 675 replica_layer_->ResetAllChangeTrackingForSubtree(); 676 } 677 678 for (size_t i = 0; i < children_.size(); ++i) 679 children_[i]->ResetAllChangeTrackingForSubtree(); 680} 681 682bool LayerImpl::LayerIsAlwaysDamaged() const { 683 return false; 684} 685 686void LayerImpl::OnOpacityAnimated(float opacity) { 687 SetOpacity(opacity); 688} 689 690void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { 691 SetTransform(transform); 692} 693 694bool LayerImpl::IsActive() const { 695 return layer_tree_impl_->IsActiveTree(); 696} 697 698void LayerImpl::SetBounds(gfx::Size bounds) { 699 if (bounds_ == bounds) 700 return; 701 702 bounds_ = bounds; 703 704 if (masks_to_bounds()) 705 NoteLayerPropertyChangedForSubtree(); 706 else 707 NoteLayerPropertyChanged(); 708} 709 710void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) { 711 int new_layer_id = mask_layer ? mask_layer->id() : -1; 712 713 if (mask_layer) { 714 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl()); 715 DCHECK_NE(new_layer_id, mask_layer_id_); 716 } else if (new_layer_id == mask_layer_id_) { 717 return; 718 } 719 720 mask_layer_ = mask_layer.Pass(); 721 mask_layer_id_ = new_layer_id; 722 if (mask_layer_) 723 mask_layer_->set_parent(this); 724 NoteLayerPropertyChangedForSubtree(); 725} 726 727scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() { 728 mask_layer_id_ = -1; 729 return mask_layer_.Pass(); 730} 731 732void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) { 733 int new_layer_id = replica_layer ? replica_layer->id() : -1; 734 735 if (replica_layer) { 736 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl()); 737 DCHECK_NE(new_layer_id, replica_layer_id_); 738 } else if (new_layer_id == replica_layer_id_) { 739 return; 740 } 741 742 replica_layer_ = replica_layer.Pass(); 743 replica_layer_id_ = new_layer_id; 744 if (replica_layer_) 745 replica_layer_->set_parent(this); 746 NoteLayerPropertyChangedForSubtree(); 747} 748 749scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() { 750 replica_layer_id_ = -1; 751 return replica_layer_.Pass(); 752} 753 754ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() { 755 return NULL; 756} 757 758void LayerImpl::SetDrawsContent(bool draws_content) { 759 if (draws_content_ == draws_content) 760 return; 761 762 draws_content_ = draws_content; 763 NoteLayerPropertyChanged(); 764} 765 766void LayerImpl::SetHideLayerAndSubtree(bool hide) { 767 if (hide_layer_and_subtree_ == hide) 768 return; 769 770 hide_layer_and_subtree_ = hide; 771 NoteLayerPropertyChangedForSubtree(); 772} 773 774void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) { 775 if (anchor_point_ == anchor_point) 776 return; 777 778 anchor_point_ = anchor_point; 779 NoteLayerPropertyChangedForSubtree(); 780} 781 782void LayerImpl::SetAnchorPointZ(float anchor_point_z) { 783 if (anchor_point_z_ == anchor_point_z) 784 return; 785 786 anchor_point_z_ = anchor_point_z; 787 NoteLayerPropertyChangedForSubtree(); 788} 789 790void LayerImpl::SetBackgroundColor(SkColor background_color) { 791 if (background_color_ == background_color) 792 return; 793 794 background_color_ = background_color; 795 NoteLayerPropertyChanged(); 796} 797 798SkColor LayerImpl::SafeOpaqueBackgroundColor() const { 799 SkColor color = background_color(); 800 if (SkColorGetA(color) == 255 && !contents_opaque()) { 801 color = SK_ColorTRANSPARENT; 802 } else if (SkColorGetA(color) != 255 && contents_opaque()) { 803 for (const LayerImpl* layer = parent(); layer; 804 layer = layer->parent()) { 805 color = layer->background_color(); 806 if (SkColorGetA(color) == 255) 807 break; 808 } 809 if (SkColorGetA(color) != 255) 810 color = layer_tree_impl()->background_color(); 811 if (SkColorGetA(color) != 255) 812 color = SkColorSetA(color, 255); 813 } 814 return color; 815} 816 817void LayerImpl::SetFilters(const FilterOperations& filters) { 818 if (filters_ == filters) 819 return; 820 821 DCHECK(!filter_); 822 filters_ = filters; 823 NoteLayerPropertyChangedForSubtree(); 824} 825 826void LayerImpl::SetBackgroundFilters( 827 const FilterOperations& filters) { 828 if (background_filters_ == filters) 829 return; 830 831 background_filters_ = filters; 832 NoteLayerPropertyChanged(); 833} 834 835void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) { 836 if (filter_.get() == filter.get()) 837 return; 838 839 DCHECK(filters_.IsEmpty()); 840 filter_ = filter; 841 NoteLayerPropertyChangedForSubtree(); 842} 843 844void LayerImpl::SetMasksToBounds(bool masks_to_bounds) { 845 if (masks_to_bounds_ == masks_to_bounds) 846 return; 847 848 masks_to_bounds_ = masks_to_bounds; 849 NoteLayerPropertyChangedForSubtree(); 850} 851 852void LayerImpl::SetContentsOpaque(bool opaque) { 853 if (contents_opaque_ == opaque) 854 return; 855 856 contents_opaque_ = opaque; 857 NoteLayerPropertyChangedForSubtree(); 858} 859 860void LayerImpl::SetOpacity(float opacity) { 861 if (opacity_ == opacity) 862 return; 863 864 opacity_ = opacity; 865 NoteLayerSurfacePropertyChanged(); 866} 867 868bool LayerImpl::OpacityIsAnimating() const { 869 return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity); 870} 871 872bool LayerImpl::OpacityIsAnimatingOnImplOnly() const { 873 Animation* opacity_animation = 874 layer_animation_controller_->GetAnimation(Animation::Opacity); 875 return opacity_animation && opacity_animation->is_impl_only(); 876} 877 878void LayerImpl::SetPosition(gfx::PointF position) { 879 if (position_ == position) 880 return; 881 882 position_ = position; 883 NoteLayerPropertyChangedForSubtree(); 884} 885 886void LayerImpl::SetPreserves3d(bool preserves3_d) { 887 if (preserves_3d_ == preserves3_d) 888 return; 889 890 preserves_3d_ = preserves3_d; 891 NoteLayerPropertyChangedForSubtree(); 892} 893 894void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) { 895 if (sublayer_transform_ == sublayer_transform) 896 return; 897 898 sublayer_transform_ = sublayer_transform; 899 // Sublayer transform does not affect the current layer; it affects only its 900 // children. 901 NoteLayerPropertyChangedForDescendants(); 902} 903 904void LayerImpl::SetTransform(const gfx::Transform& transform) { 905 if (transform_ == transform) 906 return; 907 908 transform_ = transform; 909 NoteLayerSurfacePropertyChanged(); 910} 911 912bool LayerImpl::TransformIsAnimating() const { 913 return layer_animation_controller_->IsAnimatingProperty(Animation::Transform); 914} 915 916bool LayerImpl::TransformIsAnimatingOnImplOnly() const { 917 Animation* transform_animation = 918 layer_animation_controller_->GetAnimation(Animation::Transform); 919 return transform_animation && transform_animation->is_impl_only(); 920} 921 922void LayerImpl::SetContentBounds(gfx::Size content_bounds) { 923 if (this->content_bounds() == content_bounds) 924 return; 925 926 draw_properties_.content_bounds = content_bounds; 927 NoteLayerPropertyChanged(); 928} 929 930void LayerImpl::SetContentsScale(float contents_scale_x, 931 float contents_scale_y) { 932 if (this->contents_scale_x() == contents_scale_x && 933 this->contents_scale_y() == contents_scale_y) 934 return; 935 936 draw_properties_.contents_scale_x = contents_scale_x; 937 draw_properties_.contents_scale_y = contents_scale_y; 938 NoteLayerPropertyChanged(); 939} 940 941void LayerImpl::CalculateContentsScale( 942 float ideal_contents_scale, 943 float device_scale_factor, 944 float page_scale_factor, 945 bool animating_transform_to_screen, 946 float* contents_scale_x, 947 float* contents_scale_y, 948 gfx::Size* content_bounds) { 949 // Base LayerImpl has all of its content scales and content bounds pushed 950 // from its Layer during commit and just reuses those values as-is. 951 *contents_scale_x = this->contents_scale_x(); 952 *contents_scale_y = this->contents_scale_y(); 953 *content_bounds = this->content_bounds(); 954} 955 956void LayerImpl::UpdateScrollbarPositions() { 957 gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta(); 958 959 gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_); 960 gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(), 961 max_scroll_offset_.y() + bounds_.height()); 962 if (horizontal_scrollbar_layer_) { 963 horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x()); 964 horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x()); 965 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio( 966 viewport.width() / scrollable_size.width()); 967 } 968 if (vertical_scrollbar_layer_) { 969 vertical_scrollbar_layer_->SetCurrentPos(current_offset.y()); 970 vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y()); 971 vertical_scrollbar_layer_->SetVisibleToTotalLengthRatio( 972 viewport.height() / scrollable_size.height()); 973 } 974 975 if (current_offset == last_scroll_offset_) 976 return; 977 last_scroll_offset_ = current_offset; 978 979 if (scrollbar_animation_controller_) { 980 bool should_animate = scrollbar_animation_controller_->DidScrollUpdate( 981 layer_tree_impl_->CurrentPhysicalTimeTicks()); 982 if (should_animate) 983 layer_tree_impl_->StartScrollbarAnimation(); 984 } 985 986 // Get the current_offset_.y() value for a sanity-check on scrolling 987 // benchmark metrics. Specifically, we want to make sure 988 // BasicMouseWheelSmoothScrollGesture has proper scroll curves. 989 if (layer_tree_impl()->IsActiveTree()) { 990 TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y()); 991 } 992} 993 994void LayerImpl::SetScrollOffsetDelegate( 995 LayerScrollOffsetDelegate* scroll_offset_delegate) { 996 // Having both a scroll parent and a scroll offset delegate is unsupported. 997 DCHECK(!scroll_parent_); 998 if (!scroll_offset_delegate && scroll_offset_delegate_) { 999 scroll_delta_ = 1000 scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1001 } 1002 gfx::Vector2dF total_offset = TotalScrollOffset(); 1003 scroll_offset_delegate_ = scroll_offset_delegate; 1004 if (scroll_offset_delegate_) 1005 scroll_offset_delegate_->SetTotalScrollOffset(total_offset); 1006} 1007 1008void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) { 1009 SetScrollOffsetAndDelta(scroll_offset, ScrollDelta()); 1010} 1011 1012void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset, 1013 gfx::Vector2dF scroll_delta) { 1014 bool changed = false; 1015 1016 if (scroll_offset_ != scroll_offset) { 1017 changed = true; 1018 scroll_offset_ = scroll_offset; 1019 1020 if (scroll_offset_delegate_) 1021 scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset()); 1022 } 1023 1024 if (ScrollDelta() != scroll_delta) { 1025 changed = true; 1026 if (layer_tree_impl()->IsActiveTree()) { 1027 LayerImpl* pending_twin = 1028 layer_tree_impl()->FindPendingTreeLayerById(id()); 1029 if (pending_twin) { 1030 // The pending twin can't mirror the scroll delta of the active 1031 // layer. Although the delta - sent scroll delta difference is 1032 // identical for both twins, the sent scroll delta for the pending 1033 // layer is zero, as anything that has been sent has been baked 1034 // into the layer's position/scroll offset as a part of commit. 1035 DCHECK(pending_twin->sent_scroll_delta().IsZero()); 1036 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta()); 1037 } 1038 } 1039 1040 if (scroll_offset_delegate_) { 1041 scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ + 1042 scroll_delta); 1043 } else { 1044 scroll_delta_ = scroll_delta; 1045 } 1046 } 1047 1048 if (changed) { 1049 NoteLayerPropertyChangedForSubtree(); 1050 UpdateScrollbarPositions(); 1051 } 1052} 1053 1054gfx::Vector2dF LayerImpl::ScrollDelta() const { 1055 if (scroll_offset_delegate_) 1056 return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1057 return scroll_delta_; 1058} 1059 1060void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) { 1061 SetScrollOffsetAndDelta(scroll_offset_, scroll_delta); 1062} 1063 1064gfx::Vector2dF LayerImpl::TotalScrollOffset() const { 1065 return scroll_offset_ + ScrollDelta(); 1066} 1067 1068void LayerImpl::SetDoubleSided(bool double_sided) { 1069 if (double_sided_ == double_sided) 1070 return; 1071 1072 double_sided_ = double_sided; 1073 NoteLayerPropertyChangedForSubtree(); 1074} 1075 1076Region LayerImpl::VisibleContentOpaqueRegion() const { 1077 if (contents_opaque()) 1078 return visible_content_rect(); 1079 return Region(); 1080} 1081 1082void LayerImpl::DidBeginTracing() {} 1083 1084void LayerImpl::DidLoseOutputSurface() {} 1085 1086void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) { 1087 if (max_scroll_offset_ == max_scroll_offset) 1088 return; 1089 max_scroll_offset_ = max_scroll_offset; 1090 1091 layer_tree_impl()->set_needs_update_draw_properties(); 1092 UpdateScrollbarPositions(); 1093} 1094 1095void LayerImpl::DidBecomeActive() { 1096 if (layer_tree_impl_->settings().scrollbar_animator == 1097 LayerTreeSettings::NoAnimator) { 1098 return; 1099 } 1100 1101 bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ || 1102 vertical_scrollbar_layer_; 1103 if (!need_scrollbar_animation_controller) { 1104 scrollbar_animation_controller_.reset(); 1105 return; 1106 } 1107 1108 if (scrollbar_animation_controller_) 1109 return; 1110 1111 switch (layer_tree_impl_->settings().scrollbar_animator) { 1112 case LayerTreeSettings::LinearFade: { 1113 base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds( 1114 layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms); 1115 base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds( 1116 layer_tree_impl_->settings().scrollbar_linear_fade_length_ms); 1117 1118 scrollbar_animation_controller_ = 1119 ScrollbarAnimationControllerLinearFade::Create( 1120 this, fadeout_delay, fadeout_length) 1121 .PassAs<ScrollbarAnimationController>(); 1122 break; 1123 } 1124 case LayerTreeSettings::Thinning: { 1125 scrollbar_animation_controller_ = 1126 ScrollbarAnimationControllerThinning::Create(this) 1127 .PassAs<ScrollbarAnimationController>(); 1128 break; 1129 } 1130 case LayerTreeSettings::NoAnimator: 1131 NOTREACHED(); 1132 break; 1133 } 1134} 1135void LayerImpl::SetHorizontalScrollbarLayer( 1136 ScrollbarLayerImplBase* scrollbar_layer) { 1137 horizontal_scrollbar_layer_ = scrollbar_layer; 1138 if (horizontal_scrollbar_layer_) 1139 horizontal_scrollbar_layer_->set_scroll_layer_id(id()); 1140} 1141 1142void LayerImpl::SetVerticalScrollbarLayer( 1143 ScrollbarLayerImplBase* scrollbar_layer) { 1144 vertical_scrollbar_layer_ = scrollbar_layer; 1145 if (vertical_scrollbar_layer_) 1146 vertical_scrollbar_layer_->set_scroll_layer_id(id()); 1147} 1148 1149static scoped_ptr<base::Value> 1150CompositingReasonsAsValue(CompositingReasons reasons) { 1151 scoped_ptr<base::ListValue> reason_list(new base::ListValue()); 1152 1153 if (reasons == kCompositingReasonUnknown) { 1154 reason_list->AppendString("No reasons given"); 1155 return reason_list.PassAs<base::Value>(); 1156 } 1157 1158 if (reasons & kCompositingReason3DTransform) 1159 reason_list->AppendString("Has a 3d Transform"); 1160 1161 if (reasons & kCompositingReasonVideo) 1162 reason_list->AppendString("Is accelerated video"); 1163 1164 if (reasons & kCompositingReasonCanvas) 1165 reason_list->AppendString("Is accelerated canvas"); 1166 1167 if (reasons & kCompositingReasonPlugin) 1168 reason_list->AppendString("Is accelerated plugin"); 1169 1170 if (reasons & kCompositingReasonIFrame) 1171 reason_list->AppendString("Is accelerated iframe"); 1172 1173 if (reasons & kCompositingReasonBackfaceVisibilityHidden) 1174 reason_list->AppendString("Has backface-visibility: hidden"); 1175 1176 if (reasons & kCompositingReasonAnimation) 1177 reason_list->AppendString("Has accelerated animation or transition"); 1178 1179 if (reasons & kCompositingReasonFilters) 1180 reason_list->AppendString("Has accelerated filters"); 1181 1182 if (reasons & kCompositingReasonPositionFixed) 1183 reason_list->AppendString("Is fixed position"); 1184 1185 if (reasons & kCompositingReasonPositionSticky) 1186 reason_list->AppendString("Is sticky position"); 1187 1188 if (reasons & kCompositingReasonOverflowScrollingTouch) 1189 reason_list->AppendString("Is a scrollable overflow element"); 1190 1191 if (reasons & kCompositingReasonBlending) 1192 reason_list->AppendString("Has a blend mode"); 1193 1194 if (reasons & kCompositingReasonAssumedOverlap) 1195 reason_list->AppendString("Might overlap a composited animation"); 1196 1197 if (reasons & kCompositingReasonOverlap) 1198 reason_list->AppendString("Overlaps other composited content"); 1199 1200 if (reasons & kCompositingReasonNegativeZIndexChildren) { 1201 reason_list->AppendString("Might overlap negative z-index " 1202 "composited content"); 1203 } 1204 1205 if (reasons & kCompositingReasonTransformWithCompositedDescendants) { 1206 reason_list->AppendString("Has transform needed by a " 1207 "composited descendant"); 1208 } 1209 1210 if (reasons & kCompositingReasonOpacityWithCompositedDescendants) 1211 reason_list->AppendString("Has opacity needed by a composited descendant"); 1212 1213 if (reasons & kCompositingReasonMaskWithCompositedDescendants) 1214 reason_list->AppendString("Has a mask needed by a composited descendant"); 1215 1216 if (reasons & kCompositingReasonReflectionWithCompositedDescendants) 1217 reason_list->AppendString("Has a reflection with a composited descendant"); 1218 1219 if (reasons & kCompositingReasonFilterWithCompositedDescendants) 1220 reason_list->AppendString("Has filter effect with a composited descendant"); 1221 1222 if (reasons & kCompositingReasonBlendingWithCompositedDescendants) 1223 reason_list->AppendString("Has a blend mode with a composited descendant"); 1224 1225 if (reasons & kCompositingReasonClipsCompositingDescendants) 1226 reason_list->AppendString("Clips a composited descendant"); 1227 1228 if (reasons & kCompositingReasonPerspective) { 1229 reason_list->AppendString("Has a perspective transform needed by a " 1230 "composited 3d descendant"); 1231 } 1232 1233 if (reasons & kCompositingReasonPreserve3D) { 1234 reason_list->AppendString("Has preserves-3d style with composited " 1235 "3d descendant"); 1236 } 1237 1238 if (reasons & kCompositingReasonReflectionOfCompositedParent) 1239 reason_list->AppendString("Is the reflection of a composited layer"); 1240 1241 if (reasons & kCompositingReasonRoot) 1242 reason_list->AppendString("Is the root"); 1243 1244 if (reasons & kCompositingReasonLayerForClip) 1245 reason_list->AppendString("Convenience layer, to clip subtree"); 1246 1247 if (reasons & kCompositingReasonLayerForScrollbar) 1248 reason_list->AppendString("Convenience layer for rendering scrollbar"); 1249 1250 if (reasons & kCompositingReasonLayerForScrollingContainer) 1251 reason_list->AppendString("Convenience layer, the scrolling container"); 1252 1253 if (reasons & kCompositingReasonLayerForForeground) { 1254 reason_list->AppendString("Convenience layer, foreground when main layer " 1255 "has negative z-index composited content"); 1256 } 1257 1258 if (reasons & kCompositingReasonLayerForBackground) { 1259 reason_list->AppendString("Convenience layer, background when main layer " 1260 "has a composited background"); 1261 } 1262 1263 if (reasons & kCompositingReasonLayerForMask) 1264 reason_list->AppendString("Is a mask layer"); 1265 1266 if (reasons & kCompositingReasonOverflowScrollingParent) 1267 reason_list->AppendString("Scroll parent is not an ancestor"); 1268 1269 if (reasons & kCompositingReasonOutOfFlowClipping) 1270 reason_list->AppendString("Has clipping ancestor"); 1271 1272 return reason_list.PassAs<base::Value>(); 1273} 1274 1275void LayerImpl::AsValueInto(base::DictionaryValue* state) const { 1276 TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this); 1277 state->SetInteger("layer_id", id()); 1278 state->SetString("layer_name", debug_name()); 1279 state->Set("bounds", MathUtil::AsValue(bounds()).release()); 1280 state->SetInteger("draws_content", DrawsContent()); 1281 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); 1282 state->Set("compositing_reasons", 1283 CompositingReasonsAsValue(compositing_reasons_).release()); 1284 1285 bool clipped; 1286 gfx::QuadF layer_quad = MathUtil::MapQuad( 1287 screen_space_transform(), 1288 gfx::QuadF(gfx::Rect(content_bounds())), 1289 &clipped); 1290 state->Set("layer_quad", MathUtil::AsValue(layer_quad).release()); 1291 1292 1293 scoped_ptr<base::ListValue> children_list(new base::ListValue()); 1294 for (size_t i = 0; i < children_.size(); ++i) 1295 children_list->Append(children_[i]->AsValue().release()); 1296 state->Set("children", children_list.release()); 1297 if (mask_layer_) 1298 state->Set("mask_layer", mask_layer_->AsValue().release()); 1299 if (replica_layer_) 1300 state->Set("replica_layer", replica_layer_->AsValue().release()); 1301 1302 if (scroll_parent_) 1303 state->SetInteger("scroll_parent", scroll_parent_->id()); 1304 1305 if (clip_parent_) 1306 state->SetInteger("clip_parent", clip_parent_->id()); 1307} 1308 1309size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; } 1310 1311scoped_ptr<base::Value> LayerImpl::AsValue() const { 1312 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 1313 AsValueInto(state.get()); 1314 return state.PassAs<base::Value>(); 1315} 1316 1317} // namespace cc 1318