layer_impl.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 482scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { 483 return LayerImpl::Create(tree_impl, layer_id_); 484} 485 486void LayerImpl::PushPropertiesTo(LayerImpl* layer) { 487 layer->SetTransformOrigin(transform_origin_); 488 layer->SetBackgroundColor(background_color_); 489 layer->SetBounds(bounds_); 490 layer->SetContentBounds(content_bounds()); 491 layer->SetContentsScale(contents_scale_x(), contents_scale_y()); 492 layer->SetDoubleSided(double_sided_); 493 layer->SetDrawCheckerboardForMissingTiles( 494 draw_checkerboard_for_missing_tiles_); 495 layer->SetForceRenderSurface(force_render_surface_); 496 layer->SetDrawsContent(DrawsContent()); 497 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); 498 layer->SetFilters(filters()); 499 layer->SetBackgroundFilters(background_filters()); 500 layer->SetMasksToBounds(masks_to_bounds_); 501 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); 502 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_); 503 layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_); 504 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); 505 layer->SetTouchEventHandlerRegion(touch_event_handler_region_); 506 layer->SetContentsOpaque(contents_opaque_); 507 layer->SetOpacity(opacity_); 508 layer->SetBlendMode(blend_mode_); 509 layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_); 510 layer->SetPosition(position_); 511 layer->SetIsContainerForFixedPositionLayers( 512 is_container_for_fixed_position_layers_); 513 layer->SetPositionConstraint(position_constraint_); 514 layer->SetShouldFlattenTransform(should_flatten_transform_); 515 layer->SetIs3dSorted(is_3d_sorted_); 516 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); 517 layer->SetTransformAndInvertibility(transform_, transform_is_invertible_); 518 519 layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id() 520 : Layer::INVALID_ID); 521 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_); 522 layer->set_user_scrollable_vertical(user_scrollable_vertical_); 523 layer->SetScrollOffsetAndDelta( 524 scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta()); 525 layer->SetSentScrollDelta(gfx::Vector2d()); 526 527 LayerImpl* scroll_parent = NULL; 528 if (scroll_parent_) { 529 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id()); 530 DCHECK(scroll_parent); 531 } 532 533 layer->SetScrollParent(scroll_parent); 534 if (scroll_children_) { 535 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>; 536 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin(); 537 it != scroll_children_->end(); 538 ++it) { 539 DCHECK_EQ((*it)->scroll_parent(), this); 540 LayerImpl* scroll_child = 541 layer->layer_tree_impl()->LayerById((*it)->id()); 542 DCHECK(scroll_child); 543 scroll_children->insert(scroll_child); 544 } 545 layer->SetScrollChildren(scroll_children); 546 } else { 547 layer->SetScrollChildren(NULL); 548 } 549 550 LayerImpl* clip_parent = NULL; 551 if (clip_parent_) { 552 clip_parent = layer->layer_tree_impl()->LayerById( 553 clip_parent_->id()); 554 DCHECK(clip_parent); 555 } 556 557 layer->SetClipParent(clip_parent); 558 if (clip_children_) { 559 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>; 560 for (std::set<LayerImpl*>::iterator it = clip_children_->begin(); 561 it != clip_children_->end(); ++it) 562 clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id())); 563 layer->SetClipChildren(clip_children); 564 } else { 565 layer->SetClipChildren(NULL); 566 } 567 568 layer->PassCopyRequests(©_requests_); 569 570 // If the main thread commits multiple times before the impl thread actually 571 // draws, then damage tracking will become incorrect if we simply clobber the 572 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. 573 // union) any update changes that have occurred on the main thread. 574 update_rect_.Union(layer->update_rect()); 575 layer->SetUpdateRect(update_rect_); 576 577 layer->SetStackingOrderChanged(stacking_order_changed_); 578 layer->SetDebugInfo(debug_info_); 579 580 // Reset any state that should be cleared for the next update. 581 stacking_order_changed_ = false; 582 update_rect_ = gfx::RectF(); 583 needs_push_properties_ = false; 584 num_dependents_need_push_properties_ = 0; 585} 586 587gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const { 588 if (!scroll_clip_layer_) 589 return gfx::Vector2dF(); 590 591 float scale_delta = layer_tree_impl()->page_scale_delta(); 592 float scale = layer_tree_impl()->page_scale_factor(); 593 594 gfx::Vector2dF delta_from_scroll = scroll_clip_layer_->BoundsDelta(); 595 delta_from_scroll.Scale(1.f / scale); 596 597 // The delta-from-pinch component requires some explanation: A viewport of 598 // size (w,h) will appear to be size (w/s,h/s) under scale s in the content 599 // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent 600 // viewport size change in the content space due to ds is: 601 // 602 // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds) 603 // 604 gfx::Vector2dF delta_from_pinch = 605 gfx::Rect(scroll_clip_layer_->bounds()).bottom_right() - gfx::PointF(); 606 delta_from_pinch.Scale((1.f - scale_delta) / (scale * scale_delta)); 607 608 return delta_from_scroll + delta_from_pinch; 609} 610 611base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { 612 base::DictionaryValue* result = new base::DictionaryValue; 613 result->SetString("LayerType", LayerTypeAsString()); 614 615 base::ListValue* list = new base::ListValue; 616 list->AppendInteger(bounds().width()); 617 list->AppendInteger(bounds().height()); 618 result->Set("Bounds", list); 619 620 list = new base::ListValue; 621 list->AppendDouble(position_.x()); 622 list->AppendDouble(position_.y()); 623 result->Set("Position", list); 624 625 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform; 626 double transform[16]; 627 gfx_transform.matrix().asColMajord(transform); 628 list = new base::ListValue; 629 for (int i = 0; i < 16; ++i) 630 list->AppendDouble(transform[i]); 631 result->Set("DrawTransform", list); 632 633 result->SetBoolean("DrawsContent", draws_content_); 634 result->SetBoolean("Is3DSorted", is_3d_sorted_); 635 result->SetDouble("Opacity", opacity()); 636 result->SetBoolean("ContentsOpaque", contents_opaque_); 637 638 if (scrollable()) 639 result->SetBoolean("Scrollable", true); 640 641 if (have_wheel_event_handlers_) 642 result->SetBoolean("WheelHandler", have_wheel_event_handlers_); 643 if (have_scroll_event_handlers_) 644 result->SetBoolean("ScrollHandler", have_scroll_event_handlers_); 645 if (!touch_event_handler_region_.IsEmpty()) { 646 scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue(); 647 result->Set("TouchRegion", region.release()); 648 } 649 650 list = new base::ListValue; 651 for (size_t i = 0; i < children_.size(); ++i) 652 list->Append(children_[i]->LayerTreeAsJson()); 653 result->Set("Children", list); 654 655 return result; 656} 657 658void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) { 659 if (stacking_order_changed) { 660 stacking_order_changed_ = true; 661 NoteLayerPropertyChangedForSubtree(); 662 } 663} 664 665void LayerImpl::NoteLayerPropertyChanged() { 666 layer_property_changed_ = true; 667 layer_tree_impl()->set_needs_update_draw_properties(); 668 SetNeedsPushProperties(); 669} 670 671void LayerImpl::NoteLayerPropertyChangedForSubtree() { 672 layer_property_changed_ = true; 673 layer_tree_impl()->set_needs_update_draw_properties(); 674 for (size_t i = 0; i < children_.size(); ++i) 675 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 676 SetNeedsPushProperties(); 677} 678 679void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() { 680 layer_property_changed_ = true; 681 for (size_t i = 0; i < children_.size(); ++i) 682 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 683} 684 685void LayerImpl::NoteLayerPropertyChangedForDescendants() { 686 layer_tree_impl()->set_needs_update_draw_properties(); 687 for (size_t i = 0; i < children_.size(); ++i) 688 children_[i]->NoteLayerPropertyChangedForDescendantsInternal(); 689 SetNeedsPushProperties(); 690} 691 692const char* LayerImpl::LayerTypeAsString() const { 693 return "cc::LayerImpl"; 694} 695 696void LayerImpl::ResetAllChangeTrackingForSubtree() { 697 layer_property_changed_ = false; 698 699 update_rect_ = gfx::RectF(); 700 damage_rect_ = gfx::RectF(); 701 702 if (draw_properties_.render_surface) 703 draw_properties_.render_surface->ResetPropertyChangedFlag(); 704 705 if (mask_layer_) 706 mask_layer_->ResetAllChangeTrackingForSubtree(); 707 708 if (replica_layer_) { 709 // This also resets the replica mask, if it exists. 710 replica_layer_->ResetAllChangeTrackingForSubtree(); 711 } 712 713 for (size_t i = 0; i < children_.size(); ++i) 714 children_[i]->ResetAllChangeTrackingForSubtree(); 715 716 needs_push_properties_ = false; 717 num_dependents_need_push_properties_ = 0; 718} 719 720gfx::Vector2dF LayerImpl::ScrollOffsetForAnimation() const { 721 return TotalScrollOffset(); 722} 723 724void LayerImpl::OnFilterAnimated(const FilterOperations& filters) { 725 SetFilters(filters); 726} 727 728void LayerImpl::OnOpacityAnimated(float opacity) { 729 SetOpacity(opacity); 730} 731 732void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { 733 SetTransform(transform); 734} 735 736void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset) { 737 // Only layers in the active tree should need to do anything here, since 738 // layers in the pending tree will find out about these changes as a 739 // result of the call to SetScrollDelta. 740 if (!IsActive()) 741 return; 742 743 SetScrollDelta(scroll_offset - scroll_offset_); 744 745 layer_tree_impl_->DidAnimateScrollOffset(); 746} 747 748void LayerImpl::OnAnimationWaitingForDeletion() {} 749 750bool LayerImpl::IsActive() const { 751 return layer_tree_impl_->IsActiveTree(); 752} 753 754// TODO(wjmaclean) Convert so that bounds returns SizeF. 755gfx::Size LayerImpl::bounds() const { 756 return ToFlooredSize(temporary_impl_bounds_); 757} 758 759void LayerImpl::SetBounds(const gfx::Size& bounds) { 760 if (bounds_ == bounds) 761 return; 762 763 bounds_ = bounds; 764 temporary_impl_bounds_ = bounds; 765 766 ScrollbarParametersDidChange(); 767 if (masks_to_bounds()) 768 NoteLayerPropertyChangedForSubtree(); 769 else 770 NoteLayerPropertyChanged(); 771} 772 773void LayerImpl::SetTemporaryImplBounds(const gfx::SizeF& bounds) { 774 if (temporary_impl_bounds_ == bounds) 775 return; 776 777 temporary_impl_bounds_ = bounds; 778 779 ScrollbarParametersDidChange(); 780 if (masks_to_bounds()) 781 NoteLayerPropertyChangedForSubtree(); 782 else 783 NoteLayerPropertyChanged(); 784} 785 786void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) { 787 int new_layer_id = mask_layer ? mask_layer->id() : -1; 788 789 if (mask_layer) { 790 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl()); 791 DCHECK_NE(new_layer_id, mask_layer_id_); 792 } else if (new_layer_id == mask_layer_id_) { 793 return; 794 } 795 796 mask_layer_ = mask_layer.Pass(); 797 mask_layer_id_ = new_layer_id; 798 if (mask_layer_) 799 mask_layer_->SetParent(this); 800 NoteLayerPropertyChangedForSubtree(); 801} 802 803scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() { 804 mask_layer_id_ = -1; 805 return mask_layer_.Pass(); 806} 807 808void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) { 809 int new_layer_id = replica_layer ? replica_layer->id() : -1; 810 811 if (replica_layer) { 812 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl()); 813 DCHECK_NE(new_layer_id, replica_layer_id_); 814 } else if (new_layer_id == replica_layer_id_) { 815 return; 816 } 817 818 replica_layer_ = replica_layer.Pass(); 819 replica_layer_id_ = new_layer_id; 820 if (replica_layer_) 821 replica_layer_->SetParent(this); 822 NoteLayerPropertyChangedForSubtree(); 823} 824 825scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() { 826 replica_layer_id_ = -1; 827 return replica_layer_.Pass(); 828} 829 830ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() { 831 return NULL; 832} 833 834void LayerImpl::SetDrawsContent(bool draws_content) { 835 if (draws_content_ == draws_content) 836 return; 837 838 draws_content_ = draws_content; 839 NoteLayerPropertyChanged(); 840} 841 842void LayerImpl::SetHideLayerAndSubtree(bool hide) { 843 if (hide_layer_and_subtree_ == hide) 844 return; 845 846 hide_layer_and_subtree_ = hide; 847 NoteLayerPropertyChangedForSubtree(); 848} 849 850void LayerImpl::SetTransformOrigin(const gfx::Point3F& transform_origin) { 851 if (transform_origin_ == transform_origin) 852 return; 853 transform_origin_ = transform_origin; 854 NoteLayerPropertyChangedForSubtree(); 855} 856 857void LayerImpl::SetBackgroundColor(SkColor background_color) { 858 if (background_color_ == background_color) 859 return; 860 861 background_color_ = background_color; 862 NoteLayerPropertyChanged(); 863} 864 865SkColor LayerImpl::SafeOpaqueBackgroundColor() const { 866 SkColor color = background_color(); 867 if (SkColorGetA(color) == 255 && !contents_opaque()) { 868 color = SK_ColorTRANSPARENT; 869 } else if (SkColorGetA(color) != 255 && contents_opaque()) { 870 for (const LayerImpl* layer = parent(); layer; 871 layer = layer->parent()) { 872 color = layer->background_color(); 873 if (SkColorGetA(color) == 255) 874 break; 875 } 876 if (SkColorGetA(color) != 255) 877 color = layer_tree_impl()->background_color(); 878 if (SkColorGetA(color) != 255) 879 color = SkColorSetA(color, 255); 880 } 881 return color; 882} 883 884void LayerImpl::SetFilters(const FilterOperations& filters) { 885 if (filters_ == filters) 886 return; 887 888 filters_ = filters; 889 NoteLayerPropertyChangedForSubtree(); 890} 891 892bool LayerImpl::FilterIsAnimating() const { 893 return layer_animation_controller_->IsAnimatingProperty(Animation::Filter); 894} 895 896bool LayerImpl::FilterIsAnimatingOnImplOnly() const { 897 Animation* filter_animation = 898 layer_animation_controller_->GetAnimation(Animation::Filter); 899 return filter_animation && filter_animation->is_impl_only(); 900} 901 902void LayerImpl::SetBackgroundFilters( 903 const FilterOperations& filters) { 904 if (background_filters_ == filters) 905 return; 906 907 background_filters_ = filters; 908 NoteLayerPropertyChanged(); 909} 910 911void LayerImpl::SetMasksToBounds(bool masks_to_bounds) { 912 if (masks_to_bounds_ == masks_to_bounds) 913 return; 914 915 masks_to_bounds_ = masks_to_bounds; 916 NoteLayerPropertyChangedForSubtree(); 917} 918 919void LayerImpl::SetContentsOpaque(bool opaque) { 920 if (contents_opaque_ == opaque) 921 return; 922 923 contents_opaque_ = opaque; 924 NoteLayerPropertyChangedForSubtree(); 925} 926 927void LayerImpl::SetOpacity(float opacity) { 928 if (opacity_ == opacity) 929 return; 930 931 opacity_ = opacity; 932 NoteLayerPropertyChangedForSubtree(); 933} 934 935bool LayerImpl::OpacityIsAnimating() const { 936 return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity); 937} 938 939bool LayerImpl::OpacityIsAnimatingOnImplOnly() const { 940 Animation* opacity_animation = 941 layer_animation_controller_->GetAnimation(Animation::Opacity); 942 return opacity_animation && opacity_animation->is_impl_only(); 943} 944 945void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) { 946 if (blend_mode_ == blend_mode) 947 return; 948 949 blend_mode_ = blend_mode; 950 NoteLayerPropertyChangedForSubtree(); 951} 952 953void LayerImpl::SetIsRootForIsolatedGroup(bool root) { 954 if (is_root_for_isolated_group_ == root) 955 return; 956 957 is_root_for_isolated_group_ = root; 958 SetNeedsPushProperties(); 959} 960 961void LayerImpl::SetPosition(const gfx::PointF& position) { 962 if (position_ == position) 963 return; 964 965 position_ = position; 966 NoteLayerPropertyChangedForSubtree(); 967} 968 969void LayerImpl::SetShouldFlattenTransform(bool flatten) { 970 if (should_flatten_transform_ == flatten) 971 return; 972 973 should_flatten_transform_ = flatten; 974 NoteLayerPropertyChangedForSubtree(); 975} 976 977void LayerImpl::SetIs3dSorted(bool sorted) { 978 if (is_3d_sorted_ == sorted) 979 return; 980 981 is_3d_sorted_ = sorted; 982 NoteLayerPropertyChangedForSubtree(); 983} 984 985void LayerImpl::SetTransform(const gfx::Transform& transform) { 986 if (transform_ == transform) 987 return; 988 989 transform_ = transform; 990 transform_is_invertible_ = transform_.IsInvertible(); 991 NoteLayerPropertyChangedForSubtree(); 992} 993 994void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform, 995 bool transform_is_invertible) { 996 if (transform_ == transform) { 997 DCHECK(transform_is_invertible_ == transform_is_invertible) 998 << "Can't change invertibility if transform is unchanged"; 999 return; 1000 } 1001 transform_ = transform; 1002 transform_is_invertible_ = transform_is_invertible; 1003 NoteLayerPropertyChangedForSubtree(); 1004} 1005 1006bool LayerImpl::TransformIsAnimating() const { 1007 return layer_animation_controller_->IsAnimatingProperty(Animation::Transform); 1008} 1009 1010bool LayerImpl::TransformIsAnimatingOnImplOnly() const { 1011 Animation* transform_animation = 1012 layer_animation_controller_->GetAnimation(Animation::Transform); 1013 return transform_animation && transform_animation->is_impl_only(); 1014} 1015 1016void LayerImpl::SetUpdateRect(const gfx::RectF& update_rect) { 1017 update_rect_ = update_rect; 1018 SetNeedsPushProperties(); 1019} 1020 1021void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) { 1022 damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect); 1023} 1024 1025void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) { 1026 if (this->content_bounds() == content_bounds) 1027 return; 1028 1029 draw_properties_.content_bounds = content_bounds; 1030 NoteLayerPropertyChanged(); 1031} 1032 1033void LayerImpl::SetContentsScale(float contents_scale_x, 1034 float contents_scale_y) { 1035 if (this->contents_scale_x() == contents_scale_x && 1036 this->contents_scale_y() == contents_scale_y) 1037 return; 1038 1039 draw_properties_.contents_scale_x = contents_scale_x; 1040 draw_properties_.contents_scale_y = contents_scale_y; 1041 NoteLayerPropertyChanged(); 1042} 1043 1044void LayerImpl::SetScrollOffsetDelegate( 1045 ScrollOffsetDelegate* scroll_offset_delegate) { 1046 // Having both a scroll parent and a scroll offset delegate is unsupported. 1047 DCHECK(!scroll_parent_); 1048 if (!scroll_offset_delegate && scroll_offset_delegate_) { 1049 scroll_delta_ = 1050 scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1051 } 1052 gfx::Vector2dF total_offset = TotalScrollOffset(); 1053 scroll_offset_delegate_ = scroll_offset_delegate; 1054 if (scroll_offset_delegate_) 1055 scroll_offset_delegate_->SetTotalScrollOffset(total_offset); 1056} 1057 1058bool LayerImpl::IsExternalFlingActive() const { 1059 return scroll_offset_delegate_ && 1060 scroll_offset_delegate_->IsExternalFlingActive(); 1061} 1062 1063void LayerImpl::SetScrollOffset(const gfx::Vector2d& scroll_offset) { 1064 SetScrollOffsetAndDelta(scroll_offset, ScrollDelta()); 1065} 1066 1067void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d& scroll_offset, 1068 const gfx::Vector2dF& scroll_delta) { 1069 bool changed = false; 1070 1071 last_scroll_offset_ = scroll_offset; 1072 1073 if (scroll_offset_ != scroll_offset) { 1074 changed = true; 1075 scroll_offset_ = scroll_offset; 1076 1077 if (scroll_offset_delegate_) 1078 scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset()); 1079 } 1080 1081 if (ScrollDelta() != scroll_delta) { 1082 changed = true; 1083 if (layer_tree_impl()->IsActiveTree()) { 1084 LayerImpl* pending_twin = 1085 layer_tree_impl()->FindPendingTreeLayerById(id()); 1086 if (pending_twin) { 1087 // The pending twin can't mirror the scroll delta of the active 1088 // layer. Although the delta - sent scroll delta difference is 1089 // identical for both twins, the sent scroll delta for the pending 1090 // layer is zero, as anything that has been sent has been baked 1091 // into the layer's position/scroll offset as a part of commit. 1092 DCHECK(pending_twin->sent_scroll_delta().IsZero()); 1093 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta()); 1094 } 1095 } 1096 1097 if (scroll_offset_delegate_) { 1098 scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ + 1099 scroll_delta); 1100 } else { 1101 scroll_delta_ = scroll_delta; 1102 } 1103 } 1104 1105 if (changed) { 1106 NoteLayerPropertyChangedForSubtree(); 1107 ScrollbarParametersDidChange(); 1108 } 1109} 1110 1111gfx::Vector2dF LayerImpl::ScrollDelta() const { 1112 if (scroll_offset_delegate_) 1113 return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_; 1114 return scroll_delta_; 1115} 1116 1117void LayerImpl::SetScrollDelta(const gfx::Vector2dF& scroll_delta) { 1118 SetScrollOffsetAndDelta(scroll_offset_, scroll_delta); 1119} 1120 1121gfx::Vector2dF LayerImpl::TotalScrollOffset() const { 1122 return scroll_offset_ + ScrollDelta(); 1123} 1124 1125void LayerImpl::SetDoubleSided(bool double_sided) { 1126 if (double_sided_ == double_sided) 1127 return; 1128 1129 double_sided_ = double_sided; 1130 NoteLayerPropertyChangedForSubtree(); 1131} 1132 1133Region LayerImpl::VisibleContentOpaqueRegion() const { 1134 if (contents_opaque()) 1135 return visible_content_rect(); 1136 return Region(); 1137} 1138 1139void LayerImpl::DidBeginTracing() {} 1140 1141void LayerImpl::ReleaseResources() {} 1142 1143gfx::Vector2d LayerImpl::MaxScrollOffset() const { 1144 if (!scroll_clip_layer_ || bounds().IsEmpty()) 1145 return gfx::Vector2d(); 1146 1147 LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1148 DCHECK(this != page_scale_layer); 1149 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || 1150 IsContainerForFixedPositionLayers()); 1151 1152 gfx::SizeF scaled_scroll_bounds(bounds()); 1153 1154 float scale_factor = 1.f; 1155 for (LayerImpl const* current_layer = this; 1156 current_layer != scroll_clip_layer_; 1157 current_layer = current_layer->parent()) { 1158 DCHECK(current_layer); 1159 float current_layer_scale = 1.f; 1160 1161 const gfx::Transform& layer_transform = current_layer->transform(); 1162 if (current_layer == page_scale_layer) { 1163 DCHECK(layer_transform.IsIdentity()); 1164 current_layer_scale = layer_tree_impl()->total_page_scale_factor(); 1165 } else { 1166 // TODO(wjmaclean) Should we allow for translation too? 1167 DCHECK(layer_transform.IsScale2d()); 1168 gfx::Vector2dF layer_scale = layer_transform.Scale2d(); 1169 // TODO(wjmaclean) Allow for non-isotropic scales. 1170 DCHECK(layer_scale.x() == layer_scale.y()); 1171 current_layer_scale = layer_scale.x(); 1172 } 1173 1174 scale_factor *= current_layer_scale; 1175 } 1176 // TODO(wjmaclean) Once we move to a model where the two-viewport model is 1177 // turned on in all builds, remove the next two lines. For now however, the 1178 // page scale layer may coincide with the clip layer, and so this is 1179 // necessary. 1180 if (page_scale_layer == scroll_clip_layer_) 1181 scale_factor *= layer_tree_impl()->total_page_scale_factor(); 1182 1183 scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(), 1184 scale_factor * scaled_scroll_bounds.height()); 1185 scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds); 1186 1187 gfx::Vector2dF max_offset( 1188 scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(), 1189 scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height()); 1190 // We need the final scroll offset to be in CSS coords. 1191 max_offset.Scale(1 / scale_factor); 1192 max_offset.SetToMax(gfx::Vector2dF()); 1193 return gfx::ToFlooredVector2d(max_offset); 1194} 1195 1196gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() { 1197 gfx::Vector2dF max_offset = MaxScrollOffset(); 1198 gfx::Vector2dF old_offset = TotalScrollOffset(); 1199 gfx::Vector2dF clamped_offset = old_offset; 1200 1201 clamped_offset.SetToMin(max_offset); 1202 clamped_offset.SetToMax(gfx::Vector2d()); 1203 gfx::Vector2dF delta = clamped_offset - old_offset; 1204 if (!delta.IsZero()) 1205 ScrollBy(delta); 1206 1207 return delta; 1208} 1209 1210void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer, 1211 LayerImpl* scrollbar_clip_layer) const { 1212 DCHECK(scrollbar_layer); 1213 LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1214 1215 DCHECK(this != page_scale_layer); 1216 DCHECK(scrollbar_clip_layer); 1217 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || 1218 IsContainerForFixedPositionLayers()); 1219 gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->bounds()); 1220 1221 // See comment in MaxScrollOffset() regarding the use of the content layer 1222 // bounds here. 1223 gfx::RectF scroll_rect(gfx::PointF(), bounds()); 1224 1225 if (scroll_rect.size().IsEmpty()) 1226 return; 1227 1228 // TODO(wjmaclean) This computation is nearly identical to the one in 1229 // MaxScrollOffset. Find some way to combine these. 1230 gfx::Vector2dF current_offset; 1231 for (LayerImpl const* current_layer = this; 1232 current_layer != scrollbar_clip_layer; 1233 current_layer = current_layer->parent()) { 1234 DCHECK(current_layer); 1235 const gfx::Transform& layer_transform = current_layer->transform(); 1236 if (current_layer == page_scale_layer) { 1237 DCHECK(layer_transform.IsIdentity()); 1238 float scale_factor = layer_tree_impl()->total_page_scale_factor(); 1239 current_offset.Scale(scale_factor); 1240 scroll_rect.Scale(scale_factor); 1241 } else { 1242 DCHECK(layer_transform.IsScale2d()); 1243 gfx::Vector2dF layer_scale = layer_transform.Scale2d(); 1244 DCHECK(layer_scale.x() == layer_scale.y()); 1245 gfx::Vector2dF new_offset = 1246 current_layer->scroll_offset() + current_layer->ScrollDelta(); 1247 new_offset.Scale(layer_scale.x(), layer_scale.y()); 1248 current_offset += new_offset; 1249 } 1250 } 1251 // TODO(wjmaclean) Once we move to a model where the two-viewport model is 1252 // turned on in all builds, remove the next two lines. For now however, the 1253 // page scale layer may coincide with the clip layer, and so this is 1254 // necessary. 1255 if (page_scale_layer == scrollbar_clip_layer) { 1256 scroll_rect.Scale(layer_tree_impl()->total_page_scale_factor()); 1257 current_offset.Scale(layer_tree_impl()->total_page_scale_factor()); 1258 } 1259 1260 scrollbar_layer->SetVerticalAdjust( 1261 layer_tree_impl()->VerticalAdjust(scrollbar_clip_layer->id())); 1262 if (scrollbar_layer->orientation() == HORIZONTAL) { 1263 float visible_ratio = clip_rect.width() / scroll_rect.width(); 1264 scrollbar_layer->SetCurrentPos(current_offset.x()); 1265 scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width()); 1266 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1267 } else { 1268 float visible_ratio = clip_rect.height() / scroll_rect.height(); 1269 scrollbar_layer->SetCurrentPos(current_offset.y()); 1270 scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height()); 1271 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1272 } 1273 1274 layer_tree_impl()->set_needs_update_draw_properties(); 1275 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should 1276 // activate for every scroll on the main frame, not just the scrolls that move 1277 // the pinch virtual viewport (i.e. trigger from either inner or outer 1278 // viewport). 1279 if (scrollbar_animation_controller_) { 1280 // When both non-overlay and overlay scrollbars are both present, don't 1281 // animate the overlay scrollbars when page scale factor is at the min. 1282 // Non-overlay scrollbars also shouldn't trigger animations. 1283 bool is_animatable_scrollbar = 1284 scrollbar_layer->is_overlay_scrollbar() && 1285 ((layer_tree_impl()->total_page_scale_factor() > 1286 layer_tree_impl()->min_page_scale_factor()) || 1287 !layer_tree_impl()->settings().use_pinch_zoom_scrollbars); 1288 if (is_animatable_scrollbar) 1289 scrollbar_animation_controller_->DidScrollUpdate(); 1290 } 1291} 1292 1293void LayerImpl::DidBecomeActive() { 1294 if (layer_tree_impl_->settings().scrollbar_animator == 1295 LayerTreeSettings::NoAnimator) { 1296 return; 1297 } 1298 1299 bool need_scrollbar_animation_controller = scrollable() && scrollbars_; 1300 if (!need_scrollbar_animation_controller) { 1301 scrollbar_animation_controller_.reset(); 1302 return; 1303 } 1304 1305 if (scrollbar_animation_controller_) 1306 return; 1307 1308 scrollbar_animation_controller_ = 1309 layer_tree_impl_->CreateScrollbarAnimationController(this); 1310} 1311 1312void LayerImpl::ClearScrollbars() { 1313 if (!scrollbars_) 1314 return; 1315 1316 scrollbars_.reset(NULL); 1317} 1318 1319void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) { 1320 DCHECK(layer); 1321 DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end()); 1322 if (!scrollbars_) 1323 scrollbars_.reset(new ScrollbarSet()); 1324 1325 scrollbars_->insert(layer); 1326} 1327 1328void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) { 1329 DCHECK(scrollbars_); 1330 DCHECK(layer); 1331 DCHECK(scrollbars_->find(layer) != scrollbars_->end()); 1332 1333 scrollbars_->erase(layer); 1334 if (scrollbars_->empty()) 1335 scrollbars_.reset(); 1336} 1337 1338bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const { 1339 if (!scrollbars_) 1340 return false; 1341 1342 for (ScrollbarSet::iterator it = scrollbars_->begin(); 1343 it != scrollbars_->end(); 1344 ++it) 1345 if ((*it)->orientation() == orientation) 1346 return true; 1347 1348 return false; 1349} 1350 1351void LayerImpl::ScrollbarParametersDidChange() { 1352 if (!scrollbars_) 1353 return; 1354 1355 for (ScrollbarSet::iterator it = scrollbars_->begin(); 1356 it != scrollbars_->end(); 1357 ++it) 1358 (*it)->ScrollbarParametersDidChange(); 1359} 1360 1361void LayerImpl::SetNeedsPushProperties() { 1362 if (needs_push_properties_) 1363 return; 1364 if (!parent_should_know_need_push_properties() && parent_) 1365 parent_->AddDependentNeedsPushProperties(); 1366 needs_push_properties_ = true; 1367} 1368 1369void LayerImpl::AddDependentNeedsPushProperties() { 1370 DCHECK_GE(num_dependents_need_push_properties_, 0); 1371 1372 if (!parent_should_know_need_push_properties() && parent_) 1373 parent_->AddDependentNeedsPushProperties(); 1374 1375 num_dependents_need_push_properties_++; 1376} 1377 1378void LayerImpl::RemoveDependentNeedsPushProperties() { 1379 num_dependents_need_push_properties_--; 1380 DCHECK_GE(num_dependents_need_push_properties_, 0); 1381 1382 if (!parent_should_know_need_push_properties() && parent_) 1383 parent_->RemoveDependentNeedsPushProperties(); 1384} 1385 1386void LayerImpl::AsValueInto(base::DictionaryValue* state) const { 1387 TracedValue::MakeDictIntoImplicitSnapshotWithCategory( 1388 TRACE_DISABLED_BY_DEFAULT("cc.debug"), 1389 state, 1390 "cc::LayerImpl", 1391 LayerTypeAsString(), 1392 this); 1393 state->SetInteger("layer_id", id()); 1394 state->Set("bounds", MathUtil::AsValue(bounds_).release()); 1395 state->Set("position", MathUtil::AsValue(position_).release()); 1396 state->SetInteger("draws_content", DrawsContent()); 1397 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); 1398 state->Set("scroll_offset", MathUtil::AsValue(scroll_offset_).release()); 1399 state->Set("transform_origin", 1400 MathUtil::AsValue(transform_origin_).release()); 1401 1402 bool clipped; 1403 gfx::QuadF layer_quad = MathUtil::MapQuad( 1404 screen_space_transform(), 1405 gfx::QuadF(gfx::Rect(content_bounds())), 1406 &clipped); 1407 state->Set("layer_quad", MathUtil::AsValue(layer_quad).release()); 1408 1409 if (!touch_event_handler_region_.IsEmpty()) { 1410 state->Set("touch_event_handler_region", 1411 touch_event_handler_region_.AsValue().release()); 1412 } 1413 if (have_wheel_event_handlers_) { 1414 gfx::Rect wheel_rect(content_bounds()); 1415 Region wheel_region(wheel_rect); 1416 state->Set("wheel_event_handler_region", 1417 wheel_region.AsValue().release()); 1418 } 1419 if (have_scroll_event_handlers_) { 1420 gfx::Rect scroll_rect(content_bounds()); 1421 Region scroll_region(scroll_rect); 1422 state->Set("scroll_event_handler_region", 1423 scroll_region.AsValue().release()); 1424 } 1425 if (!non_fast_scrollable_region_.IsEmpty()) { 1426 state->Set("non_fast_scrollable_region", 1427 non_fast_scrollable_region_.AsValue().release()); 1428 } 1429 1430 scoped_ptr<base::ListValue> children_list(new base::ListValue()); 1431 for (size_t i = 0; i < children_.size(); ++i) 1432 children_list->Append(children_[i]->AsValue().release()); 1433 state->Set("children", children_list.release()); 1434 if (mask_layer_) 1435 state->Set("mask_layer", mask_layer_->AsValue().release()); 1436 if (replica_layer_) 1437 state->Set("replica_layer", replica_layer_->AsValue().release()); 1438 1439 if (scroll_parent_) 1440 state->SetInteger("scroll_parent", scroll_parent_->id()); 1441 1442 if (clip_parent_) 1443 state->SetInteger("clip_parent", clip_parent_->id()); 1444 1445 state->SetBoolean("can_use_lcd_text", can_use_lcd_text()); 1446 state->SetBoolean("contents_opaque", contents_opaque()); 1447 1448 state->SetBoolean( 1449 "has_animation_bounds", 1450 layer_animation_controller()->HasAnimationThatInflatesBounds()); 1451 1452 gfx::BoxF box; 1453 if (LayerUtils::GetAnimationBounds(*this, &box)) 1454 state->Set("animation_bounds", MathUtil::AsValue(box).release()); 1455 1456 if (debug_info_.get()) { 1457 std::string str; 1458 debug_info_->AppendAsTraceFormat(&str); 1459 base::JSONReader json_reader; 1460 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str)); 1461 1462 if (debug_info_value->IsType(base::Value::TYPE_DICTIONARY)) { 1463 base::DictionaryValue* dictionary_value = NULL; 1464 bool converted_to_dictionary = 1465 debug_info_value->GetAsDictionary(&dictionary_value); 1466 DCHECK(converted_to_dictionary); 1467 state->MergeDictionary(dictionary_value); 1468 } else { 1469 NOTREACHED(); 1470 } 1471 } 1472} 1473 1474bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const { 1475 return draw_properties_.last_drawn_render_surface_layer_list_id == 1476 layer_tree_impl_->current_render_surface_list_id(); 1477} 1478 1479size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; } 1480 1481scoped_ptr<base::Value> LayerImpl::AsValue() const { 1482 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 1483 AsValueInto(state.get()); 1484 return state.PassAs<base::Value>(); 1485} 1486 1487void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) { 1488 benchmark->RunOnLayer(this); 1489} 1490} // namespace cc 1491