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