1 // Copyright 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.
5 #include "cc/layers/layer_impl.h"
7 #include "base/debug/trace_event.h"
8 #include "base/json/json_reader.h"
9 #include "base/strings/stringprintf.h"
10 #include "cc/animation/animation_registrar.h"
11 #include "cc/animation/scrollbar_animation_controller.h"
12 #include "cc/animation/scrollbar_animation_controller_linear_fade.h"
13 #include "cc/animation/scrollbar_animation_controller_thinning.h"
14 #include "cc/base/math_util.h"
15 #include "cc/debug/debug_colors.h"
16 #include "cc/debug/layer_tree_debug_state.h"
17 #include "cc/debug/micro_benchmark_impl.h"
18 #include "cc/debug/traced_value.h"
19 #include "cc/input/layer_scroll_offset_delegate.h"
20 #include "cc/layers/layer_utils.h"
21 #include "cc/layers/painted_scrollbar_layer_impl.h"
22 #include "cc/layers/quad_sink.h"
23 #include "cc/output/copy_output_request.h"
24 #include "cc/quads/debug_border_draw_quad.h"
25 #include "cc/trees/layer_tree_host_common.h"
26 #include "cc/trees/layer_tree_impl.h"
27 #include "cc/trees/layer_tree_settings.h"
28 #include "cc/trees/proxy.h"
29 #include "ui/gfx/box_f.h"
30 #include "ui/gfx/geometry/vector2d_conversions.h"
31 #include "ui/gfx/point_conversions.h"
32 #include "ui/gfx/quad_f.h"
33 #include "ui/gfx/rect_conversions.h"
34 #include "ui/gfx/size_conversions.h"
37 LayerImpl::LayerImpl(LayerTreeImpl
* tree_impl
, int id
)
42 replica_layer_id_(-1),
44 layer_tree_impl_(tree_impl
),
45 anchor_point_(0.5f
, 0.5f
),
47 scroll_offset_delegate_(NULL
),
48 scroll_clip_layer_(NULL
),
49 should_scroll_on_main_thread_(false),
50 have_wheel_event_handlers_(false),
51 have_scroll_event_handlers_(false),
52 user_scrollable_horizontal_(true),
53 user_scrollable_vertical_(true),
54 stacking_order_changed_(false),
56 should_flatten_transform_(true),
57 layer_property_changed_(false),
58 masks_to_bounds_(false),
59 contents_opaque_(false),
60 is_root_for_isolated_group_(false),
61 use_parent_backface_visibility_(false),
62 draw_checkerboard_for_missing_tiles_(false),
63 draws_content_(false),
64 hide_layer_and_subtree_(false),
65 force_render_surface_(false),
66 transform_is_invertible_(true),
67 is_container_for_fixed_position_layers_(false),
71 blend_mode_(SkXfermode::kSrcOver_Mode
),
73 needs_push_properties_(false),
74 num_dependents_need_push_properties_(0),
75 current_draw_mode_(DRAW_MODE_NONE
) {
76 DCHECK_GT(layer_id_
, 0);
77 DCHECK(layer_tree_impl_
);
78 layer_tree_impl_
->RegisterLayer(this);
79 AnimationRegistrar
* registrar
= layer_tree_impl_
->animationRegistrar();
80 layer_animation_controller_
=
81 registrar
->GetAnimationControllerForId(layer_id_
);
82 layer_animation_controller_
->AddValueObserver(this);
84 layer_animation_controller_
->set_value_provider(this);
85 SetNeedsPushProperties();
88 LayerImpl::~LayerImpl() {
89 DCHECK_EQ(DRAW_MODE_NONE
, current_draw_mode_
);
91 layer_animation_controller_
->RemoveValueObserver(this);
92 layer_animation_controller_
->remove_value_provider(this);
94 if (!copy_requests_
.empty() && layer_tree_impl_
->IsActiveTree())
95 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
96 layer_tree_impl_
->UnregisterLayer(this);
98 TRACE_EVENT_OBJECT_DELETED_WITH_ID(
99 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerImpl", this);
102 void LayerImpl::AddChild(scoped_ptr
<LayerImpl
> child
) {
103 child
->SetParent(this);
104 DCHECK_EQ(layer_tree_impl(), child
->layer_tree_impl());
105 children_
.push_back(child
.Pass());
106 layer_tree_impl()->set_needs_update_draw_properties();
109 scoped_ptr
<LayerImpl
> LayerImpl::RemoveChild(LayerImpl
* child
) {
110 for (OwnedLayerImplList::iterator it
= children_
.begin();
111 it
!= children_
.end();
114 scoped_ptr
<LayerImpl
> ret
= children_
.take(it
);
116 layer_tree_impl()->set_needs_update_draw_properties();
120 return scoped_ptr
<LayerImpl
>();
123 void LayerImpl::SetParent(LayerImpl
* parent
) {
124 if (parent_should_know_need_push_properties()) {
126 parent_
->RemoveDependentNeedsPushProperties();
128 parent
->AddDependentNeedsPushProperties();
133 void LayerImpl::ClearChildList() {
134 if (children_
.empty())
138 layer_tree_impl()->set_needs_update_draw_properties();
141 bool LayerImpl::HasAncestor(const LayerImpl
* ancestor
) const {
145 for (const LayerImpl
* layer
= this; layer
; layer
= layer
->parent()) {
146 if (layer
== ancestor
)
153 void LayerImpl::SetScrollParent(LayerImpl
* parent
) {
154 if (scroll_parent_
== parent
)
157 // Having both a scroll parent and a scroll offset delegate is unsupported.
158 DCHECK(!scroll_offset_delegate_
);
161 DCHECK_EQ(layer_tree_impl()->LayerById(parent
->id()), parent
);
163 scroll_parent_
= parent
;
164 SetNeedsPushProperties();
167 void LayerImpl::SetDebugInfo(
168 scoped_refptr
<base::debug::ConvertableToTraceFormat
> other
) {
170 SetNeedsPushProperties();
173 void LayerImpl::SetScrollChildren(std::set
<LayerImpl
*>* children
) {
174 if (scroll_children_
.get() == children
)
176 scroll_children_
.reset(children
);
177 SetNeedsPushProperties();
180 void LayerImpl::SetClipParent(LayerImpl
* ancestor
) {
181 if (clip_parent_
== ancestor
)
184 clip_parent_
= ancestor
;
185 SetNeedsPushProperties();
188 void LayerImpl::SetClipChildren(std::set
<LayerImpl
*>* children
) {
189 if (clip_children_
.get() == children
)
191 clip_children_
.reset(children
);
192 SetNeedsPushProperties();
195 void LayerImpl::PassCopyRequests(ScopedPtrVector
<CopyOutputRequest
>* requests
) {
196 if (requests
->empty())
199 bool was_empty
= copy_requests_
.empty();
200 copy_requests_
.insert_and_take(copy_requests_
.end(), *requests
);
203 if (was_empty
&& layer_tree_impl()->IsActiveTree())
204 layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
205 NoteLayerPropertyChangedForSubtree();
208 void LayerImpl::TakeCopyRequestsAndTransformToTarget(
209 ScopedPtrVector
<CopyOutputRequest
>* requests
) {
210 DCHECK(!copy_requests_
.empty());
211 DCHECK(layer_tree_impl()->IsActiveTree());
213 size_t first_inserted_request
= requests
->size();
214 requests
->insert_and_take(requests
->end(), copy_requests_
);
215 copy_requests_
.clear();
217 for (size_t i
= first_inserted_request
; i
< requests
->size(); ++i
) {
218 CopyOutputRequest
* request
= requests
->at(i
);
219 if (!request
->has_area())
222 gfx::Rect request_in_layer_space
= request
->area();
223 gfx::Rect request_in_content_space
=
224 LayerRectToContentRect(request_in_layer_space
);
225 request
->set_area(MathUtil::MapEnclosingClippedRect(
226 draw_properties_
.target_space_transform
, request_in_content_space
));
229 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
232 void LayerImpl::CreateRenderSurface() {
233 DCHECK(!draw_properties_
.render_surface
);
234 draw_properties_
.render_surface
=
235 make_scoped_ptr(new RenderSurfaceImpl(this));
236 draw_properties_
.render_target
= this;
239 void LayerImpl::ClearRenderSurface() {
240 draw_properties_
.render_surface
.reset();
243 scoped_ptr
<SharedQuadState
> LayerImpl::CreateSharedQuadState() const {
244 scoped_ptr
<SharedQuadState
> state
= SharedQuadState::Create();
245 state
->SetAll(draw_properties_
.target_space_transform
,
246 draw_properties_
.content_bounds
,
247 draw_properties_
.visible_content_rect
,
248 draw_properties_
.clip_rect
,
249 draw_properties_
.is_clipped
,
250 draw_properties_
.opacity
,
255 bool LayerImpl::WillDraw(DrawMode draw_mode
,
256 ResourceProvider
* resource_provider
) {
257 // WillDraw/DidDraw must be matched.
258 DCHECK_NE(DRAW_MODE_NONE
, draw_mode
);
259 DCHECK_EQ(DRAW_MODE_NONE
, current_draw_mode_
);
260 current_draw_mode_
= draw_mode
;
264 void LayerImpl::DidDraw(ResourceProvider
* resource_provider
) {
265 DCHECK_NE(DRAW_MODE_NONE
, current_draw_mode_
);
266 current_draw_mode_
= DRAW_MODE_NONE
;
269 bool LayerImpl::ShowDebugBorders() const {
270 return layer_tree_impl()->debug_state().show_debug_borders
;
273 void LayerImpl::GetDebugBorderProperties(SkColor
* color
, float* width
) const {
274 if (draws_content_
) {
275 *color
= DebugColors::ContentLayerBorderColor();
276 *width
= DebugColors::ContentLayerBorderWidth(layer_tree_impl());
280 if (masks_to_bounds_
) {
281 *color
= DebugColors::MaskingLayerBorderColor();
282 *width
= DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
286 *color
= DebugColors::ContainerLayerBorderColor();
287 *width
= DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
290 void LayerImpl::AppendDebugBorderQuad(
292 const SharedQuadState
* shared_quad_state
,
293 AppendQuadsData
* append_quads_data
) const {
296 GetDebugBorderProperties(&color
, &width
);
297 AppendDebugBorderQuad(
298 quad_sink
, shared_quad_state
, append_quads_data
, color
, width
);
301 void LayerImpl::AppendDebugBorderQuad(QuadSink
* quad_sink
,
302 const SharedQuadState
* shared_quad_state
,
303 AppendQuadsData
* append_quads_data
,
306 if (!ShowDebugBorders())
309 gfx::Rect
quad_rect(content_bounds());
310 gfx::Rect
visible_quad_rect(quad_rect
);
311 scoped_ptr
<DebugBorderDrawQuad
> debug_border_quad
=
312 DebugBorderDrawQuad::Create();
313 debug_border_quad
->SetNew(
314 shared_quad_state
, quad_rect
, visible_quad_rect
, color
, width
);
315 quad_sink
->Append(debug_border_quad
.PassAs
<DrawQuad
>());
318 bool LayerImpl::HasDelegatedContent() const {
322 bool LayerImpl::HasContributingDelegatedRenderPasses() const {
326 RenderPass::Id
LayerImpl::FirstContributingRenderPassId() const {
327 return RenderPass::Id(0, 0);
330 RenderPass::Id
LayerImpl::NextContributingRenderPassId(RenderPass::Id id
)
332 return RenderPass::Id(0, 0);
335 ResourceProvider::ResourceId
LayerImpl::ContentsResourceId() const {
340 void LayerImpl::SetSentScrollDelta(const gfx::Vector2d
& sent_scroll_delta
) {
341 // Pending tree never has sent scroll deltas
342 DCHECK(layer_tree_impl()->IsActiveTree());
344 if (sent_scroll_delta_
== sent_scroll_delta
)
347 sent_scroll_delta_
= sent_scroll_delta
;
350 gfx::Vector2dF
LayerImpl::ScrollBy(const gfx::Vector2dF
& scroll
) {
351 DCHECK(scrollable());
352 gfx::Vector2dF min_delta
= -scroll_offset_
;
353 gfx::Vector2dF max_delta
= MaxScrollOffset() - scroll_offset_
;
354 // Clamp new_delta so that position + delta stays within scroll bounds.
355 gfx::Vector2dF new_delta
= (ScrollDelta() + scroll
);
356 new_delta
.SetToMax(min_delta
);
357 new_delta
.SetToMin(max_delta
);
358 gfx::Vector2dF unscrolled
=
359 ScrollDelta() + scroll
- new_delta
;
360 SetScrollDelta(new_delta
);
365 void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id
) {
366 scroll_clip_layer_
= layer_tree_impl()->LayerById(scroll_clip_layer_id
);
369 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
370 // Pending tree never has sent scroll deltas
371 DCHECK(layer_tree_impl()->IsActiveTree());
373 // Apply sent scroll deltas to scroll position / scroll delta as if the
374 // main thread had applied them and then committed those values.
376 // This function should not change the total scroll offset; it just shifts
377 // some of the scroll delta to the scroll offset. Therefore, adjust these
378 // variables directly rather than calling the scroll offset delegate to
379 // avoid sending it multiple spurious calls.
381 // Because of the way scroll delta is calculated with a delegate, this will
382 // leave the total scroll offset unchanged on this layer regardless of
383 // whether a delegate is being used.
384 scroll_offset_
+= sent_scroll_delta_
;
385 scroll_delta_
-= sent_scroll_delta_
;
386 sent_scroll_delta_
= gfx::Vector2d();
389 void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
390 // Only the pending tree can have missing scrolls.
391 DCHECK(layer_tree_impl()->IsPendingTree());
395 // Pending tree should never have sent scroll deltas.
396 DCHECK(sent_scroll_delta().IsZero());
398 LayerImpl
* active_twin
= layer_tree_impl()->FindActiveTreeLayerById(id());
400 // Scrolls that happens after begin frame (where the sent scroll delta
401 // comes from) and commit need to be applied to the pending tree
402 // so that it is up to date with the total scroll.
403 SetScrollDelta(active_twin
->ScrollDelta() -
404 active_twin
->sent_scroll_delta());
408 InputHandler::ScrollStatus
LayerImpl::TryScroll(
409 const gfx::PointF
& screen_space_point
,
410 InputHandler::ScrollInputType type
) const {
411 if (should_scroll_on_main_thread()) {
412 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
413 return InputHandler::ScrollOnMainThread
;
416 if (!screen_space_transform().IsInvertible()) {
417 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
418 return InputHandler::ScrollIgnored
;
421 if (!non_fast_scrollable_region().IsEmpty()) {
422 bool clipped
= false;
423 gfx::Transform
inverse_screen_space_transform(
424 gfx::Transform::kSkipInitialization
);
425 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform
)) {
426 // TODO(shawnsingh): We shouldn't be applying a projection if screen space
427 // transform is uninvertible here. Perhaps we should be returning
428 // ScrollOnMainThread in this case?
431 gfx::PointF hit_test_point_in_content_space
=
432 MathUtil::ProjectPoint(inverse_screen_space_transform
,
435 gfx::PointF hit_test_point_in_layer_space
=
436 gfx::ScalePoint(hit_test_point_in_content_space
,
437 1.f
/ contents_scale_x(),
438 1.f
/ contents_scale_y());
440 non_fast_scrollable_region().Contains(
441 gfx::ToRoundedPoint(hit_test_point_in_layer_space
))) {
443 "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
444 return InputHandler::ScrollOnMainThread
;
448 if (type
== InputHandler::Wheel
&& have_wheel_event_handlers()) {
449 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
450 return InputHandler::ScrollOnMainThread
;
454 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
455 return InputHandler::ScrollIgnored
;
458 gfx::Vector2d max_scroll_offset
= MaxScrollOffset();
459 if (max_scroll_offset
.x() <= 0 && max_scroll_offset
.y() <= 0) {
461 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
462 " but has no affordance in either direction.");
463 return InputHandler::ScrollIgnored
;
466 return InputHandler::ScrollStarted
;
469 gfx::Rect
LayerImpl::LayerRectToContentRect(
470 const gfx::RectF
& layer_rect
) const {
471 gfx::RectF content_rect
=
472 gfx::ScaleRect(layer_rect
, contents_scale_x(), contents_scale_y());
473 // Intersect with content rect to avoid the extra pixel because for some
474 // values x and y, ceil((x / y) * y) may be x + 1.
475 content_rect
.Intersect(gfx::Rect(content_bounds()));
476 return gfx::ToEnclosingRect(content_rect
);
479 skia::RefPtr
<SkPicture
> LayerImpl::GetPicture() {
480 return skia::RefPtr
<SkPicture
>();
483 bool LayerImpl::AreVisibleResourcesReady() const {
487 scoped_ptr
<LayerImpl
> LayerImpl::CreateLayerImpl(LayerTreeImpl
* tree_impl
) {
488 return LayerImpl::Create(tree_impl
, layer_id_
);
491 void LayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
492 layer
->SetAnchorPoint(anchor_point_
);
493 layer
->SetAnchorPointZ(anchor_point_z_
);
494 layer
->SetBackgroundColor(background_color_
);
495 layer
->SetBounds(bounds_
);
496 layer
->SetContentBounds(content_bounds());
497 layer
->SetContentsScale(contents_scale_x(), contents_scale_y());
498 layer
->SetDoubleSided(double_sided_
);
499 layer
->SetDrawCheckerboardForMissingTiles(
500 draw_checkerboard_for_missing_tiles_
);
501 layer
->SetForceRenderSurface(force_render_surface_
);
502 layer
->SetDrawsContent(DrawsContent());
503 layer
->SetHideLayerAndSubtree(hide_layer_and_subtree_
);
504 layer
->SetFilters(filters());
505 layer
->SetBackgroundFilters(background_filters());
506 layer
->SetMasksToBounds(masks_to_bounds_
);
507 layer
->SetShouldScrollOnMainThread(should_scroll_on_main_thread_
);
508 layer
->SetHaveWheelEventHandlers(have_wheel_event_handlers_
);
509 layer
->SetHaveScrollEventHandlers(have_scroll_event_handlers_
);
510 layer
->SetNonFastScrollableRegion(non_fast_scrollable_region_
);
511 layer
->SetTouchEventHandlerRegion(touch_event_handler_region_
);
512 layer
->SetContentsOpaque(contents_opaque_
);
513 layer
->SetOpacity(opacity_
);
514 layer
->SetBlendMode(blend_mode_
);
515 layer
->SetIsRootForIsolatedGroup(is_root_for_isolated_group_
);
516 layer
->SetPosition(position_
);
517 layer
->SetIsContainerForFixedPositionLayers(
518 is_container_for_fixed_position_layers_
);
519 layer
->SetPositionConstraint(position_constraint_
);
520 layer
->SetShouldFlattenTransform(should_flatten_transform_
);
521 layer
->SetIs3dSorted(is_3d_sorted_
);
522 layer
->SetUseParentBackfaceVisibility(use_parent_backface_visibility_
);
523 layer
->SetTransformAndInvertibility(transform_
, transform_is_invertible_
);
525 layer
->SetScrollClipLayer(scroll_clip_layer_
? scroll_clip_layer_
->id()
526 : Layer::INVALID_ID
);
527 layer
->set_user_scrollable_horizontal(user_scrollable_horizontal_
);
528 layer
->set_user_scrollable_vertical(user_scrollable_vertical_
);
529 layer
->SetScrollOffsetAndDelta(
530 scroll_offset_
, layer
->ScrollDelta() - layer
->sent_scroll_delta());
531 layer
->SetSentScrollDelta(gfx::Vector2d());
533 LayerImpl
* scroll_parent
= NULL
;
534 if (scroll_parent_
) {
535 scroll_parent
= layer
->layer_tree_impl()->LayerById(scroll_parent_
->id());
536 DCHECK(scroll_parent
);
539 layer
->SetScrollParent(scroll_parent
);
540 if (scroll_children_
) {
541 std::set
<LayerImpl
*>* scroll_children
= new std::set
<LayerImpl
*>;
542 for (std::set
<LayerImpl
*>::iterator it
= scroll_children_
->begin();
543 it
!= scroll_children_
->end();
545 DCHECK_EQ((*it
)->scroll_parent(), this);
546 LayerImpl
* scroll_child
=
547 layer
->layer_tree_impl()->LayerById((*it
)->id());
548 DCHECK(scroll_child
);
549 scroll_children
->insert(scroll_child
);
551 layer
->SetScrollChildren(scroll_children
);
553 layer
->SetScrollChildren(NULL
);
556 LayerImpl
* clip_parent
= NULL
;
558 clip_parent
= layer
->layer_tree_impl()->LayerById(
563 layer
->SetClipParent(clip_parent
);
564 if (clip_children_
) {
565 std::set
<LayerImpl
*>* clip_children
= new std::set
<LayerImpl
*>;
566 for (std::set
<LayerImpl
*>::iterator it
= clip_children_
->begin();
567 it
!= clip_children_
->end(); ++it
)
568 clip_children
->insert(layer
->layer_tree_impl()->LayerById((*it
)->id()));
569 layer
->SetClipChildren(clip_children
);
571 layer
->SetClipChildren(NULL
);
574 layer
->PassCopyRequests(©_requests_
);
576 // If the main thread commits multiple times before the impl thread actually
577 // draws, then damage tracking will become incorrect if we simply clobber the
578 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
579 // union) any update changes that have occurred on the main thread.
580 update_rect_
.Union(layer
->update_rect());
581 layer
->SetUpdateRect(update_rect_
);
583 layer
->SetStackingOrderChanged(stacking_order_changed_
);
584 layer
->SetDebugInfo(debug_info_
);
586 // Reset any state that should be cleared for the next update.
587 stacking_order_changed_
= false;
588 update_rect_
= gfx::RectF();
589 needs_push_properties_
= false;
590 num_dependents_need_push_properties_
= 0;
593 gfx::Vector2dF
LayerImpl::FixedContainerSizeDelta() const {
594 if (!scroll_clip_layer_
)
595 return gfx::Vector2dF();
597 float scale_delta
= layer_tree_impl()->page_scale_delta();
598 float scale
= layer_tree_impl()->page_scale_factor();
600 gfx::Vector2dF delta_from_scroll
= scroll_clip_layer_
->BoundsDelta();
601 delta_from_scroll
.Scale(1.f
/ scale
);
603 // The delta-from-pinch component requires some explanation: A viewport of
604 // size (w,h) will appear to be size (w/s,h/s) under scale s in the content
605 // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent
606 // viewport size change in the content space due to ds is:
608 // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds)
610 gfx::Vector2dF delta_from_pinch
=
611 gfx::Rect(scroll_clip_layer_
->bounds()).bottom_right() - gfx::PointF();
612 delta_from_pinch
.Scale((1.f
- scale_delta
) / (scale
* scale_delta
));
614 return delta_from_scroll
+ delta_from_pinch
;
617 base::DictionaryValue
* LayerImpl::LayerTreeAsJson() const {
618 base::DictionaryValue
* result
= new base::DictionaryValue
;
619 result
->SetString("LayerType", LayerTypeAsString());
621 base::ListValue
* list
= new base::ListValue
;
622 list
->AppendInteger(bounds().width());
623 list
->AppendInteger(bounds().height());
624 result
->Set("Bounds", list
);
626 list
= new base::ListValue
;
627 list
->AppendDouble(position_
.x());
628 list
->AppendDouble(position_
.y());
629 result
->Set("Position", list
);
631 const gfx::Transform
& gfx_transform
= draw_properties_
.target_space_transform
;
632 double transform
[16];
633 gfx_transform
.matrix().asColMajord(transform
);
634 list
= new base::ListValue
;
635 for (int i
= 0; i
< 16; ++i
)
636 list
->AppendDouble(transform
[i
]);
637 result
->Set("DrawTransform", list
);
639 result
->SetBoolean("DrawsContent", draws_content_
);
640 result
->SetDouble("Opacity", opacity());
641 result
->SetBoolean("ContentsOpaque", contents_opaque_
);
644 result
->SetBoolean("Scrollable", true);
646 if (have_wheel_event_handlers_
)
647 result
->SetBoolean("WheelHandler", have_wheel_event_handlers_
);
648 if (have_scroll_event_handlers_
)
649 result
->SetBoolean("ScrollHandler", have_scroll_event_handlers_
);
650 if (!touch_event_handler_region_
.IsEmpty()) {
651 scoped_ptr
<base::Value
> region
= touch_event_handler_region_
.AsValue();
652 result
->Set("TouchRegion", region
.release());
655 list
= new base::ListValue
;
656 for (size_t i
= 0; i
< children_
.size(); ++i
)
657 list
->Append(children_
[i
]->LayerTreeAsJson());
658 result
->Set("Children", list
);
663 void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed
) {
664 if (stacking_order_changed
) {
665 stacking_order_changed_
= true;
666 NoteLayerPropertyChangedForSubtree();
670 void LayerImpl::NoteLayerPropertyChanged() {
671 layer_property_changed_
= true;
672 layer_tree_impl()->set_needs_update_draw_properties();
673 SetNeedsPushProperties();
676 void LayerImpl::NoteLayerPropertyChangedForSubtree() {
677 layer_property_changed_
= true;
678 layer_tree_impl()->set_needs_update_draw_properties();
679 for (size_t i
= 0; i
< children_
.size(); ++i
)
680 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
681 SetNeedsPushProperties();
684 void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() {
685 layer_property_changed_
= true;
686 for (size_t i
= 0; i
< children_
.size(); ++i
)
687 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
690 void LayerImpl::NoteLayerPropertyChangedForDescendants() {
691 layer_tree_impl()->set_needs_update_draw_properties();
692 for (size_t i
= 0; i
< children_
.size(); ++i
)
693 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
694 SetNeedsPushProperties();
697 const char* LayerImpl::LayerTypeAsString() const {
698 return "cc::LayerImpl";
701 void LayerImpl::ResetAllChangeTrackingForSubtree() {
702 layer_property_changed_
= false;
704 update_rect_
= gfx::RectF();
706 if (draw_properties_
.render_surface
)
707 draw_properties_
.render_surface
->ResetPropertyChangedFlag();
710 mask_layer_
->ResetAllChangeTrackingForSubtree();
712 if (replica_layer_
) {
713 // This also resets the replica mask, if it exists.
714 replica_layer_
->ResetAllChangeTrackingForSubtree();
717 for (size_t i
= 0; i
< children_
.size(); ++i
)
718 children_
[i
]->ResetAllChangeTrackingForSubtree();
720 needs_push_properties_
= false;
721 num_dependents_need_push_properties_
= 0;
724 gfx::Vector2dF
LayerImpl::ScrollOffsetForAnimation() const {
725 return TotalScrollOffset();
728 void LayerImpl::OnFilterAnimated(const FilterOperations
& filters
) {
732 void LayerImpl::OnOpacityAnimated(float opacity
) {
736 void LayerImpl::OnTransformAnimated(const gfx::Transform
& transform
) {
737 SetTransform(transform
);
740 void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF
& scroll_offset
) {
741 // Only layers in the active tree should need to do anything here, since
742 // layers in the pending tree will find out about these changes as a
743 // result of the call to SetScrollDelta.
747 SetScrollDelta(scroll_offset
- scroll_offset_
);
749 layer_tree_impl_
->DidAnimateScrollOffset();
752 void LayerImpl::OnAnimationWaitingForDeletion() {}
754 bool LayerImpl::IsActive() const {
755 return layer_tree_impl_
->IsActiveTree();
758 // TODO(wjmaclean) Convert so that bounds returns SizeF.
759 gfx::Size
LayerImpl::bounds() const {
760 return ToFlooredSize(temporary_impl_bounds_
);
763 void LayerImpl::SetBounds(const gfx::Size
& bounds
) {
764 if (bounds_
== bounds
)
768 temporary_impl_bounds_
= bounds
;
770 ScrollbarParametersDidChange();
771 if (masks_to_bounds())
772 NoteLayerPropertyChangedForSubtree();
774 NoteLayerPropertyChanged();
777 void LayerImpl::SetTemporaryImplBounds(const gfx::SizeF
& bounds
) {
778 if (temporary_impl_bounds_
== bounds
)
781 temporary_impl_bounds_
= bounds
;
783 ScrollbarParametersDidChange();
784 if (masks_to_bounds())
785 NoteLayerPropertyChangedForSubtree();
787 NoteLayerPropertyChanged();
790 void LayerImpl::SetMaskLayer(scoped_ptr
<LayerImpl
> mask_layer
) {
791 int new_layer_id
= mask_layer
? mask_layer
->id() : -1;
794 DCHECK_EQ(layer_tree_impl(), mask_layer
->layer_tree_impl());
795 DCHECK_NE(new_layer_id
, mask_layer_id_
);
796 } else if (new_layer_id
== mask_layer_id_
) {
800 mask_layer_
= mask_layer
.Pass();
801 mask_layer_id_
= new_layer_id
;
803 mask_layer_
->SetParent(this);
804 NoteLayerPropertyChangedForSubtree();
807 scoped_ptr
<LayerImpl
> LayerImpl::TakeMaskLayer() {
809 return mask_layer_
.Pass();
812 void LayerImpl::SetReplicaLayer(scoped_ptr
<LayerImpl
> replica_layer
) {
813 int new_layer_id
= replica_layer
? replica_layer
->id() : -1;
816 DCHECK_EQ(layer_tree_impl(), replica_layer
->layer_tree_impl());
817 DCHECK_NE(new_layer_id
, replica_layer_id_
);
818 } else if (new_layer_id
== replica_layer_id_
) {
822 replica_layer_
= replica_layer
.Pass();
823 replica_layer_id_
= new_layer_id
;
825 replica_layer_
->SetParent(this);
826 NoteLayerPropertyChangedForSubtree();
829 scoped_ptr
<LayerImpl
> LayerImpl::TakeReplicaLayer() {
830 replica_layer_id_
= -1;
831 return replica_layer_
.Pass();
834 ScrollbarLayerImplBase
* LayerImpl::ToScrollbarLayer() {
838 void LayerImpl::SetDrawsContent(bool draws_content
) {
839 if (draws_content_
== draws_content
)
842 draws_content_
= draws_content
;
843 NoteLayerPropertyChanged();
846 void LayerImpl::SetHideLayerAndSubtree(bool hide
) {
847 if (hide_layer_and_subtree_
== hide
)
850 hide_layer_and_subtree_
= hide
;
851 NoteLayerPropertyChangedForSubtree();
854 void LayerImpl::SetAnchorPoint(const gfx::PointF
& anchor_point
) {
855 if (anchor_point_
== anchor_point
)
858 anchor_point_
= anchor_point
;
859 NoteLayerPropertyChangedForSubtree();
862 void LayerImpl::SetAnchorPointZ(float anchor_point_z
) {
863 if (anchor_point_z_
== anchor_point_z
)
866 anchor_point_z_
= anchor_point_z
;
867 NoteLayerPropertyChangedForSubtree();
870 void LayerImpl::SetBackgroundColor(SkColor background_color
) {
871 if (background_color_
== background_color
)
874 background_color_
= background_color
;
875 NoteLayerPropertyChanged();
878 SkColor
LayerImpl::SafeOpaqueBackgroundColor() const {
879 SkColor color
= background_color();
880 if (SkColorGetA(color
) == 255 && !contents_opaque()) {
881 color
= SK_ColorTRANSPARENT
;
882 } else if (SkColorGetA(color
) != 255 && contents_opaque()) {
883 for (const LayerImpl
* layer
= parent(); layer
;
884 layer
= layer
->parent()) {
885 color
= layer
->background_color();
886 if (SkColorGetA(color
) == 255)
889 if (SkColorGetA(color
) != 255)
890 color
= layer_tree_impl()->background_color();
891 if (SkColorGetA(color
) != 255)
892 color
= SkColorSetA(color
, 255);
897 void LayerImpl::SetFilters(const FilterOperations
& filters
) {
898 if (filters_
== filters
)
902 NoteLayerPropertyChangedForSubtree();
905 bool LayerImpl::FilterIsAnimating() const {
906 return layer_animation_controller_
->IsAnimatingProperty(Animation::Filter
);
909 bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
910 Animation
* filter_animation
=
911 layer_animation_controller_
->GetAnimation(Animation::Filter
);
912 return filter_animation
&& filter_animation
->is_impl_only();
915 void LayerImpl::SetBackgroundFilters(
916 const FilterOperations
& filters
) {
917 if (background_filters_
== filters
)
920 background_filters_
= filters
;
921 NoteLayerPropertyChanged();
924 void LayerImpl::SetMasksToBounds(bool masks_to_bounds
) {
925 if (masks_to_bounds_
== masks_to_bounds
)
928 masks_to_bounds_
= masks_to_bounds
;
929 NoteLayerPropertyChangedForSubtree();
932 void LayerImpl::SetContentsOpaque(bool opaque
) {
933 if (contents_opaque_
== opaque
)
936 contents_opaque_
= opaque
;
937 NoteLayerPropertyChangedForSubtree();
940 void LayerImpl::SetOpacity(float opacity
) {
941 if (opacity_
== opacity
)
945 NoteLayerPropertyChangedForSubtree();
948 bool LayerImpl::OpacityIsAnimating() const {
949 return layer_animation_controller_
->IsAnimatingProperty(Animation::Opacity
);
952 bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
953 Animation
* opacity_animation
=
954 layer_animation_controller_
->GetAnimation(Animation::Opacity
);
955 return opacity_animation
&& opacity_animation
->is_impl_only();
958 void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode
) {
959 if (blend_mode_
== blend_mode
)
962 blend_mode_
= blend_mode
;
963 NoteLayerPropertyChangedForSubtree();
966 void LayerImpl::SetIsRootForIsolatedGroup(bool root
) {
967 if (is_root_for_isolated_group_
== root
)
970 is_root_for_isolated_group_
= root
;
971 SetNeedsPushProperties();
974 void LayerImpl::SetPosition(const gfx::PointF
& position
) {
975 if (position_
== position
)
978 position_
= position
;
979 NoteLayerPropertyChangedForSubtree();
982 void LayerImpl::SetShouldFlattenTransform(bool flatten
) {
983 if (should_flatten_transform_
== flatten
)
986 should_flatten_transform_
= flatten
;
987 NoteLayerPropertyChangedForSubtree();
990 void LayerImpl::SetIs3dSorted(bool sorted
) {
991 if (is_3d_sorted_
== sorted
)
994 is_3d_sorted_
= sorted
;
995 NoteLayerPropertyChangedForSubtree();
998 void LayerImpl::SetTransform(const gfx::Transform
& transform
) {
999 if (transform_
== transform
)
1002 transform_
= transform
;
1003 transform_is_invertible_
= transform_
.IsInvertible();
1004 NoteLayerPropertyChangedForSubtree();
1007 void LayerImpl::SetTransformAndInvertibility(const gfx::Transform
& transform
,
1008 bool transform_is_invertible
) {
1009 if (transform_
== transform
) {
1010 DCHECK(transform_is_invertible_
== transform_is_invertible
)
1011 << "Can't change invertibility if transform is unchanged";
1014 transform_
= transform
;
1015 transform_is_invertible_
= transform_is_invertible
;
1016 NoteLayerPropertyChangedForSubtree();
1019 bool LayerImpl::TransformIsAnimating() const {
1020 return layer_animation_controller_
->IsAnimatingProperty(Animation::Transform
);
1023 bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
1024 Animation
* transform_animation
=
1025 layer_animation_controller_
->GetAnimation(Animation::Transform
);
1026 return transform_animation
&& transform_animation
->is_impl_only();
1029 void LayerImpl::SetUpdateRect(const gfx::RectF
& update_rect
) {
1030 update_rect_
= update_rect
;
1031 SetNeedsPushProperties();
1034 void LayerImpl::SetContentBounds(const gfx::Size
& content_bounds
) {
1035 if (this->content_bounds() == content_bounds
)
1038 draw_properties_
.content_bounds
= content_bounds
;
1039 NoteLayerPropertyChanged();
1042 void LayerImpl::SetContentsScale(float contents_scale_x
,
1043 float contents_scale_y
) {
1044 if (this->contents_scale_x() == contents_scale_x
&&
1045 this->contents_scale_y() == contents_scale_y
)
1048 draw_properties_
.contents_scale_x
= contents_scale_x
;
1049 draw_properties_
.contents_scale_y
= contents_scale_y
;
1050 NoteLayerPropertyChanged();
1053 void LayerImpl::CalculateContentsScale(float ideal_contents_scale
,
1054 float device_scale_factor
,
1055 float page_scale_factor
,
1056 float maximum_animation_contents_scale
,
1057 bool animating_transform_to_screen
,
1058 float* contents_scale_x
,
1059 float* contents_scale_y
,
1060 gfx::Size
* content_bounds
) {
1061 // Base LayerImpl has all of its content scales and content bounds pushed
1062 // from its Layer during commit and just reuses those values as-is.
1063 *contents_scale_x
= this->contents_scale_x();
1064 *contents_scale_y
= this->contents_scale_y();
1065 *content_bounds
= this->content_bounds();
1068 void LayerImpl::SetScrollOffsetDelegate(
1069 LayerScrollOffsetDelegate
* scroll_offset_delegate
) {
1070 // Having both a scroll parent and a scroll offset delegate is unsupported.
1071 DCHECK(!scroll_parent_
);
1072 if (!scroll_offset_delegate
&& scroll_offset_delegate_
) {
1074 scroll_offset_delegate_
->GetTotalScrollOffset() - scroll_offset_
;
1076 gfx::Vector2dF total_offset
= TotalScrollOffset();
1077 scroll_offset_delegate_
= scroll_offset_delegate
;
1078 if (scroll_offset_delegate_
)
1079 scroll_offset_delegate_
->SetTotalScrollOffset(total_offset
);
1082 bool LayerImpl::IsExternalFlingActive() const {
1083 return scroll_offset_delegate_
&&
1084 scroll_offset_delegate_
->IsExternalFlingActive();
1087 void LayerImpl::SetScrollOffset(const gfx::Vector2d
& scroll_offset
) {
1088 SetScrollOffsetAndDelta(scroll_offset
, ScrollDelta());
1091 void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d
& scroll_offset
,
1092 const gfx::Vector2dF
& scroll_delta
) {
1093 bool changed
= false;
1095 last_scroll_offset_
= scroll_offset
;
1097 if (scroll_offset_
!= scroll_offset
) {
1099 scroll_offset_
= scroll_offset
;
1101 if (scroll_offset_delegate_
)
1102 scroll_offset_delegate_
->SetTotalScrollOffset(TotalScrollOffset());
1105 if (ScrollDelta() != scroll_delta
) {
1107 if (layer_tree_impl()->IsActiveTree()) {
1108 LayerImpl
* pending_twin
=
1109 layer_tree_impl()->FindPendingTreeLayerById(id());
1111 // The pending twin can't mirror the scroll delta of the active
1112 // layer. Although the delta - sent scroll delta difference is
1113 // identical for both twins, the sent scroll delta for the pending
1114 // layer is zero, as anything that has been sent has been baked
1115 // into the layer's position/scroll offset as a part of commit.
1116 DCHECK(pending_twin
->sent_scroll_delta().IsZero());
1117 pending_twin
->SetScrollDelta(scroll_delta
- sent_scroll_delta());
1121 if (scroll_offset_delegate_
) {
1122 scroll_offset_delegate_
->SetTotalScrollOffset(scroll_offset_
+
1125 scroll_delta_
= scroll_delta
;
1130 NoteLayerPropertyChangedForSubtree();
1131 ScrollbarParametersDidChange();
1135 gfx::Vector2dF
LayerImpl::ScrollDelta() const {
1136 if (scroll_offset_delegate_
)
1137 return scroll_offset_delegate_
->GetTotalScrollOffset() - scroll_offset_
;
1138 return scroll_delta_
;
1141 void LayerImpl::SetScrollDelta(const gfx::Vector2dF
& scroll_delta
) {
1142 SetScrollOffsetAndDelta(scroll_offset_
, scroll_delta
);
1145 gfx::Vector2dF
LayerImpl::TotalScrollOffset() const {
1146 return scroll_offset_
+ ScrollDelta();
1149 void LayerImpl::SetDoubleSided(bool double_sided
) {
1150 if (double_sided_
== double_sided
)
1153 double_sided_
= double_sided
;
1154 NoteLayerPropertyChangedForSubtree();
1157 Region
LayerImpl::VisibleContentOpaqueRegion() const {
1158 if (contents_opaque())
1159 return visible_content_rect();
1163 void LayerImpl::DidBeginTracing() {}
1165 void LayerImpl::ReleaseResources() {}
1167 gfx::Vector2d
LayerImpl::MaxScrollOffset() const {
1168 if (!scroll_clip_layer_
|| bounds().IsEmpty())
1169 return gfx::Vector2d();
1171 LayerImpl
const* page_scale_layer
= layer_tree_impl()->page_scale_layer();
1172 DCHECK(this != page_scale_layer
);
1173 DCHECK(scroll_clip_layer_
);
1174 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1175 IsContainerForFixedPositionLayers());
1177 gfx::SizeF
scaled_scroll_bounds(bounds());
1179 float scale_factor
= 1.f
;
1180 for (LayerImpl
const* current_layer
= this;
1181 current_layer
!= scroll_clip_layer_
;
1182 current_layer
= current_layer
->parent()) {
1183 DCHECK(current_layer
);
1184 float current_layer_scale
= 1.f
;
1186 const gfx::Transform
& layer_transform
= current_layer
->transform();
1187 if (current_layer
== page_scale_layer
) {
1188 DCHECK(layer_transform
.IsIdentity());
1189 current_layer_scale
= layer_tree_impl()->total_page_scale_factor();
1191 // TODO(wjmaclean) Should we allow for translation too?
1192 DCHECK(layer_transform
.IsScale2d());
1193 gfx::Vector2dF layer_scale
= layer_transform
.Scale2d();
1194 // TODO(wjmaclean) Allow for non-isotropic scales.
1195 DCHECK(layer_scale
.x() == layer_scale
.y());
1196 current_layer_scale
= layer_scale
.x();
1199 scale_factor
*= current_layer_scale
;
1201 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1202 // turned on in all builds, remove the next two lines. For now however, the
1203 // page scale layer may coincide with the clip layer, and so this is
1205 if (page_scale_layer
== scroll_clip_layer_
)
1206 scale_factor
*= layer_tree_impl()->total_page_scale_factor();
1208 scaled_scroll_bounds
.SetSize(scale_factor
* scaled_scroll_bounds
.width(),
1209 scale_factor
* scaled_scroll_bounds
.height());
1210 scaled_scroll_bounds
= gfx::ToFlooredSize(scaled_scroll_bounds
);
1212 gfx::Vector2dF
max_offset(
1213 scaled_scroll_bounds
.width() - scroll_clip_layer_
->bounds().width(),
1214 scaled_scroll_bounds
.height() - scroll_clip_layer_
->bounds().height());
1215 // We need the final scroll offset to be in CSS coords.
1216 max_offset
.Scale(1 / scale_factor
);
1217 max_offset
.SetToMax(gfx::Vector2dF());
1218 return gfx::ToFlooredVector2d(max_offset
);
1221 gfx::Vector2dF
LayerImpl::ClampScrollToMaxScrollOffset() {
1222 gfx::Vector2dF max_offset
= MaxScrollOffset();
1223 gfx::Vector2dF old_offset
= TotalScrollOffset();
1224 gfx::Vector2dF clamped_offset
= old_offset
;
1226 clamped_offset
.SetToMin(max_offset
);
1227 clamped_offset
.SetToMax(gfx::Vector2d());
1228 gfx::Vector2dF delta
= clamped_offset
- old_offset
;
1229 if (!delta
.IsZero())
1235 void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase
* scrollbar_layer
,
1236 LayerImpl
* scrollbar_clip_layer
) const {
1237 DCHECK(scrollbar_layer
);
1238 LayerImpl
* page_scale_layer
= layer_tree_impl()->page_scale_layer();
1240 DCHECK(this != page_scale_layer
);
1241 DCHECK(scrollbar_clip_layer
);
1242 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1243 IsContainerForFixedPositionLayers());
1244 gfx::RectF
clip_rect(gfx::PointF(), scrollbar_clip_layer
->bounds());
1246 // See comment in MaxScrollOffset() regarding the use of the content layer
1248 gfx::RectF
scroll_rect(gfx::PointF(), bounds());
1250 if (scroll_rect
.size().IsEmpty())
1253 // TODO(wjmaclean) This computation is nearly identical to the one in
1254 // MaxScrollOffset. Find some way to combine these.
1255 gfx::Vector2dF current_offset
;
1256 for (LayerImpl
const* current_layer
= this;
1257 current_layer
!= scrollbar_clip_layer
;
1258 current_layer
= current_layer
->parent()) {
1259 DCHECK(current_layer
);
1260 const gfx::Transform
& layer_transform
= current_layer
->transform();
1261 if (current_layer
== page_scale_layer
) {
1262 DCHECK(layer_transform
.IsIdentity());
1263 float scale_factor
= layer_tree_impl()->total_page_scale_factor();
1264 current_offset
.Scale(scale_factor
);
1265 scroll_rect
.Scale(scale_factor
);
1267 DCHECK(layer_transform
.IsScale2d());
1268 gfx::Vector2dF layer_scale
= layer_transform
.Scale2d();
1269 DCHECK(layer_scale
.x() == layer_scale
.y());
1270 gfx::Vector2dF new_offset
=
1271 current_layer
->scroll_offset() + current_layer
->ScrollDelta();
1272 new_offset
.Scale(layer_scale
.x(), layer_scale
.y());
1273 current_offset
+= new_offset
;
1276 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1277 // turned on in all builds, remove the next two lines. For now however, the
1278 // page scale layer may coincide with the clip layer, and so this is
1280 if (page_scale_layer
== scrollbar_clip_layer
) {
1281 scroll_rect
.Scale(layer_tree_impl()->total_page_scale_factor());
1282 current_offset
.Scale(layer_tree_impl()->total_page_scale_factor());
1285 scrollbar_layer
->SetVerticalAdjust(
1286 layer_tree_impl()->VerticalAdjust(scrollbar_clip_layer
->id()));
1287 if (scrollbar_layer
->orientation() == HORIZONTAL
) {
1288 float visible_ratio
= clip_rect
.width() / scroll_rect
.width();
1289 scrollbar_layer
->SetCurrentPos(current_offset
.x());
1290 scrollbar_layer
->SetMaximum(scroll_rect
.width() - clip_rect
.width());
1291 scrollbar_layer
->SetVisibleToTotalLengthRatio(visible_ratio
);
1293 float visible_ratio
= clip_rect
.height() / scroll_rect
.height();
1294 scrollbar_layer
->SetCurrentPos(current_offset
.y());
1295 scrollbar_layer
->SetMaximum(scroll_rect
.height() - clip_rect
.height());
1296 scrollbar_layer
->SetVisibleToTotalLengthRatio(visible_ratio
);
1299 layer_tree_impl()->set_needs_update_draw_properties();
1300 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should
1301 // activate for every scroll on the main frame, not just the scrolls that move
1302 // the pinch virtual viewport (i.e. trigger from either inner or outer
1304 if (scrollbar_animation_controller_
) {
1305 // When both non-overlay and overlay scrollbars are both present, don't
1306 // animate the overlay scrollbars when page scale factor is at the min.
1307 // Non-overlay scrollbars also shouldn't trigger animations.
1308 bool is_animatable_scrollbar
=
1309 scrollbar_layer
->is_overlay_scrollbar() &&
1310 ((layer_tree_impl()->total_page_scale_factor() >
1311 layer_tree_impl()->min_page_scale_factor()) ||
1312 !layer_tree_impl()->settings().use_pinch_zoom_scrollbars
);
1313 // Note that DidScrollUpdate() has the side-effect of setting the
1314 // scrollbar's opacity to 1.0 even if the function returns false, so
1315 // evaluate it last in the boolean expression.
1316 bool should_animate
= is_animatable_scrollbar
&&
1317 scrollbar_animation_controller_
->DidScrollUpdate(
1318 layer_tree_impl_
->CurrentFrameTimeTicks());
1320 layer_tree_impl_
->StartScrollbarAnimation();
1324 void LayerImpl::DidBecomeActive() {
1325 if (layer_tree_impl_
->settings().scrollbar_animator
==
1326 LayerTreeSettings::NoAnimator
) {
1330 bool need_scrollbar_animation_controller
= scrollable() && scrollbars_
;
1331 if (!need_scrollbar_animation_controller
) {
1332 scrollbar_animation_controller_
.reset();
1336 if (scrollbar_animation_controller_
)
1339 switch (layer_tree_impl_
->settings().scrollbar_animator
) {
1340 case LayerTreeSettings::LinearFade
: {
1341 base::TimeDelta fadeout_delay
= base::TimeDelta::FromMilliseconds(
1342 layer_tree_impl_
->settings().scrollbar_linear_fade_delay_ms
);
1343 base::TimeDelta fadeout_length
= base::TimeDelta::FromMilliseconds(
1344 layer_tree_impl_
->settings().scrollbar_linear_fade_length_ms
);
1346 scrollbar_animation_controller_
=
1347 ScrollbarAnimationControllerLinearFade::Create(
1348 this, fadeout_delay
, fadeout_length
)
1349 .PassAs
<ScrollbarAnimationController
>();
1352 case LayerTreeSettings::Thinning
: {
1353 scrollbar_animation_controller_
=
1354 ScrollbarAnimationControllerThinning::Create(this)
1355 .PassAs
<ScrollbarAnimationController
>();
1358 case LayerTreeSettings::NoAnimator
:
1364 void LayerImpl::ClearScrollbars() {
1368 scrollbars_
.reset(NULL
);
1371 void LayerImpl::AddScrollbar(ScrollbarLayerImplBase
* layer
) {
1373 DCHECK(!scrollbars_
|| scrollbars_
->find(layer
) == scrollbars_
->end());
1375 scrollbars_
.reset(new ScrollbarSet());
1377 scrollbars_
->insert(layer
);
1380 void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase
* layer
) {
1381 DCHECK(scrollbars_
);
1383 DCHECK(scrollbars_
->find(layer
) != scrollbars_
->end());
1385 scrollbars_
->erase(layer
);
1386 if (scrollbars_
->empty())
1387 scrollbars_
.reset();
1390 bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation
) const {
1394 for (ScrollbarSet::iterator it
= scrollbars_
->begin();
1395 it
!= scrollbars_
->end();
1397 if ((*it
)->orientation() == orientation
)
1403 void LayerImpl::ScrollbarParametersDidChange() {
1407 for (ScrollbarSet::iterator it
= scrollbars_
->begin();
1408 it
!= scrollbars_
->end();
1410 (*it
)->ScrollbarParametersDidChange();
1413 void LayerImpl::SetNeedsPushProperties() {
1414 if (needs_push_properties_
)
1416 if (!parent_should_know_need_push_properties() && parent_
)
1417 parent_
->AddDependentNeedsPushProperties();
1418 needs_push_properties_
= true;
1421 void LayerImpl::AddDependentNeedsPushProperties() {
1422 DCHECK_GE(num_dependents_need_push_properties_
, 0);
1424 if (!parent_should_know_need_push_properties() && parent_
)
1425 parent_
->AddDependentNeedsPushProperties();
1427 num_dependents_need_push_properties_
++;
1430 void LayerImpl::RemoveDependentNeedsPushProperties() {
1431 num_dependents_need_push_properties_
--;
1432 DCHECK_GE(num_dependents_need_push_properties_
, 0);
1434 if (!parent_should_know_need_push_properties() && parent_
)
1435 parent_
->RemoveDependentNeedsPushProperties();
1438 void LayerImpl::AsValueInto(base::DictionaryValue
* state
) const {
1439 TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
1440 TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1443 LayerTypeAsString(),
1445 state
->SetInteger("layer_id", id());
1446 state
->Set("bounds", MathUtil::AsValue(bounds_
).release());
1447 state
->Set("position", MathUtil::AsValue(position_
).release());
1448 state
->SetInteger("draws_content", DrawsContent());
1449 state
->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1450 state
->Set("scroll_offset", MathUtil::AsValue(scroll_offset_
).release());
1453 gfx::QuadF layer_quad
= MathUtil::MapQuad(
1454 screen_space_transform(),
1455 gfx::QuadF(gfx::Rect(content_bounds())),
1457 state
->Set("layer_quad", MathUtil::AsValue(layer_quad
).release());
1459 if (!touch_event_handler_region_
.IsEmpty()) {
1460 state
->Set("touch_event_handler_region",
1461 touch_event_handler_region_
.AsValue().release());
1463 if (have_wheel_event_handlers_
) {
1464 gfx::Rect
wheel_rect(content_bounds());
1465 Region
wheel_region(wheel_rect
);
1466 state
->Set("wheel_event_handler_region",
1467 wheel_region
.AsValue().release());
1469 if (have_scroll_event_handlers_
) {
1470 gfx::Rect
scroll_rect(content_bounds());
1471 Region
scroll_region(scroll_rect
);
1472 state
->Set("scroll_event_handler_region",
1473 scroll_region
.AsValue().release());
1475 if (!non_fast_scrollable_region_
.IsEmpty()) {
1476 state
->Set("non_fast_scrollable_region",
1477 non_fast_scrollable_region_
.AsValue().release());
1480 scoped_ptr
<base::ListValue
> children_list(new base::ListValue());
1481 for (size_t i
= 0; i
< children_
.size(); ++i
)
1482 children_list
->Append(children_
[i
]->AsValue().release());
1483 state
->Set("children", children_list
.release());
1485 state
->Set("mask_layer", mask_layer_
->AsValue().release());
1487 state
->Set("replica_layer", replica_layer_
->AsValue().release());
1490 state
->SetInteger("scroll_parent", scroll_parent_
->id());
1493 state
->SetInteger("clip_parent", clip_parent_
->id());
1495 state
->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1496 state
->SetBoolean("contents_opaque", contents_opaque());
1499 "has_animation_bounds",
1500 layer_animation_controller()->HasAnimationThatInflatesBounds());
1503 if (LayerUtils::GetAnimationBounds(*this, &box
))
1504 state
->Set("animation_bounds", MathUtil::AsValue(box
).release());
1506 if (debug_info_
.get()) {
1508 debug_info_
->AppendAsTraceFormat(&str
);
1509 base::JSONReader json_reader
;
1510 scoped_ptr
<base::Value
> debug_info_value(json_reader
.ReadToValue(str
));
1512 if (debug_info_value
->IsType(base::Value::TYPE_DICTIONARY
)) {
1513 base::DictionaryValue
* dictionary_value
= NULL
;
1514 bool converted_to_dictionary
=
1515 debug_info_value
->GetAsDictionary(&dictionary_value
);
1516 DCHECK(converted_to_dictionary
);
1517 state
->MergeDictionary(dictionary_value
);
1524 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1526 scoped_ptr
<base::Value
> LayerImpl::AsValue() const {
1527 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1528 AsValueInto(state
.get());
1529 return state
.PassAs
<base::Value
>();
1532 void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl
* benchmark
) {
1533 benchmark
->RunOnLayer(this);