Adding a logging class to cast.
[chromium-blink-merge.git] / cc / layers / layer_impl.cc
blob14f3e2afe1dedad71f987e1d6514b4bb8e22ed54
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/layer_impl.h"
7 #include "base/debug/trace_event.h"
8 #include "base/strings/stringprintf.h"
9 #include "cc/animation/animation_registrar.h"
10 #include "cc/animation/scrollbar_animation_controller.h"
11 #include "cc/animation/scrollbar_animation_controller_linear_fade.h"
12 #include "cc/animation/scrollbar_animation_controller_thinning.h"
13 #include "cc/base/math_util.h"
14 #include "cc/debug/debug_colors.h"
15 #include "cc/debug/layer_tree_debug_state.h"
16 #include "cc/debug/traced_value.h"
17 #include "cc/input/layer_scroll_offset_delegate.h"
18 #include "cc/layers/painted_scrollbar_layer_impl.h"
19 #include "cc/layers/quad_sink.h"
20 #include "cc/output/copy_output_request.h"
21 #include "cc/quads/debug_border_draw_quad.h"
22 #include "cc/trees/layer_tree_impl.h"
23 #include "cc/trees/layer_tree_settings.h"
24 #include "cc/trees/proxy.h"
25 #include "ui/gfx/point_conversions.h"
26 #include "ui/gfx/quad_f.h"
27 #include "ui/gfx/rect_conversions.h"
29 namespace cc {
31 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id)
32 : parent_(NULL),
33 scroll_parent_(NULL),
34 clip_parent_(NULL),
35 mask_layer_id_(-1),
36 replica_layer_id_(-1),
37 layer_id_(id),
38 layer_tree_impl_(tree_impl),
39 anchor_point_(0.5f, 0.5f),
40 anchor_point_z_(0.f),
41 scroll_offset_delegate_(NULL),
42 scrollable_(false),
43 should_scroll_on_main_thread_(false),
44 have_wheel_event_handlers_(false),
45 user_scrollable_horizontal_(true),
46 user_scrollable_vertical_(true),
47 background_color_(0),
48 stacking_order_changed_(false),
49 double_sided_(true),
50 layer_property_changed_(false),
51 masks_to_bounds_(false),
52 contents_opaque_(false),
53 opacity_(1.0),
54 preserves_3d_(false),
55 use_parent_backface_visibility_(false),
56 draw_checkerboard_for_missing_tiles_(false),
57 draws_content_(false),
58 hide_layer_and_subtree_(false),
59 force_render_surface_(false),
60 is_container_for_fixed_position_layers_(false),
61 draw_depth_(0.f),
62 compositing_reasons_(kCompositingReasonUnknown),
63 current_draw_mode_(DRAW_MODE_NONE),
64 horizontal_scrollbar_layer_(NULL),
65 vertical_scrollbar_layer_(NULL) {
66 DCHECK_GT(layer_id_, 0);
67 DCHECK(layer_tree_impl_);
68 layer_tree_impl_->RegisterLayer(this);
69 AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar();
70 layer_animation_controller_ =
71 registrar->GetAnimationControllerForId(layer_id_);
72 layer_animation_controller_->AddValueObserver(this);
75 LayerImpl::~LayerImpl() {
76 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
78 layer_tree_impl_->UnregisterLayer(this);
79 layer_animation_controller_->RemoveValueObserver(this);
81 if (scroll_children_) {
82 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
83 it != scroll_children_->end(); ++it)
84 (*it)->scroll_parent_ = NULL;
87 if (scroll_parent_)
88 scroll_parent_->RemoveScrollChild(this);
90 if (clip_children_) {
91 for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
92 it != clip_children_->end(); ++it)
93 (*it)->clip_parent_ = NULL;
96 if (clip_parent_)
97 clip_parent_->RemoveClipChild(this);
100 void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) {
101 child->set_parent(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();
110 ++it) {
111 if (*it == child) {
112 scoped_ptr<LayerImpl> ret = children_.take(it);
113 children_.erase(it);
114 layer_tree_impl()->set_needs_update_draw_properties();
115 return ret.Pass();
118 return scoped_ptr<LayerImpl>();
121 void LayerImpl::ClearChildList() {
122 if (children_.empty())
123 return;
125 children_.clear();
126 layer_tree_impl()->set_needs_update_draw_properties();
129 bool LayerImpl::HasAncestor(const LayerImpl* ancestor) const {
130 if (!ancestor)
131 return false;
133 for (const LayerImpl* layer = this; layer; layer = layer->parent()) {
134 if (layer == ancestor)
135 return true;
138 return false;
141 void LayerImpl::SetScrollParent(LayerImpl* parent) {
142 if (scroll_parent_ == parent)
143 return;
145 // Having both a scroll parent and a scroll offset delegate is unsupported.
146 DCHECK(!scroll_offset_delegate_);
148 if (scroll_parent_)
149 scroll_parent_->RemoveScrollChild(this);
151 scroll_parent_ = parent;
154 void LayerImpl::SetScrollChildren(std::set<LayerImpl*>* children) {
155 if (scroll_children_.get() == children)
156 return;
157 scroll_children_.reset(children);
160 void LayerImpl::RemoveScrollChild(LayerImpl* child) {
161 DCHECK(scroll_children_);
162 scroll_children_->erase(child);
163 if (scroll_children_->empty())
164 scroll_children_.reset();
167 void LayerImpl::SetClipParent(LayerImpl* ancestor) {
168 if (clip_parent_ == ancestor)
169 return;
171 if (clip_parent_)
172 clip_parent_->RemoveClipChild(this);
174 clip_parent_ = ancestor;
177 void LayerImpl::SetClipChildren(std::set<LayerImpl*>* children) {
178 if (clip_children_.get() == children)
179 return;
180 clip_children_.reset(children);
183 void LayerImpl::RemoveClipChild(LayerImpl* child) {
184 DCHECK(clip_children_);
185 clip_children_->erase(child);
186 if (clip_children_->empty())
187 clip_children_.reset();
190 void LayerImpl::PassCopyRequests(ScopedPtrVector<CopyOutputRequest>* requests) {
191 if (requests->empty())
192 return;
194 bool was_empty = copy_requests_.empty();
195 copy_requests_.insert_and_take(copy_requests_.end(), *requests);
196 requests->clear();
198 if (was_empty && layer_tree_impl()->IsActiveTree())
199 layer_tree_impl()->AddLayerWithCopyOutputRequest(this);
200 NoteLayerPropertyChangedForSubtree();
203 void LayerImpl::TakeCopyRequestsAndTransformToTarget(
204 ScopedPtrVector<CopyOutputRequest>* requests) {
205 if (copy_requests_.empty())
206 return;
208 size_t first_inserted_request = requests->size();
209 requests->insert_and_take(requests->end(), copy_requests_);
210 copy_requests_.clear();
212 for (size_t i = first_inserted_request; i < requests->size(); ++i) {
213 CopyOutputRequest* request = requests->at(i);
214 if (!request->has_area())
215 continue;
217 gfx::Rect request_in_layer_space = request->area();
218 gfx::Rect request_in_content_space =
219 LayerRectToContentRect(request_in_layer_space);
220 request->set_area(
221 MathUtil::MapClippedRect(draw_properties_.target_space_transform,
222 request_in_content_space));
225 if (layer_tree_impl()->IsActiveTree())
226 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
229 void LayerImpl::CreateRenderSurface() {
230 DCHECK(!draw_properties_.render_surface);
231 draw_properties_.render_surface =
232 make_scoped_ptr(new RenderSurfaceImpl(this));
233 draw_properties_.render_target = this;
236 void LayerImpl::ClearRenderSurface() {
237 draw_properties_.render_surface.reset();
240 scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const {
241 scoped_ptr<SharedQuadState> state = SharedQuadState::Create();
242 state->SetAll(draw_properties_.target_space_transform,
243 draw_properties_.content_bounds,
244 draw_properties_.visible_content_rect,
245 draw_properties_.clip_rect,
246 draw_properties_.is_clipped,
247 draw_properties_.opacity);
248 return state.Pass();
251 bool LayerImpl::WillDraw(DrawMode draw_mode,
252 ResourceProvider* resource_provider) {
253 // WillDraw/DidDraw must be matched.
254 DCHECK_NE(DRAW_MODE_NONE, draw_mode);
255 DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
256 current_draw_mode_ = draw_mode;
257 return true;
260 void LayerImpl::DidDraw(ResourceProvider* resource_provider) {
261 DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
262 current_draw_mode_ = DRAW_MODE_NONE;
265 bool LayerImpl::ShowDebugBorders() const {
266 return layer_tree_impl()->debug_state().show_debug_borders;
269 void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const {
270 if (draws_content_) {
271 *color = DebugColors::ContentLayerBorderColor();
272 *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl());
273 return;
276 if (masks_to_bounds_) {
277 *color = DebugColors::MaskingLayerBorderColor();
278 *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl());
279 return;
282 *color = DebugColors::ContainerLayerBorderColor();
283 *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl());
286 void LayerImpl::AppendDebugBorderQuad(
287 QuadSink* quad_sink,
288 const SharedQuadState* shared_quad_state,
289 AppendQuadsData* append_quads_data) const {
290 SkColor color;
291 float width;
292 GetDebugBorderProperties(&color, &width);
293 AppendDebugBorderQuad(
294 quad_sink, shared_quad_state, append_quads_data, color, width);
297 void LayerImpl::AppendDebugBorderQuad(QuadSink* quad_sink,
298 const SharedQuadState* shared_quad_state,
299 AppendQuadsData* append_quads_data,
300 SkColor color,
301 float width) const {
302 if (!ShowDebugBorders())
303 return;
305 gfx::Rect content_rect(content_bounds());
306 scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
307 DebugBorderDrawQuad::Create();
308 debug_border_quad->SetNew(shared_quad_state, content_rect, color, width);
309 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), append_quads_data);
312 bool LayerImpl::HasDelegatedContent() const {
313 return false;
316 bool LayerImpl::HasContributingDelegatedRenderPasses() const {
317 return false;
320 RenderPass::Id LayerImpl::FirstContributingRenderPassId() const {
321 return RenderPass::Id(0, 0);
324 RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id)
325 const {
326 return RenderPass::Id(0, 0);
329 ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const {
330 NOTREACHED();
331 return 0;
334 void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) {
335 // Pending tree never has sent scroll deltas
336 DCHECK(layer_tree_impl()->IsActiveTree());
338 if (sent_scroll_delta_ == sent_scroll_delta)
339 return;
341 sent_scroll_delta_ = sent_scroll_delta;
344 gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) {
345 DCHECK(scrollable());
346 gfx::Vector2dF scroll_hidden;
347 if (!user_scrollable_horizontal_) {
348 scroll_hidden.set_x(scroll.x());
349 scroll.set_x(0.f);
351 if (!user_scrollable_vertical_) {
352 scroll_hidden.set_y(scroll.y());
353 scroll.set_y(0.f);
356 gfx::Vector2dF min_delta = -scroll_offset_;
357 gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_;
358 // Clamp new_delta so that position + delta stays within scroll bounds.
359 gfx::Vector2dF new_delta = (ScrollDelta() + scroll);
360 new_delta.SetToMax(min_delta);
361 new_delta.SetToMin(max_delta);
362 gfx::Vector2dF unscrolled =
363 ScrollDelta() + scroll + scroll_hidden - new_delta;
364 SetScrollDelta(new_delta);
365 return unscrolled;
368 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
369 // Pending tree never has sent scroll deltas
370 DCHECK(layer_tree_impl()->IsActiveTree());
372 // Apply sent scroll deltas to scroll position / scroll delta as if the
373 // main thread had applied them and then committed those values.
375 // This function should not change the total scroll offset; it just shifts
376 // some of the scroll delta to the scroll offset. Therefore, adjust these
377 // variables directly rather than calling the scroll offset delegate to
378 // avoid sending it multiple spurious calls.
380 // Because of the way scroll delta is calculated with a delegate, this will
381 // leave the total scroll offset unchanged on this layer regardless of
382 // whether a delegate is being used.
383 scroll_offset_ += sent_scroll_delta_;
384 scroll_delta_ -= sent_scroll_delta_;
385 sent_scroll_delta_ = gfx::Vector2d();
388 void LayerImpl::ApplyScrollDeltasSinceBeginFrame() {
389 // Only the pending tree can have missing scrolls.
390 DCHECK(layer_tree_impl()->IsPendingTree());
391 if (!scrollable())
392 return;
394 // Pending tree should never have sent scroll deltas.
395 DCHECK(sent_scroll_delta().IsZero());
397 LayerImpl* active_twin = layer_tree_impl()->FindActiveTreeLayerById(id());
398 if (active_twin) {
399 // Scrolls that happens after begin frame (where the sent scroll delta
400 // comes from) and commit need to be applied to the pending tree
401 // so that it is up to date with the total scroll.
402 SetScrollDelta(active_twin->ScrollDelta() -
403 active_twin->sent_scroll_delta());
407 InputHandler::ScrollStatus LayerImpl::TryScroll(
408 gfx::PointF screen_space_point,
409 InputHandler::ScrollInputType type) const {
410 if (should_scroll_on_main_thread()) {
411 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
412 return InputHandler::ScrollOnMainThread;
415 if (!screen_space_transform().IsInvertible()) {
416 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform");
417 return InputHandler::ScrollIgnored;
420 if (!non_fast_scrollable_region().IsEmpty()) {
421 bool clipped = false;
422 gfx::Transform inverse_screen_space_transform(
423 gfx::Transform::kSkipInitialization);
424 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) {
425 // TODO(shawnsingh): We shouldn't be applying a projection if screen space
426 // transform is uninvertible here. Perhaps we should be returning
427 // ScrollOnMainThread in this case?
430 gfx::PointF hit_test_point_in_content_space =
431 MathUtil::ProjectPoint(inverse_screen_space_transform,
432 screen_space_point,
433 &clipped);
434 gfx::PointF hit_test_point_in_layer_space =
435 gfx::ScalePoint(hit_test_point_in_content_space,
436 1.f / contents_scale_x(),
437 1.f / contents_scale_y());
438 if (!clipped &&
439 non_fast_scrollable_region().Contains(
440 gfx::ToRoundedPoint(hit_test_point_in_layer_space))) {
441 TRACE_EVENT0("cc",
442 "LayerImpl::tryScroll: Failed NonFastScrollableRegion");
443 return InputHandler::ScrollOnMainThread;
447 if (type == InputHandler::Wheel && have_wheel_event_handlers()) {
448 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed WheelEventHandlers");
449 return InputHandler::ScrollOnMainThread;
452 if (!scrollable()) {
453 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable");
454 return InputHandler::ScrollIgnored;
457 if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) {
458 TRACE_EVENT0("cc",
459 "LayerImpl::tryScroll: Ignored. Technically scrollable,"
460 " but has no affordance in either direction.");
461 return InputHandler::ScrollIgnored;
464 if (!user_scrollable_horizontal_ && !user_scrollable_vertical_) {
465 TRACE_EVENT0("cc",
466 "LayerImpl::TryScroll: Ignored. User gesture is not allowed"
467 " to scroll this layer.");
468 return InputHandler::ScrollIgnored;
471 return InputHandler::ScrollStarted;
474 bool LayerImpl::DrawCheckerboardForMissingTiles() const {
475 return draw_checkerboard_for_missing_tiles_ &&
476 !layer_tree_impl()->settings().background_color_instead_of_checkerboard;
479 gfx::Rect LayerImpl::LayerRectToContentRect(
480 const gfx::RectF& layer_rect) const {
481 gfx::RectF content_rect =
482 gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y());
483 // Intersect with content rect to avoid the extra pixel because for some
484 // values x and y, ceil((x / y) * y) may be x + 1.
485 content_rect.Intersect(gfx::Rect(content_bounds()));
486 return gfx::ToEnclosingRect(content_rect);
489 skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
490 return skia::RefPtr<SkPicture>();
493 bool LayerImpl::AreVisibleResourcesReady() const {
494 return true;
497 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
498 return LayerImpl::Create(tree_impl, layer_id_);
501 void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
502 layer->SetAnchorPoint(anchor_point_);
503 layer->SetAnchorPointZ(anchor_point_z_);
504 layer->SetBackgroundColor(background_color_);
505 layer->SetBounds(bounds_);
506 layer->SetContentBounds(content_bounds());
507 layer->SetContentsScale(contents_scale_x(), contents_scale_y());
508 layer->SetDebugName(debug_name_);
509 layer->SetCompositingReasons(compositing_reasons_);
510 layer->SetDoubleSided(double_sided_);
511 layer->SetDrawCheckerboardForMissingTiles(
512 draw_checkerboard_for_missing_tiles_);
513 layer->SetForceRenderSurface(force_render_surface_);
514 layer->SetDrawsContent(DrawsContent());
515 layer->SetHideLayerAndSubtree(hide_layer_and_subtree_);
516 layer->SetFilters(filters());
517 layer->SetBackgroundFilters(background_filters());
518 layer->SetMasksToBounds(masks_to_bounds_);
519 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
520 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
521 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
522 layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
523 layer->SetContentsOpaque(contents_opaque_);
524 layer->SetOpacity(opacity_);
525 layer->SetPosition(position_);
526 layer->SetIsContainerForFixedPositionLayers(
527 is_container_for_fixed_position_layers_);
528 layer->SetFixedContainerSizeDelta(fixed_container_size_delta_);
529 layer->SetPositionConstraint(position_constraint_);
530 layer->SetPreserves3d(preserves_3d());
531 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
532 layer->SetSublayerTransform(sublayer_transform_);
533 layer->SetTransform(transform_);
535 layer->SetScrollable(scrollable_);
536 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
537 layer->set_user_scrollable_vertical(user_scrollable_vertical_);
538 layer->SetScrollOffsetAndDelta(
539 scroll_offset_, layer->ScrollDelta() - layer->sent_scroll_delta());
540 layer->SetSentScrollDelta(gfx::Vector2d());
542 layer->SetMaxScrollOffset(max_scroll_offset_);
544 LayerImpl* scroll_parent = NULL;
545 if (scroll_parent_)
546 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
548 layer->SetScrollParent(scroll_parent);
549 if (scroll_children_) {
550 std::set<LayerImpl*>* scroll_children = new std::set<LayerImpl*>;
551 for (std::set<LayerImpl*>::iterator it = scroll_children_->begin();
552 it != scroll_children_->end(); ++it)
553 scroll_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
554 layer->SetScrollChildren(scroll_children);
557 LayerImpl* clip_parent = NULL;
558 if (clip_parent_) {
559 clip_parent = layer->layer_tree_impl()->LayerById(
560 clip_parent_->id());
563 layer->SetClipParent(clip_parent);
564 if (clip_children_) {
565 std::set<LayerImpl*>* clip_children = new std::set<LayerImpl*>;
566 for (std::set<LayerImpl*>::iterator it = clip_children_->begin();
567 it != clip_children_->end(); ++it)
568 clip_children->insert(layer->layer_tree_impl()->LayerById((*it)->id()));
569 layer->SetClipChildren(clip_children);
572 layer->PassCopyRequests(&copy_requests_);
574 // If the main thread commits multiple times before the impl thread actually
575 // draws, then damage tracking will become incorrect if we simply clobber the
576 // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e.
577 // union) any update changes that have occurred on the main thread.
578 update_rect_.Union(layer->update_rect());
579 layer->set_update_rect(update_rect_);
581 layer->SetStackingOrderChanged(stacking_order_changed_);
583 // Reset any state that should be cleared for the next update.
584 stacking_order_changed_ = false;
585 update_rect_ = gfx::RectF();
588 base::DictionaryValue* LayerImpl::LayerTreeAsJson() const {
589 base::DictionaryValue* result = new base::DictionaryValue;
590 result->SetString("LayerType", LayerTypeAsString());
592 base::ListValue* list = new base::ListValue;
593 list->AppendInteger(bounds().width());
594 list->AppendInteger(bounds().height());
595 result->Set("Bounds", list);
597 list = new base::ListValue;
598 list->AppendDouble(position_.x());
599 list->AppendDouble(position_.y());
600 result->Set("Position", list);
602 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform;
603 double transform[16];
604 gfx_transform.matrix().asColMajord(transform);
605 list = new base::ListValue;
606 for (int i = 0; i < 16; ++i)
607 list->AppendDouble(transform[i]);
608 result->Set("DrawTransform", list);
610 result->SetBoolean("DrawsContent", draws_content_);
611 result->SetDouble("Opacity", opacity());
612 result->SetBoolean("ContentsOpaque", contents_opaque_);
614 if (scrollable_)
615 result->SetBoolean("Scrollable", scrollable_);
617 list = new base::ListValue;
618 for (size_t i = 0; i < children_.size(); ++i)
619 list->Append(children_[i]->LayerTreeAsJson());
620 result->Set("Children", list);
622 return result;
625 void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) {
626 if (stacking_order_changed) {
627 stacking_order_changed_ = true;
628 NoteLayerPropertyChangedForSubtree();
632 void LayerImpl::NoteLayerPropertyChanged() {
633 layer_property_changed_ = true;
634 layer_tree_impl()->set_needs_update_draw_properties();
637 void LayerImpl::NoteLayerPropertyChangedForSubtree() {
638 NoteLayerPropertyChanged();
639 NoteLayerPropertyChangedForDescendants();
642 void LayerImpl::NoteLayerPropertyChangedForDescendants() {
643 layer_tree_impl()->set_needs_update_draw_properties();
644 for (size_t i = 0; i < children_.size(); ++i)
645 children_[i]->NoteLayerPropertyChangedForSubtree();
648 const char* LayerImpl::LayerTypeAsString() const {
649 return "cc::LayerImpl";
652 void LayerImpl::ResetAllChangeTrackingForSubtree() {
653 layer_property_changed_ = false;
655 update_rect_ = gfx::RectF();
657 if (draw_properties_.render_surface)
658 draw_properties_.render_surface->ResetPropertyChangedFlag();
660 if (mask_layer_)
661 mask_layer_->ResetAllChangeTrackingForSubtree();
663 if (replica_layer_) {
664 // This also resets the replica mask, if it exists.
665 replica_layer_->ResetAllChangeTrackingForSubtree();
668 for (size_t i = 0; i < children_.size(); ++i)
669 children_[i]->ResetAllChangeTrackingForSubtree();
672 bool LayerImpl::LayerIsAlwaysDamaged() const {
673 return false;
676 void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
677 SetFilters(filters);
680 void LayerImpl::OnOpacityAnimated(float opacity) {
681 SetOpacity(opacity);
684 void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
685 SetTransform(transform);
688 bool LayerImpl::IsActive() const {
689 return layer_tree_impl_->IsActiveTree();
692 void LayerImpl::SetBounds(gfx::Size bounds) {
693 if (bounds_ == bounds)
694 return;
696 bounds_ = bounds;
698 if (masks_to_bounds())
699 NoteLayerPropertyChangedForSubtree();
700 else
701 NoteLayerPropertyChanged();
704 void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) {
705 int new_layer_id = mask_layer ? mask_layer->id() : -1;
707 if (mask_layer) {
708 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl());
709 DCHECK_NE(new_layer_id, mask_layer_id_);
710 } else if (new_layer_id == mask_layer_id_) {
711 return;
714 mask_layer_ = mask_layer.Pass();
715 mask_layer_id_ = new_layer_id;
716 if (mask_layer_)
717 mask_layer_->set_parent(this);
718 NoteLayerPropertyChangedForSubtree();
721 scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() {
722 mask_layer_id_ = -1;
723 return mask_layer_.Pass();
726 void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) {
727 int new_layer_id = replica_layer ? replica_layer->id() : -1;
729 if (replica_layer) {
730 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl());
731 DCHECK_NE(new_layer_id, replica_layer_id_);
732 } else if (new_layer_id == replica_layer_id_) {
733 return;
736 replica_layer_ = replica_layer.Pass();
737 replica_layer_id_ = new_layer_id;
738 if (replica_layer_)
739 replica_layer_->set_parent(this);
740 NoteLayerPropertyChangedForSubtree();
743 scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() {
744 replica_layer_id_ = -1;
745 return replica_layer_.Pass();
748 ScrollbarLayerImplBase* LayerImpl::ToScrollbarLayer() {
749 return NULL;
752 void LayerImpl::SetDrawsContent(bool draws_content) {
753 if (draws_content_ == draws_content)
754 return;
756 draws_content_ = draws_content;
757 NoteLayerPropertyChanged();
760 void LayerImpl::SetHideLayerAndSubtree(bool hide) {
761 if (hide_layer_and_subtree_ == hide)
762 return;
764 hide_layer_and_subtree_ = hide;
765 NoteLayerPropertyChangedForSubtree();
768 void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) {
769 if (anchor_point_ == anchor_point)
770 return;
772 anchor_point_ = anchor_point;
773 NoteLayerPropertyChangedForSubtree();
776 void LayerImpl::SetAnchorPointZ(float anchor_point_z) {
777 if (anchor_point_z_ == anchor_point_z)
778 return;
780 anchor_point_z_ = anchor_point_z;
781 NoteLayerPropertyChangedForSubtree();
784 void LayerImpl::SetBackgroundColor(SkColor background_color) {
785 if (background_color_ == background_color)
786 return;
788 background_color_ = background_color;
789 NoteLayerPropertyChanged();
792 SkColor LayerImpl::SafeOpaqueBackgroundColor() const {
793 SkColor color = background_color();
794 if (SkColorGetA(color) == 255 && !contents_opaque()) {
795 color = SK_ColorTRANSPARENT;
796 } else if (SkColorGetA(color) != 255 && contents_opaque()) {
797 for (const LayerImpl* layer = parent(); layer;
798 layer = layer->parent()) {
799 color = layer->background_color();
800 if (SkColorGetA(color) == 255)
801 break;
803 if (SkColorGetA(color) != 255)
804 color = layer_tree_impl()->background_color();
805 if (SkColorGetA(color) != 255)
806 color = SkColorSetA(color, 255);
808 return color;
811 void LayerImpl::SetFilters(const FilterOperations& filters) {
812 if (filters_ == filters)
813 return;
815 filters_ = filters;
816 NoteLayerPropertyChangedForSubtree();
819 bool LayerImpl::FilterIsAnimating() const {
820 return layer_animation_controller_->IsAnimatingProperty(Animation::Filter);
823 bool LayerImpl::FilterIsAnimatingOnImplOnly() const {
824 Animation* filter_animation =
825 layer_animation_controller_->GetAnimation(Animation::Filter);
826 return filter_animation && filter_animation->is_impl_only();
829 void LayerImpl::SetBackgroundFilters(
830 const FilterOperations& filters) {
831 if (background_filters_ == filters)
832 return;
834 background_filters_ = filters;
835 NoteLayerPropertyChanged();
838 void LayerImpl::SetMasksToBounds(bool masks_to_bounds) {
839 if (masks_to_bounds_ == masks_to_bounds)
840 return;
842 masks_to_bounds_ = masks_to_bounds;
843 NoteLayerPropertyChangedForSubtree();
846 void LayerImpl::SetContentsOpaque(bool opaque) {
847 if (contents_opaque_ == opaque)
848 return;
850 contents_opaque_ = opaque;
851 NoteLayerPropertyChangedForSubtree();
854 void LayerImpl::SetOpacity(float opacity) {
855 if (opacity_ == opacity)
856 return;
858 opacity_ = opacity;
859 NoteLayerPropertyChangedForSubtree();
862 bool LayerImpl::OpacityIsAnimating() const {
863 return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity);
866 bool LayerImpl::OpacityIsAnimatingOnImplOnly() const {
867 Animation* opacity_animation =
868 layer_animation_controller_->GetAnimation(Animation::Opacity);
869 return opacity_animation && opacity_animation->is_impl_only();
872 void LayerImpl::SetPosition(gfx::PointF position) {
873 if (position_ == position)
874 return;
876 position_ = position;
877 NoteLayerPropertyChangedForSubtree();
880 void LayerImpl::SetPreserves3d(bool preserves3_d) {
881 if (preserves_3d_ == preserves3_d)
882 return;
884 preserves_3d_ = preserves3_d;
885 NoteLayerPropertyChangedForSubtree();
888 void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) {
889 if (sublayer_transform_ == sublayer_transform)
890 return;
892 sublayer_transform_ = sublayer_transform;
893 // Sublayer transform does not affect the current layer; it affects only its
894 // children.
895 NoteLayerPropertyChangedForDescendants();
898 void LayerImpl::SetTransform(const gfx::Transform& transform) {
899 if (transform_ == transform)
900 return;
902 transform_ = transform;
903 NoteLayerPropertyChangedForSubtree();
906 bool LayerImpl::TransformIsAnimating() const {
907 return layer_animation_controller_->IsAnimatingProperty(Animation::Transform);
910 bool LayerImpl::TransformIsAnimatingOnImplOnly() const {
911 Animation* transform_animation =
912 layer_animation_controller_->GetAnimation(Animation::Transform);
913 return transform_animation && transform_animation->is_impl_only();
916 void LayerImpl::SetContentBounds(gfx::Size content_bounds) {
917 if (this->content_bounds() == content_bounds)
918 return;
920 draw_properties_.content_bounds = content_bounds;
921 NoteLayerPropertyChanged();
924 void LayerImpl::SetContentsScale(float contents_scale_x,
925 float contents_scale_y) {
926 if (this->contents_scale_x() == contents_scale_x &&
927 this->contents_scale_y() == contents_scale_y)
928 return;
930 draw_properties_.contents_scale_x = contents_scale_x;
931 draw_properties_.contents_scale_y = contents_scale_y;
932 NoteLayerPropertyChanged();
935 void LayerImpl::CalculateContentsScale(
936 float ideal_contents_scale,
937 float device_scale_factor,
938 float page_scale_factor,
939 bool animating_transform_to_screen,
940 float* contents_scale_x,
941 float* contents_scale_y,
942 gfx::Size* content_bounds) {
943 // Base LayerImpl has all of its content scales and content bounds pushed
944 // from its Layer during commit and just reuses those values as-is.
945 *contents_scale_x = this->contents_scale_x();
946 *contents_scale_y = this->contents_scale_y();
947 *content_bounds = this->content_bounds();
950 void LayerImpl::UpdateScrollbarPositions() {
951 gfx::Vector2dF current_offset = scroll_offset_ + ScrollDelta();
953 gfx::RectF viewport(PointAtOffsetFromOrigin(current_offset), bounds_);
954 gfx::SizeF scrollable_size(max_scroll_offset_.x() + bounds_.width(),
955 max_scroll_offset_.y() + bounds_.height());
956 if (horizontal_scrollbar_layer_) {
957 horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x());
958 horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x());
959 horizontal_scrollbar_layer_->SetVisibleToTotalLengthRatio(
960 viewport.width() / scrollable_size.width());
962 if (vertical_scrollbar_layer_) {
963 vertical_scrollbar_layer_->SetCurrentPos(current_offset.y());
964 vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y());
965 vertical_scrollbar_layer_->SetVisibleToTotalLengthRatio(
966 viewport.height() / scrollable_size.height());
969 if (current_offset == last_scroll_offset_)
970 return;
971 last_scroll_offset_ = current_offset;
973 if (scrollbar_animation_controller_) {
974 bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
975 layer_tree_impl_->CurrentPhysicalTimeTicks());
976 if (should_animate)
977 layer_tree_impl_->StartScrollbarAnimation();
980 // Get the current_offset_.y() value for a sanity-check on scrolling
981 // benchmark metrics. Specifically, we want to make sure
982 // BasicMouseWheelSmoothScrollGesture has proper scroll curves.
983 if (layer_tree_impl()->IsActiveTree()) {
984 TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y());
988 void LayerImpl::SetScrollOffsetDelegate(
989 LayerScrollOffsetDelegate* scroll_offset_delegate) {
990 // Having both a scroll parent and a scroll offset delegate is unsupported.
991 DCHECK(!scroll_parent_);
992 if (!scroll_offset_delegate && scroll_offset_delegate_) {
993 scroll_delta_ =
994 scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
996 gfx::Vector2dF total_offset = TotalScrollOffset();
997 scroll_offset_delegate_ = scroll_offset_delegate;
998 if (scroll_offset_delegate_) {
999 scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
1000 scroll_offset_delegate_->SetTotalScrollOffset(total_offset);
1004 bool LayerImpl::IsExternalFlingActive() const {
1005 return scroll_offset_delegate_ &&
1006 scroll_offset_delegate_->IsExternalFlingActive();
1009 void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) {
1010 SetScrollOffsetAndDelta(scroll_offset, ScrollDelta());
1013 void LayerImpl::SetScrollOffsetAndDelta(gfx::Vector2d scroll_offset,
1014 gfx::Vector2dF scroll_delta) {
1015 bool changed = false;
1017 if (scroll_offset_ != scroll_offset) {
1018 changed = true;
1019 scroll_offset_ = scroll_offset;
1021 if (scroll_offset_delegate_)
1022 scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
1025 if (ScrollDelta() != scroll_delta) {
1026 changed = true;
1027 if (layer_tree_impl()->IsActiveTree()) {
1028 LayerImpl* pending_twin =
1029 layer_tree_impl()->FindPendingTreeLayerById(id());
1030 if (pending_twin) {
1031 // The pending twin can't mirror the scroll delta of the active
1032 // layer. Although the delta - sent scroll delta difference is
1033 // identical for both twins, the sent scroll delta for the pending
1034 // layer is zero, as anything that has been sent has been baked
1035 // into the layer's position/scroll offset as a part of commit.
1036 DCHECK(pending_twin->sent_scroll_delta().IsZero());
1037 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
1041 if (scroll_offset_delegate_) {
1042 scroll_offset_delegate_->SetTotalScrollOffset(scroll_offset_ +
1043 scroll_delta);
1044 } else {
1045 scroll_delta_ = scroll_delta;
1049 if (changed) {
1050 NoteLayerPropertyChangedForSubtree();
1051 UpdateScrollbarPositions();
1055 gfx::Vector2dF LayerImpl::ScrollDelta() const {
1056 if (scroll_offset_delegate_)
1057 return scroll_offset_delegate_->GetTotalScrollOffset() - scroll_offset_;
1058 return scroll_delta_;
1061 void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) {
1062 SetScrollOffsetAndDelta(scroll_offset_, scroll_delta);
1065 gfx::Vector2dF LayerImpl::TotalScrollOffset() const {
1066 return scroll_offset_ + ScrollDelta();
1069 void LayerImpl::SetDoubleSided(bool double_sided) {
1070 if (double_sided_ == double_sided)
1071 return;
1073 double_sided_ = double_sided;
1074 NoteLayerPropertyChangedForSubtree();
1077 Region LayerImpl::VisibleContentOpaqueRegion() const {
1078 if (contents_opaque())
1079 return visible_content_rect();
1080 return Region();
1083 void LayerImpl::DidBeginTracing() {}
1085 void LayerImpl::DidLoseOutputSurface() {}
1087 void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) {
1088 if (max_scroll_offset_ == max_scroll_offset)
1089 return;
1090 max_scroll_offset_ = max_scroll_offset;
1092 if (scroll_offset_delegate_)
1093 scroll_offset_delegate_->SetMaxScrollOffset(max_scroll_offset_);
1095 layer_tree_impl()->set_needs_update_draw_properties();
1096 UpdateScrollbarPositions();
1099 void LayerImpl::DidBecomeActive() {
1100 if (layer_tree_impl_->settings().scrollbar_animator ==
1101 LayerTreeSettings::NoAnimator) {
1102 return;
1105 bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ ||
1106 vertical_scrollbar_layer_;
1107 if (!need_scrollbar_animation_controller) {
1108 scrollbar_animation_controller_.reset();
1109 return;
1112 if (scrollbar_animation_controller_)
1113 return;
1115 switch (layer_tree_impl_->settings().scrollbar_animator) {
1116 case LayerTreeSettings::LinearFade: {
1117 base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(
1118 layer_tree_impl_->settings().scrollbar_linear_fade_delay_ms);
1119 base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(
1120 layer_tree_impl_->settings().scrollbar_linear_fade_length_ms);
1122 scrollbar_animation_controller_ =
1123 ScrollbarAnimationControllerLinearFade::Create(
1124 this, fadeout_delay, fadeout_length)
1125 .PassAs<ScrollbarAnimationController>();
1126 break;
1128 case LayerTreeSettings::Thinning: {
1129 scrollbar_animation_controller_ =
1130 ScrollbarAnimationControllerThinning::Create(this)
1131 .PassAs<ScrollbarAnimationController>();
1132 break;
1134 case LayerTreeSettings::NoAnimator:
1135 NOTREACHED();
1136 break;
1139 void LayerImpl::SetHorizontalScrollbarLayer(
1140 ScrollbarLayerImplBase* scrollbar_layer) {
1141 horizontal_scrollbar_layer_ = scrollbar_layer;
1142 if (horizontal_scrollbar_layer_)
1143 horizontal_scrollbar_layer_->set_scroll_layer_id(id());
1146 void LayerImpl::SetVerticalScrollbarLayer(
1147 ScrollbarLayerImplBase* scrollbar_layer) {
1148 vertical_scrollbar_layer_ = scrollbar_layer;
1149 if (vertical_scrollbar_layer_)
1150 vertical_scrollbar_layer_->set_scroll_layer_id(id());
1153 static scoped_ptr<base::Value>
1154 CompositingReasonsAsValue(CompositingReasons reasons) {
1155 scoped_ptr<base::ListValue> reason_list(new base::ListValue());
1157 if (reasons == kCompositingReasonUnknown) {
1158 reason_list->AppendString("No reasons given");
1159 return reason_list.PassAs<base::Value>();
1162 if (reasons & kCompositingReason3DTransform)
1163 reason_list->AppendString("Has a 3d Transform");
1165 if (reasons & kCompositingReasonVideo)
1166 reason_list->AppendString("Is accelerated video");
1168 if (reasons & kCompositingReasonCanvas)
1169 reason_list->AppendString("Is accelerated canvas");
1171 if (reasons & kCompositingReasonPlugin)
1172 reason_list->AppendString("Is accelerated plugin");
1174 if (reasons & kCompositingReasonIFrame)
1175 reason_list->AppendString("Is accelerated iframe");
1177 if (reasons & kCompositingReasonBackfaceVisibilityHidden)
1178 reason_list->AppendString("Has backface-visibility: hidden");
1180 if (reasons & kCompositingReasonAnimation)
1181 reason_list->AppendString("Has accelerated animation or transition");
1183 if (reasons & kCompositingReasonFilters)
1184 reason_list->AppendString("Has accelerated filters");
1186 if (reasons & kCompositingReasonPositionFixed)
1187 reason_list->AppendString("Is fixed position");
1189 if (reasons & kCompositingReasonPositionSticky)
1190 reason_list->AppendString("Is sticky position");
1192 if (reasons & kCompositingReasonOverflowScrollingTouch)
1193 reason_list->AppendString("Is a scrollable overflow element");
1195 if (reasons & kCompositingReasonAssumedOverlap)
1196 reason_list->AppendString("Might overlap a composited animation");
1198 if (reasons & kCompositingReasonOverlap)
1199 reason_list->AppendString("Overlaps other composited content");
1201 if (reasons & kCompositingReasonNegativeZIndexChildren) {
1202 reason_list->AppendString("Might overlap negative z-index "
1203 "composited content");
1206 if (reasons & kCompositingReasonTransformWithCompositedDescendants) {
1207 reason_list->AppendString("Has transform needed by a "
1208 "composited descendant");
1211 if (reasons & kCompositingReasonOpacityWithCompositedDescendants)
1212 reason_list->AppendString("Has opacity needed by a composited descendant");
1214 if (reasons & kCompositingReasonMaskWithCompositedDescendants)
1215 reason_list->AppendString("Has a mask needed by a composited descendant");
1217 if (reasons & kCompositingReasonReflectionWithCompositedDescendants)
1218 reason_list->AppendString("Has a reflection with a composited descendant");
1220 if (reasons & kCompositingReasonFilterWithCompositedDescendants)
1221 reason_list->AppendString("Has filter effect with a composited descendant");
1223 if (reasons & kCompositingReasonBlendingWithCompositedDescendants)
1224 reason_list->AppendString("Has a blend mode with a composited descendant");
1226 if (reasons & kCompositingReasonClipsCompositingDescendants)
1227 reason_list->AppendString("Clips a composited descendant");
1229 if (reasons & kCompositingReasonPerspective) {
1230 reason_list->AppendString("Has a perspective transform needed by a "
1231 "composited 3d descendant");
1234 if (reasons & kCompositingReasonPreserve3D) {
1235 reason_list->AppendString("Has preserves-3d style with composited "
1236 "3d descendant");
1239 if (reasons & kCompositingReasonReflectionOfCompositedParent)
1240 reason_list->AppendString("Is the reflection of a composited layer");
1242 if (reasons & kCompositingReasonRoot)
1243 reason_list->AppendString("Is the root");
1245 if (reasons & kCompositingReasonLayerForClip)
1246 reason_list->AppendString("Convenience layer, to clip subtree");
1248 if (reasons & kCompositingReasonLayerForScrollbar)
1249 reason_list->AppendString("Convenience layer for rendering scrollbar");
1251 if (reasons & kCompositingReasonLayerForScrollingContainer)
1252 reason_list->AppendString("Convenience layer, the scrolling container");
1254 if (reasons & kCompositingReasonLayerForForeground) {
1255 reason_list->AppendString("Convenience layer, foreground when main layer "
1256 "has negative z-index composited content");
1259 if (reasons & kCompositingReasonLayerForBackground) {
1260 reason_list->AppendString("Convenience layer, background when main layer "
1261 "has a composited background");
1264 if (reasons & kCompositingReasonLayerForMask)
1265 reason_list->AppendString("Is a mask layer");
1267 if (reasons & kCompositingReasonOverflowScrollingParent)
1268 reason_list->AppendString("Scroll parent is not an ancestor");
1270 if (reasons & kCompositingReasonOutOfFlowClipping)
1271 reason_list->AppendString("Has clipping ancestor");
1273 return reason_list.PassAs<base::Value>();
1276 void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
1277 TracedValue::MakeDictIntoImplicitSnapshot(state, LayerTypeAsString(), this);
1278 state->SetInteger("layer_id", id());
1279 state->SetString("layer_name", debug_name());
1280 state->Set("bounds", MathUtil::AsValue(bounds()).release());
1281 state->SetInteger("draws_content", DrawsContent());
1282 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1283 state->Set("compositing_reasons",
1284 CompositingReasonsAsValue(compositing_reasons_).release());
1286 bool clipped;
1287 gfx::QuadF layer_quad = MathUtil::MapQuad(
1288 screen_space_transform(),
1289 gfx::QuadF(gfx::Rect(content_bounds())),
1290 &clipped);
1291 state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
1293 if (!touch_event_handler_region_.IsEmpty()) {
1294 state->Set("touch_event_handler_region",
1295 touch_event_handler_region_.AsValue().release());
1297 if (have_wheel_event_handlers_) {
1298 gfx::Rect wheel_rect(content_bounds());
1299 Region wheel_region(wheel_rect);
1300 state->Set("wheel_event_handler_region",
1301 wheel_region.AsValue().release());
1303 if (!non_fast_scrollable_region_.IsEmpty()) {
1304 state->Set("non_fast_scrollable_region",
1305 non_fast_scrollable_region_.AsValue().release());
1308 scoped_ptr<base::ListValue> children_list(new base::ListValue());
1309 for (size_t i = 0; i < children_.size(); ++i)
1310 children_list->Append(children_[i]->AsValue().release());
1311 state->Set("children", children_list.release());
1312 if (mask_layer_)
1313 state->Set("mask_layer", mask_layer_->AsValue().release());
1314 if (replica_layer_)
1315 state->Set("replica_layer", replica_layer_->AsValue().release());
1317 if (scroll_parent_)
1318 state->SetInteger("scroll_parent", scroll_parent_->id());
1320 if (clip_parent_)
1321 state->SetInteger("clip_parent", clip_parent_->id());
1323 state->SetBoolean("can_use_lcd_text", can_use_lcd_text());
1324 state->SetBoolean("contents_opaque", contents_opaque());
1327 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
1329 scoped_ptr<base::Value> LayerImpl::AsValue() const {
1330 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1331 AsValueInto(state.get());
1332 return state.PassAs<base::Value>();
1335 } // namespace cc