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