Update comments of TabObserver#onLoadStarted and rename onContentChanged
[chromium-blink-merge.git] / cc / layers / layer_impl.cc
blob46a4c950aef8fb4e2a450eea608c30fcd6fda48e
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/json/json_reader.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/trace_event/trace_event.h"
10 #include "base/trace_event/trace_event_argument.h"
11 #include "cc/animation/animation_registrar.h"
12 #include "cc/animation/scrollbar_animation_controller.h"
13 #include "cc/base/math_util.h"
14 #include "cc/base/simple_enclosed_region.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/layers/layer_utils.h"
20 #include "cc/layers/painted_scrollbar_layer_impl.h"
21 #include "cc/output/copy_output_request.h"
22 #include "cc/quads/debug_border_draw_quad.h"
23 #include "cc/quads/render_pass.h"
24 #include "cc/trees/layer_tree_host_common.h"
25 #include "cc/trees/layer_tree_impl.h"
26 #include "cc/trees/layer_tree_settings.h"
27 #include "cc/trees/proxy.h"
28 #include "ui/gfx/geometry/box_f.h"
29 #include "ui/gfx/geometry/point_conversions.h"
30 #include "ui/gfx/geometry/quad_f.h"
31 #include "ui/gfx/geometry/rect_conversions.h"
32 #include "ui/gfx/geometry/size_conversions.h"
33 #include "ui/gfx/geometry/vector2d_conversions.h"
35 namespace cc {
36 LayerImpl::LayerImpl(LayerTreeImpl* layer_impl, int id)
37 : LayerImpl(layer_impl, id, new LayerImpl::SyncedScrollOffset) {
40 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
41 int id,
42 scoped_refptr<SyncedScrollOffset> scroll_offset)
43 : parent_(nullptr),
44 scroll_parent_(nullptr),
45 clip_parent_(nullptr),
46 mask_layer_id_(-1),
47 replica_layer_id_(-1),
48 layer_id_(id),
49 layer_tree_impl_(tree_impl),
50 scroll_offset_(scroll_offset),
51 scroll_clip_layer_(nullptr),
52 should_scroll_on_main_thread_(false),
53 have_wheel_event_handlers_(false),
54 have_scroll_event_handlers_(false),
55 scroll_blocks_on_(SCROLL_BLOCKS_ON_NONE),
56 user_scrollable_horizontal_(true),
57 user_scrollable_vertical_(true),
58 stacking_order_changed_(false),
59 double_sided_(true),
60 should_flatten_transform_(true),
61 should_flatten_transform_from_property_tree_(false),
62 layer_property_changed_(false),
63 masks_to_bounds_(false),
64 contents_opaque_(false),
65 is_root_for_isolated_group_(false),
66 use_parent_backface_visibility_(false),
67 draw_checkerboard_for_missing_tiles_(false),
68 draws_content_(false),
69 hide_layer_and_subtree_(false),
70 transform_is_invertible_(true),
71 is_container_for_fixed_position_layers_(false),
72 background_color_(0),
73 opacity_(1.0),
74 blend_mode_(SkXfermode::kSrcOver_Mode),
75 num_descendants_that_draw_content_(0),
76 transform_tree_index_(-1),
77 opacity_tree_index_(-1),
78 clip_tree_index_(-1),
79 draw_depth_(0.f),
80 needs_push_properties_(false),
81 num_dependents_need_push_properties_(0),
82 sorting_context_id_(0),
83 current_draw_mode_(DRAW_MODE_NONE),
84 frame_timing_requests_dirty_(false) {
85 DCHECK_GT(layer_id_, 0);
86 DCHECK(layer_tree_impl_);
87 layer_tree_impl_->RegisterLayer(this);
88 AnimationRegistrar* registrar = layer_tree_impl_->GetAnimationRegistrar();
89 layer_animation_controller_ =
90 registrar->GetAnimationControllerForId(layer_id_);
91 layer_animation_controller_->AddValueObserver(this);
92 if (IsActive()) {
93 layer_animation_controller_->set_value_provider(this);
94 layer_animation_controller_->set_layer_animation_delegate(this);
96 SetNeedsPushProperties();
99 LayerImpl::~LayerImpl() {
100 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
102 layer_animation_controller_->RemoveValueObserver(this);
103 layer_animation_controller_->remove_value_provider(this);
104 layer_animation_controller_->remove_layer_animation_delegate(this);
106 if (!copy_requests_.empty() && layer_tree_impl_->IsActiveTree())
107 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
108 layer_tree_impl_->UnregisterLayer(this);
110 TRACE_EVENT_OBJECT_DELETED_WITH_ID(
111 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerImpl", this);
114 void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
115 child->SetParent(this);
116 DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl());
117 children_.push_back(child.Pass());
118 layer_tree_impl()->set_needs_update_draw_properties();
121 scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) {
122 for (OwnedLayerImplList::iterator it = children_.begin();
123 it != children_.end();
124 ++it) {
125 if (*it == child) {
126 scoped_ptr<LayerImpl> ret = children_.take(it);
127 children_.erase(it);
128 layer_tree_impl()->set_needs_update_draw_properties();
129 return ret.Pass();
132 return nullptr;
135 void LayerImpl::SetParent(LayerImpl* parent) {
136 if (parent_should_know_need_push_properties()) {
137 if (parent_)
138 parent_->RemoveDependentNeedsPushProperties();
139 if (parent)
140 parent->AddDependentNeedsPushProperties();
142 parent_ = parent;
145 void LayerImpl::ClearChildList() {
146 if (children_.empty())
147 return;
149 children_.clear();
150 layer_tree_impl()->set_needs_update_draw_properties();
153 bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const {
154 if (!ancestor)
155 return false;
157 for (const LayerImpl* layer = this; layer; layer = layer->parent()) {
158 if (layer == ancestor)
159 return true;
162 return false;
165 void LayerImpl::SetScrollParent(LayerImpl* parent) {
166 if (scroll_parent_ == parent)
167 return;
169 if (parent)
170 DCHECK_EQ(layer_tree_impl()->LayerById(parent->id()), parent);
172 scroll_parent_ = parent;
173 SetNeedsPushProperties();
176 void LayerImpl::SetDebugInfo(
177 scoped_refptr<base::trace_event::ConvertableToTraceFormat> other) {
178 debug_info_ = other;
179 SetNeedsPushProperties();
182 void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
183 if (scroll_children_.get() == children)
184 return;
185 scroll_children_.reset(children);
186 SetNeedsPushProperties();
189 void LayerImpl::SetNumDescendantsThatDrawContent(int num_descendants) {
190 if (num_descendants_that_draw_content_ == num_descendants)
191 return;
192 num_descendants_that_draw_content_ = num_descendants;
193 SetNeedsPushProperties();
196 void LayerImpl::SetClipParent(LayerImpl* ancestor) {
197 if (clip_parent_ == ancestor)
198 return;
200 clip_parent_ = ancestor;
201 SetNeedsPushProperties();
204 void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) {
205 if (clip_children_.get() == children)
206 return;
207 clip_children_.reset(children);
208 SetNeedsPushProperties();
211 void LayerImpl::SetTransformTreeIndex(int index) {
212 transform_tree_index_ = index;
213 SetNeedsPushProperties();
216 void LayerImpl::SetClipTreeIndex(int index) {
217 clip_tree_index_ = index;
218 SetNeedsPushProperties();
221 void LayerImpl::SetOpacityTreeIndex(int index) {
222 opacity_tree_index_ = index;
223 SetNeedsPushProperties();
226 void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
227 if (requests->empty())
228 return;
229 DCHECK(render_surface());
230 bool was_empty = copy_requests_.empty();
231 copy_requests_.insert_and_take(copy_requests_.end(), requests);
232 requests->clear();
234 if (was_empty && layer_tree_impl()->IsActiveTree())
235 layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
236 NoteLayerPropertyChangedForSubtree();
239 void LayerImpl::TakeCopyRequestsAndTransformToTarget(
240 ScopedPtrVector<CopyOutputRequest>* requests) {
241 DCHECK(!copy_requests_.empty());
242 DCHECK(layer_tree_impl()->IsActiveTree());
243 DCHECK_EQ(render_target(), this);
245 size_t first_inserted_request = requests->size();
246 requests->insert_and_take(requests->end(), &copy_requests_);
247 copy_requests_.clear();
249 for (size_t i = first_inserted_request; i < requests->size(); ++i) {
250 CopyOutputRequest* request = requests->at(i);
251 if (!request->has_area())
252 continue;
254 gfx::Rect request_in_layer_space = request->area();
255 gfx::Rect request_in_content_space =
256 LayerRectToContentRect(request_in_layer_space);
257 request->set_area(MathUtil::MapEnclosingClippedRect(
258 draw_properties_.target_space_transform, request_in_content_space));
261 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
262 layer_tree_impl()->set_needs_update_draw_properties();
265 void LayerImpl::ClearRenderSurfaceLayerList() {
266 if (render_surface_)
267 render_surface_->ClearLayerLists();
270 void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
271 state->SetAll(
272 draw_properties_.target_space_transform, draw_properties_.content_bounds,
273 draw_properties_.visible_content_rect, draw_properties_.clip_rect,
274 draw_properties_.is_clipped, draw_properties_.opacity,
275 draw_properties_.blend_mode, sorting_context_id_);
278 void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state,
279 float scale) const {
280 gfx::Transform scaled_draw_transform =
281 draw_properties_.target_space_transform;
282 scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale);
283 gfx::Size scaled_content_bounds =
284 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
285 gfx::Rect scaled_visible_content_rect =
286 gfx::ScaleToEnclosingRect(visible_content_rect(), scale);
287 scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
289 state->SetAll(scaled_draw_transform, scaled_content_bounds,
290 scaled_visible_content_rect, draw_properties().clip_rect,
291 draw_properties().is_clipped, draw_properties().opacity,
292 draw_properties().blend_mode, sorting_context_id_);
295 bool LayerImpl::WillDraw(DrawMode draw_mode,
296 ResourceProvider* resource_provider) {
297 // WillDraw/DidDraw must be matched.
298 DCHECK_NE(DRAW_MODE_NONE, draw_mode);
299 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
300 current_draw_mode_ = draw_mode;
301 return true;
304 void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
305 DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
306 current_draw_mode_ = DRAW_MODE_NONE;
309 bool LayerImpl::ShowDebugBorders() const {
310 return layer_tree_impl()->debug_state().show_debug_borders;
313 void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
314 if (draws_content_) {
315 *color = DebugColors::ContentLayerBorderColor();
316 *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
317 return;
320 if (masks_to_bounds_) {
321 *color = DebugColors::MaskingLayerBorderColor();
322 *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
323 return;
326 *color = DebugColors::ContainerLayerBorderColor();
327 *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
330 void LayerImpl::AppendDebugBorderQuad(
331 RenderPass* render_pass,
332 const gfx::Size& content_bounds,
333 const SharedQuadState* shared_quad_state,
334 AppendQuadsData* append_quads_data) const {
335 SkColor color;
336 float width;
337 GetDebugBorderProperties(&color, &width);
338 AppendDebugBorderQuad(render_pass,
339 content_bounds,
340 shared_quad_state,
341 append_quads_data,
342 color,
343 width);
346 void LayerImpl::AppendDebugBorderQuad(RenderPass* render_pass,
347 const gfx::Size& content_bounds,
348 const SharedQuadState* shared_quad_state,
349 AppendQuadsData* append_quads_data,
350 SkColor color,
351 float width) const {
352 if (!ShowDebugBorders())
353 return;
355 gfx::Rect quad_rect(content_bounds);
356 gfx::Rect visible_quad_rect(quad_rect);
357 DebugBorderDrawQuad* debug_border_quad =
358 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
359 debug_border_quad->SetNew(
360 shared_quad_state, quad_rect, visible_quad_rect, color, width);
361 if (contents_opaque()) {
362 // When opaque, draw a second inner border that is thicker than the outer
363 // border, but more transparent.
364 static const float kFillOpacity = 0.3f;
365 SkColor fill_color = SkColorSetA(
366 color, static_cast<uint8_t>(SkColorGetA(color) * kFillOpacity));
367 float fill_width = width * 3;
368 gfx::Rect fill_rect = quad_rect;
369 fill_rect.Inset(fill_width / 2.f, fill_width / 2.f);
370 if (fill_rect.IsEmpty())
371 return;
372 gfx::Rect visible_fill_rect =
373 gfx::IntersectRects(visible_quad_rect, fill_rect);
374 DebugBorderDrawQuad* fill_quad =
375 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
376 fill_quad->SetNew(shared_quad_state, fill_rect, visible_fill_rect,
377 fill_color, fill_width);
381 bool LayerImpl::HasDelegatedContent() const {
382 return false;
385 bool LayerImpl::HasContributingDelegatedRenderPasses() const {
386 return false;
389 RenderPassId LayerImpl::FirstContributingRenderPassId() const {
390 return RenderPassId(0, 0);
393 RenderPassId LayerImpl::NextContributingRenderPassId(RenderPassId id) const {
394 return RenderPassId(0, 0);
397 void LayerImpl::GetContentsResourceId(ResourceId* resource_id,
398 gfx::Size* resource_size) const {
399 NOTREACHED();
400 *resource_id = 0;
403 gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
404 gfx::ScrollOffset adjusted_scroll(scroll);
405 if (layer_tree_impl()->settings().use_pinch_virtual_viewport) {
406 if (!user_scrollable_horizontal_)
407 adjusted_scroll.set_x(0);
408 if (!user_scrollable_vertical_)
409 adjusted_scroll.set_y(0);
411 DCHECK(scrollable());
412 gfx::ScrollOffset old_offset = CurrentScrollOffset();
413 gfx::ScrollOffset new_offset =
414 ClampScrollOffsetToLimits(old_offset + adjusted_scroll);
415 SetCurrentScrollOffset(new_offset);
417 gfx::ScrollOffset unscrolled =
418 old_offset + gfx::ScrollOffset(scroll) - new_offset;
419 return gfx::Vector2dF(unscrolled.x(), unscrolled.y());
422 void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) {
423 scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id);
426 bool LayerImpl::user_scrollable(ScrollbarOrientation orientation) const {
427 return (orientation == HORIZONTAL) ? user_scrollable_horizontal_
428 : user_scrollable_vertical_;
431 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
432 DCHECK(layer_tree_impl()->IsActiveTree());
433 scroll_offset_->AbortCommit();
436 InputHandler::ScrollStatus LayerImpl::TryScroll(
437 const gfx::PointF& screen_space_point,
438 InputHandler::ScrollInputType type,
439 ScrollBlocksOn effective_block_mode) const {
440 if (should_scroll_on_main_thread()) {
441 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
442 return InputHandler::SCROLL_ON_MAIN_THREAD;
445 if (!screen_space_transform().IsInvertible()) {
446 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
447 return InputHandler::SCROLL_IGNORED;
450 if (!non_fast_scrollable_region().IsEmpty()) {
451 bool clipped = false;
452 gfx::Transform inverse_screen_space_transform(
453 gfx::Transform::kSkipInitialization);
454 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
455 // TODO(shawnsingh): We shouldn't be applying a projection if screen space
456 // transform is uninvertible here. Perhaps we should be returning
457 // SCROLL_ON_MAIN_THREAD in this case?
460 gfx::PointF hit_test_point_in_content_space =
461 MathUtil::ProjectPoint(inverse_screen_space_transform,
462 screen_space_point,
463 &clipped);
464 gfx::PointF hit_test_point_in_layer_space =
465 gfx::ScalePoint(hit_test_point_in_content_space,
466 1.f / contents_scale_x(),
467 1.f / contents_scale_y());
468 if (!clipped &&
469 non_fast_scrollable_region().Contains(
470 gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
471 TRACE_EVENT0("cc",
472 "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
473 return InputHandler::SCROLL_ON_MAIN_THREAD;
477 if (have_scroll_event_handlers() &&
478 effective_block_mode & SCROLL_BLOCKS_ON_SCROLL_EVENT) {
479 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed ScrollEventHandlers");
480 return InputHandler::SCROLL_ON_MAIN_THREAD;
483 if (type == InputHandler::WHEEL && have_wheel_event_handlers() &&
484 effective_block_mode & SCROLL_BLOCKS_ON_WHEEL_EVENT) {
485 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
486 return InputHandler::SCROLL_ON_MAIN_THREAD;
489 if (!scrollable()) {
490 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
491 return InputHandler::SCROLL_IGNORED;
494 gfx::ScrollOffset max_scroll_offset = MaxScrollOffset();
495 if (max_scroll_offset.x() <= 0 && max_scroll_offset.y() <= 0) {
496 TRACE_EVENT0("cc",
497 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
498 " but has no affordance in either direction.");
499 return InputHandler::SCROLL_IGNORED;
502 return InputHandler::SCROLL_STARTED;
505 gfx::Rect LayerImpl::LayerRectToContentRect(
506 const gfx::RectF& layer_rect) const {
507 gfx::RectF content_rect =
508 gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
509 // Intersect with content rect to avoid the extra pixel because for some
510 // values x and y, ceil((x / y) * y) may be x + 1.
511 content_rect.Intersect(gfx::Rect(content_bounds()));
512 return gfx::ToEnclosingRect(content_rect);
515 skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
516 return skia::RefPtr<SkPicture>();
519 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
520 return LayerImpl::Create(tree_impl, layer_id_, scroll_offset_);
523 void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
524 layer->SetTransformOrigin(transform_origin_);
525 layer->SetBackgroundColor(background_color_);
526 layer->SetBounds(bounds_);
527 layer->SetContentBounds(content_bounds());
528 layer->SetContentsScale(contents_scale_x(), contents_scale_y());
529 layer->SetDoubleSided(double_sided_);
530 layer->SetDrawCheckerboardForMissingTiles(
531 draw_checkerboard_for_missing_tiles_);
532 layer->SetDrawsContent(DrawsContent());
533 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
534 layer->SetHasRenderSurface(!!render_surface() || layer->HasCopyRequest());
535 layer->SetFilters(filters());
536 layer->SetBackgroundFilters(background_filters());
537 layer->SetMasksToBounds(masks_to_bounds_);
538 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
539 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
540 layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
541 layer->SetScrollBlocksOn(scroll_blocks_on_);
542 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
543 layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
544 layer->SetContentsOpaque(contents_opaque_);
545 layer->SetOpacity(opacity_);
546 layer->SetBlendMode(blend_mode_);
547 layer->SetIsRootForIsolatedGroup(is_root_for_isolated_group_);
548 layer->SetPosition(position_);
549 layer->SetIsContainerForFixedPositionLayers(
550 is_container_for_fixed_position_layers_);
551 layer->SetPositionConstraint(position_constraint_);
552 layer->SetShouldFlattenTransform(should_flatten_transform_);
553 layer->set_should_flatten_transform_from_property_tree(
554 should_flatten_transform_from_property_tree_);
555 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
556 layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
558 layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id()
559 : Layer::INVALID_ID);
560 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
561 layer->set_user_scrollable_vertical(user_scrollable_vertical_);
563 layer->SetScrollCompensationAdjustment(scroll_compensation_adjustment_);
565 layer->PushScrollOffset(nullptr);
567 layer->Set3dSortingContextId(sorting_context_id_);
568 layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_);
570 layer->SetTransformTreeIndex(transform_tree_index_);
571 layer->SetClipTreeIndex(clip_tree_index_);
572 layer->SetOpacityTreeIndex(opacity_tree_index_);
573 layer->set_offset_to_transform_parent(offset_to_transform_parent_);
575 LayerImpl* scroll_parent = nullptr;
576 if (scroll_parent_) {
577 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
578 DCHECK(scroll_parent);
581 layer->SetScrollParent(scroll_parent);
582 if (scroll_children_) {
583 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
584 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
585 it != scroll_children_->end();
586 ++it) {
587 DCHECK_EQ((*it)->scroll_parent(), this);
588 LayerImpl* scroll_child =
589 layer->layer_tree_impl()->LayerById((*it)->id());
590 DCHECK(scroll_child);
591 scroll_children->insert(scroll_child);
593 layer->SetScrollChildren(scroll_children);
594 } else {
595 layer->SetScrollChildren(nullptr);
598 LayerImpl* clip_parent = nullptr;
599 if (clip_parent_) {
600 clip_parent = layer->layer_tree_impl()->LayerById(
601 clip_parent_->id());
602 DCHECK(clip_parent);
605 layer->SetClipParent(clip_parent);
606 if (clip_children_) {
607 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>;
608 for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
609 it != clip_children_->end(); ++it)
610 clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
611 layer->SetClipChildren(clip_children);
612 } else {
613 layer->SetClipChildren(nullptr);
616 layer->PassCopyRequests(&copy_requests_);
618 // If the main thread commits multiple times before the impl thread actually
619 // draws, then damage tracking will become incorrect if we simply clobber the
620 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
621 // union) any update changes that have occurred on the main thread.
622 update_rect_.Union(layer->update_rect());
623 layer->SetUpdateRect(update_rect_);
625 layer->SetStackingOrderChanged(stacking_order_changed_);
626 layer->SetDebugInfo(debug_info_);
628 if (frame_timing_requests_dirty_) {
629 layer->PassFrameTimingRequests(&frame_timing_requests_);
630 frame_timing_requests_dirty_ = false;
633 // Reset any state that should be cleared for the next update.
634 stacking_order_changed_ = false;
635 update_rect_ = gfx::Rect();
636 needs_push_properties_ = false;
637 num_dependents_need_push_properties_ = 0;
640 gfx::Vector2dF LayerImpl::FixedContainerSizeDelta() const {
641 if (!scroll_clip_layer_)
642 return gfx::Vector2dF();
644 gfx::Vector2dF delta_from_scroll = scroll_clip_layer_->bounds_delta();
646 // In virtual-viewport mode, we don't need to compensate for pinch zoom or
647 // scale since the fixed container is the outer viewport, which sits below
648 // the page scale.
649 if (layer_tree_impl()->settings().use_pinch_virtual_viewport)
650 return delta_from_scroll;
652 float scale_delta = layer_tree_impl()->page_scale_delta();
653 float scale = layer_tree_impl()->current_page_scale_factor() /
654 layer_tree_impl()->page_scale_delta();
656 delta_from_scroll.Scale(1.f / scale);
658 // The delta-from-pinch component requires some explanation: A viewport of
659 // size (w,h) will appear to be size (w/s,h/s) under scale s in the content
660 // space. If s -> s' on the impl thread, where s' = s * ds, then the apparent
661 // viewport size change in the content space due to ds is:
663 // (w/s',h/s') - (w/s,h/s) = (w,h)(1/s' - 1/s) = (w,h)(1 - ds)/(s ds)
665 gfx::Vector2dF delta_from_pinch =
666 gfx::Rect(scroll_clip_layer_->bounds()).bottom_right() - gfx::PointF();
667 delta_from_pinch.Scale((1.f - scale_delta) / (scale * scale_delta));
669 return delta_from_scroll + delta_from_pinch;
672 base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
673 base::DictionaryValue* result = new base::DictionaryValue;
674 result->SetInteger("LayerId", id());
675 result->SetString("LayerType", LayerTypeAsString());
677 base::ListValue* list = new base::ListValue;
678 list->AppendInteger(bounds().width());
679 list->AppendInteger(bounds().height());
680 result->Set("Bounds", list);
682 list = new base::ListValue;
683 list->AppendDouble(position_.x());
684 list->AppendDouble(position_.y());
685 result->Set("Position", list);
687 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
688 double transform[16];
689 gfx_transform.matrix().asColMajord(transform);
690 list = new base::ListValue;
691 for (int i = 0; i < 16; ++i)
692 list->AppendDouble(transform[i]);
693 result->Set("DrawTransform", list);
695 result->SetBoolean("DrawsContent", draws_content_);
696 result->SetBoolean("Is3dSorted", Is3dSorted());
697 result->SetDouble("OPACITY", opacity());
698 result->SetBoolean("ContentsOpaque", contents_opaque_);
700 if (scrollable())
701 result->SetBoolean("Scrollable", true);
703 if (have_wheel_event_handlers_)
704 result->SetBoolean("WheelHandler", have_wheel_event_handlers_);
705 if (have_scroll_event_handlers_)
706 result->SetBoolean("ScrollHandler", have_scroll_event_handlers_);
707 if (!touch_event_handler_region_.IsEmpty()) {
708 scoped_ptr<base::Value> region = touch_event_handler_region_.AsValue();
709 result->Set("TouchRegion", region.release());
712 if (scroll_blocks_on_) {
713 list = new base::ListValue;
714 if (scroll_blocks_on_ & SCROLL_BLOCKS_ON_START_TOUCH)
715 list->AppendString("StartTouch");
716 if (scroll_blocks_on_ & SCROLL_BLOCKS_ON_WHEEL_EVENT)
717 list->AppendString("WheelEvent");
718 if (scroll_blocks_on_ & SCROLL_BLOCKS_ON_SCROLL_EVENT)
719 list->AppendString("ScrollEvent");
720 result->Set("ScrollBlocksOn", list);
723 list = new base::ListValue;
724 for (size_t i = 0; i < children_.size(); ++i)
725 list->Append(children_[i]->LayerTreeAsJson());
726 result->Set("Children", list);
728 return result;
731 void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
732 if (stacking_order_changed) {
733 stacking_order_changed_ = true;
734 NoteLayerPropertyChangedForSubtree();
738 void LayerImpl::NoteLayerPropertyChanged() {
739 layer_property_changed_ = true;
740 layer_tree_impl()->set_needs_update_draw_properties();
741 SetNeedsPushProperties();
744 void LayerImpl::NoteLayerPropertyChangedForSubtree() {
745 layer_property_changed_ = true;
746 layer_tree_impl()->set_needs_update_draw_properties();
747 for (size_t i = 0; i < children_.size(); ++i)
748 children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
749 SetNeedsPushProperties();
752 void LayerImpl::NoteLayerPropertyChangedForDescendantsInternal() {
753 layer_property_changed_ = true;
754 for (size_t i = 0; i < children_.size(); ++i)
755 children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
758 void LayerImpl::NoteLayerPropertyChangedForDescendants() {
759 layer_tree_impl()->set_needs_update_draw_properties();
760 for (size_t i = 0; i < children_.size(); ++i)
761 children_[i]->NoteLayerPropertyChangedForDescendantsInternal();
762 SetNeedsPushProperties();
765 #if DCHECK_IS_ON()
766 // Verify that the resource id is valid.
767 static ResourceId ValidateResource(const ResourceProvider* provider,
768 ResourceId id) {
769 provider->ValidateResource(id);
770 return id;
772 #endif
774 void LayerImpl::ValidateQuadResourcesInternal(DrawQuad* quad) const {
775 #if DCHECK_IS_ON()
776 quad->IterateResources(
777 base::Bind(&ValidateResource, layer_tree_impl_->resource_provider()));
778 #endif
781 const char* LayerImpl::LayerTypeAsString() const {
782 return "cc::LayerImpl";
785 void LayerImpl::ResetAllChangeTrackingForSubtree() {
786 layer_property_changed_ = false;
788 update_rect_ = gfx::Rect();
789 damage_rect_ = gfx::RectF();
791 if (render_surface_)
792 render_surface_->ResetPropertyChangedFlag();
794 if (mask_layer_)
795 mask_layer_->ResetAllChangeTrackingForSubtree();
797 if (replica_layer_) {
798 // This also resets the replica mask, if it exists.
799 replica_layer_->ResetAllChangeTrackingForSubtree();
802 for (size_t i = 0; i < children_.size(); ++i)
803 children_[i]->ResetAllChangeTrackingForSubtree();
805 needs_push_properties_ = false;
806 num_dependents_need_push_properties_ = 0;
809 gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const {
810 return CurrentScrollOffset();
813 void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
814 SetFilters(filters);
817 void LayerImpl::OnOpacityAnimated(float opacity) {
818 SetOpacity(opacity);
821 void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
822 SetTransform(transform);
825 void LayerImpl::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) {
826 // Only layers in the active tree should need to do anything here, since
827 // layers in the pending tree will find out about these changes as a
828 // result of the shared SyncedProperty.
829 if (!IsActive())
830 return;
832 SetCurrentScrollOffset(scroll_offset);
834 layer_tree_impl_->DidAnimateScrollOffset();
837 void LayerImpl::OnAnimationWaitingForDeletion() {}
839 bool LayerImpl::IsActive() const {
840 return layer_tree_impl_->IsActiveTree();
843 gfx::Size LayerImpl::bounds() const {
844 gfx::Vector2d delta = gfx::ToCeiledVector2d(bounds_delta_);
845 return gfx::Size(bounds_.width() + delta.x(),
846 bounds_.height() + delta.y());
849 gfx::SizeF LayerImpl::BoundsForScrolling() const {
850 return gfx::SizeF(bounds_.width() + bounds_delta_.x(),
851 bounds_.height() + bounds_delta_.y());
854 void LayerImpl::SetBounds(const gfx::Size& bounds) {
855 if (bounds_ == bounds)
856 return;
858 bounds_ = bounds;
860 ScrollbarParametersDidChange(true);
861 if (masks_to_bounds())
862 NoteLayerPropertyChangedForSubtree();
863 else
864 NoteLayerPropertyChanged();
867 void LayerImpl::SetBoundsDelta(const gfx::Vector2dF& bounds_delta) {
868 if (bounds_delta_ == bounds_delta)
869 return;
871 bounds_delta_ = bounds_delta;
873 ScrollbarParametersDidChange(true);
874 if (masks_to_bounds())
875 NoteLayerPropertyChangedForSubtree();
876 else
877 NoteLayerPropertyChanged();
880 void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
881 int new_layer_id = mask_layer ? mask_layer->id() : -1;
883 if (mask_layer) {
884 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
885 DCHECK_NE(new_layer_id, mask_layer_id_);
886 } else if (new_layer_id == mask_layer_id_) {
887 return;
890 mask_layer_ = mask_layer.Pass();
891 mask_layer_id_ = new_layer_id;
892 if (mask_layer_)
893 mask_layer_->SetParent(this);
894 NoteLayerPropertyChangedForSubtree();
897 scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
898 mask_layer_id_ = -1;
899 return mask_layer_.Pass();
902 void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
903 int new_layer_id = replica_layer ? replica_layer->id() : -1;
905 if (replica_layer) {
906 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
907 DCHECK_NE(new_layer_id, replica_layer_id_);
908 } else if (new_layer_id == replica_layer_id_) {
909 return;
912 replica_layer_ = replica_layer.Pass();
913 replica_layer_id_ = new_layer_id;
914 if (replica_layer_)
915 replica_layer_->SetParent(this);
916 NoteLayerPropertyChangedForSubtree();
919 scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
920 replica_layer_id_ = -1;
921 return replica_layer_.Pass();
924 ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() {
925 return nullptr;
928 void LayerImpl::SetDrawsContent(bool draws_content) {
929 if (draws_content_ == draws_content)
930 return;
932 draws_content_ = draws_content;
933 NoteLayerPropertyChanged();
936 void LayerImpl::SetHideLayerAndSubtree(bool hide) {
937 if (hide_layer_and_subtree_ == hide)
938 return;
940 hide_layer_and_subtree_ = hide;
941 NoteLayerPropertyChangedForSubtree();
944 void LayerImpl::SetTransformOrigin(const gfx::Point3F& transform_origin) {
945 if (transform_origin_ == transform_origin)
946 return;
947 transform_origin_ = transform_origin;
948 NoteLayerPropertyChangedForSubtree();
951 void LayerImpl::SetBackgroundColor(SkColor background_color) {
952 if (background_color_ == background_color)
953 return;
955 background_color_ = background_color;
956 NoteLayerPropertyChanged();
959 SkColor LayerImpl::SafeOpaqueBackgroundColor() const {
960 SkColor color = background_color();
961 if (SkColorGetA(color) == 255 && !contents_opaque()) {
962 color = SK_ColorTRANSPARENT;
963 } else if (SkColorGetA(color) != 255 && contents_opaque()) {
964 for (const LayerImpl* layer = parent(); layer;
965 layer = layer->parent()) {
966 color = layer->background_color();
967 if (SkColorGetA(color) == 255)
968 break;
970 if (SkColorGetA(color) != 255)
971 color = layer_tree_impl()->background_color();
972 if (SkColorGetA(color) != 255)
973 color = SkColorSetA(color, 255);
975 return color;
978 void LayerImpl::SetFilters(const FilterOperations& filters) {
979 if (filters_ == filters)
980 return;
982 filters_ = filters;
983 NoteLayerPropertyChangedForSubtree();
986 bool LayerImpl::FilterIsAnimating() const {
987 return layer_animation_controller_->IsAnimatingProperty(Animation::FILTER);
990 bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
991 Animation* filter_animation =
992 layer_animation_controller_->GetAnimation(Animation::FILTER);
993 return filter_animation && filter_animation->is_impl_only();
996 void LayerImpl::SetBackgroundFilters(
997 const FilterOperations& filters) {
998 if (background_filters_ == filters)
999 return;
1001 background_filters_ = filters;
1002 NoteLayerPropertyChanged();
1005 void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
1006 if (masks_to_bounds_ == masks_to_bounds)
1007 return;
1009 masks_to_bounds_ = masks_to_bounds;
1010 NoteLayerPropertyChangedForSubtree();
1013 void LayerImpl::SetContentsOpaque(bool opaque) {
1014 if (contents_opaque_ == opaque)
1015 return;
1017 contents_opaque_ = opaque;
1018 NoteLayerPropertyChangedForSubtree();
1021 void LayerImpl::SetOpacity(float opacity) {
1022 if (opacity_ == opacity)
1023 return;
1025 opacity_ = opacity;
1026 NoteLayerPropertyChangedForSubtree();
1029 bool LayerImpl::OpacityIsAnimating() const {
1030 return layer_animation_controller_->IsAnimatingProperty(Animation::OPACITY);
1033 bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
1034 Animation* opacity_animation =
1035 layer_animation_controller_->GetAnimation(Animation::OPACITY);
1036 return opacity_animation && opacity_animation->is_impl_only();
1039 void LayerImpl::SetBlendMode(SkXfermode::Mode blend_mode) {
1040 if (blend_mode_ == blend_mode)
1041 return;
1043 blend_mode_ = blend_mode;
1044 NoteLayerPropertyChangedForSubtree();
1047 void LayerImpl::SetIsRootForIsolatedGroup(bool root) {
1048 if (is_root_for_isolated_group_ == root)
1049 return;
1051 is_root_for_isolated_group_ = root;
1052 SetNeedsPushProperties();
1055 void LayerImpl::SetPosition(const gfx::PointF& position) {
1056 if (position_ == position)
1057 return;
1059 position_ = position;
1060 NoteLayerPropertyChangedForSubtree();
1063 void LayerImpl::SetShouldFlattenTransform(bool flatten) {
1064 if (should_flatten_transform_ == flatten)
1065 return;
1067 should_flatten_transform_ = flatten;
1068 NoteLayerPropertyChangedForSubtree();
1071 void LayerImpl::Set3dSortingContextId(int id) {
1072 if (id == sorting_context_id_)
1073 return;
1074 sorting_context_id_ = id;
1075 NoteLayerPropertyChangedForSubtree();
1078 void LayerImpl::PassFrameTimingRequests(
1079 std::vector<FrameTimingRequest>* requests) {
1080 frame_timing_requests_.swap(*requests);
1081 frame_timing_requests_dirty_ = true;
1082 SetNeedsPushProperties();
1085 void LayerImpl::GatherFrameTimingRequestIds(std::vector<int64_t>* request_ids) {
1086 for (const auto& request : frame_timing_requests_)
1087 request_ids->push_back(request.id());
1090 void LayerImpl::SetTransform(const gfx::Transform& transform) {
1091 if (transform_ == transform)
1092 return;
1094 transform_ = transform;
1095 transform_is_invertible_ = transform_.IsInvertible();
1096 NoteLayerPropertyChangedForSubtree();
1099 void LayerImpl::SetTransformAndInvertibility(const gfx::Transform& transform,
1100 bool transform_is_invertible) {
1101 if (transform_ == transform) {
1102 DCHECK(transform_is_invertible_ == transform_is_invertible)
1103 << "Can't change invertibility if transform is unchanged";
1104 return;
1106 transform_ = transform;
1107 transform_is_invertible_ = transform_is_invertible;
1108 NoteLayerPropertyChangedForSubtree();
1111 bool LayerImpl::TransformIsAnimating() const {
1112 return layer_animation_controller_->IsAnimatingProperty(Animation::TRANSFORM);
1115 bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
1116 Animation* transform_animation =
1117 layer_animation_controller_->GetAnimation(Animation::TRANSFORM);
1118 return transform_animation && transform_animation->is_impl_only();
1121 void LayerImpl::SetUpdateRect(const gfx::Rect& update_rect) {
1122 update_rect_ = update_rect;
1123 SetNeedsPushProperties();
1126 void LayerImpl::AddDamageRect(const gfx::RectF& damage_rect) {
1127 damage_rect_ = gfx::UnionRects(damage_rect_, damage_rect);
1130 void LayerImpl::SetContentBounds(const gfx::Size& content_bounds) {
1131 if (this->content_bounds() == content_bounds)
1132 return;
1134 draw_properties_.content_bounds = content_bounds;
1135 NoteLayerPropertyChanged();
1138 void LayerImpl::SetContentsScale(float contents_scale_x,
1139 float contents_scale_y) {
1140 if (this->contents_scale_x() == contents_scale_x &&
1141 this->contents_scale_y() == contents_scale_y)
1142 return;
1144 draw_properties_.contents_scale_x = contents_scale_x;
1145 draw_properties_.contents_scale_y = contents_scale_y;
1146 NoteLayerPropertyChanged();
1149 bool LayerImpl::IsExternalFlingActive() const {
1150 return layer_tree_impl_->IsExternalFlingActive();
1153 void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) {
1154 DCHECK(IsActive());
1155 if (scroll_offset_->SetCurrent(scroll_offset))
1156 DidUpdateScrollOffset(false);
1159 void LayerImpl::SetCurrentScrollOffsetFromDelegate(
1160 const gfx::ScrollOffset& scroll_offset) {
1161 DCHECK(IsActive());
1162 if (scroll_offset_->SetCurrent(scroll_offset))
1163 DidUpdateScrollOffset(true);
1166 void LayerImpl::PushScrollOffsetFromMainThread(
1167 const gfx::ScrollOffset& scroll_offset) {
1168 PushScrollOffset(&scroll_offset);
1171 void LayerImpl::PushScrollOffsetFromMainThreadAndClobberActiveValue(
1172 const gfx::ScrollOffset& scroll_offset) {
1173 scroll_offset_->set_clobber_active_value();
1174 PushScrollOffset(&scroll_offset);
1177 gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
1178 // TODO(miletus): Remove all this temporary flooring machinery when
1179 // Blink fully supports fractional scrolls.
1180 gfx::ScrollOffset current_offset = CurrentScrollOffset();
1181 gfx::Vector2dF current_delta = ScrollDelta();
1182 gfx::Vector2dF floored_delta(floor(current_delta.x()),
1183 floor(current_delta.y()));
1184 gfx::Vector2dF diff_delta = floored_delta - current_delta;
1185 gfx::ScrollOffset tmp_offset = ScrollOffsetWithDelta(current_offset,
1186 diff_delta);
1187 scroll_offset_->SetCurrent(tmp_offset);
1188 gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread();
1189 scroll_offset_->SetCurrent(current_offset);
1190 return delta;
1193 gfx::ScrollOffset LayerImpl::CurrentScrollOffset() const {
1194 return scroll_offset_->Current(IsActive());
1197 gfx::Vector2dF LayerImpl::ScrollDelta() const {
1198 if (IsActive())
1199 return gfx::Vector2dF(scroll_offset_->Delta().x(),
1200 scroll_offset_->Delta().y());
1201 else
1202 return gfx::Vector2dF(scroll_offset_->PendingDelta().get().x(),
1203 scroll_offset_->PendingDelta().get().y());
1206 void LayerImpl::SetScrollDelta(const gfx::Vector2dF& delta) {
1207 DCHECK(IsActive());
1208 SetCurrentScrollOffset(scroll_offset_->ActiveBase() +
1209 gfx::ScrollOffset(delta));
1212 gfx::ScrollOffset LayerImpl::BaseScrollOffset() const {
1213 if (IsActive())
1214 return scroll_offset_->ActiveBase();
1215 else
1216 return scroll_offset_->PendingBase();
1219 void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) {
1220 DCHECK(scroll_offset || IsActive());
1221 bool changed = false;
1222 if (scroll_offset) {
1223 DCHECK(!IsActive() || !layer_tree_impl_->FindPendingTreeLayerById(id()));
1224 changed |= scroll_offset_->PushFromMainThread(*scroll_offset);
1226 if (IsActive()) {
1227 changed |= scroll_offset_->PushPendingToActive();
1230 if (changed)
1231 DidUpdateScrollOffset(false);
1234 void LayerImpl::DidUpdateScrollOffset(bool is_from_root_delegate) {
1235 DCHECK(scroll_offset_);
1237 if (!is_from_root_delegate)
1238 layer_tree_impl()->DidUpdateScrollOffset(id());
1239 NoteLayerPropertyChangedForSubtree();
1240 ScrollbarParametersDidChange(false);
1242 // TODO(enne): in the future, scrolling should update the scroll tree
1243 // directly instead of going through layers.
1244 if (transform_tree_index_ != -1) {
1245 TransformTree& transform_tree =
1246 layer_tree_impl()->property_trees()->transform_tree;
1247 TransformNode* node = transform_tree.Node(transform_tree_index_);
1248 node->data.scroll_offset = scroll_offset_->Current(IsActive());
1249 node->data.needs_local_transform_update = true;
1250 transform_tree.set_needs_update(true);
1253 // Inform the pending twin that a property changed.
1254 if (layer_tree_impl()->IsActiveTree()) {
1255 LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id());
1256 if (pending_twin)
1257 pending_twin->DidUpdateScrollOffset(is_from_root_delegate);
1261 void LayerImpl::SetDoubleSided(bool double_sided) {
1262 if (double_sided_ == double_sided)
1263 return;
1265 double_sided_ = double_sided;
1266 NoteLayerPropertyChangedForSubtree();
1269 SimpleEnclosedRegion LayerImpl::VisibleContentOpaqueRegion() const {
1270 if (contents_opaque())
1271 return SimpleEnclosedRegion(visible_content_rect());
1272 return SimpleEnclosedRegion();
1275 void LayerImpl::DidBeginTracing() {}
1277 void LayerImpl::ReleaseResources() {}
1279 void LayerImpl::RecreateResources() {
1282 gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
1283 if (!scroll_clip_layer_ || bounds().IsEmpty())
1284 return gfx::ScrollOffset();
1286 LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
1287 DCHECK(this != page_scale_layer);
1288 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1289 IsContainerForFixedPositionLayers());
1291 float scale_factor = 1.f;
1292 for (LayerImpl const* current_layer = this;
1293 current_layer != scroll_clip_layer_->parent();
1294 current_layer = current_layer->parent()) {
1295 if (current_layer == page_scale_layer)
1296 scale_factor = layer_tree_impl()->current_page_scale_factor();
1299 gfx::SizeF scaled_scroll_bounds =
1300 gfx::ToFlooredSize(gfx::ScaleSize(BoundsForScrolling(), scale_factor));
1301 scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds);
1303 gfx::ScrollOffset max_offset(
1304 scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
1305 scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height());
1306 // We need the final scroll offset to be in CSS coords.
1307 max_offset.Scale(1 / scale_factor);
1308 max_offset.SetToMax(gfx::ScrollOffset());
1309 return max_offset;
1312 gfx::ScrollOffset LayerImpl::ClampScrollOffsetToLimits(
1313 gfx::ScrollOffset offset) const {
1314 offset.SetToMin(MaxScrollOffset());
1315 offset.SetToMax(gfx::ScrollOffset());
1316 return offset;
1319 gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() {
1320 gfx::ScrollOffset old_offset = CurrentScrollOffset();
1321 gfx::ScrollOffset clamped_offset = ClampScrollOffsetToLimits(old_offset);
1322 gfx::Vector2dF delta = clamped_offset.DeltaFrom(old_offset);
1323 if (!delta.IsZero())
1324 ScrollBy(delta);
1325 return delta;
1328 void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
1329 LayerImpl* scrollbar_clip_layer,
1330 bool on_resize) const {
1331 DCHECK(scrollbar_layer);
1332 LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
1334 DCHECK(this != page_scale_layer);
1335 DCHECK(scrollbar_clip_layer);
1336 gfx::RectF clip_rect(gfx::PointF(),
1337 scrollbar_clip_layer->BoundsForScrolling());
1339 // See comment in MaxScrollOffset() regarding the use of the content layer
1340 // bounds here.
1341 gfx::RectF scroll_rect(gfx::PointF(), BoundsForScrolling());
1343 if (scroll_rect.size().IsEmpty())
1344 return;
1346 gfx::ScrollOffset current_offset;
1347 for (LayerImpl const* current_layer = this;
1348 current_layer != scrollbar_clip_layer->parent();
1349 current_layer = current_layer->parent()) {
1350 current_offset += current_layer->CurrentScrollOffset();
1351 if (current_layer == page_scale_layer) {
1352 float scale_factor = layer_tree_impl()->current_page_scale_factor();
1353 current_offset.Scale(scale_factor);
1354 scroll_rect.Scale(scale_factor);
1358 bool scrollbar_needs_animation = false;
1359 scrollbar_needs_animation |= scrollbar_layer->SetVerticalAdjust(
1360 scrollbar_clip_layer->bounds_delta().y());
1361 if (scrollbar_layer->orientation() == HORIZONTAL) {
1362 float visible_ratio = clip_rect.width() / scroll_rect.width();
1363 scrollbar_needs_animation |=
1364 scrollbar_layer->SetCurrentPos(current_offset.x());
1365 scrollbar_needs_animation |=
1366 scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width());
1367 scrollbar_needs_animation |=
1368 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1369 } else {
1370 float visible_ratio = clip_rect.height() / scroll_rect.height();
1371 bool y_offset_did_change =
1372 scrollbar_layer->SetCurrentPos(current_offset.y());
1373 scrollbar_needs_animation |= y_offset_did_change;
1374 scrollbar_needs_animation |=
1375 scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height());
1376 scrollbar_needs_animation |=
1377 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1378 if (y_offset_did_change && layer_tree_impl()->IsActiveTree() &&
1379 this == layer_tree_impl()->InnerViewportScrollLayer()) {
1380 TRACE_COUNTER_ID1("cc", "scroll_offset_y", this->id(),
1381 current_offset.y());
1384 if (scrollbar_needs_animation) {
1385 layer_tree_impl()->set_needs_update_draw_properties();
1386 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars
1387 // should activate for every scroll on the main frame, not just the
1388 // scrolls that move the pinch virtual viewport (i.e. trigger from
1389 // either inner or outer viewport).
1390 if (scrollbar_animation_controller_) {
1391 // Non-overlay scrollbars shouldn't trigger animations.
1392 if (scrollbar_layer->is_overlay_scrollbar())
1393 scrollbar_animation_controller_->DidScrollUpdate(on_resize);
1398 void LayerImpl::DidBecomeActive() {
1399 if (layer_tree_impl_->settings().scrollbar_animator ==
1400 LayerTreeSettings::NO_ANIMATOR) {
1401 return;
1404 bool need_scrollbar_animation_controller = scrollable() && scrollbars_;
1405 if (!need_scrollbar_animation_controller) {
1406 scrollbar_animation_controller_ = nullptr;
1407 return;
1410 if (scrollbar_animation_controller_)
1411 return;
1413 scrollbar_animation_controller_ =
1414 layer_tree_impl_->CreateScrollbarAnimationController(this);
1417 void LayerImpl::ClearScrollbars() {
1418 if (!scrollbars_)
1419 return;
1421 scrollbars_.reset(nullptr);
1424 void LayerImpl::AddScrollbar(ScrollbarLayerImplBase* layer) {
1425 DCHECK(layer);
1426 DCHECK(!scrollbars_ || scrollbars_->find(layer) == scrollbars_->end());
1427 if (!scrollbars_)
1428 scrollbars_.reset(new ScrollbarSet());
1430 scrollbars_->insert(layer);
1433 void LayerImpl::RemoveScrollbar(ScrollbarLayerImplBase* layer) {
1434 DCHECK(scrollbars_);
1435 DCHECK(layer);
1436 DCHECK(scrollbars_->find(layer) != scrollbars_->end());
1438 scrollbars_->erase(layer);
1439 if (scrollbars_->empty())
1440 scrollbars_ = nullptr;
1443 bool LayerImpl::HasScrollbar(ScrollbarOrientation orientation) const {
1444 if (!scrollbars_)
1445 return false;
1447 for (ScrollbarSet::iterator it = scrollbars_->begin();
1448 it != scrollbars_->end();
1449 ++it)
1450 if ((*it)->orientation() == orientation)
1451 return true;
1453 return false;
1456 void LayerImpl::ScrollbarParametersDidChange(bool on_resize) {
1457 if (!scrollbars_)
1458 return;
1460 for (ScrollbarSet::iterator it = scrollbars_->begin();
1461 it != scrollbars_->end();
1462 ++it) {
1463 bool is_scroll_layer = (*it)->ScrollLayerId() == layer_id_;
1464 bool scroll_layer_resized = is_scroll_layer && on_resize;
1465 (*it)->ScrollbarParametersDidChange(scroll_layer_resized);
1469 void LayerImpl::SetNeedsPushProperties() {
1470 if (needs_push_properties_)
1471 return;
1472 if (!parent_should_know_need_push_properties() && parent_)
1473 parent_->AddDependentNeedsPushProperties();
1474 needs_push_properties_ = true;
1477 void LayerImpl::AddDependentNeedsPushProperties() {
1478 DCHECK_GE(num_dependents_need_push_properties_, 0);
1480 if (!parent_should_know_need_push_properties() && parent_)
1481 parent_->AddDependentNeedsPushProperties();
1483 num_dependents_need_push_properties_++;
1486 void LayerImpl::RemoveDependentNeedsPushProperties() {
1487 num_dependents_need_push_properties_--;
1488 DCHECK_GE(num_dependents_need_push_properties_, 0);
1490 if (!parent_should_know_need_push_properties() && parent_)
1491 parent_->RemoveDependentNeedsPushProperties();
1494 void LayerImpl::GetAllPrioritizedTilesForTracing(
1495 std::vector<PrioritizedTile>* prioritized_tiles) const {
1498 void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const {
1499 TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
1500 TRACE_DISABLED_BY_DEFAULT("cc.debug"),
1501 state,
1502 "cc::LayerImpl",
1503 LayerTypeAsString(),
1504 this);
1505 state->SetInteger("layer_id", id());
1506 MathUtil::AddToTracedValue("bounds", bounds_, state);
1508 state->SetDouble("opacity", opacity());
1510 MathUtil::AddToTracedValue("position", position_, state);
1512 state->SetInteger("draws_content", DrawsContent());
1513 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1515 MathUtil::AddToTracedValue(
1516 "scroll_offset", scroll_offset_ ? scroll_offset_->Current(IsActive())
1517 : gfx::ScrollOffset(),
1518 state);
1520 MathUtil::AddToTracedValue("transform_origin", transform_origin_, state);
1522 bool clipped;
1523 gfx::QuadF layer_quad = MathUtil::MapQuad(
1524 screen_space_transform(),
1525 gfx::QuadF(gfx::Rect(content_bounds())),
1526 &clipped);
1527 MathUtil::AddToTracedValue("layer_quad", layer_quad, state);
1528 if (!touch_event_handler_region_.IsEmpty()) {
1529 state->BeginArray("touch_event_handler_region");
1530 touch_event_handler_region_.AsValueInto(state);
1531 state->EndArray();
1533 if (have_wheel_event_handlers_) {
1534 gfx::Rect wheel_rect(content_bounds());
1535 Region wheel_region(wheel_rect);
1536 state->BeginArray("wheel_event_handler_region");
1537 wheel_region.AsValueInto(state);
1538 state->EndArray();
1540 if (have_scroll_event_handlers_) {
1541 gfx::Rect scroll_rect(content_bounds());
1542 Region scroll_region(scroll_rect);
1543 state->BeginArray("scroll_event_handler_region");
1544 scroll_region.AsValueInto(state);
1545 state->EndArray();
1547 if (!non_fast_scrollable_region_.IsEmpty()) {
1548 state->BeginArray("non_fast_scrollable_region");
1549 non_fast_scrollable_region_.AsValueInto(state);
1550 state->EndArray();
1552 if (scroll_blocks_on_) {
1553 state->SetInteger("scroll_blocks_on", scroll_blocks_on_);
1556 state->BeginArray("children");
1557 for (size_t i = 0; i < children_.size(); ++i) {
1558 state->BeginDictionary();
1559 children_[i]->AsValueInto(state);
1560 state->EndDictionary();
1562 state->EndArray();
1563 if (mask_layer_) {
1564 state->BeginDictionary("mask_layer");
1565 mask_layer_->AsValueInto(state);
1566 state->EndDictionary();
1568 if (replica_layer_) {
1569 state->BeginDictionary("replica_layer");
1570 replica_layer_->AsValueInto(state);
1571 state->EndDictionary();
1574 if (scroll_parent_)
1575 state->SetInteger("scroll_parent", scroll_parent_->id());
1577 if (clip_parent_)
1578 state->SetInteger("clip_parent", clip_parent_->id());
1580 state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1581 state->SetBoolean("contents_opaque", contents_opaque());
1583 state->SetBoolean(
1584 "has_animation_bounds",
1585 layer_animation_controller()->HasAnimationThatInflatesBounds());
1587 gfx::BoxF box;
1588 if (LayerUtils::GetAnimationBounds(*this, &box))
1589 MathUtil::AddToTracedValue("animation_bounds", box, state);
1591 if (debug_info_.get()) {
1592 std::string str;
1593 debug_info_->AppendAsTraceFormat(&str);
1594 base::JSONReader json_reader;
1595 scoped_ptr<base::Value> debug_info_value(json_reader.ReadToValue(str));
1597 if (debug_info_value->IsType(base::Value::TYPE_DICTIONARY)) {
1598 base::DictionaryValue* dictionary_value = nullptr;
1599 bool converted_to_dictionary =
1600 debug_info_value->GetAsDictionary(&dictionary_value);
1601 DCHECK(converted_to_dictionary);
1602 for (base::DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd();
1603 it.Advance()) {
1604 state->SetValue(it.key().data(), it.value().CreateDeepCopy());
1606 } else {
1607 NOTREACHED();
1611 if (!frame_timing_requests_.empty()) {
1612 state->BeginArray("frame_timing_requests");
1613 for (const auto& request : frame_timing_requests_) {
1614 state->BeginDictionary();
1615 state->SetInteger("request_id", request.id());
1616 MathUtil::AddToTracedValue("request_rect", request.rect(), state);
1617 state->EndDictionary();
1619 state->EndArray();
1623 bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const {
1624 return draw_properties_.last_drawn_render_surface_layer_list_id ==
1625 layer_tree_impl_->current_render_surface_list_id();
1628 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1630 void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
1631 benchmark->RunOnLayer(this);
1634 int LayerImpl::NumDescendantsThatDrawContent() const {
1635 return num_descendants_that_draw_content_;
1638 void LayerImpl::NotifyAnimationFinished(
1639 base::TimeTicks monotonic_time,
1640 Animation::TargetProperty target_property,
1641 int group) {
1642 if (target_property == Animation::SCROLL_OFFSET)
1643 layer_tree_impl_->InputScrollAnimationFinished();
1646 void LayerImpl::SetHasRenderSurface(bool should_have_render_surface) {
1647 if (!!render_surface() == should_have_render_surface)
1648 return;
1650 SetNeedsPushProperties();
1651 layer_tree_impl()->set_needs_update_draw_properties();
1652 if (should_have_render_surface) {
1653 render_surface_ = make_scoped_ptr(new RenderSurfaceImpl(this));
1654 return;
1656 render_surface_.reset();
1659 Region LayerImpl::GetInvalidationRegion() {
1660 return Region(update_rect_);
1663 gfx::Rect LayerImpl::GetEnclosingRectInTargetSpace() const {
1664 return MathUtil::MapEnclosingClippedRect(
1665 draw_properties_.target_space_transform,
1666 gfx::Rect(draw_properties_.content_bounds));
1669 gfx::Rect LayerImpl::GetScaledEnclosingRectInTargetSpace(float scale) const {
1670 gfx::Transform scaled_draw_transform =
1671 draw_properties_.target_space_transform;
1672 scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale);
1673 gfx::Size scaled_content_bounds =
1674 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), scale));
1675 return MathUtil::MapEnclosingClippedRect(scaled_draw_transform,
1676 gfx::Rect(scaled_content_bounds));
1679 } // namespace cc