layer_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/layers/layer_impl.h" 6 7#include "base/debug/trace_event.h" 8#include "base/json/json_reader.h" 9#include "base/strings/stringprintf.h" 10#include "cc/animation/animation_registrar.h" 11#include "cc/animation/scrollbar_animation_controller.h" 12#include "cc/animation/scrollbar_animation_controller_linear_fade.h" 13#include "cc/animation/scrollbar_animation_controller_thinning.h" 14#include "cc/base/math_util.h" 15#include "cc/debug/debug_colors.h" 16#include "cc/debug/layer_tree_debug_state.h" 17#include "cc/debug/micro_benchmark_impl.h" 18#include "cc/debug/traced_value.h" 19#include "cc/input/layer_scroll_offset_delegate.h" 20#include "cc/layers/layer_utils.h" 21#include "cc/layers/painted_scrollbar_layer_impl.h" 22#include "cc/layers/quad_sink.h" 23#include "cc/output/copy_output_request.h" 24#include "cc/quads/debug_border_draw_quad.h" 25#include "cc/trees/layer_tree_host_common.h" 26#include "cc/trees/layer_tree_impl.h" 27#include "cc/trees/layer_tree_settings.h" 28#include "cc/trees/proxy.h" 29#include "ui/gfx/box_f.h" 30#include "ui/gfx/geometry/vector2d_conversions.h" 31#include "ui/gfx/point_conversions.h" 32#include "ui/gfx/quad_f.h" 33#include "ui/gfx/rect_conversions.h" 34 35namespace cc { 36LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) 37 : parent_(NULL), 38 scroll_parent_(NULL), 39 clip_parent_(NULL), 40 mask_layer_id_(-1), 41 replica_layer_id_(-1), 42 layer_id_(id), 43 layer_tree_impl_(tree_impl), 44 anchor_point_(0.5f, 0.5f), 45 anchor_point_z_(0.f), 46 scroll_offset_delegate_(NULL), 47 scroll_clip_layer_(NULL), 48 should_scroll_on_main_thread_(false), 49 have_wheel_event_handlers_(false), 50 user_scrollable_horizontal_(true), 51 user_scrollable_vertical_(true), 52 stacking_order_changed_(false), 53 double_sided_(true), 54 should_flatten_transform_(true), 55 layer_property_changed_(false), 56 masks_to_bounds_(false), 57 contents_opaque_(false), 58 is_root_for_isolated_group_(false), 59 use_parent_backface_visibility_(false), 60 draw_checkerboard_for_missing_tiles_(false), 61 draws_content_(false), 62 hide_layer_and_subtree_(false), 63 force_render_surface_(false), 64 is_container_for_fixed_position_layers_(false), 65 is_3d_sorted_(false), 66 background_color_(0), 67 opacity_(1.0), 68 blend_mode_(SkXfermode::kSrcOver_Mode), 69 draw_depth_(0.f), 70 needs_push_properties_(false), 71 num_dependents_need_push_properties_(0), 72 current_draw_mode_(DRAW_MODE_NONE) { 73 DCHECK_GT(layer_id_, 0); 74 DCHECK(layer_tree_impl_); 75 layer_tree_impl_->RegisterLayer(this); 76 AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar(); 77 layer_animation_controller_ = 78 registrar->GetAnimationControllerForId(layer_id_); 79 layer_animation_controller_->AddValueObserver(this); 80 if (IsActive()) 81 layer_animation_controller_->set_value_provider(this); 82 SetNeedsPushProperties(); 83} 84 85LayerImpl::~LayerImpl() { 86 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_); 87 88 layer_animation_controller_->RemoveValueObserver(this); 89 layer_animation_controller_->remove_value_provider(this); 90 91 if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree()) 92 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); 93 layer_tree_impl_->UnregisterLayer(this); 94 95 if (scroll_children_) { 96 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin(); 97 it != scroll_children_->end(); ++it) 98 (*it)->scroll_parent_ = NULL; 99 } 100 101 if (scroll_parent_) 102 scroll_parent_->RemoveScrollChild(this); 103 104 if (clip_children_) { 105 for (std::set<LayerImpl*>::iterator it = clip_children_->begin(); 106 it != clip_children_->end(); ++it) 107 (*it)->clip_parent_ = NULL; 108 } 109 110 if (clip_parent_) 111 clip_parent_->RemoveClipChild(this); 112 113 TRACE_EVENT_OBJECT_DELETED_WITH_ID( 114 TRACE_DISABLED_BY_DEFAULT("cc.debug"), 115 LayerTypeAsString(), this); 116} 117 118void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) { 119 child->SetParent(this); 120 DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl()); 121 children_.push_back(child.Pass()); 122 layer_tree_impl()->set_needs_update_draw_properties(); 123} 124 125scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) { 126 for (OwnedLayerImplList::iterator it = children_.begin(); 127 it != children_.end(); 128 ++it) { 129 if (*it == child) { 130 scoped_ptr<LayerImpl> ret = children_.take(it); 131 children_.erase(it); 132 layer_tree_impl()->set_needs_update_draw_properties(); 133 return ret.Pass(); 134 } 135 } 136 return scoped_ptr<LayerImpl>(); 137} 138 139void LayerImpl::SetParent(LayerImpl* parent) { 140 if (parent_should_know_need_push_properties()) { 141 if (parent_) 142 parent_->RemoveDependentNeedsPushProperties(); 143 if (parent) 144 parent->AddDependentNeedsPushProperties(); 145 } 146 parent_ = parent; 147} 148 149void LayerImpl::ClearChildList() { 150 if (children_.empty()) 151 return; 152 153 children_.clear(); 154 layer_tree_impl()->set_needs_update_draw_properties(); 155} 156 157bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const { 158 if (!ancestor) 159 return false; 160 161 for (const LayerImpl* layer = this; layer; layer = layer->parent()) { 162 if (layer == ancestor) 163 return true; 164 } 165 166 return false; 167} 168 169void LayerImpl::SetScrollParent(LayerImpl* parent) { 170 if (scroll_parent_ == parent) 171 return; 172 173 // Having both a scroll parent and a scroll offset delegate is unsupported. 174 DCHECK(!scroll_offset_delegate_); 175 176 if (scroll_parent_) 177 scroll_parent_->RemoveScrollChild(this); 178 179 scroll_parent_ = parent; 180 SetNeedsPushProperties(); 181} 182 183void LayerImpl::SetDebugInfo( 184 scoped_refptr<base::debug::ConvertableToTraceFormat> other) { 185 debug_info_ = other; 186 SetNeedsPushProperties(); 187} 188 189void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) { 190 if (scroll_children_.get() == children) 191 return; 192 scroll_children_.reset(children); 193 SetNeedsPushProperties(); 194} 195 196void LayerImpl::RemoveScrollChild(LayerImpl* child) { 197 DCHECK(scroll_children_); 198 scroll_children_->erase(child); 199 if (scroll_children_->empty()) 200 scroll_children_.reset(); 201 SetNeedsPushProperties(); 202} 203 204void LayerImpl::SetClipParent(LayerImpl* ancestor) { 205 if (clip_parent_ == ancestor) 206 return; 207 208 if (clip_parent_) 209 clip_parent_->RemoveClipChild(this); 210 211 clip_parent_ = ancestor; 212 SetNeedsPushProperties(); 213} 214 215void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) { 216 if (clip_children_.get() == children) 217 return; 218 clip_children_.reset(children); 219 SetNeedsPushProperties(); 220} 221 222void LayerImpl::RemoveClipChild(LayerImpl* child) { 223 DCHECK(clip_children_); 224 clip_children_->erase(child); 225 if (clip_children_->empty()) 226 clip_children_.reset(); 227 SetNeedsPushProperties(); 228} 229 230void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) { 231 if (requests->empty()) 232 return; 233 234 bool was_empty = copy_requests_.empty(); 235 copy_requests_.insert_and_take(copy_requests_.end(), *requests); 236 requests->clear(); 237 238 if (was_empty && layer_tree_impl()->IsActiveTree()) 239 layer_tree_impl()->AddLayerWithCopyOutputRequest(this); 240 NoteLayerPropertyChangedForSubtree(); 241} 242 243void LayerImpl::TakeCopyRequestsAndTransformToTarget( 244 ScopedPtrVector<CopyOutputRequest>* requests) { 245 DCHECK(!copy_requests_.empty()); 246 DCHECK(layer_tree_impl()->IsActiveTree()); 247 248 size_t first_inserted_request = requests->size(); 249 requests->insert_and_take(requests->end(), copy_requests_); 250 copy_requests_.clear(); 251 252 for (size_t i = first_inserted_request; i < requests->size(); ++i) { 253 CopyOutputRequest* request = requests->at(i); 254 if (!request->has_area()) 255 continue; 256 257 gfx::Rect request_in_layer_space = request->area(); 258 gfx::Rect request_in_content_space = 259 LayerRectToContentRect(request_in_layer_space); 260 request->set_area(MathUtil::MapEnclosingClippedRect( 261 draw_properties_.target_space_transform, request_in_content_space)); 262 } 263 264 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); 265} 266 267void LayerImpl::CreateRenderSurface() { 268 DCHECK(!draw_properties_.render_surface); 269 draw_properties_.render_surface = 270 make_scoped_ptr(new RenderSurfaceImpl(this)); 271 draw_properties_.render_target = this; 272} 273 274void LayerImpl::ClearRenderSurface() { 275 draw_properties_.render_surface.reset(); 276} 277 278scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const { 279 scoped_ptr<SharedQuadState> state = SharedQuadState::Create(); 280 state->SetAll(draw_properties_.target_space_transform, 281 draw_properties_.content_bounds, 282 draw_properties_.visible_content_rect, 283 draw_properties_.clip_rect, 284 draw_properties_.is_clipped, 285 draw_properties_.opacity, 286 blend_mode_); 287 return state.Pass(); 288} 289 290bool LayerImpl::WillDraw(DrawMode draw_mode, 291 ResourceProvider* resource_provider) { 292 // WillDraw/DidDraw must be matched. 293 DCHECK_NE(DRAW_MODE_NONE, draw_mode); 294 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_); 295 current_draw_mode_ = draw_mode; 296 return true; 297} 298 299void LayerImpl::DidDraw(ResourceProvider* resource_provider) { 300 DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_); 301 current_draw_mode_ = DRAW_MODE_NONE; 302} 303 304bool LayerImpl::ShowDebugBorders() const { 305 return layer_tree_impl()->debug_state().show_debug_borders; 306} 307 308void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { 309 if (draws_content_) { 310 *color = DebugColors::ContentLayerBorderColor(); 311 *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl()); 312 return; 313 } 314 315 if (masks_to_bounds_) { 316 *color = DebugColors::MaskingLayerBorderColor(); 317 *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl()); 318 return; 319 } 320 321 *color = DebugColors::ContainerLayerBorderColor(); 322 *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl()); 323} 324 325void LayerImpl::AppendDebugBorderQuad( 326 QuadSink* quad_sink, 327 const SharedQuadState* shared_quad_state, 328 AppendQuadsData* append_quads_data) const { 329 SkColor color; 330 float width; 331 GetDebugBorderProperties(&color, &width); 332 AppendDebugBorderQuad( 333 quad_sink, shared_quad_state, append_quads_data, color, width); 334} 335 336void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink, 337 const SharedQuadState* shared_quad_state, 338 AppendQuadsData* append_quads_data, 339 SkColor color, 340 float width) const { 341 if (!ShowDebugBorders()) 342 return; 343 344 gfx::Rect content_rect(content_bounds()); 345 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = 346 DebugBorderDrawQuad::Create(); 347 debug_border_quad->SetNew(shared_quad_state, content_rect, color, width); 348 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data); 349} 350 351bool LayerImpl::HasDelegatedContent() const { 352 return false; 353} 354 355bool LayerImpl::HasContributingDelegatedRenderPasses() const { 356 return false; 357} 358 359RenderPass::Id LayerImpl::FirstContributingRenderPassId() const { 360 return RenderPass::Id(0, 0); 361} 362 363RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id) 364 const { 365 return RenderPass::Id(0, 0); 366} 367 368ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const { 369 NOTREACHED(); 370 return 0; 371} 372 373void LayerImpl::SetSentScrollDelta(const gfx::Vector2d& sent_scroll_delta) { 374 // Pending tree never has sent scroll deltas 375 DCHECK(layer_tree_impl()->IsActiveTree()); 376 377 if (sent_scroll_delta_ == sent_scroll_delta) 378 return; 379 380 sent_scroll_delta_ = sent_scroll_delta; 381} 382 383gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) { 384 DCHECK(scrollable()); 385 gfx::Vector2dF min_delta = -scroll_offset_; 386 gfx::Vector2dF max_delta = MaxScrollOffset() - scroll_offset_; 387 // Clamp new_delta so that position + delta stays within scroll bounds. 388 gfx::Vector2dF new_delta = (ScrollDelta() + scroll); 389 new_delta.SetToMax(min_delta); 390 new_delta.SetToMin(max_delta); 391 gfx::Vector2dF unscrolled = 392 ScrollDelta() + scroll - new_delta; 393 SetScrollDelta(new_delta); 394 395 return unscrolled; 396} 397 398void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) { 399 scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id); 400} 401 402void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() { 403 // Pending tree never has sent scroll deltas 404 DCHECK(layer_tree_impl()->IsActiveTree()); 405 406 // Apply sent scroll deltas to scroll position / scroll delta as if the 407 // main thread had applied them and then committed those values. 408 // 409 // This function should not change the total scroll offset; it just shifts 410 // some of the scroll delta to the scroll offset. Therefore, adjust these 411 // variables directly rather than calling the scroll offset delegate to 412 // avoid sending it multiple spurious calls. 413 // 414 // Because of the way scroll delta is calculated with a delegate, this will 415 // leave the total scroll offset unchanged on this layer regardless of 416 // whether a delegate is being used. 417 scroll_offset_ += sent_scroll_delta_; 418 scroll_delta_ -= sent_scroll_delta_; 419 sent_scroll_delta_ = gfx::Vector2d(); 420} 421 422void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() { 423 // Only the pending tree can have missing scrolls. 424 DCHECK(layer_tree_impl()->IsPendingTree()); 425 if (!scrollable()) 426 return; 427 428 // Pending tree should never have sent scroll deltas. 429 DCHECK(sent_scroll_delta().IsZero()); 430 431 LayerImpl* active_twin = layer_tree_impl()->FindActiveTreeLayerById(id()); 432 if (active_twin) { 433 // Scrolls that happens after begin frame (where the sent scroll delta 434 // comes from) and commit need to be applied to the pending tree 435 // so that it is up to date with the total scroll. 436 SetScrollDelta(active_twin->ScrollDelta() - 437 active_twin->sent_scroll_delta()); 438 } 439} 440 441InputHandler::ScrollStatus LayerImpl::TryScroll( 442 const gfx::PointF& screen_space_point, 443 InputHandler::ScrollInputType type) const { 444 if (should_scroll_on_main_thread()) { 445 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread"); 446 return InputHandler::ScrollOnMainThread; 447 } 448 449 if (!screen_space_transform().IsInvertible()) { 450 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform"); 451 return InputHandler::ScrollIgnored; 452 } 453 454 if (!non_fast_scrollable_region().IsEmpty()) { 455 bool clipped = false; 456 gfx::Transform inverse_screen_space_transform( 457 gfx::Transform::kSkipInitialization); 458 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) { 459 // TODO(shawnsingh): We shouldn't be applying a projection if screen space 460 // transform is uninvertible here. Perhaps we should be returning 461 // ScrollOnMainThread in this case? 462 } 463 464 gfx::PointF hit_test_point_in_content_space = 465 MathUtil::ProjectPoint(inverse_screen_space_transform, 466 screen_space_point, 467 &clipped); 468 gfx::PointF hit_test_point_in_layer_space = 469 gfx::ScalePoint(hit_test_point_in_content_space, 470 1.f / contents_scale_x(), 471 1.f / contents_scale_y()); 472 if (!clipped && 473 non_fast_scrollable_region().Contains( 474 gfx::ToRoundedPoint(hit_test_point_in_layer_space))) { 475 TRACE_EVENT0("cc", 476 "LayerImpl::tryScroll: Failed NonFastScrollableRegion"); 477 return InputHandler::ScrollOnMainThread; 478 } 479 } 480 481 if (type == InputHandler::Wheel && have_wheel_event_handlers()) { 482 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers"); 483 return InputHandler::ScrollOnMainThread; 484 } 485 486 if (!scrollable()) { 487 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); 488 return InputHandler::ScrollIgnored; 489 } 490 491 gfx::Vector2d max_scroll_offset = MaxScrollOffset(); 492 if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0) { 493 TRACE_EVENT0("cc", 494 "LayerImpl::tryScroll: Ignored. Technically scrollable," 495 " but has no affordance in either direction."); 496 return InputHandler::ScrollIgnored; 497 } 498 499 return InputHandler::ScrollStarted; 500} 501 502bool LayerImpl::DrawCheckerboardForMissingTiles() const { 503 return draw_checkerboard_for_missing_tiles_ && 504 !layer_tree_impl()->settings().background_color_instead_of_checkerboard; 505} 506 507gfx::Rect LayerImpl::LayerRectToContentRect( 508 const gfx::RectF& layer_rect) const { 509 gfx::RectF content_rect = 510 gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y()); 511 // Intersect with content rect to avoid the extra pixel because for some 512 // values x and y, ceil((x / y) * y) may be x + 1. 513 content_rect.Intersect(gfx::Rect(content_bounds())); 514 return gfx::ToEnclosingRect(content_rect); 515} 516 517skia::RefPtr<SkPicture> LayerImpl::GetPicture() { 518 return skia::RefPtr<SkPicture>(); 519} 520 521bool LayerImpl::AreVisibleResourcesReady() const { 522 return true; 523} 524 525scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { 526 return LayerImpl::Create(tree_impl, layer_id_); 527} 528 529void LayerImpl::PushPropertiesTo(LayerImpl* layer) { 530 layer->SetAnchorPoint(anchor_point_); 531 layer->SetAnchorPointZ(anchor_point_z_); 532 layer->SetBackgroundColor(background_color_); 533 layer->SetBounds(bounds_); 534 layer->SetContentBounds(content_bounds()); 535 layer->SetContentsScale(contents_scale_x(), contents_scale_y()); 536 layer->SetDoubleSided(double_sided_); 537 layer->SetDrawCheckerboardForMissingTiles( 538 draw_checkerboard_for_missing_tiles_); 539 layer->SetForceRenderSurface(force_render_surface_); 540 layer->SetDrawsContent(DrawsContent()); 541 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); 542 layer->SetFilters(filters()); 543 layer->SetBackgroundFilters(background_filters()); 544 layer->SetMasksToBounds(masks_to_bounds_); 545 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); 546 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_); 547 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); 548 layer->SetTouchEventHandlerRegion(touch_event_handler_region_); 549 layer->SetContentsOpaque(contents_opaque_); 550 layer->SetOpacity(opacity_); 551 layer->SetBlendMode(blend_mode_); 552 layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_); 553 layer->SetPosition(position_); 554 layer->SetIsContainerForFixedPositionLayers( 555 is_container_for_fixed_position_layers_); 556 layer->SetFixedContainerSizeDelta(fixed_container_size_delta_); 557 layer->SetPositionConstraint(position_constraint_); 558 layer->SetShouldFlattenTransform(should_flatten_transform_); 559 layer->SetIs3dSorted(is_3d_sorted_); 560 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); 561 layer->SetTransform(transform_); 562 563 layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id() 564 : Layer::INVALID_ID); 565 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_); 566 layer->set_user_scrollable_vertical(user_scrollable_vertical_); 567 layer->SetScrollOffsetAndDelta( 568 scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta()); 569 layer->SetSentScrollDelta(gfx::Vector2d()); 570 571 LayerImpl* scroll_parent = NULL; 572 if (scroll_parent_) 573 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id()); 574 575 layer->SetScrollParent(scroll_parent); 576 if (scroll_children_) { 577 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>; 578 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin(); 579 it != scroll_children_->end(); ++it) 580 scroll_children->insert(layer->layer_tree_impl()->LayerById((*it)->id())); 581 layer->SetScrollChildren(scroll_children); 582 } 583 584 LayerImpl* clip_parent = NULL; 585 if (clip_parent_) { 586 clip_parent = layer->layer_tree_impl()->LayerById( 587 clip_parent_->id()); 588 } 589 590 layer->SetClipParent(clip_parent); 591 if (clip_children_) { 592 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>; 593 for (std::set<LayerImpl*>::iterator it = clip_children_->begin(); 594 it != clip_children_->end(); ++it) 595 clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id())); 596 layer->SetClipChildren(clip_children); 597 } 598 599 layer->PassCopyRequests(©_requests_); 600 601 // If the main thread commits multiple times before the impl thread actually 602 // draws, then damage tracking will become incorrect if we simply clobber the 603 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. 604 // union) any update changes that have occurred on the main thread. 605 update_rect_.Union(layer->update_rect()); 606 layer->SetUpdateRect(update_rect_); 607 608 layer->SetStackingOrderChanged(stacking_order_changed_); 609 layer->SetDebugInfo(debug_info_); 610 611 // Reset any state that should be cleared for the next update. 612 stacking_order_changed_ = false; 613 update_rect_ = gfx::RectF(); 614 needs_push_properties_ = false; 615 num_dependents_need_push_properties_ = 0; 616} 617 618base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { 619 base::DictionaryValue* result = new base::DictionaryValue; 620 result->SetString("LayerType", LayerTypeAsString()); 621 622 base::ListValue* list = new base::ListValue; 623 list->AppendInteger(bounds().width()); 624 list->AppendInteger(bounds().height()); 625 result->Set("Bounds", list); 626 627 list = new base::ListValue; 628 list->AppendDouble(position_.x()); 629 list->AppendDouble(position_.y()); 630 result->Set("Position", list); 631 632 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform; 633 double transform[16]; 634 gfx_transform.matrix().asColMajord(transform); 635 list = new base::ListValue; 636 for (int i = 0; i < 16; ++i) 637 list->AppendDouble(transform[i]); 638 result->Set("DrawTransform", list); 639 640 result->SetBoolean("DrawsContent", draws_content_); 641 result->SetDouble("Opacity", opacity()); 642 result->SetBoolean("ContentsOpaque", contents_opaque_); 643 644 if (scrollable()) 645 result->SetBoolean("Scrollable", true); 646 647 if (have_wheel_event_handlers_) 648 result->SetBoolean("WheelHandler", have_wheel_event_handlers_); 649 if (!touch_event_handler_region_.IsEmpty()) { 650 scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue(); 651 result->Set("TouchRegion", region.release()); 652 } 653 654 list = new base::ListValue; 655 for (size_t i = 0; i < children_.size(); ++i) 656 list->Append(children_[i]->LayerTreeAsJson()); 657 result->Set("Children", list); 658 659 return result; 660} 661 662void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) { 663 if (stacking_order_changed) { 664 stacking_order_changed_ = true; 665 NoteLayerPropertyChangedForSubtree(); 666 } 667} 668 669void LayerImpl::NoteLayerPropertyChanged() { 670 layer_property_changed_ = true; 671 layer_tree_impl()->set_needs_update_draw_properties(); 672 SetNeedsPushProperties(); 673} 674 675void LayerImpl::NoteLayerPropertyChangedForSubtree() { 676 layer_property_changed_ = true; 677 layer_tree_impl()->set_needs_update_draw_properties(); 678 for (size_t i = 0; i < children_.size(); ++i) 679 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 680 SetNeedsPushProperties(); 681} 682 683void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() { 684 layer_property_changed_ = true; 685 for (size_t i = 0; i < children_.size(); ++i) 686 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 687} 688 689void LayerImpl::NoteLayerPropertyChangedForDescendants() { 690 layer_tree_impl()->set_needs_update_draw_properties(); 691 for (size_t i = 0; i < children_.size(); ++i) 692 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 693 SetNeedsPushProperties(); 694} 695 696const char* LayerImpl::LayerTypeAsString() const { 697 return "cc::LayerImpl"; 698} 699 700void LayerImpl::ResetAllChangeTrackingForSubtree() { 701 layer_property_changed_ = false; 702 703 update_rect_ = gfx::RectF(); 704 705 if (draw_properties_.render_surface) 706 draw_properties_.render_surface->ResetPropertyChangedFlag(); 707 708 if (mask_layer_) 709 mask_layer_->ResetAllChangeTrackingForSubtree(); 710 711 if (replica_layer_) { 712 // This also resets the replica mask, if it exists. 713 replica_layer_->ResetAllChangeTrackingForSubtree(); 714 } 715 716 for (size_t i = 0; i < children_.size(); ++i) 717 children_[i]->ResetAllChangeTrackingForSubtree(); 718 719 needs_push_properties_ = false; 720 num_dependents_need_push_properties_ = 0; 721} 722 723bool LayerImpl::LayerIsAlwaysDamaged() const { 724 return false; 725} 726 727gfx::Vector2dF LayerImpl::ScrollOffsetForAnimation() const { 728 return TotalScrollOffset(); 729} 730 731void LayerImpl::OnFilterAnimated(const FilterOperations& filters) { 732 SetFilters(filters); 733} 734 735void LayerImpl::OnOpacityAnimated(float opacity) { 736 SetOpacity(opacity); 737} 738 739void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { 740 SetTransform(transform); 741} 742 743void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset) { 744 // Only layers in the active tree should need to do anything here, since 745 // layers in the pending tree will find out about these changes as a 746 // result of the call to SetScrollDelta. 747 if (!IsActive()) 748 return; 749 750 SetScrollDelta(scroll_offset - scroll_offset_); 751 752 layer_tree_impl_->DidAnimateScrollOffset(); 753} 754 755void LayerImpl::OnAnimationWaitingForDeletion() {} 756 757bool LayerImpl::IsActive() const { 758 return layer_tree_impl_->IsActiveTree(); 759} 760 761void LayerImpl::SetBounds(const gfx::Size& bounds) { 762 if (bounds_ == bounds) 763 return; 764 765 bounds_ = bounds; 766 767 ScrollbarParametersDidChange(); 768 if (masks_to_bounds()) 769 NoteLayerPropertyChangedForSubtree(); 770 else 771 NoteLayerPropertyChanged(); 772} 773 774void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) { 775 int new_layer_id = mask_layer ? mask_layer->id() : -1; 776 777 if (mask_layer) { 778 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl()); 779 DCHECK_NE(new_layer_id, mask_layer_id_); 780 } else if (new_layer_id == mask_layer_id_) { 781 return; 782 } 783 784 mask_layer_ = mask_layer.Pass(); 785 mask_layer_id_ = new_layer_id; 786 if (mask_layer_) 787 mask_layer_->SetParent(this); 788 NoteLayerPropertyChangedForSubtree(); 789} 790 791scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() { 792 mask_layer_id_ = -1; 793 return mask_layer_.Pass(); 794} 795 796void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) { 797 int new_layer_id = replica_layer ? replica_layer->id() : -1; 798 799 if (replica_layer) { 800 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl()); 801 DCHECK_NE(new_layer_id, replica_layer_id_); 802 } else if (new_layer_id == replica_layer_id_) { 803 return; 804 } 805 806 replica_layer_ = replica_layer.Pass(); 807 replica_layer_id_ = new_layer_id; 808 if (replica_layer_) 809 replica_layer_->SetParent(this); 810 NoteLayerPropertyChangedForSubtree(); 811} 812 813scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() { 814 replica_layer_id_ = -1; 815 return replica_layer_.Pass(); 816} 817 818ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() { 819 return NULL; 820} 821 822void LayerImpl::SetDrawsContent(bool draws_content) { 823 if (draws_content_ == draws_content) 824 return; 825 826 draws_content_ = draws_content; 827 NoteLayerPropertyChanged(); 828} 829 830void LayerImpl::SetHideLayerAndSubtree(bool hide) { 831 if (hide_layer_and_subtree_ == hide) 832 return; 833 834 hide_layer_and_subtree_ = hide; 835 NoteLayerPropertyChangedForSubtree(); 836} 837 838void LayerImpl::SetAnchorPoint(const gfx::PointF& anchor_point) { 839 if (anchor_point_ == anchor_point) 840 return; 841 842 anchor_point_ = anchor_point; 843 NoteLayerPropertyChangedForSubtree(); 844} 845 846void LayerImpl::SetAnchorPointZ(float anchor_point_z) { 847 if (anchor_point_z_ == anchor_point_z) 848 return; 849 850 anchor_point_z_ = anchor_point_z; 851 NoteLayerPropertyChangedForSubtree(); 852} 853 854void LayerImpl::SetBackgroundColor(SkColor background_color) { 855 if (background_color_ == background_color) 856 return; 857 858 background_color_ = background_color; 859 NoteLayerPropertyChanged(); 860} 861 862SkColor LayerImpl::SafeOpaqueBackgroundColor() const { 863 SkColor color = background_color(); 864 if (SkColorGetA(color) == 255 && !contents_opaque()) { 865 color = SK_ColorTRANSPARENT; 866 } else if (SkColorGetA(color) != 255 && contents_opaque()) { 867 for (const LayerImpl* layer = parent(); layer; 868 layer = layer->parent()) { 869 color = layer->background_color(); 870 if (SkColorGetA(color) == 255) 871 break; 872 } 873 if (SkColorGetA(color) != 255) 874 color = layer_tree_impl()->background_color(); 875 if (SkColorGetA(color) != 255) 876 color = SkColorSetA(color, 255); 877 } 878 return color; 879} 880 881void LayerImpl::SetFilters(const FilterOperations& filters) { 882 if (filters_ == filters) 883 return; 884 885 filters_ = filters; 886 NoteLayerPropertyChangedForSubtree(); 887} 888 889bool LayerImpl::FilterIsAnimating() const { 890 return layer_animation_controller_->IsAnimatingProperty(Animation::Filter); 891} 892 893bool LayerImpl::FilterIsAnimatingOnImplOnly() const { 894 Animation* filter_animation = 895 layer_animation_controller_->GetAnimation(Animation::Filter); 896 return filter_animation && filter_animation->is_impl_only(); 897} 898 899void LayerImpl::SetBackgroundFilters( 900 const FilterOperations& filters) { 901 if (background_filters_ == filters) 902 return; 903 904 background_filters_ = filters; 905 NoteLayerPropertyChanged(); 906} 907 908void LayerImpl::SetMasksToBounds(bool masks_to_bounds) { 909 if (masks_to_bounds_ == masks_to_bounds) 910 return; 911 912 masks_to_bounds_ = masks_to_bounds; 913 NoteLayerPropertyChangedForSubtree(); 914} 915 916void LayerImpl::SetContentsOpaque(bool opaque) { 917 if (contents_opaque_ == opaque) 918 return; 919 920 contents_opaque_ = opaque; 921 NoteLayerPropertyChangedForSubtree(); 922} 923 924void LayerImpl::SetOpacity(float opacity) { 925 if (opacity_ == opacity) 926 return; 927 928 opacity_ = opacity; 929 NoteLayerPropertyChangedForSubtree(); 930} 931 932bool LayerImpl::OpacityIsAnimating() const { 933 return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity); 934} 935 936bool LayerImpl::OpacityIsAnimatingOnImplOnly() const { 937 Animation* opacity_animation = 938 layer_animation_controller_->GetAnimation(Animation::Opacity); 939 return opacity_animation && opacity_animation->is_impl_only(); 940} 941 942void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) { 943 if (blend_mode_ == blend_mode) 944 return; 945 946 blend_mode_ = blend_mode; 947 NoteLayerPropertyChangedForSubtree(); 948} 949 950void LayerImpl::SetIsRootForIsolatedGroup(bool root) { 951 if (is_root_for_isolated_group_ == root) 952 return; 953 954 is_root_for_isolated_group_ = root; 955 SetNeedsPushProperties(); 956} 957 958void LayerImpl::SetPosition(const gfx::PointF& position) { 959 if (position_ == position) 960 return; 961 962 position_ = position; 963 NoteLayerPropertyChangedForSubtree(); 964} 965 966void LayerImpl::SetShouldFlattenTransform(bool flatten) { 967 if (should_flatten_transform_ == flatten) 968 return; 969 970 should_flatten_transform_ = flatten; 971 NoteLayerPropertyChangedForSubtree(); 972} 973 974void LayerImpl::SetIs3dSorted(bool sorted) { 975 if (is_3d_sorted_ == sorted) 976 return; 977 978 is_3d_sorted_ = sorted; 979 NoteLayerPropertyChangedForSubtree(); 980} 981 982void LayerImpl::SetTransform(const gfx::Transform& transform) { 983 if (transform_ == transform) 984 return; 985 986 transform_ = transform; 987 NoteLayerPropertyChangedForSubtree(); 988} 989 990bool LayerImpl::TransformIsAnimating() const { 991 return layer_animation_controller_->IsAnimatingProperty(Animation::Transform); 992} 993 994bool LayerImpl::TransformIsAnimatingOnImplOnly() const { 995 Animation* transform_animation = 996 layer_animation_controller_->GetAnimation(Animation::Transform); 997 return transform_animation && transform_animation->is_impl_only(); 998} 999 1000void LayerImpl::SetUpdateRect(const gfx::RectF& update_rect) { 1001 update_rect_ = update_rect; 1002 SetNeedsPushProperties(); 1003} 1004 1005void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) { 1006 if (this->content_bounds() == content_bounds) 1007 return; 1008 1009 draw_properties_.content_bounds = content_bounds; 1010 NoteLayerPropertyChanged(); 1011} 1012 1013void LayerImpl::SetContentsScale(float contents_scale_x, 1014 float contents_scale_y) { 1015 if (this->contents_scale_x() == contents_scale_x && 1016 this->contents_scale_y() == contents_scale_y) 1017 return; 1018 1019 draw_properties_.contents_scale_x = contents_scale_x; 1020 draw_properties_.contents_scale_y = contents_scale_y; 1021 NoteLayerPropertyChanged(); 1022} 1023 1024void LayerImpl::CalculateContentsScale( 1025 float ideal_contents_scale, 1026 float device_scale_factor, 1027 float page_scale_factor, 1028 bool animating_transform_to_screen, 1029 float* contents_scale_x, 1030 float* contents_scale_y, 1031 gfx::Size* content_bounds) { 1032 // Base LayerImpl has all of its content scales and content bounds pushed 1033 // from its Layer during commit and just reuses those values as-is. 1034 *contents_scale_x = this->contents_scale_x(); 1035 *contents_scale_y = this->contents_scale_y(); 1036 *content_bounds = this->content_bounds(); 1037} 1038 1039void LayerImpl::SetScrollOffsetDelegate( 1040 LayerScrollOffsetDelegate* scroll_offset_delegate) { 1041 // Having both a scroll parent and a scroll offset delegate is unsupported. 1042 DCHECK(!scroll_parent_); 1043 if (!scroll_offset_delegate && scroll_offset_delegate_) { 1044 scroll_delta_ = 1045 scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1046 } 1047 gfx::Vector2dF total_offset = TotalScrollOffset(); 1048 scroll_offset_delegate_ = scroll_offset_delegate; 1049 if (scroll_offset_delegate_) 1050 scroll_offset_delegate_->SetTotalScrollOffset(total_offset); 1051} 1052 1053bool LayerImpl::IsExternalFlingActive() const { 1054 return scroll_offset_delegate_ && 1055 scroll_offset_delegate_->IsExternalFlingActive(); 1056} 1057 1058void LayerImpl::SetScrollOffset(const gfx::Vector2d& scroll_offset) { 1059 SetScrollOffsetAndDelta(scroll_offset, ScrollDelta()); 1060} 1061 1062void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d& scroll_offset, 1063 const gfx::Vector2dF& scroll_delta) { 1064 bool changed = false; 1065 1066 last_scroll_offset_ = scroll_offset; 1067 1068 if (scroll_offset_ != scroll_offset) { 1069 changed = true; 1070 scroll_offset_ = scroll_offset; 1071 1072 if (scroll_offset_delegate_) 1073 scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset()); 1074 } 1075 1076 if (ScrollDelta() != scroll_delta) { 1077 changed = true; 1078 if (layer_tree_impl()->IsActiveTree()) { 1079 LayerImpl* pending_twin = 1080 layer_tree_impl()->FindPendingTreeLayerById(id()); 1081 if (pending_twin) { 1082 // The pending twin can't mirror the scroll delta of the active 1083 // layer. Although the delta - sent scroll delta difference is 1084 // identical for both twins, the sent scroll delta for the pending 1085 // layer is zero, as anything that has been sent has been baked 1086 // into the layer's position/scroll offset as a part of commit. 1087 DCHECK(pending_twin->sent_scroll_delta().IsZero()); 1088 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta()); 1089 } 1090 } 1091 1092 if (scroll_offset_delegate_) { 1093 scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ + 1094 scroll_delta); 1095 } else { 1096 scroll_delta_ = scroll_delta; 1097 } 1098 } 1099 1100 if (changed) { 1101 NoteLayerPropertyChangedForSubtree(); 1102 ScrollbarParametersDidChange(); 1103 } 1104} 1105 1106gfx::Vector2dF LayerImpl::ScrollDelta() const { 1107 if (scroll_offset_delegate_) 1108 return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1109 return scroll_delta_; 1110} 1111 1112void LayerImpl::SetScrollDelta(const gfx::Vector2dF& scroll_delta) { 1113 SetScrollOffsetAndDelta(scroll_offset_, scroll_delta); 1114} 1115 1116gfx::Vector2dF LayerImpl::TotalScrollOffset() const { 1117 return scroll_offset_ + ScrollDelta(); 1118} 1119 1120void LayerImpl::SetDoubleSided(bool double_sided) { 1121 if (double_sided_ == double_sided) 1122 return; 1123 1124 double_sided_ = double_sided; 1125 NoteLayerPropertyChangedForSubtree(); 1126} 1127 1128Region LayerImpl::VisibleContentOpaqueRegion() const { 1129 if (contents_opaque()) 1130 return visible_content_rect(); 1131 return Region(); 1132} 1133 1134void LayerImpl::DidBeginTracing() {} 1135 1136void LayerImpl::ReleaseResources() {} 1137 1138gfx::Vector2d LayerImpl::MaxScrollOffset() const { 1139 if (!scroll_clip_layer_ || bounds().IsEmpty()) 1140 return gfx::Vector2d(); 1141 1142 LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1143 DCHECK(this != page_scale_layer); 1144 DCHECK(scroll_clip_layer_); 1145 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || 1146 IsContainerForFixedPositionLayers()); 1147 1148 gfx::Size scaled_scroll_bounds(bounds()); 1149 1150 float scale_factor = 1.f; 1151 for (LayerImpl const* current_layer = this; 1152 current_layer != scroll_clip_layer_; 1153 current_layer = current_layer->parent()) { 1154 DCHECK(current_layer); 1155 float current_layer_scale = 1.f; 1156 1157 const gfx::Transform& layer_transform = current_layer->transform(); 1158 if (current_layer == page_scale_layer) { 1159 DCHECK(layer_transform.IsIdentity()); 1160 current_layer_scale = layer_tree_impl()->total_page_scale_factor(); 1161 } else { 1162 // TODO(wjmaclean) Should we allow for translation too? 1163 DCHECK(layer_transform.IsScale2d()); 1164 gfx::Vector2dF layer_scale = layer_transform.Scale2d(); 1165 // TODO(wjmaclean) Allow for non-isotropic scales. 1166 DCHECK(layer_scale.x() == layer_scale.y()); 1167 current_layer_scale = layer_scale.x(); 1168 } 1169 1170 scale_factor *= current_layer_scale; 1171 } 1172 // TODO(wjmaclean) Once we move to a model where the two-viewport model is 1173 // turned on in all builds, remove the next two lines. For now however, the 1174 // page scale layer may coincide with the clip layer, and so this is 1175 // necessary. 1176 if (page_scale_layer == scroll_clip_layer_) 1177 scale_factor *= layer_tree_impl()->total_page_scale_factor(); 1178 1179 scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(), 1180 scale_factor * scaled_scroll_bounds.height()); 1181 1182 gfx::RectF clip_rect(gfx::PointF(), scroll_clip_layer_->bounds()); 1183 if (this == layer_tree_impl()->InnerViewportScrollLayer()) 1184 clip_rect = 1185 gfx::RectF(gfx::PointF(), layer_tree_impl()->ScrollableViewportSize()); 1186 gfx::Vector2dF max_offset( 1187 scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(), 1188 scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height()); 1189 // We need the final scroll offset to be in CSS coords. 1190 max_offset.Scale(1 / scale_factor); 1191 max_offset.SetToMax(gfx::Vector2dF()); 1192 return gfx::ToFlooredVector2d(max_offset); 1193} 1194 1195gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() { 1196 gfx::Vector2dF max_offset = MaxScrollOffset(); 1197 gfx::Vector2dF old_offset = TotalScrollOffset(); 1198 gfx::Vector2dF clamped_offset = old_offset; 1199 1200 clamped_offset.SetToMin(max_offset); 1201 clamped_offset.SetToMax(gfx::Vector2d()); 1202 gfx::Vector2dF delta = clamped_offset - old_offset; 1203 if (!delta.IsZero()) 1204 ScrollBy(delta); 1205 1206 return delta; 1207} 1208 1209void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer, 1210 LayerImpl* scrollbar_clip_layer) const { 1211 DCHECK(scrollbar_layer); 1212 LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1213 1214 DCHECK(this != page_scale_layer); 1215 DCHECK(scrollbar_clip_layer); 1216 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || 1217 IsContainerForFixedPositionLayers()); 1218 gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds()); 1219 1220 // See comment in MaxScrollOffset() regarding the use of the content layer 1221 // bounds here. 1222 gfx::RectF scroll_rect(gfx::PointF(), bounds()); 1223 1224 if (scroll_rect.size().IsEmpty()) 1225 return; 1226 1227 // TODO(wjmaclean) This computation is nearly identical to the one in 1228 // MaxScrollOffset. Find some way to combine these. 1229 gfx::Vector2dF current_offset; 1230 for (LayerImpl const* current_layer = this; 1231 current_layer != scrollbar_clip_layer; 1232 current_layer = current_layer->parent()) { 1233 DCHECK(current_layer); 1234 const gfx::Transform& layer_transform = current_layer->transform(); 1235 if (current_layer == page_scale_layer) { 1236 DCHECK(layer_transform.IsIdentity()); 1237 float scale_factor = layer_tree_impl()->total_page_scale_factor(); 1238 current_offset.Scale(scale_factor); 1239 scroll_rect.Scale(scale_factor); 1240 } else { 1241 DCHECK(layer_transform.IsScale2d()); 1242 gfx::Vector2dF layer_scale = layer_transform.Scale2d(); 1243 DCHECK(layer_scale.x() == layer_scale.y()); 1244 gfx::Vector2dF new_offset = 1245 current_layer->scroll_offset() + current_layer->ScrollDelta(); 1246 new_offset.Scale(layer_scale.x(), layer_scale.y()); 1247 current_offset += new_offset; 1248 } 1249 } 1250 // TODO(wjmaclean) Once we move to a model where the two-viewport model is 1251 // turned on in all builds, remove the next two lines. For now however, the 1252 // page scale layer may coincide with the clip layer, and so this is 1253 // necessary. 1254 if (page_scale_layer == scrollbar_clip_layer) { 1255 scroll_rect.Scale(layer_tree_impl()->total_page_scale_factor()); 1256 current_offset.Scale(layer_tree_impl()->total_page_scale_factor()); 1257 } 1258 1259 scrollbar_layer->SetVerticalAdjust(layer_tree_impl()->VerticalAdjust(this)); 1260 if (scrollbar_layer->orientation() == HORIZONTAL) { 1261 float visible_ratio = clip_rect.width() / scroll_rect.width(); 1262 scrollbar_layer->SetCurrentPos(current_offset.x()); 1263 scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width()); 1264 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1265 } else { 1266 float visible_ratio = clip_rect.height() / scroll_rect.height(); 1267 scrollbar_layer->SetCurrentPos(current_offset.y()); 1268 scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height()); 1269 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1270 } 1271 1272 layer_tree_impl()->set_needs_update_draw_properties(); 1273 // TODO(wjmaclean) Should the rest of this function be deleted? 1274 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should 1275 // activate for every scroll on the main frame, not just the scrolls that move 1276 // the pinch virtual viewport (i.e. trigger from either inner or outer 1277 // viewport). 1278 if (scrollbar_animation_controller_) { 1279 bool should_animate = scrollbar_animation_controller_->DidScrollUpdate( 1280 layer_tree_impl_->CurrentPhysicalTimeTicks()); 1281 if (should_animate) 1282 layer_tree_impl_->StartScrollbarAnimation(); 1283 } 1284} 1285 1286void LayerImpl::DidBecomeActive() { 1287 if (layer_tree_impl_->settings().scrollbar_animator == 1288 LayerTreeSettings::NoAnimator) { 1289 return; 1290 } 1291 1292 bool need_scrollbar_animation_controller = scrollable() && scrollbars_; 1293 if (!need_scrollbar_animation_controller) { 1294 scrollbar_animation_controller_.reset(); 1295 return; 1296 } 1297 1298 if (scrollbar_animation_controller_) 1299 return; 1300 1301 switch (layer_tree_impl_->settings().scrollbar_animator) { 1302 case LayerTreeSettings::LinearFade: { 1303 base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds( 1304 layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms); 1305 base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds( 1306 layer_tree_impl_->settings().scrollbar_linear_fade_length_ms); 1307 1308 scrollbar_animation_controller_ = 1309 ScrollbarAnimationControllerLinearFade::Create( 1310 this, fadeout_delay, fadeout_length) 1311 .PassAs<ScrollbarAnimationController>(); 1312 break; 1313 } 1314 case LayerTreeSettings::Thinning: { 1315 scrollbar_animation_controller_ = 1316 ScrollbarAnimationControllerThinning::Create(this) 1317 .PassAs<ScrollbarAnimationController>(); 1318 break; 1319 } 1320 case LayerTreeSettings::NoAnimator: 1321 NOTREACHED(); 1322 break; 1323 } 1324} 1325 1326void LayerImpl::ClearScrollbars() { 1327 if (!scrollbars_) 1328 return; 1329 1330 scrollbars_.reset(NULL); 1331} 1332 1333void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) { 1334 DCHECK(layer); 1335 DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end()); 1336 if (!scrollbars_) 1337 scrollbars_.reset(new ScrollbarSet()); 1338 1339 scrollbars_->insert(layer); 1340} 1341 1342void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) { 1343 DCHECK(scrollbars_); 1344 DCHECK(layer); 1345 DCHECK(scrollbars_->find(layer) != scrollbars_->end()); 1346 1347 scrollbars_->erase(layer); 1348 if (scrollbars_->empty()) 1349 scrollbars_.reset(); 1350} 1351 1352bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const { 1353 if (!scrollbars_) 1354 return false; 1355 1356 for (ScrollbarSet::iterator it = scrollbars_->begin(); 1357 it != scrollbars_->end(); 1358 ++it) 1359 if ((*it)->orientation() == orientation) 1360 return true; 1361 1362 return false; 1363} 1364 1365void LayerImpl::ScrollbarParametersDidChange() { 1366 if (!scrollbars_) 1367 return; 1368 1369 for (ScrollbarSet::iterator it = scrollbars_->begin(); 1370 it != scrollbars_->end(); 1371 ++it) 1372 (*it)->ScrollbarParametersDidChange(); 1373} 1374 1375void LayerImpl::SetNeedsPushProperties() { 1376 if (needs_push_properties_) 1377 return; 1378 if (!parent_should_know_need_push_properties() && parent_) 1379 parent_->AddDependentNeedsPushProperties(); 1380 needs_push_properties_ = true; 1381} 1382 1383void LayerImpl::AddDependentNeedsPushProperties() { 1384 DCHECK_GE(num_dependents_need_push_properties_, 0); 1385 1386 if (!parent_should_know_need_push_properties() && parent_) 1387 parent_->AddDependentNeedsPushProperties(); 1388 1389 num_dependents_need_push_properties_++; 1390} 1391 1392void LayerImpl::RemoveDependentNeedsPushProperties() { 1393 num_dependents_need_push_properties_--; 1394 DCHECK_GE(num_dependents_need_push_properties_, 0); 1395 1396 if (!parent_should_know_need_push_properties() && parent_) 1397 parent_->RemoveDependentNeedsPushProperties(); 1398} 1399 1400void LayerImpl::AsValueInto(base::DictionaryValue* state) const { 1401 TracedValue::MakeDictIntoImplicitSnapshotWithCategory( 1402 TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1403 state, LayerTypeAsString(), this); 1404 state->SetInteger("layer_id", id()); 1405 state->Set("bounds", MathUtil::AsValue(bounds()).release()); 1406 state->SetInteger("draws_content", DrawsContent()); 1407 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); 1408 1409 bool clipped; 1410 gfx::QuadF layer_quad = MathUtil::MapQuad( 1411 screen_space_transform(), 1412 gfx::QuadF(gfx::Rect(content_bounds())), 1413 &clipped); 1414 state->Set("layer_quad", MathUtil::AsValue(layer_quad).release()); 1415 1416 if (!touch_event_handler_region_.IsEmpty()) { 1417 state->Set("touch_event_handler_region", 1418 touch_event_handler_region_.AsValue().release()); 1419 } 1420 if (have_wheel_event_handlers_) { 1421 gfx::Rect wheel_rect(content_bounds()); 1422 Region wheel_region(wheel_rect); 1423 state->Set("wheel_event_handler_region", 1424 wheel_region.AsValue().release()); 1425 } 1426 if (!non_fast_scrollable_region_.IsEmpty()) { 1427 state->Set("non_fast_scrollable_region", 1428 non_fast_scrollable_region_.AsValue().release()); 1429 } 1430 1431 scoped_ptr<base::ListValue> children_list(new base::ListValue()); 1432 for (size_t i = 0; i < children_.size(); ++i) 1433 children_list->Append(children_[i]->AsValue().release()); 1434 state->Set("children", children_list.release()); 1435 if (mask_layer_) 1436 state->Set("mask_layer", mask_layer_->AsValue().release()); 1437 if (replica_layer_) 1438 state->Set("replica_layer", replica_layer_->AsValue().release()); 1439 1440 if (scroll_parent_) 1441 state->SetInteger("scroll_parent", scroll_parent_->id()); 1442 1443 if (clip_parent_) 1444 state->SetInteger("clip_parent", clip_parent_->id()); 1445 1446 state->SetBoolean("can_use_lcd_text", can_use_lcd_text()); 1447 state->SetBoolean("contents_opaque", contents_opaque()); 1448 1449 state->SetBoolean( 1450 "has_animation_bounds", 1451 layer_animation_controller()->HasAnimationThatInflatesBounds()); 1452 1453 gfx::BoxF box; 1454 if (LayerUtils::GetAnimationBounds(*this, &box)) 1455 state->Set("animation_bounds", MathUtil::AsValue(box).release()); 1456 1457 if (debug_info_.get()) { 1458 std::string str; 1459 debug_info_->AppendAsTraceFormat(&str); 1460 base::JSONReader json_reader; 1461 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str)); 1462 1463 if (debug_info_value->IsType(base::Value::TYPE_DICTIONARY)) { 1464 base::DictionaryValue* dictionary_value = NULL; 1465 bool converted_to_dictionary = 1466 debug_info_value->GetAsDictionary(&dictionary_value); 1467 DCHECK(converted_to_dictionary); 1468 state->MergeDictionary(dictionary_value); 1469 } else { 1470 NOTREACHED(); 1471 } 1472 } 1473} 1474 1475size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; } 1476 1477scoped_ptr<base::Value> LayerImpl::AsValue() const { 1478 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 1479 AsValueInto(state.get()); 1480 return state.PassAs<base::Value>(); 1481} 1482 1483void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) { 1484 benchmark->RunOnLayer(this); 1485} 1486} // namespace cc 1487