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