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/base/math_util.h"
13 #include "cc/debug/debug_colors.h"
14 #include "cc/debug/layer_tree_debug_state.h"
15 #include "cc/debug/micro_benchmark_impl.h"
16 #include "cc/debug/traced_value.h"
17 #include "cc/input/layer_scroll_offset_delegate.h"
18 #include "cc/layers/layer_utils.h"
19 #include "cc/layers/painted_scrollbar_layer_impl.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/quads/debug_border_draw_quad.h"
22 #include "cc/trees/layer_tree_host_common.h"
23 #include "cc/trees/layer_tree_impl.h"
24 #include "cc/trees/layer_tree_settings.h"
25 #include "cc/trees/proxy.h"
26 #include "ui/gfx/box_f.h"
27 #include "ui/gfx/geometry/vector2d_conversions.h"
28 #include "ui/gfx/point_conversions.h"
29 #include "ui/gfx/quad_f.h"
30 #include "ui/gfx/rect_conversions.h"
31 #include "ui/gfx/size_conversions.h"
34 LayerImpl::LayerImpl(LayerTreeImpl
* tree_impl
, int id
)
39 replica_layer_id_(-1),
41 layer_tree_impl_(tree_impl
),
42 scroll_offset_delegate_(NULL
),
43 scroll_clip_layer_(NULL
),
44 should_scroll_on_main_thread_(false),
45 have_wheel_event_handlers_(false),
46 have_scroll_event_handlers_(false),
47 user_scrollable_horizontal_(true),
48 user_scrollable_vertical_(true),
49 stacking_order_changed_(false),
51 should_flatten_transform_(true),
52 layer_property_changed_(false),
53 masks_to_bounds_(false),
54 contents_opaque_(false),
55 is_root_for_isolated_group_(false),
56 use_parent_backface_visibility_(false),
57 draw_checkerboard_for_missing_tiles_(false),
58 draws_content_(false),
59 hide_layer_and_subtree_(false),
60 force_render_surface_(false),
61 transform_is_invertible_(true),
62 is_container_for_fixed_position_layers_(false),
65 blend_mode_(SkXfermode::kSrcOver_Mode
),
67 needs_push_properties_(false),
68 num_dependents_need_push_properties_(0),
69 sorting_context_id_(0),
70 current_draw_mode_(DRAW_MODE_NONE
) {
71 DCHECK_GT(layer_id_
, 0);
72 DCHECK(layer_tree_impl_
);
73 layer_tree_impl_
->RegisterLayer(this);
74 AnimationRegistrar
* registrar
= layer_tree_impl_
->animationRegistrar();
75 layer_animation_controller_
=
76 registrar
->GetAnimationControllerForId(layer_id_
);
77 layer_animation_controller_
->AddValueObserver(this);
79 layer_animation_controller_
->set_value_provider(this);
80 layer_animation_controller_
->set_layer_animation_delegate(this);
82 SetNeedsPushProperties();
85 LayerImpl::~LayerImpl() {
86 DCHECK_EQ(DRAW_MODE_NONE
, current_draw_mode_
);
88 layer_animation_controller_
->RemoveValueObserver(this);
89 layer_animation_controller_
->remove_value_provider(this);
90 layer_animation_controller_
->remove_layer_animation_delegate(this);
92 if (!copy_requests_
.empty() && layer_tree_impl_
->IsActiveTree())
93 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
94 layer_tree_impl_
->UnregisterLayer(this);
96 TRACE_EVENT_OBJECT_DELETED_WITH_ID(
97 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerImpl", this);
100 void LayerImpl::AddChild(scoped_ptr
<LayerImpl
> child
) {
101 child
->SetParent(this);
102 DCHECK_EQ(layer_tree_impl(), child
->layer_tree_impl());
103 children_
.push_back(child
.Pass());
104 layer_tree_impl()->set_needs_update_draw_properties();
107 scoped_ptr
<LayerImpl
> LayerImpl::RemoveChild(LayerImpl
* child
) {
108 for (OwnedLayerImplList::iterator it
= children_
.begin();
109 it
!= children_
.end();
112 scoped_ptr
<LayerImpl
> ret
= children_
.take(it
);
114 layer_tree_impl()->set_needs_update_draw_properties();
118 return scoped_ptr
<LayerImpl
>();
121 void LayerImpl::SetParent(LayerImpl
* parent
) {
122 if (parent_should_know_need_push_properties()) {
124 parent_
->RemoveDependentNeedsPushProperties();
126 parent
->AddDependentNeedsPushProperties();
131 void LayerImpl::ClearChildList() {
132 if (children_
.empty())
136 layer_tree_impl()->set_needs_update_draw_properties();
139 bool LayerImpl::HasAncestor(const LayerImpl
* ancestor
) const {
143 for (const LayerImpl
* layer
= this; layer
; layer
= layer
->parent()) {
144 if (layer
== ancestor
)
151 void LayerImpl::SetScrollParent(LayerImpl
* parent
) {
152 if (scroll_parent_
== parent
)
155 // Having both a scroll parent and a scroll offset delegate is unsupported.
156 DCHECK(!scroll_offset_delegate_
);
159 DCHECK_EQ(layer_tree_impl()->LayerById(parent
->id()), parent
);
161 scroll_parent_
= parent
;
162 SetNeedsPushProperties();
165 void LayerImpl::SetDebugInfo(
166 scoped_refptr
<base::debug::ConvertableToTraceFormat
> other
) {
168 SetNeedsPushProperties();
171 void LayerImpl::SetScrollChildren(std::set
<LayerImpl
*>* children
) {
172 if (scroll_children_
.get() == children
)
174 scroll_children_
.reset(children
);
175 SetNeedsPushProperties();
178 void LayerImpl::SetClipParent(LayerImpl
* ancestor
) {
179 if (clip_parent_
== ancestor
)
182 clip_parent_
= ancestor
;
183 SetNeedsPushProperties();
186 void LayerImpl::SetClipChildren(std::set
<LayerImpl
*>* children
) {
187 if (clip_children_
.get() == children
)
189 clip_children_
.reset(children
);
190 SetNeedsPushProperties();
193 void LayerImpl::PassCopyRequests(ScopedPtrVector
<CopyOutputRequest
>* requests
) {
194 if (requests
->empty())
197 bool was_empty
= copy_requests_
.empty();
198 copy_requests_
.insert_and_take(copy_requests_
.end(), *requests
);
201 if (was_empty
&& layer_tree_impl()->IsActiveTree())
202 layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
203 NoteLayerPropertyChangedForSubtree();
206 void LayerImpl::TakeCopyRequestsAndTransformToTarget(
207 ScopedPtrVector
<CopyOutputRequest
>* requests
) {
208 DCHECK(!copy_requests_
.empty());
209 DCHECK(layer_tree_impl()->IsActiveTree());
211 size_t first_inserted_request
= requests
->size();
212 requests
->insert_and_take(requests
->end(), copy_requests_
);
213 copy_requests_
.clear();
215 for (size_t i
= first_inserted_request
; i
< requests
->size(); ++i
) {
216 CopyOutputRequest
* request
= requests
->at(i
);
217 if (!request
->has_area())
220 gfx::Rect request_in_layer_space
= request
->area();
221 gfx::Rect request_in_content_space
=
222 LayerRectToContentRect(request_in_layer_space
);
223 request
->set_area(MathUtil::MapEnclosingClippedRect(
224 draw_properties_
.target_space_transform
, request_in_content_space
));
227 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
230 void LayerImpl::CreateRenderSurface() {
231 DCHECK(!draw_properties_
.render_surface
);
232 draw_properties_
.render_surface
=
233 make_scoped_ptr(new RenderSurfaceImpl(this));
234 draw_properties_
.render_target
= this;
237 void LayerImpl::ClearRenderSurface() {
238 draw_properties_
.render_surface
.reset();
241 void LayerImpl::ClearRenderSurfaceLayerList() {
242 if (draw_properties_
.render_surface
)
243 draw_properties_
.render_surface
->layer_list().clear();
246 void LayerImpl::PopulateSharedQuadState(SharedQuadState
* state
) const {
247 state
->SetAll(draw_properties_
.target_space_transform
,
248 draw_properties_
.content_bounds
,
249 draw_properties_
.visible_content_rect
,
250 draw_properties_
.clip_rect
,
251 draw_properties_
.is_clipped
,
252 draw_properties_
.opacity
,
254 sorting_context_id_
);
257 bool LayerImpl::WillDraw(DrawMode draw_mode
,
258 ResourceProvider
* resource_provider
) {
259 // WillDraw/DidDraw must be matched.
260 DCHECK_NE(DRAW_MODE_NONE
, draw_mode
);
261 DCHECK_EQ(DRAW_MODE_NONE
, current_draw_mode_
);
262 current_draw_mode_
= draw_mode
;
266 void LayerImpl::DidDraw(ResourceProvider
* resource_provider
) {
267 DCHECK_NE(DRAW_MODE_NONE
, current_draw_mode_
);
268 current_draw_mode_
= DRAW_MODE_NONE
;
271 bool LayerImpl::ShowDebugBorders() const {
272 return layer_tree_impl()->debug_state().show_debug_borders
;
275 void LayerImpl::GetDebugBorderProperties(SkColor
* color
, float* width
) const {
276 if (draws_content_
) {
277 *color
= DebugColors::ContentLayerBorderColor();
278 *width
= DebugColors::ContentLayerBorderWidth(layer_tree_impl());
282 if (masks_to_bounds_
) {
283 *color
= DebugColors::MaskingLayerBorderColor();
284 *width
= DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
288 *color
= DebugColors::ContainerLayerBorderColor();
289 *width
= DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
292 void LayerImpl::AppendDebugBorderQuad(
293 RenderPass
* render_pass
,
294 const gfx::Size
& content_bounds
,
295 const SharedQuadState
* shared_quad_state
,
296 AppendQuadsData
* append_quads_data
) const {
299 GetDebugBorderProperties(&color
, &width
);
300 AppendDebugBorderQuad(render_pass
,
308 void LayerImpl::AppendDebugBorderQuad(RenderPass
* render_pass
,
309 const gfx::Size
& content_bounds
,
310 const SharedQuadState
* shared_quad_state
,
311 AppendQuadsData
* append_quads_data
,
314 if (!ShowDebugBorders())
317 gfx::Rect
quad_rect(content_bounds
);
318 gfx::Rect
visible_quad_rect(quad_rect
);
319 DebugBorderDrawQuad
* debug_border_quad
=
320 render_pass
->CreateAndAppendDrawQuad
<DebugBorderDrawQuad
>();
321 debug_border_quad
->SetNew(
322 shared_quad_state
, quad_rect
, visible_quad_rect
, color
, width
);
325 bool LayerImpl::HasDelegatedContent() const {
329 bool LayerImpl::HasContributingDelegatedRenderPasses() const {
333 RenderPass::Id
LayerImpl::FirstContributingRenderPassId() const {
334 return RenderPass::Id(0, 0);
337 RenderPass::Id
LayerImpl::NextContributingRenderPassId(RenderPass::Id id
)
339 return RenderPass::Id(0, 0);
342 ResourceProvider::ResourceId
LayerImpl::ContentsResourceId() const {
347 void LayerImpl::SetSentScrollDelta(const gfx::Vector2d
& sent_scroll_delta
) {
348 // Pending tree never has sent scroll deltas
349 DCHECK(layer_tree_impl()->IsActiveTree());
351 if (sent_scroll_delta_
== sent_scroll_delta
)
354 sent_scroll_delta_
= sent_scroll_delta
;
357 gfx::Vector2dF
LayerImpl::ScrollBy(const gfx::Vector2dF
& scroll
) {
358 DCHECK(scrollable());
359 gfx::Vector2dF min_delta
= -scroll_offset_
;
360 gfx::Vector2dF max_delta
= MaxScrollOffset() - scroll_offset_
;
361 // Clamp new_delta so that position + delta stays within scroll bounds.
362 gfx::Vector2dF new_delta
= (ScrollDelta() + scroll
);
363 new_delta
.SetToMax(min_delta
);
364 new_delta
.SetToMin(max_delta
);
365 gfx::Vector2dF unscrolled
=
366 ScrollDelta() + scroll
- new_delta
;
367 SetScrollDelta(new_delta
);
372 void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id
) {
373 scroll_clip_layer_
= layer_tree_impl()->LayerById(scroll_clip_layer_id
);
376 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
377 // Pending tree never has sent scroll deltas
378 DCHECK(layer_tree_impl()->IsActiveTree());
380 // Apply sent scroll deltas to scroll position / scroll delta as if the
381 // main thread had applied them and then committed those values.
383 // This function should not change the total scroll offset; it just shifts
384 // some of the scroll delta to the scroll offset. Therefore, adjust these
385 // variables directly rather than calling the scroll offset delegate to
386 // avoid sending it multiple spurious calls.
388 // Because of the way scroll delta is calculated with a delegate, this will
389 // leave the total scroll offset unchanged on this layer regardless of
390 // whether a delegate is being used.
391 scroll_offset_
+= sent_scroll_delta_
;
392 scroll_delta_
-= sent_scroll_delta_
;
393 sent_scroll_delta_
= gfx::Vector2d();
396 void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
397 // Only the pending tree can have missing scrolls.
398 DCHECK(layer_tree_impl()->IsPendingTree());
402 // Pending tree should never have sent scroll deltas.
403 DCHECK(sent_scroll_delta().IsZero());
405 LayerImpl
* active_twin
= layer_tree_impl()->FindActiveTreeLayerById(id());
407 // Scrolls that happens after begin frame (where the sent scroll delta
408 // comes from) and commit need to be applied to the pending tree
409 // so that it is up to date with the total scroll.
410 SetScrollDelta(active_twin
->ScrollDelta() -
411 active_twin
->sent_scroll_delta());
415 InputHandler::ScrollStatus
LayerImpl::TryScroll(
416 const gfx::PointF
& screen_space_point
,
417 InputHandler::ScrollInputType type
) const {
418 if (should_scroll_on_main_thread()) {
419 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
420 return InputHandler::ScrollOnMainThread
;
423 if (!screen_space_transform().IsInvertible()) {
424 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
425 return InputHandler::ScrollIgnored
;
428 if (!non_fast_scrollable_region().IsEmpty()) {
429 bool clipped
= false;
430 gfx::Transform
inverse_screen_space_transform(
431 gfx::Transform::kSkipInitialization
);
432 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform
)) {
433 // TODO(shawnsingh): We shouldn't be applying a projection if screen space
434 // transform is uninvertible here. Perhaps we should be returning
435 // ScrollOnMainThread in this case?
438 gfx::PointF hit_test_point_in_content_space
=
439 MathUtil::ProjectPoint(inverse_screen_space_transform
,
442 gfx::PointF hit_test_point_in_layer_space
=
443 gfx::ScalePoint(hit_test_point_in_content_space
,
444 1.f
/ contents_scale_x(),
445 1.f
/ contents_scale_y());
447 non_fast_scrollable_region().Contains(
448 gfx::ToRoundedPoint(hit_test_point_in_layer_space
))) {
450 "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
451 return InputHandler::ScrollOnMainThread
;
455 if (type
== InputHandler::Wheel
&& have_wheel_event_handlers()) {
456 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
457 return InputHandler::ScrollOnMainThread
;
461 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
462 return InputHandler::ScrollIgnored
;
465 gfx::Vector2d max_scroll_offset
= MaxScrollOffset();
466 if (max_scroll_offset
.x() <= 0 && max_scroll_offset
.y() <= 0) {
468 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
469 " but has no affordance in either direction.");
470 return InputHandler::ScrollIgnored
;
473 return InputHandler::ScrollStarted
;
476 gfx::Rect
LayerImpl::LayerRectToContentRect(
477 const gfx::RectF
& layer_rect
) const {
478 gfx::RectF content_rect
=
479 gfx::ScaleRect(layer_rect
, contents_scale_x(), contents_scale_y());
480 // Intersect with content rect to avoid the extra pixel because for some
481 // values x and y, ceil((x / y) * y) may be x + 1.
482 content_rect
.Intersect(gfx::Rect(content_bounds()));
483 return gfx::ToEnclosingRect(content_rect
);
486 skia::RefPtr
<SkPicture
> LayerImpl::GetPicture() {
487 return skia::RefPtr
<SkPicture
>();
490 scoped_ptr
<LayerImpl
> LayerImpl::CreateLayerImpl(LayerTreeImpl
* tree_impl
) {
491 return LayerImpl::Create(tree_impl
, layer_id_
);
494 void LayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
495 layer
->SetTransformOrigin(transform_origin_
);
496 layer
->SetBackgroundColor(background_color_
);
497 layer
->SetBounds(bounds_
);
498 layer
->SetContentBounds(content_bounds());
499 layer
->SetContentsScale(contents_scale_x(), contents_scale_y());
500 layer
->SetDoubleSided(double_sided_
);
501 layer
->SetDrawCheckerboardForMissingTiles(
502 draw_checkerboard_for_missing_tiles_
);
503 layer
->SetForceRenderSurface(force_render_surface_
);
504 layer
->SetDrawsContent(DrawsContent());
505 layer
->SetHideLayerAndSubtree(hide_layer_and_subtree_
);
506 layer
->SetFilters(filters());
507 layer
->SetBackgroundFilters(background_filters());
508 layer
->SetMasksToBounds(masks_to_bounds_
);
509 layer
->SetShouldScrollOnMainThread(should_scroll_on_main_thread_
);
510 layer
->SetHaveWheelEventHandlers(have_wheel_event_handlers_
);
511 layer
->SetHaveScrollEventHandlers(have_scroll_event_handlers_
);
512 layer
->SetNonFastScrollableRegion(non_fast_scrollable_region_
);
513 layer
->SetTouchEventHandlerRegion(touch_event_handler_region_
);
514 layer
->SetContentsOpaque(contents_opaque_
);
515 layer
->SetOpacity(opacity_
);
516 layer
->SetBlendMode(blend_mode_
);
517 layer
->SetIsRootForIsolatedGroup(is_root_for_isolated_group_
);
518 layer
->SetPosition(position_
);
519 layer
->SetIsContainerForFixedPositionLayers(
520 is_container_for_fixed_position_layers_
);
521 layer
->SetPositionConstraint(position_constraint_
);
522 layer
->SetShouldFlattenTransform(should_flatten_transform_
);
523 layer
->SetUseParentBackfaceVisibility(use_parent_backface_visibility_
);
524 layer
->SetTransformAndInvertibility(transform_
, transform_is_invertible_
);
526 layer
->SetScrollClipLayer(scroll_clip_layer_
? scroll_clip_layer_
->id()
527 : Layer::INVALID_ID
);
528 layer
->set_user_scrollable_horizontal(user_scrollable_horizontal_
);
529 layer
->set_user_scrollable_vertical(user_scrollable_vertical_
);
530 layer
->SetScrollOffsetAndDelta(
531 scroll_offset_
, layer
->ScrollDelta() - layer
->sent_scroll_delta());
532 layer
->SetSentScrollDelta(gfx::Vector2d());
533 layer
->Set3dSortingContextId(sorting_context_id_
);
535 LayerImpl
* scroll_parent
= NULL
;
536 if (scroll_parent_
) {
537 scroll_parent
= layer
->layer_tree_impl()->LayerById(scroll_parent_
->id());
538 DCHECK(scroll_parent
);
541 layer
->SetScrollParent(scroll_parent
);
542 if (scroll_children_
) {
543 std::set
<LayerImpl
*>* scroll_children
= new std::set
<LayerImpl
*>;
544 for (std::set
<LayerImpl
*>::iterator it
= scroll_children_
->begin();
545 it
!= scroll_children_
->end();
547 DCHECK_EQ((*it
)->scroll_parent(), this);
548 LayerImpl
* scroll_child
=
549 layer
->layer_tree_impl()->LayerById((*it
)->id());
550 DCHECK(scroll_child
);
551 scroll_children
->insert(scroll_child
);
553 layer
->SetScrollChildren(scroll_children
);
555 layer
->SetScrollChildren(NULL
);
558 LayerImpl
* clip_parent
= NULL
;
560 clip_parent
= layer
->layer_tree_impl()->LayerById(
565 layer
->SetClipParent(clip_parent
);
566 if (clip_children_
) {
567 std::set
<LayerImpl
*>* clip_children
= new std::set
<LayerImpl
*>;
568 for (std::set
<LayerImpl
*>::iterator it
= clip_children_
->begin();
569 it
!= clip_children_
->end(); ++it
)
570 clip_children
->insert(layer
->layer_tree_impl()->LayerById((*it
)->id()));
571 layer
->SetClipChildren(clip_children
);
573 layer
->SetClipChildren(NULL
);
576 layer
->PassCopyRequests(©_requests_
);
578 // If the main thread commits multiple times before the impl thread actually
579 // draws, then damage tracking will become incorrect if we simply clobber the
580 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
581 // union) any update changes that have occurred on the main thread.
582 update_rect_
.Union(layer
->update_rect());
583 layer
->SetUpdateRect(update_rect_
);
585 layer
->SetStackingOrderChanged(stacking_order_changed_
);
586 layer
->SetDebugInfo(debug_info_
);
588 // Reset any state that should be cleared for the next update.
589 stacking_order_changed_
= false;
590 update_rect_
= gfx::RectF();
591 needs_push_properties_
= false;
592 num_dependents_need_push_properties_
= 0;
595 gfx::Vector2dF
LayerImpl::FixedContainerSizeDelta() const {
596 if (!scroll_clip_layer_
)
597 return gfx::Vector2dF();
599 float scale_delta
= layer_tree_impl()->page_scale_delta();
600 float scale
= layer_tree_impl()->page_scale_factor();
602 gfx::Vector2dF delta_from_scroll
= scroll_clip_layer_
->BoundsDelta();
603 delta_from_scroll
.Scale(1.f
/ scale
);
605 // The delta-from-pinch component requires some explanation: A viewport of
606 // size (w,h) will appear to be size (w/s,h/s) under scale s in the content
607 // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent
608 // viewport size change in the content space due to ds is:
610 // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds)
612 gfx::Vector2dF delta_from_pinch
=
613 gfx::Rect(scroll_clip_layer_
->bounds()).bottom_right() - gfx::PointF();
614 delta_from_pinch
.Scale((1.f
- scale_delta
) / (scale
* scale_delta
));
616 return delta_from_scroll
+ delta_from_pinch
;
619 base::DictionaryValue
* LayerImpl::LayerTreeAsJson() const {
620 base::DictionaryValue
* result
= new base::DictionaryValue
;
621 result
->SetString("LayerType", LayerTypeAsString());
623 base::ListValue
* list
= new base::ListValue
;
624 list
->AppendInteger(bounds().width());
625 list
->AppendInteger(bounds().height());
626 result
->Set("Bounds", list
);
628 list
= new base::ListValue
;
629 list
->AppendDouble(position_
.x());
630 list
->AppendDouble(position_
.y());
631 result
->Set("Position", list
);
633 const gfx::Transform
& gfx_transform
= draw_properties_
.target_space_transform
;
634 double transform
[16];
635 gfx_transform
.matrix().asColMajord(transform
);
636 list
= new base::ListValue
;
637 for (int i
= 0; i
< 16; ++i
)
638 list
->AppendDouble(transform
[i
]);
639 result
->Set("DrawTransform", list
);
641 result
->SetBoolean("DrawsContent", draws_content_
);
642 result
->SetBoolean("Is3dSorted", Is3dSorted());
643 result
->SetDouble("Opacity", opacity());
644 result
->SetBoolean("ContentsOpaque", contents_opaque_
);
647 result
->SetBoolean("Scrollable", true);
649 if (have_wheel_event_handlers_
)
650 result
->SetBoolean("WheelHandler", have_wheel_event_handlers_
);
651 if (have_scroll_event_handlers_
)
652 result
->SetBoolean("ScrollHandler", have_scroll_event_handlers_
);
653 if (!touch_event_handler_region_
.IsEmpty()) {
654 scoped_ptr
<base::Value
> region
= touch_event_handler_region_
.AsValue();
655 result
->Set("TouchRegion", region
.release());
658 list
= new base::ListValue
;
659 for (size_t i
= 0; i
< children_
.size(); ++i
)
660 list
->Append(children_
[i
]->LayerTreeAsJson());
661 result
->Set("Children", list
);
666 void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed
) {
667 if (stacking_order_changed
) {
668 stacking_order_changed_
= true;
669 NoteLayerPropertyChangedForSubtree();
673 void LayerImpl::NoteLayerPropertyChanged() {
674 layer_property_changed_
= true;
675 layer_tree_impl()->set_needs_update_draw_properties();
676 SetNeedsPushProperties();
679 void LayerImpl::NoteLayerPropertyChangedForSubtree() {
680 layer_property_changed_
= true;
681 layer_tree_impl()->set_needs_update_draw_properties();
682 for (size_t i
= 0; i
< children_
.size(); ++i
)
683 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
684 SetNeedsPushProperties();
687 void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() {
688 layer_property_changed_
= true;
689 for (size_t i
= 0; i
< children_
.size(); ++i
)
690 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
693 void LayerImpl::NoteLayerPropertyChangedForDescendants() {
694 layer_tree_impl()->set_needs_update_draw_properties();
695 for (size_t i
= 0; i
< children_
.size(); ++i
)
696 children_
[i
]->NoteLayerPropertyChangedForDescendantsInternal();
697 SetNeedsPushProperties();
700 const char* LayerImpl::LayerTypeAsString() const {
701 return "cc::LayerImpl";
704 void LayerImpl::ResetAllChangeTrackingForSubtree() {
705 layer_property_changed_
= false;
707 update_rect_
= gfx::RectF();
708 damage_rect_
= gfx::RectF();
710 if (draw_properties_
.render_surface
)
711 draw_properties_
.render_surface
->ResetPropertyChangedFlag();
714 mask_layer_
->ResetAllChangeTrackingForSubtree();
716 if (replica_layer_
) {
717 // This also resets the replica mask, if it exists.
718 replica_layer_
->ResetAllChangeTrackingForSubtree();
721 for (size_t i
= 0; i
< children_
.size(); ++i
)
722 children_
[i
]->ResetAllChangeTrackingForSubtree();
724 needs_push_properties_
= false;
725 num_dependents_need_push_properties_
= 0;
728 gfx::Vector2dF
LayerImpl::ScrollOffsetForAnimation() const {
729 return TotalScrollOffset();
732 void LayerImpl::OnFilterAnimated(const FilterOperations
& filters
) {
736 void LayerImpl::OnOpacityAnimated(float opacity
) {
740 void LayerImpl::OnTransformAnimated(const gfx::Transform
& transform
) {
741 SetTransform(transform
);
744 void LayerImpl::OnScrollOffsetAnimated(const gfx::Vector2dF
& scroll_offset
) {
745 // Only layers in the active tree should need to do anything here, since
746 // layers in the pending tree will find out about these changes as a
747 // result of the call to SetScrollDelta.
751 SetScrollDelta(scroll_offset
- scroll_offset_
);
753 layer_tree_impl_
->DidAnimateScrollOffset();
756 void LayerImpl::OnAnimationWaitingForDeletion() {}
758 bool LayerImpl::IsActive() const {
759 return layer_tree_impl_
->IsActiveTree();
762 // TODO(wjmaclean) Convert so that bounds returns SizeF.
763 gfx::Size
LayerImpl::bounds() const {
764 return ToFlooredSize(temporary_impl_bounds_
);
767 void LayerImpl::SetBounds(const gfx::Size
& bounds
) {
768 if (bounds_
== bounds
)
772 temporary_impl_bounds_
= bounds
;
774 ScrollbarParametersDidChange();
775 if (masks_to_bounds())
776 NoteLayerPropertyChangedForSubtree();
778 NoteLayerPropertyChanged();
781 void LayerImpl::SetTemporaryImplBounds(const gfx::SizeF
& bounds
) {
782 if (temporary_impl_bounds_
== bounds
)
785 temporary_impl_bounds_
= bounds
;
787 ScrollbarParametersDidChange();
788 if (masks_to_bounds())
789 NoteLayerPropertyChangedForSubtree();
791 NoteLayerPropertyChanged();
794 void LayerImpl::SetMaskLayer(scoped_ptr
<LayerImpl
> mask_layer
) {
795 int new_layer_id
= mask_layer
? mask_layer
->id() : -1;
798 DCHECK_EQ(layer_tree_impl(), mask_layer
->layer_tree_impl());
799 DCHECK_NE(new_layer_id
, mask_layer_id_
);
800 } else if (new_layer_id
== mask_layer_id_
) {
804 mask_layer_
= mask_layer
.Pass();
805 mask_layer_id_
= new_layer_id
;
807 mask_layer_
->SetParent(this);
808 NoteLayerPropertyChangedForSubtree();
811 scoped_ptr
<LayerImpl
> LayerImpl::TakeMaskLayer() {
813 return mask_layer_
.Pass();
816 void LayerImpl::SetReplicaLayer(scoped_ptr
<LayerImpl
> replica_layer
) {
817 int new_layer_id
= replica_layer
? replica_layer
->id() : -1;
820 DCHECK_EQ(layer_tree_impl(), replica_layer
->layer_tree_impl());
821 DCHECK_NE(new_layer_id
, replica_layer_id_
);
822 } else if (new_layer_id
== replica_layer_id_
) {
826 replica_layer_
= replica_layer
.Pass();
827 replica_layer_id_
= new_layer_id
;
829 replica_layer_
->SetParent(this);
830 NoteLayerPropertyChangedForSubtree();
833 scoped_ptr
<LayerImpl
> LayerImpl::TakeReplicaLayer() {
834 replica_layer_id_
= -1;
835 return replica_layer_
.Pass();
838 ScrollbarLayerImplBase
* LayerImpl::ToScrollbarLayer() {
842 void LayerImpl::SetDrawsContent(bool draws_content
) {
843 if (draws_content_
== draws_content
)
846 draws_content_
= draws_content
;
847 NoteLayerPropertyChanged();
850 void LayerImpl::SetHideLayerAndSubtree(bool hide
) {
851 if (hide_layer_and_subtree_
== hide
)
854 hide_layer_and_subtree_
= hide
;
855 NoteLayerPropertyChangedForSubtree();
858 void LayerImpl::SetTransformOrigin(const gfx::Point3F
& transform_origin
) {
859 if (transform_origin_
== transform_origin
)
861 transform_origin_
= transform_origin
;
862 NoteLayerPropertyChangedForSubtree();
865 void LayerImpl::SetBackgroundColor(SkColor background_color
) {
866 if (background_color_
== background_color
)
869 background_color_
= background_color
;
870 NoteLayerPropertyChanged();
873 SkColor
LayerImpl::SafeOpaqueBackgroundColor() const {
874 SkColor color
= background_color();
875 if (SkColorGetA(color
) == 255 && !contents_opaque()) {
876 color
= SK_ColorTRANSPARENT
;
877 } else if (SkColorGetA(color
) != 255 && contents_opaque()) {
878 for (const LayerImpl
* layer
= parent(); layer
;
879 layer
= layer
->parent()) {
880 color
= layer
->background_color();
881 if (SkColorGetA(color
) == 255)
884 if (SkColorGetA(color
) != 255)
885 color
= layer_tree_impl()->background_color();
886 if (SkColorGetA(color
) != 255)
887 color
= SkColorSetA(color
, 255);
892 void LayerImpl::SetFilters(const FilterOperations
& filters
) {
893 if (filters_
== filters
)
897 NoteLayerPropertyChangedForSubtree();
900 bool LayerImpl::FilterIsAnimating() const {
901 return layer_animation_controller_
->IsAnimatingProperty(Animation::Filter
);
904 bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
905 Animation
* filter_animation
=
906 layer_animation_controller_
->GetAnimation(Animation::Filter
);
907 return filter_animation
&& filter_animation
->is_impl_only();
910 void LayerImpl::SetBackgroundFilters(
911 const FilterOperations
& filters
) {
912 if (background_filters_
== filters
)
915 background_filters_
= filters
;
916 NoteLayerPropertyChanged();
919 void LayerImpl::SetMasksToBounds(bool masks_to_bounds
) {
920 if (masks_to_bounds_
== masks_to_bounds
)
923 masks_to_bounds_
= masks_to_bounds
;
924 NoteLayerPropertyChangedForSubtree();
927 void LayerImpl::SetContentsOpaque(bool opaque
) {
928 if (contents_opaque_
== opaque
)
931 contents_opaque_
= opaque
;
932 NoteLayerPropertyChangedForSubtree();
935 void LayerImpl::SetOpacity(float opacity
) {
936 if (opacity_
== opacity
)
940 NoteLayerPropertyChangedForSubtree();
943 bool LayerImpl::OpacityIsAnimating() const {
944 return layer_animation_controller_
->IsAnimatingProperty(Animation::Opacity
);
947 bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
948 Animation
* opacity_animation
=
949 layer_animation_controller_
->GetAnimation(Animation::Opacity
);
950 return opacity_animation
&& opacity_animation
->is_impl_only();
953 void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode
) {
954 if (blend_mode_
== blend_mode
)
957 blend_mode_
= blend_mode
;
958 NoteLayerPropertyChangedForSubtree();
961 void LayerImpl::SetIsRootForIsolatedGroup(bool root
) {
962 if (is_root_for_isolated_group_
== root
)
965 is_root_for_isolated_group_
= root
;
966 SetNeedsPushProperties();
969 void LayerImpl::SetPosition(const gfx::PointF
& position
) {
970 if (position_
== position
)
973 position_
= position
;
974 NoteLayerPropertyChangedForSubtree();
977 void LayerImpl::SetShouldFlattenTransform(bool flatten
) {
978 if (should_flatten_transform_
== flatten
)
981 should_flatten_transform_
= flatten
;
982 NoteLayerPropertyChangedForSubtree();
985 void LayerImpl::Set3dSortingContextId(int id
) {
986 if (id
== sorting_context_id_
)
988 sorting_context_id_
= id
;
989 NoteLayerPropertyChangedForSubtree();
992 void LayerImpl::SetTransform(const gfx::Transform
& transform
) {
993 if (transform_
== transform
)
996 transform_
= transform
;
997 transform_is_invertible_
= transform_
.IsInvertible();
998 NoteLayerPropertyChangedForSubtree();
1001 void LayerImpl::SetTransformAndInvertibility(const gfx::Transform
& transform
,
1002 bool transform_is_invertible
) {
1003 if (transform_
== transform
) {
1004 DCHECK(transform_is_invertible_
== transform_is_invertible
)
1005 << "Can't change invertibility if transform is unchanged";
1008 transform_
= transform
;
1009 transform_is_invertible_
= transform_is_invertible
;
1010 NoteLayerPropertyChangedForSubtree();
1013 bool LayerImpl::TransformIsAnimating() const {
1014 return layer_animation_controller_
->IsAnimatingProperty(Animation::Transform
);
1017 bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
1018 Animation
* transform_animation
=
1019 layer_animation_controller_
->GetAnimation(Animation::Transform
);
1020 return transform_animation
&& transform_animation
->is_impl_only();
1023 void LayerImpl::SetUpdateRect(const gfx::RectF
& update_rect
) {
1024 update_rect_
= update_rect
;
1025 SetNeedsPushProperties();
1028 void LayerImpl::AddDamageRect(const gfx::RectF
& damage_rect
) {
1029 damage_rect_
= gfx::UnionRects(damage_rect_
, damage_rect
);
1032 void LayerImpl::SetContentBounds(const gfx::Size
& content_bounds
) {
1033 if (this->content_bounds() == content_bounds
)
1036 draw_properties_
.content_bounds
= content_bounds
;
1037 NoteLayerPropertyChanged();
1040 void LayerImpl::SetContentsScale(float contents_scale_x
,
1041 float contents_scale_y
) {
1042 if (this->contents_scale_x() == contents_scale_x
&&
1043 this->contents_scale_y() == contents_scale_y
)
1046 draw_properties_
.contents_scale_x
= contents_scale_x
;
1047 draw_properties_
.contents_scale_y
= contents_scale_y
;
1048 NoteLayerPropertyChanged();
1051 void LayerImpl::SetScrollOffsetDelegate(
1052 ScrollOffsetDelegate
* scroll_offset_delegate
) {
1053 // Having both a scroll parent and a scroll offset delegate is unsupported.
1054 DCHECK(!scroll_parent_
);
1055 if (!scroll_offset_delegate
&& scroll_offset_delegate_
) {
1057 scroll_offset_delegate_
->GetTotalScrollOffset() - scroll_offset_
;
1059 gfx::Vector2dF total_offset
= TotalScrollOffset();
1060 scroll_offset_delegate_
= scroll_offset_delegate
;
1061 if (scroll_offset_delegate_
)
1062 scroll_offset_delegate_
->SetTotalScrollOffset(total_offset
);
1065 bool LayerImpl::IsExternalFlingActive() const {
1066 return scroll_offset_delegate_
&&
1067 scroll_offset_delegate_
->IsExternalFlingActive();
1070 void LayerImpl::SetScrollOffset(const gfx::Vector2d
& scroll_offset
) {
1071 SetScrollOffsetAndDelta(scroll_offset
, ScrollDelta());
1074 void LayerImpl::SetScrollOffsetAndDelta(const gfx::Vector2d
& scroll_offset
,
1075 const gfx::Vector2dF
& scroll_delta
) {
1076 bool changed
= false;
1078 last_scroll_offset_
= scroll_offset
;
1080 if (scroll_offset_
!= scroll_offset
) {
1082 scroll_offset_
= scroll_offset
;
1084 if (scroll_offset_delegate_
)
1085 scroll_offset_delegate_
->SetTotalScrollOffset(TotalScrollOffset());
1088 if (ScrollDelta() != scroll_delta
) {
1090 if (layer_tree_impl()->IsActiveTree()) {
1091 LayerImpl
* pending_twin
=
1092 layer_tree_impl()->FindPendingTreeLayerById(id());
1094 // The pending twin can't mirror the scroll delta of the active
1095 // layer. Although the delta - sent scroll delta difference is
1096 // identical for both twins, the sent scroll delta for the pending
1097 // layer is zero, as anything that has been sent has been baked
1098 // into the layer's position/scroll offset as a part of commit.
1099 DCHECK(pending_twin
->sent_scroll_delta().IsZero());
1100 pending_twin
->SetScrollDelta(scroll_delta
- sent_scroll_delta());
1104 if (scroll_offset_delegate_
) {
1105 scroll_offset_delegate_
->SetTotalScrollOffset(scroll_offset_
+
1108 scroll_delta_
= scroll_delta
;
1113 NoteLayerPropertyChangedForSubtree();
1114 ScrollbarParametersDidChange();
1118 gfx::Vector2dF
LayerImpl::ScrollDelta() const {
1119 if (scroll_offset_delegate_
)
1120 return scroll_offset_delegate_
->GetTotalScrollOffset() - scroll_offset_
;
1121 return scroll_delta_
;
1124 void LayerImpl::SetScrollDelta(const gfx::Vector2dF
& scroll_delta
) {
1125 SetScrollOffsetAndDelta(scroll_offset_
, scroll_delta
);
1128 gfx::Vector2dF
LayerImpl::TotalScrollOffset() const {
1129 return scroll_offset_
+ ScrollDelta();
1132 void LayerImpl::SetDoubleSided(bool double_sided
) {
1133 if (double_sided_
== double_sided
)
1136 double_sided_
= double_sided
;
1137 NoteLayerPropertyChangedForSubtree();
1140 Region
LayerImpl::VisibleContentOpaqueRegion() const {
1141 if (contents_opaque())
1142 return visible_content_rect();
1146 void LayerImpl::DidBeginTracing() {}
1148 void LayerImpl::ReleaseResources() {}
1150 gfx::Vector2d
LayerImpl::MaxScrollOffset() const {
1151 if (!scroll_clip_layer_
|| bounds().IsEmpty())
1152 return gfx::Vector2d();
1154 LayerImpl
const* page_scale_layer
= layer_tree_impl()->page_scale_layer();
1155 DCHECK(this != page_scale_layer
);
1156 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1157 IsContainerForFixedPositionLayers());
1159 gfx::SizeF
scaled_scroll_bounds(bounds());
1161 float scale_factor
= 1.f
;
1162 for (LayerImpl
const* current_layer
= this;
1163 current_layer
!= scroll_clip_layer_
;
1164 current_layer
= current_layer
->parent()) {
1165 DCHECK(current_layer
);
1166 float current_layer_scale
= 1.f
;
1168 const gfx::Transform
& layer_transform
= current_layer
->transform();
1169 if (current_layer
== page_scale_layer
) {
1170 DCHECK(layer_transform
.IsIdentity());
1171 current_layer_scale
= layer_tree_impl()->total_page_scale_factor();
1173 // TODO(wjmaclean) Should we allow for translation too?
1174 DCHECK(layer_transform
.IsScale2d());
1175 gfx::Vector2dF layer_scale
= layer_transform
.Scale2d();
1176 // TODO(wjmaclean) Allow for non-isotropic scales.
1177 DCHECK(layer_scale
.x() == layer_scale
.y());
1178 current_layer_scale
= layer_scale
.x();
1181 scale_factor
*= current_layer_scale
;
1183 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1184 // turned on in all builds, remove the next two lines. For now however, the
1185 // page scale layer may coincide with the clip layer, and so this is
1187 if (page_scale_layer
== scroll_clip_layer_
)
1188 scale_factor
*= layer_tree_impl()->total_page_scale_factor();
1190 scaled_scroll_bounds
.SetSize(scale_factor
* scaled_scroll_bounds
.width(),
1191 scale_factor
* scaled_scroll_bounds
.height());
1192 scaled_scroll_bounds
= gfx::ToFlooredSize(scaled_scroll_bounds
);
1194 gfx::Vector2dF
max_offset(
1195 scaled_scroll_bounds
.width() - scroll_clip_layer_
->bounds().width(),
1196 scaled_scroll_bounds
.height() - scroll_clip_layer_
->bounds().height());
1197 // We need the final scroll offset to be in CSS coords.
1198 max_offset
.Scale(1 / scale_factor
);
1199 max_offset
.SetToMax(gfx::Vector2dF());
1200 return gfx::ToFlooredVector2d(max_offset
);
1203 gfx::Vector2dF
LayerImpl::ClampScrollToMaxScrollOffset() {
1204 gfx::Vector2dF max_offset
= MaxScrollOffset();
1205 gfx::Vector2dF old_offset
= TotalScrollOffset();
1206 gfx::Vector2dF clamped_offset
= old_offset
;
1208 clamped_offset
.SetToMin(max_offset
);
1209 clamped_offset
.SetToMax(gfx::Vector2d());
1210 gfx::Vector2dF delta
= clamped_offset
- old_offset
;
1211 if (!delta
.IsZero())
1217 void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase
* scrollbar_layer
,
1218 LayerImpl
* scrollbar_clip_layer
) const {
1219 DCHECK(scrollbar_layer
);
1220 LayerImpl
* page_scale_layer
= layer_tree_impl()->page_scale_layer();
1222 DCHECK(this != page_scale_layer
);
1223 DCHECK(scrollbar_clip_layer
);
1224 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1225 IsContainerForFixedPositionLayers());
1226 gfx::RectF
clip_rect(gfx::PointF(), scrollbar_clip_layer
->bounds());
1228 // See comment in MaxScrollOffset() regarding the use of the content layer
1230 gfx::RectF
scroll_rect(gfx::PointF(), bounds());
1232 if (scroll_rect
.size().IsEmpty())
1235 // TODO(wjmaclean) This computation is nearly identical to the one in
1236 // MaxScrollOffset. Find some way to combine these.
1237 gfx::Vector2dF current_offset
;
1238 for (LayerImpl
const* current_layer
= this;
1239 current_layer
!= scrollbar_clip_layer
;
1240 current_layer
= current_layer
->parent()) {
1241 DCHECK(current_layer
);
1242 const gfx::Transform
& layer_transform
= current_layer
->transform();
1243 if (current_layer
== page_scale_layer
) {
1244 DCHECK(layer_transform
.IsIdentity());
1245 float scale_factor
= layer_tree_impl()->total_page_scale_factor();
1246 current_offset
.Scale(scale_factor
);
1247 scroll_rect
.Scale(scale_factor
);
1249 DCHECK(layer_transform
.IsScale2d());
1250 gfx::Vector2dF layer_scale
= layer_transform
.Scale2d();
1251 DCHECK(layer_scale
.x() == layer_scale
.y());
1252 gfx::Vector2dF new_offset
=
1253 current_layer
->scroll_offset() + current_layer
->ScrollDelta();
1254 new_offset
.Scale(layer_scale
.x(), layer_scale
.y());
1255 current_offset
+= new_offset
;
1258 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1259 // turned on in all builds, remove the next two lines. For now however, the
1260 // page scale layer may coincide with the clip layer, and so this is
1262 if (page_scale_layer
== scrollbar_clip_layer
) {
1263 scroll_rect
.Scale(layer_tree_impl()->total_page_scale_factor());
1264 current_offset
.Scale(layer_tree_impl()->total_page_scale_factor());
1267 scrollbar_layer
->SetVerticalAdjust(
1268 layer_tree_impl()->VerticalAdjust(scrollbar_clip_layer
->id()));
1269 if (scrollbar_layer
->orientation() == HORIZONTAL
) {
1270 float visible_ratio
= clip_rect
.width() / scroll_rect
.width();
1271 scrollbar_layer
->SetCurrentPos(current_offset
.x());
1272 scrollbar_layer
->SetMaximum(scroll_rect
.width() - clip_rect
.width());
1273 scrollbar_layer
->SetVisibleToTotalLengthRatio(visible_ratio
);
1275 float visible_ratio
= clip_rect
.height() / scroll_rect
.height();
1276 scrollbar_layer
->SetCurrentPos(current_offset
.y());
1277 scrollbar_layer
->SetMaximum(scroll_rect
.height() - clip_rect
.height());
1278 scrollbar_layer
->SetVisibleToTotalLengthRatio(visible_ratio
);
1281 layer_tree_impl()->set_needs_update_draw_properties();
1282 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars should
1283 // activate for every scroll on the main frame, not just the scrolls that move
1284 // the pinch virtual viewport (i.e. trigger from either inner or outer
1286 if (scrollbar_animation_controller_
) {
1287 // When both non-overlay and overlay scrollbars are both present, don't
1288 // animate the overlay scrollbars when page scale factor is at the min.
1289 // Non-overlay scrollbars also shouldn't trigger animations.
1290 bool is_animatable_scrollbar
=
1291 scrollbar_layer
->is_overlay_scrollbar() &&
1292 ((layer_tree_impl()->total_page_scale_factor() >
1293 layer_tree_impl()->min_page_scale_factor()) ||
1294 !layer_tree_impl()->settings().use_pinch_zoom_scrollbars
);
1295 if (is_animatable_scrollbar
)
1296 scrollbar_animation_controller_
->DidScrollUpdate();
1300 void LayerImpl::DidBecomeActive() {
1301 if (layer_tree_impl_
->settings().scrollbar_animator
==
1302 LayerTreeSettings::NoAnimator
) {
1306 bool need_scrollbar_animation_controller
= scrollable() && scrollbars_
;
1307 if (!need_scrollbar_animation_controller
) {
1308 scrollbar_animation_controller_
.reset();
1312 if (scrollbar_animation_controller_
)
1315 scrollbar_animation_controller_
=
1316 layer_tree_impl_
->CreateScrollbarAnimationController(this);
1319 void LayerImpl::ClearScrollbars() {
1323 scrollbars_
.reset(NULL
);
1326 void LayerImpl::AddScrollbar(ScrollbarLayerImplBase
* layer
) {
1328 DCHECK(!scrollbars_
|| scrollbars_
->find(layer
) == scrollbars_
->end());
1330 scrollbars_
.reset(new ScrollbarSet());
1332 scrollbars_
->insert(layer
);
1335 void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase
* layer
) {
1336 DCHECK(scrollbars_
);
1338 DCHECK(scrollbars_
->find(layer
) != scrollbars_
->end());
1340 scrollbars_
->erase(layer
);
1341 if (scrollbars_
->empty())
1342 scrollbars_
.reset();
1345 bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation
) const {
1349 for (ScrollbarSet::iterator it
= scrollbars_
->begin();
1350 it
!= scrollbars_
->end();
1352 if ((*it
)->orientation() == orientation
)
1358 void LayerImpl::ScrollbarParametersDidChange() {
1362 for (ScrollbarSet::iterator it
= scrollbars_
->begin();
1363 it
!= scrollbars_
->end();
1365 (*it
)->ScrollbarParametersDidChange();
1368 void LayerImpl::SetNeedsPushProperties() {
1369 if (needs_push_properties_
)
1371 if (!parent_should_know_need_push_properties() && parent_
)
1372 parent_
->AddDependentNeedsPushProperties();
1373 needs_push_properties_
= true;
1376 void LayerImpl::AddDependentNeedsPushProperties() {
1377 DCHECK_GE(num_dependents_need_push_properties_
, 0);
1379 if (!parent_should_know_need_push_properties() && parent_
)
1380 parent_
->AddDependentNeedsPushProperties();
1382 num_dependents_need_push_properties_
++;
1385 void LayerImpl::RemoveDependentNeedsPushProperties() {
1386 num_dependents_need_push_properties_
--;
1387 DCHECK_GE(num_dependents_need_push_properties_
, 0);
1389 if (!parent_should_know_need_push_properties() && parent_
)
1390 parent_
->RemoveDependentNeedsPushProperties();
1393 void LayerImpl::AsValueInto(base::DictionaryValue
* state
) const {
1394 TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
1395 TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1398 LayerTypeAsString(),
1400 state
->SetInteger("layer_id", id());
1401 state
->Set("bounds", MathUtil::AsValue(bounds_
).release());
1402 state
->Set("position", MathUtil::AsValue(position_
).release());
1403 state
->SetInteger("draws_content", DrawsContent());
1404 state
->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1405 state
->Set("scroll_offset", MathUtil::AsValue(scroll_offset_
).release());
1406 state
->Set("transform_origin",
1407 MathUtil::AsValue(transform_origin_
).release());
1410 gfx::QuadF layer_quad
= MathUtil::MapQuad(
1411 screen_space_transform(),
1412 gfx::QuadF(gfx::Rect(content_bounds())),
1414 state
->Set("layer_quad", MathUtil::AsValue(layer_quad
).release());
1416 if (!touch_event_handler_region_
.IsEmpty()) {
1417 state
->Set("touch_event_handler_region",
1418 touch_event_handler_region_
.AsValue().release());
1420 if (have_wheel_event_handlers_
) {
1421 gfx::Rect
wheel_rect(content_bounds());
1422 Region
wheel_region(wheel_rect
);
1423 state
->Set("wheel_event_handler_region",
1424 wheel_region
.AsValue().release());
1426 if (have_scroll_event_handlers_
) {
1427 gfx::Rect
scroll_rect(content_bounds());
1428 Region
scroll_region(scroll_rect
);
1429 state
->Set("scroll_event_handler_region",
1430 scroll_region
.AsValue().release());
1432 if (!non_fast_scrollable_region_
.IsEmpty()) {
1433 state
->Set("non_fast_scrollable_region",
1434 non_fast_scrollable_region_
.AsValue().release());
1437 scoped_ptr
<base::ListValue
> children_list(new base::ListValue());
1438 for (size_t i
= 0; i
< children_
.size(); ++i
)
1439 children_list
->Append(children_
[i
]->AsValue().release());
1440 state
->Set("children", children_list
.release());
1442 state
->Set("mask_layer", mask_layer_
->AsValue().release());
1444 state
->Set("replica_layer", replica_layer_
->AsValue().release());
1447 state
->SetInteger("scroll_parent", scroll_parent_
->id());
1450 state
->SetInteger("clip_parent", clip_parent_
->id());
1452 state
->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1453 state
->SetBoolean("contents_opaque", contents_opaque());
1456 "has_animation_bounds",
1457 layer_animation_controller()->HasAnimationThatInflatesBounds());
1460 if (LayerUtils::GetAnimationBounds(*this, &box
))
1461 state
->Set("animation_bounds", MathUtil::AsValue(box
).release());
1463 if (debug_info_
.get()) {
1465 debug_info_
->AppendAsTraceFormat(&str
);
1466 base::JSONReader json_reader
;
1467 scoped_ptr
<base::Value
> debug_info_value(json_reader
.ReadToValue(str
));
1469 if (debug_info_value
->IsType(base::Value::TYPE_DICTIONARY
)) {
1470 base::DictionaryValue
* dictionary_value
= NULL
;
1471 bool converted_to_dictionary
=
1472 debug_info_value
->GetAsDictionary(&dictionary_value
);
1473 DCHECK(converted_to_dictionary
);
1474 state
->MergeDictionary(dictionary_value
);
1481 bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const {
1482 return draw_properties_
.last_drawn_render_surface_layer_list_id
==
1483 layer_tree_impl_
->current_render_surface_list_id();
1486 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1488 scoped_ptr
<base::Value
> LayerImpl::AsValue() const {
1489 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1490 AsValueInto(state
.get());
1491 return state
.PassAs
<base::Value
>();
1494 void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl
* benchmark
) {
1495 benchmark
->RunOnLayer(this);
1498 void LayerImpl::NotifyAnimationFinished(
1499 base::TimeTicks monotonic_time
,
1500 Animation::TargetProperty target_property
) {
1501 if (target_property
== Animation::ScrollOffset
)
1502 layer_tree_impl_
->InputScrollAnimationFinished();