1 // Copyright 2011 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.
5 #include "cc/layer_impl.h"
7 #include "base/debug/trace_event.h"
8 #include "base/stringprintf.h"
9 #include "cc/debug_border_draw_quad.h"
10 #include "cc/debug_colors.h"
11 #include "cc/layer_sorter.h"
12 #include "cc/layer_tree_host_impl.h"
13 #include "cc/math_util.h"
15 #include "cc/quad_sink.h"
16 #include "cc/scrollbar_animation_controller.h"
17 #include "ui/gfx/point_conversions.h"
18 #include "ui/gfx/rect_conversions.h"
22 LayerImpl::LayerImpl(int id
)
25 , m_replicaLayerId(-1)
27 , m_layerTreeHostImpl(0)
28 , m_anchorPoint(0.5, 0.5)
30 , m_contentsScaleX(1.0)
31 , m_contentsScaleY(1.0)
33 , m_shouldScrollOnMainThread(false)
34 , m_haveWheelEventHandlers(false)
35 , m_backgroundColor(0)
37 , m_layerPropertyChanged(false)
38 , m_layerSurfacePropertyChanged(false)
39 , m_masksToBounds(false)
40 , m_contentsOpaque(false)
42 , m_preserves3D(false)
43 , m_useParentBackfaceVisibility(false)
44 , m_drawCheckerboardForMissingTiles(false)
46 , m_drawsContent(false)
47 , m_forceRenderSurface(false)
48 , m_isContainerForFixedPositionLayers(false)
49 , m_fixedToContainerLayer(false)
52 , m_betweenWillDrawAndDidDraw(false)
54 , m_layerAnimationController(LayerAnimationController::create(this))
56 DCHECK(m_layerId
> 0);
59 LayerImpl::~LayerImpl()
62 DCHECK(!m_betweenWillDrawAndDidDraw
);
66 void LayerImpl::addChild(scoped_ptr
<LayerImpl
> child
)
68 child
->setParent(this);
69 m_children
.append(child
.Pass());
72 void LayerImpl::removeFromParent()
77 LayerImpl
* parent
= m_parent
;
80 for (size_t i
= 0; i
< parent
->m_children
.size(); ++i
) {
81 if (parent
->m_children
[i
] == this) {
82 parent
->m_children
.remove(i
);
88 void LayerImpl::removeAllChildren()
90 while (m_children
.size())
91 m_children
[0]->removeFromParent();
94 void LayerImpl::clearChildList()
99 void LayerImpl::createRenderSurface()
101 DCHECK(!m_drawProperties
.render_surface
);
102 m_drawProperties
.render_surface
= make_scoped_ptr(new RenderSurfaceImpl(this));
103 m_drawProperties
.render_target
= this;
106 int LayerImpl::descendantsDrawContent()
109 for (size_t i
= 0; i
< m_children
.size(); ++i
) {
110 if (m_children
[i
]->drawsContent())
112 result
+= m_children
[i
]->descendantsDrawContent();
119 scoped_ptr
<SharedQuadState
> LayerImpl::createSharedQuadState() const
121 scoped_ptr
<SharedQuadState
> state
= SharedQuadState::Create();
122 state
->SetAll(m_drawProperties
.target_space_transform
,
123 m_drawProperties
.visible_content_rect
,
124 m_drawProperties
.drawable_content_rect
,
125 m_drawProperties
.clip_rect
,
126 m_drawProperties
.is_clipped
,
127 m_drawProperties
.opacity
);
131 void LayerImpl::willDraw(ResourceProvider
*)
134 // willDraw/didDraw must be matched.
135 DCHECK(!m_betweenWillDrawAndDidDraw
);
136 m_betweenWillDrawAndDidDraw
= true;
140 void LayerImpl::didDraw(ResourceProvider
*)
143 DCHECK(m_betweenWillDrawAndDidDraw
);
144 m_betweenWillDrawAndDidDraw
= false;
148 bool LayerImpl::showDebugBorders() const
150 if (!m_layerTreeHostImpl
)
152 return m_layerTreeHostImpl
->debugState().showDebugBorders
;
155 void LayerImpl::getDebugBorderProperties(SkColor
* color
, float* width
) const
157 if (m_drawsContent
) {
158 *color
= DebugColors::ContentLayerBorderColor();
159 *width
= DebugColors::ContentLayerBorderWidth(m_layerTreeHostImpl
);
163 if (m_masksToBounds
) {
164 *color
= DebugColors::MaskingLayerBorderColor();
165 *width
= DebugColors::MaskingLayerBorderWidth(m_layerTreeHostImpl
);
169 *color
= DebugColors::ContainerLayerBorderColor();
170 *width
= DebugColors::ContainerLayerBorderWidth(m_layerTreeHostImpl
);
173 void LayerImpl::appendDebugBorderQuad(QuadSink
& quadList
, const SharedQuadState
* sharedQuadState
, AppendQuadsData
& appendQuadsData
) const
175 if (!showDebugBorders())
180 getDebugBorderProperties(&color
, &width
);
182 gfx::Rect
contentRect(gfx::Point(), contentBounds());
183 scoped_ptr
<DebugBorderDrawQuad
> debugBorderQuad
= DebugBorderDrawQuad::Create();
184 debugBorderQuad
->SetNew(sharedQuadState
, contentRect
, color
, width
);
185 quadList
.append(debugBorderQuad
.PassAs
<DrawQuad
>(), appendQuadsData
);
188 bool LayerImpl::hasContributingDelegatedRenderPasses() const
193 RenderPass::Id
LayerImpl::firstContributingRenderPassId() const
195 return RenderPass::Id(0, 0);
198 RenderPass::Id
LayerImpl::nextContributingRenderPassId(RenderPass::Id
) const
200 return RenderPass::Id(0, 0);
203 ResourceProvider::ResourceId
LayerImpl::contentsResourceId() const
209 gfx::Vector2dF
LayerImpl::scrollBy(const gfx::Vector2dF
& scroll
)
211 gfx::Vector2dF minDelta
= -m_scrollOffset
;
212 gfx::Vector2dF maxDelta
= m_maxScrollOffset
- m_scrollOffset
;
213 // Clamp newDelta so that position + delta stays within scroll bounds.
214 gfx::Vector2dF newDelta
= (m_scrollDelta
+ scroll
);
215 newDelta
.ClampToMin(minDelta
);
216 newDelta
.ClampToMax(maxDelta
);
217 gfx::Vector2dF unscrolled
= m_scrollDelta
+ scroll
- newDelta
;
219 if (m_scrollDelta
== newDelta
)
222 m_scrollDelta
= newDelta
;
223 if (m_scrollbarAnimationController
)
224 m_scrollbarAnimationController
->updateScrollOffset(this);
225 noteLayerPropertyChangedForSubtree();
230 InputHandlerClient::ScrollStatus
LayerImpl::tryScroll(const gfx::PointF
& screenSpacePoint
, InputHandlerClient::ScrollInputType type
) const
232 if (shouldScrollOnMainThread()) {
233 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed shouldScrollOnMainThread");
234 return InputHandlerClient::ScrollOnMainThread
;
237 if (!screenSpaceTransform().IsInvertible()) {
238 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored nonInvertibleTransform");
239 return InputHandlerClient::ScrollIgnored
;
242 if (!nonFastScrollableRegion().IsEmpty()) {
243 bool clipped
= false;
244 gfx::PointF hitTestPointInContentSpace
= MathUtil::projectPoint(MathUtil::inverse(screenSpaceTransform()), screenSpacePoint
, clipped
);
245 gfx::PointF hitTestPointInLayerSpace
= gfx::ScalePoint(hitTestPointInContentSpace
, 1 / contentsScaleX(), 1 / contentsScaleY());
246 if (!clipped
&& nonFastScrollableRegion().Contains(gfx::ToRoundedPoint(hitTestPointInLayerSpace
))) {
247 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed nonFastScrollableRegion");
248 return InputHandlerClient::ScrollOnMainThread
;
252 if (type
== InputHandlerClient::Wheel
&& haveWheelEventHandlers()) {
253 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed wheelEventHandlers");
254 return InputHandlerClient::ScrollOnMainThread
;
258 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
259 return InputHandlerClient::ScrollIgnored
;
262 return InputHandlerClient::ScrollStarted
;
265 bool LayerImpl::drawCheckerboardForMissingTiles() const
267 return m_drawCheckerboardForMissingTiles
&& !m_layerTreeHostImpl
->settings().backgroundColorInsteadOfCheckerboard
;
270 gfx::Rect
LayerImpl::layerRectToContentRect(const gfx::RectF
& layerRect
) const
272 gfx::RectF contentRect
= gfx::ScaleRect(layerRect
, contentsScaleX(), contentsScaleY());
273 // Intersect with content rect to avoid the extra pixel because for some
274 // values x and y, ceil((x / y) * y) may be x + 1.
275 contentRect
.Intersect(gfx::Rect(gfx::Point(), contentBounds()));
276 return gfx::ToEnclosingRect(contentRect
);
279 std::string
LayerImpl::indentString(int indent
)
282 for (int i
= 0; i
!= indent
; ++i
)
287 void LayerImpl::dumpLayerProperties(std::string
* str
, int indent
) const
289 std::string indentStr
= indentString(indent
);
290 str
->append(indentStr
);
291 base::StringAppendF(str
, "layer ID: %d\n", m_layerId
);
293 str
->append(indentStr
);
294 base::StringAppendF(str
, "bounds: %d, %d\n", bounds().width(), bounds().height());
296 if (m_drawProperties
.render_target
) {
297 str
->append(indentStr
);
298 base::StringAppendF(str
, "renderTarget: %d\n", m_drawProperties
.render_target
->m_layerId
);
301 str
->append(indentStr
);
302 base::StringAppendF(str
, "position: %f, %f\n", m_position
.x(), m_position
.y());
304 str
->append(indentStr
);
305 base::StringAppendF(str
, "contentsOpaque: %d\n", m_contentsOpaque
);
307 str
->append(indentStr
);
308 const gfx::Transform
& transform
= m_drawProperties
.target_space_transform
;
309 base::StringAppendF(str
, "drawTransform: %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f // %f, %f, %f, %f\n",
310 transform
.matrix().getDouble(0, 0), transform
.matrix().getDouble(0, 1), transform
.matrix().getDouble(0, 2), transform
.matrix().getDouble(0, 3),
311 transform
.matrix().getDouble(1, 0), transform
.matrix().getDouble(1, 1), transform
.matrix().getDouble(1, 2), transform
.matrix().getDouble(1, 3),
312 transform
.matrix().getDouble(2, 0), transform
.matrix().getDouble(2, 1), transform
.matrix().getDouble(2, 2), transform
.matrix().getDouble(2, 3),
313 transform
.matrix().getDouble(3, 0), transform
.matrix().getDouble(3, 1), transform
.matrix().getDouble(3, 2), transform
.matrix().getDouble(3, 3));
315 str
->append(indentStr
);
316 base::StringAppendF(str
, "drawsContent: %s\n", m_drawsContent
? "yes" : "no");
319 void sortLayers(std::vector
<LayerImpl
*>::iterator first
, std::vector
<LayerImpl
*>::iterator end
, LayerSorter
* layerSorter
)
321 TRACE_EVENT0("cc", "LayerImpl::sortLayers");
322 layerSorter
->sort(first
, end
);
325 std::string
LayerImpl::layerTreeAsText() const
332 void LayerImpl::dumpLayer(std::string
* str
, int indent
) const
334 str
->append(indentString(indent
));
335 base::StringAppendF(str
, "%s(%s)\n", layerTypeAsString(), m_debugName
.data());
336 dumpLayerProperties(str
, indent
+2);
337 if (m_replicaLayer
) {
338 str
->append(indentString(indent
+2));
339 str
->append("Replica:\n");
340 m_replicaLayer
->dumpLayer(str
, indent
+3);
343 str
->append(indentString(indent
+2));
344 str
->append("Mask:\n");
345 m_maskLayer
->dumpLayer(str
, indent
+3);
347 for (size_t i
= 0; i
< m_children
.size(); ++i
)
348 m_children
[i
]->dumpLayer(str
, indent
+1);
351 void LayerImpl::setStackingOrderChanged(bool stackingOrderChanged
)
353 // We don't need to store this flag; we only need to track that the change occurred.
354 if (stackingOrderChanged
)
355 noteLayerPropertyChangedForSubtree();
358 bool LayerImpl::layerSurfacePropertyChanged() const
360 if (m_layerSurfacePropertyChanged
)
363 // If this layer's surface property hasn't changed, we want to see if
364 // some layer above us has changed this property. This is done for the
365 // case when such parent layer does not draw content, and therefore will
366 // not be traversed by the damage tracker. We need to make sure that
367 // property change on such layer will be caught by its descendants.
368 LayerImpl
* current
= this->m_parent
;
369 while (current
&& !current
->m_drawProperties
.render_surface
) {
370 if (current
->m_layerSurfacePropertyChanged
)
372 current
= current
->m_parent
;
378 void LayerImpl::noteLayerPropertyChangedForSubtree()
380 m_layerPropertyChanged
= true;
381 noteLayerPropertyChangedForDescendants();
384 void LayerImpl::noteLayerPropertyChangedForDescendants()
386 for (size_t i
= 0; i
< m_children
.size(); ++i
)
387 m_children
[i
]->noteLayerPropertyChangedForSubtree();
390 const char* LayerImpl::layerTypeAsString() const
395 void LayerImpl::resetAllChangeTrackingForSubtree()
397 m_layerPropertyChanged
= false;
398 m_layerSurfacePropertyChanged
= false;
400 m_updateRect
= gfx::RectF();
402 if (m_drawProperties
.render_surface
)
403 m_drawProperties
.render_surface
->resetPropertyChangedFlag();
406 m_maskLayer
->resetAllChangeTrackingForSubtree();
409 m_replicaLayer
->resetAllChangeTrackingForSubtree(); // also resets the replica mask, if it exists.
411 for (size_t i
= 0; i
< m_children
.size(); ++i
)
412 m_children
[i
]->resetAllChangeTrackingForSubtree();
415 bool LayerImpl::layerIsAlwaysDamaged() const
420 int LayerImpl::id() const
425 float LayerImpl::opacity() const
430 void LayerImpl::setOpacityFromAnimation(float opacity
)
435 const gfx::Transform
& LayerImpl::transform() const
440 void LayerImpl::setTransformFromAnimation(const gfx::Transform
& transform
)
442 setTransform(transform
);
445 void LayerImpl::setBounds(const gfx::Size
& bounds
)
447 if (m_bounds
== bounds
)
453 noteLayerPropertyChangedForSubtree();
455 m_layerPropertyChanged
= true;
458 void LayerImpl::setMaskLayer(scoped_ptr
<LayerImpl
> maskLayer
)
460 m_maskLayer
= maskLayer
.Pass();
462 int newLayerId
= m_maskLayer
? m_maskLayer
->id() : -1;
463 if (newLayerId
== m_maskLayerId
)
466 m_maskLayerId
= newLayerId
;
467 noteLayerPropertyChangedForSubtree();
470 void LayerImpl::setReplicaLayer(scoped_ptr
<LayerImpl
> replicaLayer
)
472 m_replicaLayer
= replicaLayer
.Pass();
474 int newLayerId
= m_replicaLayer
? m_replicaLayer
->id() : -1;
475 if (newLayerId
== m_replicaLayerId
)
478 m_replicaLayerId
= newLayerId
;
479 noteLayerPropertyChangedForSubtree();
482 void LayerImpl::setDrawsContent(bool drawsContent
)
484 if (m_drawsContent
== drawsContent
)
487 m_drawsContent
= drawsContent
;
488 m_layerPropertyChanged
= true;
491 void LayerImpl::setAnchorPoint(const gfx::PointF
& anchorPoint
)
493 if (m_anchorPoint
== anchorPoint
)
496 m_anchorPoint
= anchorPoint
;
497 noteLayerPropertyChangedForSubtree();
500 void LayerImpl::setAnchorPointZ(float anchorPointZ
)
502 if (m_anchorPointZ
== anchorPointZ
)
505 m_anchorPointZ
= anchorPointZ
;
506 noteLayerPropertyChangedForSubtree();
509 void LayerImpl::setBackgroundColor(SkColor backgroundColor
)
511 if (m_backgroundColor
== backgroundColor
)
514 m_backgroundColor
= backgroundColor
;
515 m_layerPropertyChanged
= true;
518 void LayerImpl::setFilters(const WebKit::WebFilterOperations
& filters
)
520 if (m_filters
== filters
)
525 noteLayerPropertyChangedForSubtree();
528 void LayerImpl::setBackgroundFilters(const WebKit::WebFilterOperations
& backgroundFilters
)
530 if (m_backgroundFilters
== backgroundFilters
)
533 m_backgroundFilters
= backgroundFilters
;
534 m_layerPropertyChanged
= true;
537 void LayerImpl::setFilter(const skia::RefPtr
<SkImageFilter
>& filter
)
539 if (m_filter
.get() == filter
.get())
542 DCHECK(m_filters
.isEmpty());
544 noteLayerPropertyChangedForSubtree();
547 void LayerImpl::setMasksToBounds(bool masksToBounds
)
549 if (m_masksToBounds
== masksToBounds
)
552 m_masksToBounds
= masksToBounds
;
553 noteLayerPropertyChangedForSubtree();
556 void LayerImpl::setContentsOpaque(bool opaque
)
558 if (m_contentsOpaque
== opaque
)
561 m_contentsOpaque
= opaque
;
562 noteLayerPropertyChangedForSubtree();
565 void LayerImpl::setOpacity(float opacity
)
567 if (m_opacity
== opacity
)
571 m_layerSurfacePropertyChanged
= true;
574 bool LayerImpl::opacityIsAnimating() const
576 return m_layerAnimationController
->isAnimatingProperty(ActiveAnimation::Opacity
);
579 void LayerImpl::setPosition(const gfx::PointF
& position
)
581 if (m_position
== position
)
584 m_position
= position
;
585 noteLayerPropertyChangedForSubtree();
588 void LayerImpl::setPreserves3D(bool preserves3D
)
590 if (m_preserves3D
== preserves3D
)
593 m_preserves3D
= preserves3D
;
594 noteLayerPropertyChangedForSubtree();
597 void LayerImpl::setSublayerTransform(const gfx::Transform
& sublayerTransform
)
599 if (m_sublayerTransform
== sublayerTransform
)
602 m_sublayerTransform
= sublayerTransform
;
603 // sublayer transform does not affect the current layer; it affects only its children.
604 noteLayerPropertyChangedForDescendants();
607 void LayerImpl::setTransform(const gfx::Transform
& transform
)
609 if (m_transform
== transform
)
612 m_transform
= transform
;
613 m_layerSurfacePropertyChanged
= true;
616 bool LayerImpl::transformIsAnimating() const
618 return m_layerAnimationController
->isAnimatingProperty(ActiveAnimation::Transform
);
621 void LayerImpl::setContentBounds(const gfx::Size
& contentBounds
)
623 if (m_contentBounds
== contentBounds
)
626 m_contentBounds
= contentBounds
;
627 m_layerPropertyChanged
= true;
630 void LayerImpl::setContentsScale(float contentsScaleX
, float contentsScaleY
)
632 if (m_contentsScaleX
== contentsScaleX
&& m_contentsScaleY
== contentsScaleY
)
635 m_contentsScaleX
= contentsScaleX
;
636 m_contentsScaleY
= contentsScaleY
;
637 m_layerPropertyChanged
= true;
640 void LayerImpl::setScrollOffset(gfx::Vector2d scrollOffset
)
642 if (m_scrollOffset
== scrollOffset
)
645 m_scrollOffset
= scrollOffset
;
646 noteLayerPropertyChangedForSubtree();
649 void LayerImpl::setScrollDelta(const gfx::Vector2dF
& scrollDelta
)
651 if (m_scrollDelta
== scrollDelta
)
654 m_scrollDelta
= scrollDelta
;
655 noteLayerPropertyChangedForSubtree();
658 void LayerImpl::setImplTransform(const gfx::Transform
& transform
)
660 if (m_implTransform
== transform
)
663 m_implTransform
= transform
;
664 noteLayerPropertyChangedForSubtree();
667 void LayerImpl::setDoubleSided(bool doubleSided
)
669 if (m_doubleSided
== doubleSided
)
672 m_doubleSided
= doubleSided
;
673 noteLayerPropertyChangedForSubtree();
676 Region
LayerImpl::visibleContentOpaqueRegion() const
678 if (contentsOpaque())
679 return visibleContentRect();
683 void LayerImpl::didLoseOutputSurface()
687 void LayerImpl::setMaxScrollOffset(gfx::Vector2d maxScrollOffset
)
689 m_maxScrollOffset
= maxScrollOffset
;
691 if (!m_scrollbarAnimationController
)
693 m_scrollbarAnimationController
->updateScrollOffset(this);
696 ScrollbarLayerImpl
* LayerImpl::horizontalScrollbarLayer()
698 return m_scrollbarAnimationController
? m_scrollbarAnimationController
->horizontalScrollbarLayer() : 0;
701 const ScrollbarLayerImpl
* LayerImpl::horizontalScrollbarLayer() const
703 return m_scrollbarAnimationController
? m_scrollbarAnimationController
->horizontalScrollbarLayer() : 0;
706 void LayerImpl::setHorizontalScrollbarLayer(ScrollbarLayerImpl
* scrollbarLayer
)
708 if (!m_scrollbarAnimationController
)
709 m_scrollbarAnimationController
= ScrollbarAnimationController::create(this);
710 m_scrollbarAnimationController
->setHorizontalScrollbarLayer(scrollbarLayer
);
711 m_scrollbarAnimationController
->updateScrollOffset(this);
714 ScrollbarLayerImpl
* LayerImpl::verticalScrollbarLayer()
716 return m_scrollbarAnimationController
? m_scrollbarAnimationController
->verticalScrollbarLayer() : 0;
719 const ScrollbarLayerImpl
* LayerImpl::verticalScrollbarLayer() const
721 return m_scrollbarAnimationController
? m_scrollbarAnimationController
->verticalScrollbarLayer() : 0;
724 void LayerImpl::setVerticalScrollbarLayer(ScrollbarLayerImpl
* scrollbarLayer
)
726 if (!m_scrollbarAnimationController
)
727 m_scrollbarAnimationController
= ScrollbarAnimationController::create(this);
728 m_scrollbarAnimationController
->setVerticalScrollbarLayer(scrollbarLayer
);
729 m_scrollbarAnimationController
->updateScrollOffset(this);