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