layer.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright (c) 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 "ui/compositor/layer.h" 6 7#include <algorithm> 8 9#include "base/command_line.h" 10#include "base/debug/trace_event.h" 11#include "base/json/json_writer.h" 12#include "base/logging.h" 13#include "base/memory/scoped_ptr.h" 14#include "cc/base/scoped_ptr_algorithm.h" 15#include "cc/layers/content_layer.h" 16#include "cc/layers/delegated_renderer_layer.h" 17#include "cc/layers/picture_layer.h" 18#include "cc/layers/solid_color_layer.h" 19#include "cc/layers/texture_layer.h" 20#include "cc/output/copy_output_request.h" 21#include "cc/output/delegated_frame_data.h" 22#include "cc/output/filter_operation.h" 23#include "cc/output/filter_operations.h" 24#include "cc/resources/transferable_resource.h" 25#include "ui/compositor/compositor_switches.h" 26#include "ui/compositor/dip_util.h" 27#include "ui/compositor/layer_animator.h" 28#include "ui/gfx/animation/animation.h" 29#include "ui/gfx/canvas.h" 30#include "ui/gfx/display.h" 31#include "ui/gfx/interpolated_transform.h" 32#include "ui/gfx/point3_f.h" 33#include "ui/gfx/point_conversions.h" 34#include "ui/gfx/size_conversions.h" 35 36namespace { 37 38const ui::Layer* GetRoot(const ui::Layer* layer) { 39 while (layer->parent()) 40 layer = layer->parent(); 41 return layer; 42} 43 44struct UIImplSidePaintingStatus { 45 UIImplSidePaintingStatus() 46 : enabled(ui::IsUIImplSidePaintingEnabled()) { 47 } 48 bool enabled; 49}; 50base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status = 51 LAZY_INSTANCE_INITIALIZER; 52 53} // namespace 54 55namespace ui { 56 57Layer::Layer() 58 : type_(LAYER_TEXTURED), 59 compositor_(NULL), 60 parent_(NULL), 61 visible_(true), 62 force_render_surface_(false), 63 fills_bounds_opaquely_(true), 64 fills_bounds_completely_(false), 65 background_blur_radius_(0), 66 layer_saturation_(0.0f), 67 layer_brightness_(0.0f), 68 layer_grayscale_(0.0f), 69 layer_inverted_(false), 70 layer_mask_(NULL), 71 layer_mask_back_link_(NULL), 72 zoom_(1), 73 zoom_inset_(0), 74 delegate_(NULL), 75 owner_(NULL), 76 cc_layer_(NULL), 77 device_scale_factor_(1.0f) { 78 CreateWebLayer(); 79} 80 81Layer::Layer(LayerType type) 82 : type_(type), 83 compositor_(NULL), 84 parent_(NULL), 85 visible_(true), 86 force_render_surface_(false), 87 fills_bounds_opaquely_(true), 88 fills_bounds_completely_(false), 89 background_blur_radius_(0), 90 layer_saturation_(0.0f), 91 layer_brightness_(0.0f), 92 layer_grayscale_(0.0f), 93 layer_inverted_(false), 94 layer_mask_(NULL), 95 layer_mask_back_link_(NULL), 96 zoom_(1), 97 zoom_inset_(0), 98 delegate_(NULL), 99 owner_(NULL), 100 cc_layer_(NULL), 101 device_scale_factor_(1.0f) { 102 CreateWebLayer(); 103} 104 105Layer::~Layer() { 106 // Destroying the animator may cause observers to use the layer (and 107 // indirectly the WebLayer). Destroy the animator first so that the WebLayer 108 // is still around. 109 if (animator_.get()) 110 animator_->SetDelegate(NULL); 111 animator_ = NULL; 112 if (compositor_) 113 compositor_->SetRootLayer(NULL); 114 if (parent_) 115 parent_->Remove(this); 116 if (layer_mask_) 117 SetMaskLayer(NULL); 118 if (layer_mask_back_link_) 119 layer_mask_back_link_->SetMaskLayer(NULL); 120 for (size_t i = 0; i < children_.size(); ++i) 121 children_[i]->parent_ = NULL; 122 cc_layer_->RemoveLayerAnimationEventObserver(this); 123 cc_layer_->RemoveFromParent(); 124} 125 126// static 127bool Layer::UsingPictureLayer() { 128 return g_ui_impl_side_painting_status.Get().enabled; 129} 130 131Compositor* Layer::GetCompositor() { 132 return GetRoot(this)->compositor_; 133} 134 135float Layer::opacity() const { 136 return cc_layer_->opacity(); 137} 138 139void Layer::SetCompositor(Compositor* compositor) { 140 // This function must only be called to set the compositor on the root layer, 141 // or to reset it. 142 DCHECK(!compositor || !compositor_); 143 DCHECK(!compositor || compositor->root_layer() == this); 144 DCHECK(!parent_); 145 compositor_ = compositor; 146 if (compositor) { 147 OnDeviceScaleFactorChanged(compositor->device_scale_factor()); 148 SendPendingThreadedAnimations(); 149 } 150} 151 152void Layer::Add(Layer* child) { 153 DCHECK(!child->compositor_); 154 if (child->parent_) 155 child->parent_->Remove(child); 156 child->parent_ = this; 157 children_.push_back(child); 158 cc_layer_->AddChild(child->cc_layer_); 159 child->OnDeviceScaleFactorChanged(device_scale_factor_); 160 if (GetCompositor()) 161 child->SendPendingThreadedAnimations(); 162} 163 164void Layer::Remove(Layer* child) { 165 // Current bounds are used to calculate offsets when layers are reparented. 166 // Stop (and complete) an ongoing animation to update the bounds immediately. 167 if (child->GetAnimator()) { 168 child->GetAnimator()->StopAnimatingProperty( 169 ui::LayerAnimationElement::BOUNDS); 170 } 171 std::vector<Layer*>::iterator i = 172 std::find(children_.begin(), children_.end(), child); 173 DCHECK(i != children_.end()); 174 children_.erase(i); 175 child->parent_ = NULL; 176 child->cc_layer_->RemoveFromParent(); 177} 178 179void Layer::StackAtTop(Layer* child) { 180 if (children_.size() <= 1 || child == children_.back()) 181 return; // Already in front. 182 StackAbove(child, children_.back()); 183} 184 185void Layer::StackAbove(Layer* child, Layer* other) { 186 StackRelativeTo(child, other, true); 187} 188 189void Layer::StackAtBottom(Layer* child) { 190 if (children_.size() <= 1 || child == children_.front()) 191 return; // Already on bottom. 192 StackBelow(child, children_.front()); 193} 194 195void Layer::StackBelow(Layer* child, Layer* other) { 196 StackRelativeTo(child, other, false); 197} 198 199bool Layer::Contains(const Layer* other) const { 200 for (const Layer* parent = other; parent; parent = parent->parent()) { 201 if (parent == this) 202 return true; 203 } 204 return false; 205} 206 207void Layer::SetAnimator(LayerAnimator* animator) { 208 if (animator) 209 animator->SetDelegate(this); 210 animator_ = animator; 211} 212 213LayerAnimator* Layer::GetAnimator() { 214 if (!animator_.get()) 215 SetAnimator(LayerAnimator::CreateDefaultAnimator()); 216 return animator_.get(); 217} 218 219void Layer::SetTransform(const gfx::Transform& transform) { 220 GetAnimator()->SetTransform(transform); 221} 222 223gfx::Transform Layer::GetTargetTransform() const { 224 if (animator_.get() && animator_->IsAnimatingProperty( 225 LayerAnimationElement::TRANSFORM)) { 226 return animator_->GetTargetTransform(); 227 } 228 return transform(); 229} 230 231void Layer::SetBounds(const gfx::Rect& bounds) { 232 GetAnimator()->SetBounds(bounds); 233} 234 235gfx::Rect Layer::GetTargetBounds() const { 236 if (animator_.get() && animator_->IsAnimatingProperty( 237 LayerAnimationElement::BOUNDS)) { 238 return animator_->GetTargetBounds(); 239 } 240 return bounds_; 241} 242 243void Layer::SetMasksToBounds(bool masks_to_bounds) { 244 cc_layer_->SetMasksToBounds(masks_to_bounds); 245} 246 247bool Layer::GetMasksToBounds() const { 248 return cc_layer_->masks_to_bounds(); 249} 250 251void Layer::SetOpacity(float opacity) { 252 GetAnimator()->SetOpacity(opacity); 253} 254 255float Layer::GetCombinedOpacity() const { 256 float opacity = this->opacity(); 257 Layer* current = this->parent_; 258 while (current) { 259 opacity *= current->opacity(); 260 current = current->parent_; 261 } 262 return opacity; 263} 264 265void Layer::SetBackgroundBlur(int blur_radius) { 266 background_blur_radius_ = blur_radius; 267 268 SetLayerBackgroundFilters(); 269} 270 271void Layer::SetLayerSaturation(float saturation) { 272 layer_saturation_ = saturation; 273 SetLayerFilters(); 274} 275 276void Layer::SetLayerBrightness(float brightness) { 277 GetAnimator()->SetBrightness(brightness); 278} 279 280float Layer::GetTargetBrightness() const { 281 if (animator_.get() && animator_->IsAnimatingProperty( 282 LayerAnimationElement::BRIGHTNESS)) { 283 return animator_->GetTargetBrightness(); 284 } 285 return layer_brightness(); 286} 287 288void Layer::SetLayerGrayscale(float grayscale) { 289 GetAnimator()->SetGrayscale(grayscale); 290} 291 292float Layer::GetTargetGrayscale() const { 293 if (animator_.get() && animator_->IsAnimatingProperty( 294 LayerAnimationElement::GRAYSCALE)) { 295 return animator_->GetTargetGrayscale(); 296 } 297 return layer_grayscale(); 298} 299 300void Layer::SetLayerInverted(bool inverted) { 301 layer_inverted_ = inverted; 302 SetLayerFilters(); 303} 304 305void Layer::SetMaskLayer(Layer* layer_mask) { 306 // The provided mask should not have a layer mask itself. 307 DCHECK(!layer_mask || 308 (!layer_mask->layer_mask_layer() && 309 layer_mask->children().empty() && 310 !layer_mask->layer_mask_back_link_)); 311 DCHECK(!layer_mask_back_link_); 312 if (layer_mask_ == layer_mask) 313 return; 314 // We need to de-reference the currently linked object so that no problem 315 // arises if the mask layer gets deleted before this object. 316 if (layer_mask_) 317 layer_mask_->layer_mask_back_link_ = NULL; 318 layer_mask_ = layer_mask; 319 cc_layer_->SetMaskLayer( 320 layer_mask ? layer_mask->cc_layer() : NULL); 321 // We need to reference the linked object so that it can properly break the 322 // link to us when it gets deleted. 323 if (layer_mask) { 324 layer_mask->layer_mask_back_link_ = this; 325 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_); 326 } 327} 328 329void Layer::SetBackgroundZoom(float zoom, int inset) { 330 zoom_ = zoom; 331 zoom_inset_ = inset; 332 333 SetLayerBackgroundFilters(); 334} 335 336void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) { 337 alpha_shape_ = region.Pass(); 338 339 SetLayerFilters(); 340} 341 342void Layer::SetLayerFilters() { 343 cc::FilterOperations filters; 344 if (layer_saturation_) { 345 filters.Append(cc::FilterOperation::CreateSaturateFilter( 346 layer_saturation_)); 347 } 348 if (layer_grayscale_) { 349 filters.Append(cc::FilterOperation::CreateGrayscaleFilter( 350 layer_grayscale_)); 351 } 352 if (layer_inverted_) 353 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0)); 354 // Brightness goes last, because the resulting colors neeed clamping, which 355 // cause further color matrix filters to be applied separately. In this order, 356 // they all can be combined in a single pass. 357 if (layer_brightness_) { 358 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter( 359 layer_brightness_)); 360 } 361 if (alpha_shape_) { 362 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter( 363 *alpha_shape_, 1.f, 0.f)); 364 } 365 366 cc_layer_->SetFilters(filters); 367} 368 369void Layer::SetLayerBackgroundFilters() { 370 cc::FilterOperations filters; 371 if (zoom_ != 1) 372 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_)); 373 374 if (background_blur_radius_) { 375 filters.Append(cc::FilterOperation::CreateBlurFilter( 376 background_blur_radius_)); 377 } 378 379 cc_layer_->SetBackgroundFilters(filters); 380} 381 382float Layer::GetTargetOpacity() const { 383 if (animator_.get() && animator_->IsAnimatingProperty( 384 LayerAnimationElement::OPACITY)) 385 return animator_->GetTargetOpacity(); 386 return opacity(); 387} 388 389void Layer::SetVisible(bool visible) { 390 GetAnimator()->SetVisibility(visible); 391} 392 393bool Layer::GetTargetVisibility() const { 394 if (animator_.get() && animator_->IsAnimatingProperty( 395 LayerAnimationElement::VISIBILITY)) 396 return animator_->GetTargetVisibility(); 397 return visible_; 398} 399 400bool Layer::IsDrawn() const { 401 const Layer* layer = this; 402 while (layer && layer->visible_) 403 layer = layer->parent_; 404 return layer == NULL; 405} 406 407bool Layer::ShouldDraw() const { 408 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f; 409} 410 411// static 412void Layer::ConvertPointToLayer(const Layer* source, 413 const Layer* target, 414 gfx::Point* point) { 415 if (source == target) 416 return; 417 418 const Layer* root_layer = GetRoot(source); 419 CHECK_EQ(root_layer, GetRoot(target)); 420 421 if (source != root_layer) 422 source->ConvertPointForAncestor(root_layer, point); 423 if (target != root_layer) 424 target->ConvertPointFromAncestor(root_layer, point); 425} 426 427bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor, 428 gfx::Transform* transform) const { 429 const Layer* p = this; 430 for (; p && p != ancestor; p = p->parent()) { 431 gfx::Transform translation; 432 translation.Translate(static_cast<float>(p->bounds().x()), 433 static_cast<float>(p->bounds().y())); 434 // Use target transform so that result will be correct once animation is 435 // finished. 436 if (!p->GetTargetTransform().IsIdentity()) 437 transform->ConcatTransform(p->GetTargetTransform()); 438 transform->ConcatTransform(translation); 439 } 440 return p == ancestor; 441} 442 443void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { 444 if (fills_bounds_opaquely_ == fills_bounds_opaquely) 445 return; 446 447 fills_bounds_opaquely_ = fills_bounds_opaquely; 448 449 cc_layer_->SetContentsOpaque(fills_bounds_opaquely); 450} 451 452void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) { 453 fills_bounds_completely_ = fills_bounds_completely; 454} 455 456void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) { 457 // Finish animations being handled by cc_layer_. 458 if (animator_.get()) { 459 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); 460 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY); 461 } 462 463 if (texture_layer_.get()) 464 texture_layer_->ClearClient(); 465 // TODO(piman): delegated_renderer_layer_ cleanup. 466 467 cc_layer_->RemoveAllChildren(); 468 if (cc_layer_->parent()) { 469 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer); 470 } 471 cc_layer_->SetLayerClient(NULL); 472 cc_layer_->RemoveLayerAnimationEventObserver(this); 473 new_layer->SetOpacity(cc_layer_->opacity()); 474 new_layer->SetTransform(cc_layer_->transform()); 475 new_layer->SetPosition(cc_layer_->position()); 476 477 cc_layer_ = new_layer.get(); 478 content_layer_ = NULL; 479 solid_color_layer_ = NULL; 480 texture_layer_ = NULL; 481 delegated_renderer_layer_ = NULL; 482 483 cc_layer_->AddLayerAnimationEventObserver(this); 484 for (size_t i = 0; i < children_.size(); ++i) { 485 DCHECK(children_[i]->cc_layer_); 486 cc_layer_->AddChild(children_[i]->cc_layer_); 487 } 488 cc_layer_->SetLayerClient(this); 489 cc_layer_->SetAnchorPoint(gfx::PointF()); 490 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); 491 cc_layer_->SetForceRenderSurface(force_render_surface_); 492 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); 493 cc_layer_->SetHideLayerAndSubtree(!visible_); 494} 495 496void Layer::SwitchCCLayerForTest() { 497 scoped_refptr<cc::Layer> new_layer; 498 if (Layer::UsingPictureLayer()) 499 new_layer = cc::PictureLayer::Create(this); 500 else 501 new_layer = cc::ContentLayer::Create(this); 502 SwitchToLayer(new_layer); 503 content_layer_ = new_layer; 504} 505 506void Layer::SetTextureMailbox( 507 const cc::TextureMailbox& mailbox, 508 scoped_ptr<cc::SingleReleaseCallback> release_callback, 509 gfx::Size texture_size_in_dip) { 510 DCHECK_EQ(type_, LAYER_TEXTURED); 511 DCHECK(!solid_color_layer_.get()); 512 DCHECK(mailbox.IsValid()); 513 DCHECK(release_callback); 514 if (!texture_layer_) { 515 scoped_refptr<cc::TextureLayer> new_layer = 516 cc::TextureLayer::CreateForMailbox(this); 517 new_layer->SetFlipped(true); 518 SwitchToLayer(new_layer); 519 texture_layer_ = new_layer; 520 } 521 if (mailbox_release_callback_) 522 mailbox_release_callback_->Run(0, false); 523 mailbox_release_callback_ = release_callback.Pass(); 524 mailbox_ = mailbox; 525 SetTextureSize(texture_size_in_dip); 526} 527 528void Layer::SetTextureSize(gfx::Size texture_size_in_dip) { 529 DCHECK(texture_layer_.get()); 530 if (frame_size_in_dip_ == texture_size_in_dip) 531 return; 532 frame_size_in_dip_ = texture_size_in_dip; 533 RecomputeDrawsContentAndUVRect(); 534 texture_layer_->SetNeedsDisplay(); 535} 536 537void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider, 538 gfx::Size frame_size_in_dip) { 539 DCHECK_EQ(type_, LAYER_TEXTURED); 540 541 scoped_refptr<cc::DelegatedRendererLayer> new_layer = 542 cc::DelegatedRendererLayer::Create(frame_provider); 543 SwitchToLayer(new_layer); 544 delegated_renderer_layer_ = new_layer; 545 546 frame_size_in_dip_ = frame_size_in_dip; 547 RecomputeDrawsContentAndUVRect(); 548} 549 550void Layer::SetShowPaintedContent() { 551 if (content_layer_.get()) 552 return; 553 554 scoped_refptr<cc::Layer> new_layer; 555 if (Layer::UsingPictureLayer()) 556 new_layer = cc::PictureLayer::Create(this); 557 else 558 new_layer = cc::ContentLayer::Create(this); 559 SwitchToLayer(new_layer); 560 content_layer_ = new_layer; 561 562 mailbox_ = cc::TextureMailbox(); 563 if (mailbox_release_callback_) { 564 mailbox_release_callback_->Run(0, false); 565 mailbox_release_callback_.reset(); 566 } 567 RecomputeDrawsContentAndUVRect(); 568} 569 570void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); } 571 572bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) { 573 if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !mailbox_.IsValid())) 574 return false; 575 576 damaged_region_.op(invalid_rect.x(), 577 invalid_rect.y(), 578 invalid_rect.right(), 579 invalid_rect.bottom(), 580 SkRegion::kUnion_Op); 581 ScheduleDraw(); 582 return true; 583} 584 585void Layer::ScheduleDraw() { 586 Compositor* compositor = GetCompositor(); 587 if (compositor) 588 compositor->ScheduleDraw(); 589} 590 591void Layer::SendDamagedRects() { 592 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) { 593 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) { 594 const SkIRect& sk_damaged = iter.rect(); 595 gfx::Rect damaged( 596 sk_damaged.x(), 597 sk_damaged.y(), 598 sk_damaged.width(), 599 sk_damaged.height()); 600 cc_layer_->SetNeedsDisplayRect(damaged); 601 } 602 damaged_region_.setEmpty(); 603 } 604 for (size_t i = 0; i < children_.size(); ++i) 605 children_[i]->SendDamagedRects(); 606} 607 608void Layer::SuppressPaint() { 609 if (!delegate_) 610 return; 611 delegate_ = NULL; 612 for (size_t i = 0; i < children_.size(); ++i) 613 children_[i]->SuppressPaint(); 614} 615 616void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) { 617 if (device_scale_factor_ == device_scale_factor) 618 return; 619 if (animator_.get()) 620 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); 621 device_scale_factor_ = device_scale_factor; 622 RecomputeDrawsContentAndUVRect(); 623 RecomputePosition(); 624 SchedulePaint(gfx::Rect(bounds_.size())); 625 if (delegate_) 626 delegate_->OnDeviceScaleFactorChanged(device_scale_factor); 627 for (size_t i = 0; i < children_.size(); ++i) 628 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor); 629 if (layer_mask_) 630 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor); 631} 632 633void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) { 634 cc_layer_->RequestCopyOfOutput(request.Pass()); 635} 636 637void Layer::PaintContents(SkCanvas* sk_canvas, 638 const gfx::Rect& clip, 639 gfx::RectF* opaque, 640 ContentLayerClient::GraphicsContextStatus gc_status) { 641 TRACE_EVENT0("ui", "Layer::PaintContents"); 642 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling( 643 sk_canvas, device_scale_factor_)); 644 if (delegate_) 645 delegate_->OnPaintLayer(canvas.get()); 646} 647 648bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; } 649 650bool Layer::PrepareTextureMailbox( 651 cc::TextureMailbox* mailbox, 652 scoped_ptr<cc::SingleReleaseCallback>* release_callback, 653 bool use_shared_memory) { 654 if (!mailbox_release_callback_) 655 return false; 656 *mailbox = mailbox_; 657 *release_callback = mailbox_release_callback_.Pass(); 658 return true; 659} 660 661void Layer::SetForceRenderSurface(bool force) { 662 if (force_render_surface_ == force) 663 return; 664 665 force_render_surface_ = force; 666 cc_layer_->SetForceRenderSurface(force_render_surface_); 667} 668 669class LayerDebugInfo : public base::debug::ConvertableToTraceFormat { 670 public: 671 explicit LayerDebugInfo(std::string name) : name_(name) { } 672 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE { 673 base::DictionaryValue dictionary; 674 dictionary.SetString("layer_name", name_); 675 base::JSONWriter::Write(&dictionary, out); 676 } 677 678 private: 679 virtual ~LayerDebugInfo() { } 680 std::string name_; 681}; 682 683scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() { 684 return new LayerDebugInfo(name_); 685} 686 687void Layer::OnAnimationStarted(const cc::AnimationEvent& event) { 688 if (animator_.get()) 689 animator_->OnThreadedAnimationStarted(event); 690} 691 692void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { 693 DCHECK_NE(child, other); 694 DCHECK_EQ(this, child->parent()); 695 DCHECK_EQ(this, other->parent()); 696 697 const size_t child_i = 698 std::find(children_.begin(), children_.end(), child) - children_.begin(); 699 const size_t other_i = 700 std::find(children_.begin(), children_.end(), other) - children_.begin(); 701 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i)) 702 return; 703 704 const size_t dest_i = 705 above ? 706 (child_i < other_i ? other_i : other_i + 1) : 707 (child_i < other_i ? other_i - 1 : other_i); 708 children_.erase(children_.begin() + child_i); 709 children_.insert(children_.begin() + dest_i, child); 710 711 child->cc_layer_->RemoveFromParent(); 712 cc_layer_->InsertChild(child->cc_layer_, dest_i); 713} 714 715bool Layer::ConvertPointForAncestor(const Layer* ancestor, 716 gfx::Point* point) const { 717 gfx::Transform transform; 718 bool result = GetTargetTransformRelativeTo(ancestor, &transform); 719 gfx::Point3F p(*point); 720 transform.TransformPoint(&p); 721 *point = gfx::ToFlooredPoint(p.AsPointF()); 722 return result; 723} 724 725bool Layer::ConvertPointFromAncestor(const Layer* ancestor, 726 gfx::Point* point) const { 727 gfx::Transform transform; 728 bool result = GetTargetTransformRelativeTo(ancestor, &transform); 729 gfx::Point3F p(*point); 730 transform.TransformPointReverse(&p); 731 *point = gfx::ToFlooredPoint(p.AsPointF()); 732 return result; 733} 734 735void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) { 736 if (bounds == bounds_) 737 return; 738 739 base::Closure closure; 740 if (delegate_) 741 closure = delegate_->PrepareForLayerBoundsChange(); 742 bool was_move = bounds_.size() == bounds.size(); 743 bounds_ = bounds; 744 745 RecomputeDrawsContentAndUVRect(); 746 RecomputePosition(); 747 748 if (!closure.is_null()) 749 closure.Run(); 750 751 if (was_move) { 752 // Don't schedule a draw if we're invisible. We'll schedule one 753 // automatically when we get visible. 754 if (IsDrawn()) 755 ScheduleDraw(); 756 } else { 757 // Always schedule a paint, even if we're invisible. 758 SchedulePaint(gfx::Rect(bounds.size())); 759 } 760} 761 762void Layer::SetTransformFromAnimation(const gfx::Transform& transform) { 763 cc_layer_->SetTransform(transform); 764} 765 766void Layer::SetOpacityFromAnimation(float opacity) { 767 cc_layer_->SetOpacity(opacity); 768 ScheduleDraw(); 769} 770 771void Layer::SetVisibilityFromAnimation(bool visible) { 772 if (visible_ == visible) 773 return; 774 775 visible_ = visible; 776 cc_layer_->SetHideLayerAndSubtree(!visible_); 777} 778 779void Layer::SetBrightnessFromAnimation(float brightness) { 780 layer_brightness_ = brightness; 781 SetLayerFilters(); 782} 783 784void Layer::SetGrayscaleFromAnimation(float grayscale) { 785 layer_grayscale_ = grayscale; 786 SetLayerFilters(); 787} 788 789void Layer::SetColorFromAnimation(SkColor color) { 790 DCHECK_EQ(type_, LAYER_SOLID_COLOR); 791 solid_color_layer_->SetBackgroundColor(color); 792 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF); 793} 794 795void Layer::ScheduleDrawForAnimation() { 796 ScheduleDraw(); 797} 798 799const gfx::Rect& Layer::GetBoundsForAnimation() const { 800 return bounds(); 801} 802 803gfx::Transform Layer::GetTransformForAnimation() const { 804 return transform(); 805} 806 807float Layer::GetOpacityForAnimation() const { 808 return opacity(); 809} 810 811bool Layer::GetVisibilityForAnimation() const { 812 return visible(); 813} 814 815float Layer::GetBrightnessForAnimation() const { 816 return layer_brightness(); 817} 818 819float Layer::GetGrayscaleForAnimation() const { 820 return layer_grayscale(); 821} 822 823SkColor Layer::GetColorForAnimation() const { 824 // WebColor is equivalent to SkColor, per WebColor.h. 825 // The NULL check is here since this is invoked regardless of whether we have 826 // been configured as LAYER_SOLID_COLOR. 827 return solid_color_layer_.get() ? 828 solid_color_layer_->background_color() : SK_ColorBLACK; 829} 830 831float Layer::GetDeviceScaleFactor() const { 832 return device_scale_factor_; 833} 834 835void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) { 836 DCHECK(cc_layer_); 837 // Until this layer has a compositor (and hence cc_layer_ has a 838 // LayerTreeHost), addAnimation will fail. 839 if (GetCompositor()) 840 cc_layer_->AddAnimation(animation.Pass()); 841 else 842 pending_threaded_animations_.push_back(animation.Pass()); 843} 844 845namespace{ 846 847struct HasAnimationId { 848 HasAnimationId(int id): id_(id) { 849 } 850 851 bool operator()(cc::Animation* animation) const { 852 return animation->id() == id_; 853 } 854 855 private: 856 int id_; 857}; 858 859} 860 861void Layer::RemoveThreadedAnimation(int animation_id) { 862 DCHECK(cc_layer_); 863 if (pending_threaded_animations_.size() == 0) { 864 cc_layer_->RemoveAnimation(animation_id); 865 return; 866 } 867 868 pending_threaded_animations_.erase( 869 cc::remove_if(&pending_threaded_animations_, 870 pending_threaded_animations_.begin(), 871 pending_threaded_animations_.end(), 872 HasAnimationId(animation_id)), 873 pending_threaded_animations_.end()); 874} 875 876void Layer::SendPendingThreadedAnimations() { 877 for (cc::ScopedPtrVector<cc::Animation>::iterator it = 878 pending_threaded_animations_.begin(); 879 it != pending_threaded_animations_.end(); 880 ++it) 881 cc_layer_->AddAnimation(pending_threaded_animations_.take(it)); 882 883 pending_threaded_animations_.clear(); 884 885 for (size_t i = 0; i < children_.size(); ++i) 886 children_[i]->SendPendingThreadedAnimations(); 887} 888 889void Layer::CreateWebLayer() { 890 if (type_ == LAYER_SOLID_COLOR) { 891 solid_color_layer_ = cc::SolidColorLayer::Create(); 892 cc_layer_ = solid_color_layer_.get(); 893 } else { 894 if (Layer::UsingPictureLayer()) 895 content_layer_ = cc::PictureLayer::Create(this); 896 else 897 content_layer_ = cc::ContentLayer::Create(this); 898 cc_layer_ = content_layer_.get(); 899 } 900 cc_layer_->SetAnchorPoint(gfx::PointF()); 901 cc_layer_->SetContentsOpaque(true); 902 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); 903 cc_layer_->AddLayerAnimationEventObserver(this); 904 cc_layer_->SetLayerClient(this); 905 RecomputePosition(); 906} 907 908gfx::Transform Layer::transform() const { 909 return cc_layer_->transform(); 910} 911 912void Layer::RecomputeDrawsContentAndUVRect() { 913 DCHECK(cc_layer_); 914 gfx::Size size(bounds_.size()); 915 if (texture_layer_.get()) { 916 size.SetToMin(frame_size_in_dip_); 917 gfx::PointF uv_top_left(0.f, 0.f); 918 gfx::PointF uv_bottom_right( 919 static_cast<float>(size.width()) / frame_size_in_dip_.width(), 920 static_cast<float>(size.height()) / frame_size_in_dip_.height()); 921 texture_layer_->SetUV(uv_top_left, uv_bottom_right); 922 } else if (delegated_renderer_layer_.get()) { 923 size.SetToMin(frame_size_in_dip_); 924 delegated_renderer_layer_->SetDisplaySize(frame_size_in_dip_); 925 } 926 cc_layer_->SetBounds(size); 927} 928 929void Layer::RecomputePosition() { 930 cc_layer_->SetPosition(gfx::PointF(bounds_.x(), bounds_.y())); 931} 932 933} // namespace ui 934