layer.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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::SetAlphaShape(scoped_ptr<SkRegion> region) { 333 alpha_shape_ = region.Pass(); 334 335 SetLayerFilters(); 336} 337 338void Layer::SetLayerFilters() { 339 cc::FilterOperations filters; 340 if (layer_saturation_) { 341 filters.Append(cc::FilterOperation::CreateSaturateFilter( 342 layer_saturation_)); 343 } 344 if (layer_grayscale_) { 345 filters.Append(cc::FilterOperation::CreateGrayscaleFilter( 346 layer_grayscale_)); 347 } 348 if (layer_inverted_) 349 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0)); 350 // Brightness goes last, because the resulting colors neeed clamping, which 351 // cause further color matrix filters to be applied separately. In this order, 352 // they all can be combined in a single pass. 353 if (layer_brightness_) { 354 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter( 355 layer_brightness_)); 356 } 357 if (alpha_shape_) { 358 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter( 359 *alpha_shape_, 1.f, 0.f)); 360 } 361 362 cc_layer_->SetFilters(filters); 363} 364 365void Layer::SetLayerBackgroundFilters() { 366 cc::FilterOperations filters; 367 if (zoom_ != 1) 368 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_)); 369 370 if (background_blur_radius_) { 371 filters.Append(cc::FilterOperation::CreateBlurFilter( 372 background_blur_radius_)); 373 } 374 375 cc_layer_->SetBackgroundFilters(filters); 376} 377 378float Layer::GetTargetOpacity() const { 379 if (animator_.get() && animator_->IsAnimatingProperty( 380 LayerAnimationElement::OPACITY)) 381 return animator_->GetTargetOpacity(); 382 return opacity(); 383} 384 385void Layer::SetVisible(bool visible) { 386 GetAnimator()->SetVisibility(visible); 387} 388 389bool Layer::GetTargetVisibility() const { 390 if (animator_.get() && animator_->IsAnimatingProperty( 391 LayerAnimationElement::VISIBILITY)) 392 return animator_->GetTargetVisibility(); 393 return visible_; 394} 395 396bool Layer::IsDrawn() const { 397 const Layer* layer = this; 398 while (layer && layer->visible_) 399 layer = layer->parent_; 400 return layer == NULL; 401} 402 403bool Layer::ShouldDraw() const { 404 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f; 405} 406 407// static 408void Layer::ConvertPointToLayer(const Layer* source, 409 const Layer* target, 410 gfx::Point* point) { 411 if (source == target) 412 return; 413 414 const Layer* root_layer = GetRoot(source); 415 CHECK_EQ(root_layer, GetRoot(target)); 416 417 if (source != root_layer) 418 source->ConvertPointForAncestor(root_layer, point); 419 if (target != root_layer) 420 target->ConvertPointFromAncestor(root_layer, point); 421} 422 423bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor, 424 gfx::Transform* transform) const { 425 const Layer* p = this; 426 for (; p && p != ancestor; p = p->parent()) { 427 gfx::Transform translation; 428 translation.Translate(static_cast<float>(p->bounds().x()), 429 static_cast<float>(p->bounds().y())); 430 // Use target transform so that result will be correct once animation is 431 // finished. 432 if (!p->GetTargetTransform().IsIdentity()) 433 transform->ConcatTransform(p->GetTargetTransform()); 434 transform->ConcatTransform(translation); 435 } 436 return p == ancestor; 437} 438 439// static 440gfx::Transform Layer::ConvertTransformToCCTransform( 441 const gfx::Transform& transform, 442 float device_scale_factor) { 443 gfx::Transform cc_transform; 444 cc_transform.Scale(device_scale_factor, device_scale_factor); 445 cc_transform.PreconcatTransform(transform); 446 cc_transform.Scale(1.0f / device_scale_factor, 1.0f / device_scale_factor); 447 return cc_transform; 448} 449 450void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { 451 if (fills_bounds_opaquely_ == fills_bounds_opaquely) 452 return; 453 454 fills_bounds_opaquely_ = fills_bounds_opaquely; 455 456 cc_layer_->SetContentsOpaque(fills_bounds_opaquely); 457} 458 459void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) { 460 fills_bounds_completely_ = fills_bounds_completely; 461} 462 463void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) { 464 // Finish animations being handled by cc_layer_. 465 if (animator_.get()) { 466 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); 467 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY); 468 } 469 470 if (texture_layer_.get()) 471 texture_layer_->ClearClient(); 472 // TODO(piman): delegated_renderer_layer_ cleanup. 473 474 cc_layer_->RemoveAllChildren(); 475 if (parent_) { 476 DCHECK(parent_->cc_layer_); 477 parent_->cc_layer_->ReplaceChild(cc_layer_, new_layer); 478 } 479 cc_layer_->SetLayerClient(NULL); 480 cc_layer_->RemoveLayerAnimationEventObserver(this); 481 new_layer->SetOpacity(cc_layer_->opacity()); 482 new_layer->SetTransform(cc_layer_->transform()); 483 new_layer->SetPosition(cc_layer_->position()); 484 485 cc_layer_ = new_layer.get(); 486 content_layer_ = NULL; 487 solid_color_layer_ = NULL; 488 texture_layer_ = NULL; 489 delegated_renderer_layer_ = NULL; 490 491 cc_layer_->AddLayerAnimationEventObserver(this); 492 for (size_t i = 0; i < children_.size(); ++i) { 493 DCHECK(children_[i]->cc_layer_); 494 cc_layer_->AddChild(children_[i]->cc_layer_); 495 } 496 cc_layer_->SetLayerClient(this); 497 cc_layer_->SetAnchorPoint(gfx::PointF()); 498 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); 499 cc_layer_->SetForceRenderSurface(force_render_surface_); 500 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); 501 cc_layer_->SetHideLayerAndSubtree(!visible_); 502} 503 504void Layer::SwitchCCLayerForTest() { 505 scoped_refptr<cc::Layer> new_layer; 506 if (Layer::UsingPictureLayer()) 507 new_layer = cc::PictureLayer::Create(this); 508 else 509 new_layer = cc::ContentLayer::Create(this); 510 SwitchToLayer(new_layer); 511 content_layer_ = new_layer; 512} 513 514void Layer::SetTextureMailbox( 515 const cc::TextureMailbox& mailbox, 516 scoped_ptr<cc::SingleReleaseCallback> release_callback, 517 gfx::Size texture_size_in_dip) { 518 DCHECK_EQ(type_, LAYER_TEXTURED); 519 DCHECK(!solid_color_layer_.get()); 520 DCHECK(mailbox.IsValid()); 521 DCHECK(release_callback); 522 if (!texture_layer_) { 523 scoped_refptr<cc::TextureLayer> new_layer = 524 cc::TextureLayer::CreateForMailbox(this); 525 new_layer->SetFlipped(true); 526 SwitchToLayer(new_layer); 527 texture_layer_ = new_layer; 528 } 529 if (mailbox_release_callback_) 530 mailbox_release_callback_->Run(0, false); 531 mailbox_release_callback_ = release_callback.Pass(); 532 mailbox_ = mailbox; 533 SetTextureSize(texture_size_in_dip); 534} 535 536void Layer::SetTextureSize(gfx::Size texture_size_in_dip) { 537 DCHECK(texture_layer_.get()); 538 if (frame_size_in_dip_ == texture_size_in_dip) 539 return; 540 frame_size_in_dip_ = texture_size_in_dip; 541 RecomputeDrawsContentAndUVRect(); 542 texture_layer_->SetNeedsDisplay(); 543} 544 545void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider, 546 gfx::Size frame_size_in_dip) { 547 DCHECK_EQ(type_, LAYER_TEXTURED); 548 549 scoped_refptr<cc::DelegatedRendererLayer> new_layer = 550 cc::DelegatedRendererLayer::Create(frame_provider); 551 SwitchToLayer(new_layer); 552 delegated_renderer_layer_ = new_layer; 553 554 frame_size_in_dip_ = frame_size_in_dip; 555 RecomputeDrawsContentAndUVRect(); 556} 557 558void Layer::SetShowPaintedContent() { 559 if (content_layer_.get()) 560 return; 561 562 scoped_refptr<cc::Layer> new_layer; 563 if (Layer::UsingPictureLayer()) 564 new_layer = cc::PictureLayer::Create(this); 565 else 566 new_layer = cc::ContentLayer::Create(this); 567 SwitchToLayer(new_layer); 568 content_layer_ = new_layer; 569 570 mailbox_ = cc::TextureMailbox(); 571 if (mailbox_release_callback_) { 572 mailbox_release_callback_->Run(0, false); 573 mailbox_release_callback_.reset(); 574 } 575 RecomputeDrawsContentAndUVRect(); 576} 577 578void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); } 579 580bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) { 581 if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !mailbox_.IsValid())) 582 return false; 583 584 damaged_region_.op(invalid_rect.x(), 585 invalid_rect.y(), 586 invalid_rect.right(), 587 invalid_rect.bottom(), 588 SkRegion::kUnion_Op); 589 ScheduleDraw(); 590 return true; 591} 592 593void Layer::ScheduleDraw() { 594 Compositor* compositor = GetCompositor(); 595 if (compositor) 596 compositor->ScheduleDraw(); 597} 598 599void Layer::SendDamagedRects() { 600 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) { 601 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) { 602 const SkIRect& sk_damaged = iter.rect(); 603 gfx::Rect damaged( 604 sk_damaged.x(), 605 sk_damaged.y(), 606 sk_damaged.width(), 607 sk_damaged.height()); 608 609 gfx::Rect damaged_in_pixel = ConvertRectToPixel(this, damaged); 610 cc_layer_->SetNeedsDisplayRect(damaged_in_pixel); 611 } 612 damaged_region_.setEmpty(); 613 } 614 for (size_t i = 0; i < children_.size(); ++i) 615 children_[i]->SendDamagedRects(); 616} 617 618void Layer::SuppressPaint() { 619 if (!delegate_) 620 return; 621 delegate_ = NULL; 622 for (size_t i = 0; i < children_.size(); ++i) 623 children_[i]->SuppressPaint(); 624} 625 626void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) { 627 if (device_scale_factor_ == device_scale_factor) 628 return; 629 if (animator_.get()) 630 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); 631 gfx::Transform transform = this->transform(); 632 device_scale_factor_ = device_scale_factor; 633 RecomputeCCTransformFromTransform(transform); 634 RecomputeDrawsContentAndUVRect(); 635 RecomputePosition(); 636 SchedulePaint(gfx::Rect(bounds_.size())); 637 if (delegate_) 638 delegate_->OnDeviceScaleFactorChanged(device_scale_factor); 639 for (size_t i = 0; i < children_.size(); ++i) 640 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor); 641 if (layer_mask_) 642 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor); 643} 644 645void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) { 646 cc_layer_->RequestCopyOfOutput(request.Pass()); 647} 648 649void Layer::PaintContents(SkCanvas* sk_canvas, 650 const gfx::Rect& clip, 651 gfx::RectF* opaque) { 652 TRACE_EVENT0("ui", "Layer::PaintContents"); 653 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling( 654 sk_canvas, device_scale_factor_)); 655 656 bool scale_content = scale_content_; 657 if (scale_content) { 658 canvas->Save(); 659 canvas->sk_canvas()->scale(SkFloatToScalar(device_scale_factor_), 660 SkFloatToScalar(device_scale_factor_)); 661 } 662 663 if (delegate_) 664 delegate_->OnPaintLayer(canvas.get()); 665 if (scale_content) 666 canvas->Restore(); 667} 668 669bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; } 670 671bool Layer::PrepareTextureMailbox( 672 cc::TextureMailbox* mailbox, 673 scoped_ptr<cc::SingleReleaseCallback>* release_callback, 674 bool use_shared_memory) { 675 if (!mailbox_release_callback_) 676 return false; 677 *mailbox = mailbox_; 678 *release_callback = mailbox_release_callback_.Pass(); 679 return true; 680} 681 682void Layer::SetForceRenderSurface(bool force) { 683 if (force_render_surface_ == force) 684 return; 685 686 force_render_surface_ = force; 687 cc_layer_->SetForceRenderSurface(force_render_surface_); 688} 689 690class LayerDebugInfo : public base::debug::ConvertableToTraceFormat { 691 public: 692 explicit LayerDebugInfo(std::string name) : name_(name) { } 693 virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE { 694 base::DictionaryValue dictionary; 695 dictionary.SetString("layer_name", name_); 696 base::JSONWriter::Write(&dictionary, out); 697 } 698 699 private: 700 virtual ~LayerDebugInfo() { } 701 std::string name_; 702}; 703 704scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() { 705 return new LayerDebugInfo(name_); 706} 707 708void Layer::OnAnimationStarted(const cc::AnimationEvent& event) { 709 if (animator_.get()) 710 animator_->OnThreadedAnimationStarted(event); 711} 712 713void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { 714 DCHECK_NE(child, other); 715 DCHECK_EQ(this, child->parent()); 716 DCHECK_EQ(this, other->parent()); 717 718 const size_t child_i = 719 std::find(children_.begin(), children_.end(), child) - children_.begin(); 720 const size_t other_i = 721 std::find(children_.begin(), children_.end(), other) - children_.begin(); 722 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i)) 723 return; 724 725 const size_t dest_i = 726 above ? 727 (child_i < other_i ? other_i : other_i + 1) : 728 (child_i < other_i ? other_i - 1 : other_i); 729 children_.erase(children_.begin() + child_i); 730 children_.insert(children_.begin() + dest_i, child); 731 732 child->cc_layer_->RemoveFromParent(); 733 cc_layer_->InsertChild(child->cc_layer_, dest_i); 734} 735 736bool Layer::ConvertPointForAncestor(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.TransformPoint(&p); 742 *point = gfx::ToFlooredPoint(p.AsPointF()); 743 return result; 744} 745 746bool Layer::ConvertPointFromAncestor(const Layer* ancestor, 747 gfx::Point* point) const { 748 gfx::Transform transform; 749 bool result = GetTargetTransformRelativeTo(ancestor, &transform); 750 gfx::Point3F p(*point); 751 transform.TransformPointReverse(&p); 752 *point = gfx::ToFlooredPoint(p.AsPointF()); 753 return result; 754} 755 756void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) { 757 if (bounds == bounds_) 758 return; 759 760 base::Closure closure; 761 if (delegate_) 762 closure = delegate_->PrepareForLayerBoundsChange(); 763 bool was_move = bounds_.size() == bounds.size(); 764 bounds_ = bounds; 765 766 RecomputeDrawsContentAndUVRect(); 767 RecomputePosition(); 768 769 if (!closure.is_null()) 770 closure.Run(); 771 772 if (was_move) { 773 // Don't schedule a draw if we're invisible. We'll schedule one 774 // automatically when we get visible. 775 if (IsDrawn()) 776 ScheduleDraw(); 777 } else { 778 // Always schedule a paint, even if we're invisible. 779 SchedulePaint(gfx::Rect(bounds.size())); 780 } 781} 782 783void Layer::SetTransformFromAnimation(const gfx::Transform& transform) { 784 RecomputeCCTransformFromTransform(transform); 785} 786 787void Layer::SetOpacityFromAnimation(float opacity) { 788 cc_layer_->SetOpacity(opacity); 789 ScheduleDraw(); 790} 791 792void Layer::SetVisibilityFromAnimation(bool visible) { 793 if (visible_ == visible) 794 return; 795 796 visible_ = visible; 797 cc_layer_->SetHideLayerAndSubtree(!visible_); 798} 799 800void Layer::SetBrightnessFromAnimation(float brightness) { 801 layer_brightness_ = brightness; 802 SetLayerFilters(); 803} 804 805void Layer::SetGrayscaleFromAnimation(float grayscale) { 806 layer_grayscale_ = grayscale; 807 SetLayerFilters(); 808} 809 810void Layer::SetColorFromAnimation(SkColor color) { 811 DCHECK_EQ(type_, LAYER_SOLID_COLOR); 812 solid_color_layer_->SetBackgroundColor(color); 813 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF); 814} 815 816void Layer::ScheduleDrawForAnimation() { 817 ScheduleDraw(); 818} 819 820const gfx::Rect& Layer::GetBoundsForAnimation() const { 821 return bounds(); 822} 823 824gfx::Transform Layer::GetTransformForAnimation() const { 825 return transform(); 826} 827 828float Layer::GetOpacityForAnimation() const { 829 return opacity(); 830} 831 832bool Layer::GetVisibilityForAnimation() const { 833 return visible(); 834} 835 836float Layer::GetBrightnessForAnimation() const { 837 return layer_brightness(); 838} 839 840float Layer::GetGrayscaleForAnimation() const { 841 return layer_grayscale(); 842} 843 844SkColor Layer::GetColorForAnimation() const { 845 // WebColor is equivalent to SkColor, per WebColor.h. 846 // The NULL check is here since this is invoked regardless of whether we have 847 // been configured as LAYER_SOLID_COLOR. 848 return solid_color_layer_.get() ? 849 solid_color_layer_->background_color() : SK_ColorBLACK; 850} 851 852float Layer::GetDeviceScaleFactor() const { 853 return device_scale_factor_; 854} 855 856void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) { 857 DCHECK(cc_layer_); 858 // Until this layer has a compositor (and hence cc_layer_ has a 859 // LayerTreeHost), addAnimation will fail. 860 if (GetCompositor()) 861 cc_layer_->AddAnimation(animation.Pass()); 862 else 863 pending_threaded_animations_.push_back(animation.Pass()); 864} 865 866namespace{ 867 868struct HasAnimationId { 869 HasAnimationId(int id): id_(id) { 870 } 871 872 bool operator()(cc::Animation* animation) const { 873 return animation->id() == id_; 874 } 875 876 private: 877 int id_; 878}; 879 880} 881 882void Layer::RemoveThreadedAnimation(int animation_id) { 883 DCHECK(cc_layer_); 884 if (pending_threaded_animations_.size() == 0) { 885 cc_layer_->RemoveAnimation(animation_id); 886 return; 887 } 888 889 pending_threaded_animations_.erase( 890 cc::remove_if(&pending_threaded_animations_, 891 pending_threaded_animations_.begin(), 892 pending_threaded_animations_.end(), 893 HasAnimationId(animation_id)), 894 pending_threaded_animations_.end()); 895} 896 897void Layer::SendPendingThreadedAnimations() { 898 for (cc::ScopedPtrVector<cc::Animation>::iterator it = 899 pending_threaded_animations_.begin(); 900 it != pending_threaded_animations_.end(); 901 ++it) 902 cc_layer_->AddAnimation(pending_threaded_animations_.take(it)); 903 904 pending_threaded_animations_.clear(); 905 906 for (size_t i = 0; i < children_.size(); ++i) 907 children_[i]->SendPendingThreadedAnimations(); 908} 909 910void Layer::CreateWebLayer() { 911 if (type_ == LAYER_SOLID_COLOR) { 912 solid_color_layer_ = cc::SolidColorLayer::Create(); 913 cc_layer_ = solid_color_layer_.get(); 914 } else { 915 if (Layer::UsingPictureLayer()) 916 content_layer_ = cc::PictureLayer::Create(this); 917 else 918 content_layer_ = cc::ContentLayer::Create(this); 919 cc_layer_ = content_layer_.get(); 920 } 921 cc_layer_->SetAnchorPoint(gfx::PointF()); 922 cc_layer_->SetContentsOpaque(true); 923 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); 924 cc_layer_->AddLayerAnimationEventObserver(this); 925 cc_layer_->SetLayerClient(this); 926 RecomputePosition(); 927} 928 929void Layer::RecomputeCCTransformFromTransform(const gfx::Transform& transform) { 930 cc_layer_->SetTransform(ConvertTransformToCCTransform(transform, 931 device_scale_factor_)); 932} 933 934gfx::Transform Layer::transform() const { 935 gfx::Transform transform; 936 transform.Scale(1.0f / device_scale_factor_, 1.0f / device_scale_factor_); 937 transform.PreconcatTransform(cc_layer_->transform()); 938 transform.Scale(device_scale_factor_, device_scale_factor_); 939 return transform; 940} 941 942void Layer::RecomputeDrawsContentAndUVRect() { 943 DCHECK(cc_layer_); 944 gfx::Size size(bounds_.size()); 945 if (texture_layer_.get()) { 946 size.SetToMin(frame_size_in_dip_); 947 gfx::PointF uv_top_left(0.f, 0.f); 948 gfx::PointF uv_bottom_right( 949 static_cast<float>(size.width()) / frame_size_in_dip_.width(), 950 static_cast<float>(size.height()) / frame_size_in_dip_.height()); 951 texture_layer_->SetUV(uv_top_left, uv_bottom_right); 952 } else if (delegated_renderer_layer_.get()) { 953 size.SetToMin(frame_size_in_dip_); 954 delegated_renderer_layer_->SetDisplaySize( 955 ConvertSizeToPixel(this, frame_size_in_dip_)); 956 } 957 cc_layer_->SetBounds(ConvertSizeToPixel(this, size)); 958} 959 960void Layer::RecomputePosition() { 961 cc_layer_->SetPosition(gfx::ScalePoint( 962 gfx::PointF(bounds_.x(), bounds_.y()), 963 device_scale_factor_)); 964} 965 966} // namespace ui 967