layer.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "third_party/WebKit/Source/Platform/chromium/public/Platform.h"
14#include "third_party/WebKit/Source/Platform/chromium/public/WebCompositorSupport.h"
15#include "third_party/WebKit/Source/Platform/chromium/public/WebContentLayer.h"
16#include "third_party/WebKit/Source/Platform/chromium/public/WebExternalTextureLayer.h"
17#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation.h"
18#include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
19#include "third_party/WebKit/Source/Platform/chromium/public/WebFloatPoint.h"
20#include "third_party/WebKit/Source/Platform/chromium/public/WebFloatRect.h"
21#include "third_party/WebKit/Source/Platform/chromium/public/WebSolidColorLayer.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/point_conversions.h"
30#include "ui/gfx/point3_f.h"
31#include "ui/gfx/size_conversions.h"
32
33namespace {
34
35const float EPSILON = 1e-3f;
36
37bool IsApproximateMultipleOf(float value, float base) {
38  float remainder = fmod(fabs(value), base);
39  return remainder < EPSILON || base - remainder < EPSILON;
40}
41
42const ui::Layer* GetRoot(const ui::Layer* layer) {
43  return layer->parent() ? GetRoot(layer->parent()) : layer;
44}
45
46}  // namespace
47
48namespace ui {
49
50Layer::Layer()
51    : type_(LAYER_TEXTURED),
52      compositor_(NULL),
53      parent_(NULL),
54      visible_(true),
55      force_render_surface_(false),
56      fills_bounds_opaquely_(true),
57      layer_updated_externally_(false),
58      opacity_(1.0f),
59      background_blur_radius_(0),
60      layer_saturation_(0.0f),
61      layer_brightness_(0.0f),
62      layer_grayscale_(0.0f),
63      layer_inverted_(false),
64      layer_mask_(NULL),
65      layer_mask_back_link_(NULL),
66      delegate_(NULL),
67      web_layer_(NULL),
68      scale_content_(true),
69      device_scale_factor_(1.0f) {
70  CreateWebLayer();
71}
72
73Layer::Layer(LayerType type)
74    : type_(type),
75      compositor_(NULL),
76      parent_(NULL),
77      visible_(true),
78      force_render_surface_(false),
79      fills_bounds_opaquely_(true),
80      layer_updated_externally_(false),
81      opacity_(1.0f),
82      background_blur_radius_(0),
83      layer_saturation_(0.0f),
84      layer_brightness_(0.0f),
85      layer_grayscale_(0.0f),
86      layer_inverted_(false),
87      layer_mask_(NULL),
88      layer_mask_back_link_(NULL),
89      delegate_(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_)
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  web_layer_->removeFromParent();
113}
114
115Compositor* Layer::GetCompositor() {
116  return GetRoot(this)->compositor_;
117}
118
119void Layer::SetCompositor(Compositor* compositor) {
120  // This function must only be called to set the compositor on the root layer,
121  // or to reset it.
122  DCHECK(!compositor || !compositor_);
123  DCHECK(!compositor || compositor->root_layer() == this);
124  DCHECK(!parent_);
125  compositor_ = compositor;
126  if (compositor)
127    OnDeviceScaleFactorChanged(compositor->device_scale_factor());
128}
129
130void Layer::Add(Layer* child) {
131  DCHECK(!child->compositor_);
132  if (child->parent_)
133    child->parent_->Remove(child);
134  child->parent_ = this;
135  children_.push_back(child);
136  web_layer_->addChild(child->web_layer_);
137  child->OnDeviceScaleFactorChanged(device_scale_factor_);
138}
139
140void Layer::Remove(Layer* child) {
141  std::vector<Layer*>::iterator i =
142      std::find(children_.begin(), children_.end(), child);
143  DCHECK(i != children_.end());
144  children_.erase(i);
145  child->parent_ = NULL;
146  child->web_layer_->removeFromParent();
147}
148
149void Layer::StackAtTop(Layer* child) {
150  if (children_.size() <= 1 || child == children_.back())
151    return;  // Already in front.
152  StackAbove(child, children_.back());
153}
154
155void Layer::StackAbove(Layer* child, Layer* other) {
156  StackRelativeTo(child, other, true);
157}
158
159void Layer::StackAtBottom(Layer* child) {
160  if (children_.size() <= 1 || child == children_.front())
161    return;  // Already on bottom.
162  StackBelow(child, children_.front());
163}
164
165void Layer::StackBelow(Layer* child, Layer* other) {
166  StackRelativeTo(child, other, false);
167}
168
169bool Layer::Contains(const Layer* other) const {
170  for (const Layer* parent = other; parent; parent = parent->parent()) {
171    if (parent == this)
172      return true;
173  }
174  return false;
175}
176
177void Layer::SetAnimator(LayerAnimator* animator) {
178  if (animator)
179    animator->SetDelegate(this);
180  animator_ = animator;
181}
182
183LayerAnimator* Layer::GetAnimator() {
184  if (!animator_.get())
185    SetAnimator(LayerAnimator::CreateDefaultAnimator());
186  return animator_.get();
187}
188
189void Layer::SetTransform(const gfx::Transform& transform) {
190  GetAnimator()->SetTransform(transform);
191}
192
193gfx::Transform Layer::GetTargetTransform() const {
194  if (animator_.get() && animator_->IsAnimatingProperty(
195      LayerAnimationElement::TRANSFORM)) {
196    return animator_->GetTargetTransform();
197  }
198  return transform_;
199}
200
201void Layer::SetBounds(const gfx::Rect& bounds) {
202  GetAnimator()->SetBounds(bounds);
203}
204
205gfx::Rect Layer::GetTargetBounds() const {
206  if (animator_.get() && animator_->IsAnimatingProperty(
207      LayerAnimationElement::BOUNDS)) {
208    return animator_->GetTargetBounds();
209  }
210  return bounds_;
211}
212
213void Layer::SetMasksToBounds(bool masks_to_bounds) {
214  web_layer_->setMasksToBounds(masks_to_bounds);
215}
216
217bool Layer::GetMasksToBounds() const {
218  return web_layer_->masksToBounds();
219}
220
221void Layer::SetOpacity(float opacity) {
222  GetAnimator()->SetOpacity(opacity);
223}
224
225float Layer::GetCombinedOpacity() const {
226  float opacity = opacity_;
227  Layer* current = this->parent_;
228  while (current) {
229    opacity *= current->opacity_;
230    current = current->parent_;
231  }
232  return opacity;
233}
234
235void Layer::SetBackgroundBlur(int blur_radius) {
236  background_blur_radius_ = blur_radius;
237
238  WebKit::WebFilterOperations filters;
239  if (background_blur_radius_) {
240    filters.append(WebKit::WebFilterOperation::createBlurFilter(
241        background_blur_radius_));
242  }
243  web_layer_->setBackgroundFilters(filters);
244}
245
246void Layer::SetLayerSaturation(float saturation) {
247  layer_saturation_ = saturation;
248  SetLayerFilters();
249}
250
251void Layer::SetLayerBrightness(float brightness) {
252  GetAnimator()->SetBrightness(brightness);
253}
254
255float Layer::GetTargetBrightness() const {
256  if (animator_.get() && animator_->IsAnimatingProperty(
257      LayerAnimationElement::BRIGHTNESS)) {
258    return animator_->GetTargetBrightness();
259  }
260  return layer_brightness();
261}
262
263void Layer::SetLayerGrayscale(float grayscale) {
264  GetAnimator()->SetGrayscale(grayscale);
265}
266
267float Layer::GetTargetGrayscale() const {
268  if (animator_.get() && animator_->IsAnimatingProperty(
269      LayerAnimationElement::GRAYSCALE)) {
270    return animator_->GetTargetGrayscale();
271  }
272  return layer_grayscale();
273}
274
275void Layer::SetLayerInverted(bool inverted) {
276  layer_inverted_ = inverted;
277  SetLayerFilters();
278}
279
280void Layer::SetMaskLayer(Layer* layer_mask) {
281  // The provided mask should not have a layer mask itself.
282  DCHECK(!layer_mask ||
283         (!layer_mask->layer_mask_layer() &&
284          layer_mask->children().empty() &&
285          !layer_mask->layer_mask_back_link_));
286  DCHECK(!layer_mask_back_link_);
287  if (layer_mask_ == layer_mask)
288    return;
289  // We need to de-reference the currently linked object so that no problem
290  // arises if the mask layer gets deleted before this object.
291  if (layer_mask_)
292    layer_mask_->layer_mask_back_link_ = NULL;
293  layer_mask_ = layer_mask;
294  web_layer_->setMaskLayer(
295      layer_mask ? layer_mask->web_layer() : NULL);
296  // We need to reference the linked object so that it can properly break the
297  // link to us when it gets deleted.
298  if (layer_mask)
299    layer_mask->layer_mask_back_link_ = this;
300}
301
302void Layer::SetLayerFilters() {
303  WebKit::WebFilterOperations filters;
304  if (layer_saturation_) {
305    filters.append(WebKit::WebFilterOperation::createSaturateFilter(
306        layer_saturation_));
307  }
308  if (layer_grayscale_) {
309    filters.append(WebKit::WebFilterOperation::createGrayscaleFilter(
310        layer_grayscale_));
311  }
312  if (layer_inverted_)
313    filters.append(WebKit::WebFilterOperation::createInvertFilter(1.0));
314  // Brightness goes last, because the resulting colors neeed clamping, which
315  // cause further color matrix filters to be applied separately. In this order,
316  // they all can be combined in a single pass.
317  if (layer_brightness_) {
318    filters.append(WebKit::WebFilterOperation::createBrightnessFilter(
319        layer_brightness_));
320  }
321
322  web_layer_->setFilters(filters);
323}
324
325float Layer::GetTargetOpacity() const {
326  if (animator_.get() && animator_->IsAnimatingProperty(
327      LayerAnimationElement::OPACITY))
328    return animator_->GetTargetOpacity();
329  return opacity_;
330}
331
332void Layer::SetVisible(bool visible) {
333  GetAnimator()->SetVisibility(visible);
334}
335
336bool Layer::GetTargetVisibility() const {
337  if (animator_.get() && animator_->IsAnimatingProperty(
338      LayerAnimationElement::VISIBILITY))
339    return animator_->GetTargetVisibility();
340  return visible_;
341}
342
343bool Layer::IsDrawn() const {
344  const Layer* layer = this;
345  while (layer && layer->visible_)
346    layer = layer->parent_;
347  return layer == NULL;
348}
349
350bool Layer::ShouldDraw() const {
351  return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f;
352}
353
354// static
355void Layer::ConvertPointToLayer(const Layer* source,
356                                const Layer* target,
357                                gfx::Point* point) {
358  if (source == target)
359    return;
360
361  const Layer* root_layer = GetRoot(source);
362  CHECK_EQ(root_layer, GetRoot(target));
363
364  if (source != root_layer)
365    source->ConvertPointForAncestor(root_layer, point);
366  if (target != root_layer)
367    target->ConvertPointFromAncestor(root_layer, point);
368}
369
370void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
371  if (fills_bounds_opaquely_ == fills_bounds_opaquely)
372    return;
373
374  fills_bounds_opaquely_ = fills_bounds_opaquely;
375
376  web_layer_->setOpaque(fills_bounds_opaquely);
377  RecomputeDebugBorderColor();
378}
379
380void Layer::SetExternalTexture(Texture* texture) {
381  DCHECK_EQ(type_, LAYER_TEXTURED);
382  layer_updated_externally_ = !!texture;
383  texture_ = texture;
384  if (web_layer_is_accelerated_ != layer_updated_externally_) {
385    // Switch to a different type of layer.
386    web_layer_->removeAllChildren();
387    scoped_ptr<WebKit::WebContentLayer> old_content_layer(
388        content_layer_.release());
389    scoped_ptr<WebKit::WebSolidColorLayer> old_solid_layer(
390        solid_color_layer_.release());
391    scoped_ptr<WebKit::WebExternalTextureLayer> old_texture_layer(
392        texture_layer_.release());
393    WebKit::WebLayer* new_layer = NULL;
394    WebKit::WebCompositorSupport* compositor_support =
395        WebKit::Platform::current()->compositorSupport();
396    if (layer_updated_externally_) {
397      texture_layer_.reset(
398          compositor_support->createExternalTextureLayer(this));
399      texture_layer_->setFlipped(texture_->flipped());
400      new_layer = texture_layer_->layer();
401    } else {
402      old_texture_layer->willModifyTexture();
403      content_layer_.reset(compositor_support->createContentLayer(this));
404      new_layer = content_layer_->layer();
405    }
406    if (parent_) {
407      DCHECK(parent_->web_layer_);
408      parent_->web_layer_->replaceChild(web_layer_, new_layer);
409    }
410    web_layer_= new_layer;
411    web_layer_is_accelerated_ = layer_updated_externally_;
412    for (size_t i = 0; i < children_.size(); ++i) {
413      DCHECK(children_[i]->web_layer_);
414      web_layer_->addChild(children_[i]->web_layer_);
415    }
416    web_layer_->setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f));
417    web_layer_->setOpaque(fills_bounds_opaquely_);
418    web_layer_->setOpacity(visible_ ? opacity_ : 0.f);
419    web_layer_->setDebugBorderWidth(show_debug_borders_ ? 2 : 0);
420    web_layer_->setForceRenderSurface(force_render_surface_);
421    RecomputeTransform();
422    RecomputeDebugBorderColor();
423  }
424  RecomputeDrawsContentAndUVRect();
425}
426
427void Layer::SetColor(SkColor color) {
428  GetAnimator()->SetColor(color);
429}
430
431bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) {
432  if (type_ == LAYER_SOLID_COLOR || (!delegate_ && !texture_))
433    return false;
434
435  damaged_region_.op(invalid_rect.x(),
436                     invalid_rect.y(),
437                     invalid_rect.right(),
438                     invalid_rect.bottom(),
439                     SkRegion::kUnion_Op);
440  ScheduleDraw();
441  return true;
442}
443
444void Layer::ScheduleDraw() {
445  Compositor* compositor = GetCompositor();
446  if (compositor)
447    compositor->ScheduleDraw();
448}
449
450void Layer::SendDamagedRects() {
451  if ((delegate_ || texture_) && !damaged_region_.isEmpty()) {
452    for (SkRegion::Iterator iter(damaged_region_);
453         !iter.done(); iter.next()) {
454      const SkIRect& sk_damaged = iter.rect();
455      gfx::Rect damaged(
456          sk_damaged.x(),
457          sk_damaged.y(),
458          sk_damaged.width(),
459          sk_damaged.height());
460
461      gfx::Rect damaged_in_pixel = ConvertRectToPixel(this, damaged);
462      WebKit::WebFloatRect web_rect(
463          damaged_in_pixel.x(),
464          damaged_in_pixel.y(),
465          damaged_in_pixel.width(),
466          damaged_in_pixel.height());
467      web_layer_->invalidateRect(web_rect);
468    }
469    damaged_region_.setEmpty();
470  }
471  for (size_t i = 0; i < children_.size(); ++i)
472    children_[i]->SendDamagedRects();
473}
474
475void Layer::SuppressPaint() {
476  if (!delegate_)
477    return;
478  delegate_ = NULL;
479  for (size_t i = 0; i < children_.size(); ++i)
480    children_[i]->SuppressPaint();
481}
482
483void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
484  if (device_scale_factor_ == device_scale_factor)
485    return;
486  device_scale_factor_ = device_scale_factor;
487  RecomputeTransform();
488  RecomputeDrawsContentAndUVRect();
489  SchedulePaint(gfx::Rect(bounds_.size()));
490  if (delegate_)
491    delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
492  for (size_t i = 0; i < children_.size(); ++i)
493    children_[i]->OnDeviceScaleFactorChanged(device_scale_factor);
494}
495
496void Layer::paintContents(WebKit::WebCanvas* web_canvas,
497                          const WebKit::WebRect& clip,
498#if WEBCONTENTLAYERCLIENT_HAS_CANPAINTLCDTEXT
499                          bool can_paint_lcd_text,
500#endif  // WEBCONTENTLAYERCLIENT_HAS_CANPAINTLCDTEXT
501                          WebKit::WebFloatRect& opaque) {
502  TRACE_EVENT0("ui", "Layer::paintContents");
503  scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
504      web_canvas, ui::GetScaleFactorFromScale(device_scale_factor_)));
505
506  bool scale_content = scale_content_;
507  if (scale_content) {
508    canvas->Save();
509    canvas->sk_canvas()->scale(SkFloatToScalar(device_scale_factor_),
510                               SkFloatToScalar(device_scale_factor_));
511  }
512
513  if (delegate_)
514    delegate_->OnPaintLayer(canvas.get());
515  if (scale_content)
516    canvas->Restore();
517}
518
519unsigned Layer::prepareTexture(WebKit::WebTextureUpdater& /* updater */) {
520  DCHECK(layer_updated_externally_);
521  return texture_->PrepareTexture();
522}
523
524WebKit::WebGraphicsContext3D* Layer::context() {
525  DCHECK(layer_updated_externally_);
526  return texture_->HostContext3D();
527}
528
529void Layer::SetForceRenderSurface(bool force) {
530  if (force_render_surface_ == force)
531    return;
532
533  force_render_surface_ = force;
534  web_layer_->setForceRenderSurface(force_render_surface_);
535}
536
537void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) {
538  DCHECK_NE(child, other);
539  DCHECK_EQ(this, child->parent());
540  DCHECK_EQ(this, other->parent());
541
542  const size_t child_i =
543      std::find(children_.begin(), children_.end(), child) - children_.begin();
544  const size_t other_i =
545      std::find(children_.begin(), children_.end(), other) - children_.begin();
546  if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i))
547    return;
548
549  const size_t dest_i =
550      above ?
551      (child_i < other_i ? other_i : other_i + 1) :
552      (child_i < other_i ? other_i - 1 : other_i);
553  children_.erase(children_.begin() + child_i);
554  children_.insert(children_.begin() + dest_i, child);
555
556  child->web_layer_->removeFromParent();
557  web_layer_->insertChild(child->web_layer_, dest_i);
558}
559
560bool Layer::ConvertPointForAncestor(const Layer* ancestor,
561                                    gfx::Point* point) const {
562  gfx::Transform transform;
563  bool result = GetTransformRelativeTo(ancestor, &transform);
564  gfx::Point3F p(*point);
565  transform.TransformPoint(p);
566  *point = gfx::ToFlooredPoint(p.AsPointF());
567  return result;
568}
569
570bool Layer::ConvertPointFromAncestor(const Layer* ancestor,
571                                     gfx::Point* point) const {
572  gfx::Transform transform;
573  bool result = GetTransformRelativeTo(ancestor, &transform);
574  gfx::Point3F p(*point);
575  transform.TransformPointReverse(p);
576  *point = gfx::ToFlooredPoint(p.AsPointF());
577  return result;
578}
579
580bool Layer::GetTransformRelativeTo(const Layer* ancestor,
581                                   gfx::Transform* transform) const {
582  const Layer* p = this;
583  for (; p && p != ancestor; p = p->parent()) {
584    if (p->transform().HasChange())
585      transform->ConcatTransform(p->transform());
586    transform->ConcatTranslate(static_cast<float>(p->bounds().x()),
587                               static_cast<float>(p->bounds().y()));
588  }
589  return p == ancestor;
590}
591
592void Layer::SetBoundsImmediately(const gfx::Rect& bounds) {
593  if (bounds == bounds_)
594    return;
595
596  base::Closure closure;
597  if (delegate_)
598    closure = delegate_->PrepareForLayerBoundsChange();
599  bool was_move = bounds_.size() == bounds.size();
600  bounds_ = bounds;
601
602  RecomputeTransform();
603  RecomputeDrawsContentAndUVRect();
604  if (!closure.is_null())
605    closure.Run();
606
607  if (was_move) {
608    // Don't schedule a draw if we're invisible. We'll schedule one
609    // automatically when we get visible.
610    if (IsDrawn())
611      ScheduleDraw();
612  } else {
613    // Always schedule a paint, even if we're invisible.
614    SchedulePaint(gfx::Rect(bounds.size()));
615  }
616}
617
618void Layer::SetTransformImmediately(const gfx::Transform& transform) {
619  transform_ = transform;
620
621  RecomputeTransform();
622}
623
624void Layer::SetOpacityImmediately(float opacity) {
625  bool schedule_draw = (opacity != opacity_ && IsDrawn());
626  opacity_ = opacity;
627
628  if (visible_)
629    web_layer_->setOpacity(opacity);
630  RecomputeDebugBorderColor();
631  if (schedule_draw)
632    ScheduleDraw();
633}
634
635void Layer::SetVisibilityImmediately(bool visible) {
636  if (visible_ == visible)
637    return;
638
639  visible_ = visible;
640  // TODO(piman): Expose a visibility flag on WebLayer.
641  web_layer_->setOpacity(visible_ ? opacity_ : 0.f);
642}
643
644void Layer::SetBrightnessImmediately(float brightness) {
645  layer_brightness_ = brightness;
646  SetLayerFilters();
647}
648
649void Layer::SetGrayscaleImmediately(float grayscale) {
650  layer_grayscale_ = grayscale;
651  SetLayerFilters();
652}
653
654void Layer::SetColorImmediately(SkColor color) {
655  DCHECK_EQ(type_, LAYER_SOLID_COLOR);
656  // WebColor is equivalent to SkColor, per WebColor.h.
657  solid_color_layer_->setBackgroundColor(static_cast<WebKit::WebColor>(color));
658  SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF);
659}
660
661void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) {
662  SetBoundsImmediately(bounds);
663}
664
665void Layer::SetTransformFromAnimation(const gfx::Transform& transform) {
666  SetTransformImmediately(transform);
667}
668
669void Layer::SetOpacityFromAnimation(float opacity) {
670  SetOpacityImmediately(opacity);
671}
672
673void Layer::SetVisibilityFromAnimation(bool visibility) {
674  SetVisibilityImmediately(visibility);
675}
676
677void Layer::SetBrightnessFromAnimation(float brightness) {
678  SetBrightnessImmediately(brightness);
679}
680
681void Layer::SetGrayscaleFromAnimation(float grayscale) {
682  SetGrayscaleImmediately(grayscale);
683}
684
685void Layer::SetColorFromAnimation(SkColor color) {
686  SetColorImmediately(color);
687}
688
689void Layer::ScheduleDrawForAnimation() {
690  ScheduleDraw();
691}
692
693const gfx::Rect& Layer::GetBoundsForAnimation() const {
694  return bounds();
695}
696
697const gfx::Transform& Layer::GetTransformForAnimation() const {
698  return transform();
699}
700
701float Layer::GetOpacityForAnimation() const {
702  return opacity();
703}
704
705bool Layer::GetVisibilityForAnimation() const {
706  return visible();
707}
708
709float Layer::GetBrightnessForAnimation() const {
710  return layer_brightness();
711}
712
713float Layer::GetGrayscaleForAnimation() const {
714  return layer_grayscale();
715}
716
717SkColor Layer::GetColorForAnimation() const {
718  // WebColor is equivalent to SkColor, per WebColor.h.
719  // The NULL check is here since this is invoked regardless of whether we have
720  // been configured as LAYER_SOLID_COLOR.
721  return solid_color_layer_.get() ?
722      solid_color_layer_->layer()->backgroundColor() : SK_ColorBLACK;
723}
724
725void Layer::CreateWebLayer() {
726  WebKit::WebCompositorSupport* compositor_support =
727      WebKit::Platform::current()->compositorSupport();
728  if (type_ == LAYER_SOLID_COLOR) {
729    solid_color_layer_.reset(compositor_support->createSolidColorLayer());
730    web_layer_ = solid_color_layer_->layer();
731  } else {
732    content_layer_.reset(compositor_support->createContentLayer(this));
733    web_layer_ = content_layer_->layer();
734  }
735  web_layer_is_accelerated_ = false;
736  show_debug_borders_ = CommandLine::ForCurrentProcess()->HasSwitch(
737      switches::kUIShowLayerBorders);
738  web_layer_->setAnchorPoint(WebKit::WebFloatPoint(0.f, 0.f));
739  web_layer_->setOpaque(true);
740  web_layer_->setDebugBorderWidth(show_debug_borders_ ? 2 : 0);
741}
742
743void Layer::RecomputeTransform() {
744  gfx::Transform scale_translate;
745  scale_translate.matrix().set3x3(device_scale_factor_, 0, 0,
746                                  0, device_scale_factor_, 0,
747                                  0, 0, 1);
748  // Start with the inverse matrix of above.
749  gfx::Transform transform;
750  transform.matrix().set3x3(1.0f / device_scale_factor_, 0, 0,
751                            0, 1.0f / device_scale_factor_, 0,
752                            0, 0, 1);
753  transform.ConcatTransform(transform_);
754  transform.ConcatTranslate(bounds_.x(), bounds_.y());
755  transform.ConcatTransform(scale_translate);
756  web_layer_->setTransform(transform.matrix());
757}
758
759void Layer::RecomputeDrawsContentAndUVRect() {
760  DCHECK(web_layer_);
761  bool should_draw = type_ != LAYER_NOT_DRAWN;
762  if (!web_layer_is_accelerated_) {
763    if (type_ != LAYER_SOLID_COLOR) {
764      web_layer_->setDrawsContent(should_draw);
765    }
766    web_layer_->setBounds(ConvertSizeToPixel(this, bounds_.size()));
767  } else {
768    DCHECK(texture_);
769
770    float texture_scale_factor = 1.0f / texture_->device_scale_factor();
771    gfx::Size texture_size = gfx::ToFlooredSize(
772        gfx::ScaleSize(texture_->size(), texture_scale_factor));
773
774    gfx::Size size(std::min(bounds().width(), texture_size.width()),
775                   std::min(bounds().height(), texture_size.height()));
776    WebKit::WebFloatRect rect(
777        0,
778        0,
779        static_cast<float>(size.width())/texture_size.width(),
780        static_cast<float>(size.height())/texture_size.height());
781    texture_layer_->setUVRect(rect);
782
783    gfx::Size size_in_pixel = ConvertSizeToPixel(this, size);
784    web_layer_->setBounds(size_in_pixel);
785  }
786}
787
788void Layer::RecomputeDebugBorderColor() {
789  if (!show_debug_borders_)
790    return;
791  unsigned int color = 0xFF000000;
792  color |= web_layer_is_accelerated_ ? 0x0000FF00 : 0x00FF0000;
793  bool opaque = fills_bounds_opaquely_ && (GetCombinedOpacity() == 1.f);
794  if (!opaque)
795    color |= 0xFF;
796  web_layer_->setDebugBorderColor(color);
797}
798
799}  // namespace ui
800