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