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