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