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