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