diff options
Diffstat (limited to 'chromium/cc/layers/layer.cc')
-rw-r--r-- | chromium/cc/layers/layer.cc | 982 |
1 files changed, 982 insertions, 0 deletions
diff --git a/chromium/cc/layers/layer.cc b/chromium/cc/layers/layer.cc new file mode 100644 index 00000000000..aa4a002dff4 --- /dev/null +++ b/chromium/cc/layers/layer.cc @@ -0,0 +1,982 @@ +// Copyright 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layers/layer.h" + +#include <algorithm> + +#include "base/location.h" +#include "base/metrics/histogram.h" +#include "base/single_thread_task_runner.h" +#include "cc/animation/animation.h" +#include "cc/animation/animation_events.h" +#include "cc/animation/layer_animation_controller.h" +#include "cc/layers/layer_impl.h" +#include "cc/output/copy_output_request.h" +#include "cc/output/copy_output_result.h" +#include "cc/trees/layer_tree_host.h" +#include "cc/trees/layer_tree_impl.h" +#include "third_party/skia/include/core/SkImageFilter.h" +#include "ui/gfx/rect_conversions.h" + +namespace cc { + +static int s_next_layer_id = 1; + +scoped_refptr<Layer> Layer::Create() { + return make_scoped_refptr(new Layer()); +} + +Layer::Layer() + : needs_push_properties_(false), + num_dependents_need_push_properties_(false), + stacking_order_changed_(false), + layer_id_(s_next_layer_id++), + ignore_set_needs_commit_(false), + parent_(NULL), + layer_tree_host_(NULL), + scrollable_(false), + should_scroll_on_main_thread_(false), + have_wheel_event_handlers_(false), + anchor_point_(0.5f, 0.5f), + background_color_(0), + compositing_reasons_(kCompositingReasonUnknown), + opacity_(1.f), + anchor_point_z_(0.f), + is_container_for_fixed_position_layers_(false), + is_drawable_(false), + hide_layer_and_subtree_(false), + masks_to_bounds_(false), + contents_opaque_(false), + double_sided_(true), + preserves_3d_(false), + use_parent_backface_visibility_(false), + draw_checkerboard_for_missing_tiles_(false), + force_render_surface_(false), + replica_layer_(NULL), + raster_scale_(0.f) { + if (layer_id_ < 0) { + s_next_layer_id = 1; + layer_id_ = s_next_layer_id++; + } + + layer_animation_controller_ = LayerAnimationController::Create(layer_id_); + layer_animation_controller_->AddValueObserver(this); +} + +Layer::~Layer() { + // Our parent should be holding a reference to us so there should be no + // way for us to be destroyed while we still have a parent. + DCHECK(!parent()); + // Similarly we shouldn't have a layer tree host since it also keeps a + // reference to us. + DCHECK(!layer_tree_host()); + + layer_animation_controller_->RemoveValueObserver(this); + + // Remove the parent reference from all children and dependents. + RemoveAllChildren(); + if (mask_layer_.get()) { + DCHECK_EQ(this, mask_layer_->parent()); + mask_layer_->RemoveFromParent(); + } + if (replica_layer_.get()) { + DCHECK_EQ(this, replica_layer_->parent()); + replica_layer_->RemoveFromParent(); + } +} + +void Layer::SetLayerTreeHost(LayerTreeHost* host) { + if (layer_tree_host_ == host) + return; + + layer_tree_host_ = host; + + // When changing hosts, the layer needs to commit its properties to the impl + // side for the new host. + SetNeedsPushProperties(); + + for (size_t i = 0; i < children_.size(); ++i) + children_[i]->SetLayerTreeHost(host); + + if (mask_layer_.get()) + mask_layer_->SetLayerTreeHost(host); + if (replica_layer_.get()) + replica_layer_->SetLayerTreeHost(host); + + if (host) { + layer_animation_controller_->SetAnimationRegistrar( + host->animation_registrar()); + + if (host->settings().layer_transforms_should_scale_layer_contents) + reset_raster_scale_to_unknown(); + } + + if (host && layer_animation_controller_->has_any_animation()) + host->SetNeedsCommit(); + if (host && + (!filters_.IsEmpty() || !background_filters_.IsEmpty() || filter_)) + layer_tree_host_->set_needs_filter_context(); +} + +void Layer::SetNeedsUpdate() { + if (layer_tree_host_ && !ignore_set_needs_commit_) + layer_tree_host_->SetNeedsUpdateLayers(); +} + +void Layer::SetNeedsCommit() { + if (!layer_tree_host_) + return; + + SetNeedsPushProperties(); + + if (ignore_set_needs_commit_) + return; + + layer_tree_host_->SetNeedsCommit(); +} + +void Layer::SetNeedsFullTreeSync() { + if (!layer_tree_host_) + return; + + layer_tree_host_->SetNeedsFullTreeSync(); +} + +bool Layer::IsPropertyChangeAllowed() const { + if (!layer_tree_host_) + return true; + + if (!layer_tree_host_->settings().strict_layer_property_change_checking) + return true; + + return !layer_tree_host_->in_paint_layer_contents(); +} + +void Layer::SetNeedsPushProperties() { + if (needs_push_properties_) + return; + if (!parent_should_know_need_push_properties() && parent_) + parent_->AddDependentNeedsPushProperties(); + needs_push_properties_ = true; +} + +void Layer::AddDependentNeedsPushProperties() { + DCHECK_GE(num_dependents_need_push_properties_, 0); + + if (!parent_should_know_need_push_properties() && parent_) + parent_->AddDependentNeedsPushProperties(); + + num_dependents_need_push_properties_++; +} + +void Layer::RemoveDependentNeedsPushProperties() { + num_dependents_need_push_properties_--; + DCHECK_GE(num_dependents_need_push_properties_, 0); + + if (!parent_should_know_need_push_properties() && parent_) + parent_->RemoveDependentNeedsPushProperties(); +} + +gfx::Rect Layer::LayerRectToContentRect(const gfx::RectF& layer_rect) const { + gfx::RectF content_rect = + gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y()); + // Intersect with content rect to avoid the extra pixel because for some + // values x and y, ceil((x / y) * y) may be x + 1. + content_rect.Intersect(gfx::Rect(content_bounds())); + return gfx::ToEnclosingRect(content_rect); +} + +bool Layer::BlocksPendingCommit() const { + return false; +} + +bool Layer::CanClipSelf() const { + return false; +} + +bool Layer::BlocksPendingCommitRecursive() const { + if (BlocksPendingCommit()) + return true; + if (mask_layer() && mask_layer()->BlocksPendingCommitRecursive()) + return true; + if (replica_layer() && replica_layer()->BlocksPendingCommitRecursive()) + return true; + for (size_t i = 0; i < children_.size(); ++i) { + if (children_[i]->BlocksPendingCommitRecursive()) + return true; + } + return false; +} + +void Layer::SetParent(Layer* layer) { + DCHECK(!layer || !layer->HasAncestor(this)); + + if (parent_should_know_need_push_properties()) { + if (parent_) + parent_->RemoveDependentNeedsPushProperties(); + if (layer) + layer->AddDependentNeedsPushProperties(); + } + + parent_ = layer; + SetLayerTreeHost(parent_ ? parent_->layer_tree_host() : NULL); + + if (!layer_tree_host_) + return; + const LayerTreeSettings& settings = layer_tree_host_->settings(); + if (!settings.layer_transforms_should_scale_layer_contents) + return; + + reset_raster_scale_to_unknown(); + if (mask_layer_.get()) + mask_layer_->reset_raster_scale_to_unknown(); + if (replica_layer_.get() && replica_layer_->mask_layer_.get()) + replica_layer_->mask_layer_->reset_raster_scale_to_unknown(); +} + +void Layer::AddChild(scoped_refptr<Layer> child) { + InsertChild(child, children_.size()); +} + +void Layer::InsertChild(scoped_refptr<Layer> child, size_t index) { + DCHECK(IsPropertyChangeAllowed()); + child->RemoveFromParent(); + child->SetParent(this); + child->stacking_order_changed_ = true; + + index = std::min(index, children_.size()); + children_.insert(children_.begin() + index, child); + SetNeedsFullTreeSync(); +} + +void Layer::RemoveFromParent() { + DCHECK(IsPropertyChangeAllowed()); + if (parent_) + parent_->RemoveChildOrDependent(this); +} + +void Layer::RemoveChildOrDependent(Layer* child) { + if (mask_layer_.get() == child) { + mask_layer_->SetParent(NULL); + mask_layer_ = NULL; + SetNeedsFullTreeSync(); + return; + } + if (replica_layer_.get() == child) { + replica_layer_->SetParent(NULL); + replica_layer_ = NULL; + SetNeedsFullTreeSync(); + return; + } + + for (LayerList::iterator iter = children_.begin(); + iter != children_.end(); + ++iter) { + if (iter->get() != child) + continue; + + child->SetParent(NULL); + children_.erase(iter); + SetNeedsFullTreeSync(); + return; + } +} + +void Layer::ReplaceChild(Layer* reference, scoped_refptr<Layer> new_layer) { + DCHECK(reference); + DCHECK_EQ(reference->parent(), this); + DCHECK(IsPropertyChangeAllowed()); + + if (reference == new_layer.get()) + return; + + int reference_index = IndexOfChild(reference); + if (reference_index == -1) { + NOTREACHED(); + return; + } + + reference->RemoveFromParent(); + + if (new_layer.get()) { + new_layer->RemoveFromParent(); + InsertChild(new_layer, reference_index); + } +} + +int Layer::IndexOfChild(const Layer* reference) { + for (size_t i = 0; i < children_.size(); ++i) { + if (children_[i].get() == reference) + return i; + } + return -1; +} + +void Layer::SetBounds(gfx::Size size) { + DCHECK(IsPropertyChangeAllowed()); + if (bounds() == size) + return; + + bounds_ = size; + SetNeedsCommit(); +} + +Layer* Layer::RootLayer() { + Layer* layer = this; + while (layer->parent()) + layer = layer->parent(); + return layer; +} + +void Layer::RemoveAllChildren() { + DCHECK(IsPropertyChangeAllowed()); + while (children_.size()) { + Layer* layer = children_[0].get(); + DCHECK_EQ(this, layer->parent()); + layer->RemoveFromParent(); + } +} + +void Layer::SetChildren(const LayerList& children) { + DCHECK(IsPropertyChangeAllowed()); + if (children == children_) + return; + + RemoveAllChildren(); + for (size_t i = 0; i < children.size(); ++i) + AddChild(children[i]); +} + +bool Layer::HasAncestor(const Layer* ancestor) const { + for (const Layer* layer = parent(); layer; layer = layer->parent()) { + if (layer == ancestor) + return true; + } + return false; +} + +void Layer::RequestCopyOfOutput( + scoped_ptr<CopyOutputRequest> request) { + DCHECK(IsPropertyChangeAllowed()); + if (request->IsEmpty()) + return; + copy_requests_.push_back(request.Pass()); + SetNeedsCommit(); +} + +void Layer::SetAnchorPoint(gfx::PointF anchor_point) { + DCHECK(IsPropertyChangeAllowed()); + if (anchor_point_ == anchor_point) + return; + anchor_point_ = anchor_point; + SetNeedsCommit(); +} + +void Layer::SetAnchorPointZ(float anchor_point_z) { + DCHECK(IsPropertyChangeAllowed()); + if (anchor_point_z_ == anchor_point_z) + return; + anchor_point_z_ = anchor_point_z; + SetNeedsCommit(); +} + +void Layer::SetBackgroundColor(SkColor background_color) { + DCHECK(IsPropertyChangeAllowed()); + if (background_color_ == background_color) + return; + background_color_ = background_color; + SetNeedsCommit(); +} + +SkColor Layer::SafeOpaqueBackgroundColor() const { + SkColor color = background_color(); + if (SkColorGetA(color) == 255 && !contents_opaque()) { + color = SK_ColorTRANSPARENT; + } else if (SkColorGetA(color) != 255 && contents_opaque()) { + for (const Layer* layer = parent(); layer; + layer = layer->parent()) { + color = layer->background_color(); + if (SkColorGetA(color) == 255) + break; + } + if (SkColorGetA(color) != 255) + color = layer_tree_host_->background_color(); + if (SkColorGetA(color) != 255) + color = SkColorSetA(color, 255); + } + return color; +} + +void Layer::CalculateContentsScale( + float ideal_contents_scale, + float device_scale_factor, + float page_scale_factor, + bool animating_transform_to_screen, + float* contents_scale_x, + float* contents_scale_y, + gfx::Size* content_bounds) { + DCHECK(layer_tree_host_); + + *contents_scale_x = 1; + *contents_scale_y = 1; + *content_bounds = bounds(); +} + +void Layer::SetMasksToBounds(bool masks_to_bounds) { + DCHECK(IsPropertyChangeAllowed()); + if (masks_to_bounds_ == masks_to_bounds) + return; + masks_to_bounds_ = masks_to_bounds; + SetNeedsCommit(); +} + +void Layer::SetMaskLayer(Layer* mask_layer) { + DCHECK(IsPropertyChangeAllowed()); + if (mask_layer_.get() == mask_layer) + return; + if (mask_layer_.get()) { + DCHECK_EQ(this, mask_layer_->parent()); + mask_layer_->RemoveFromParent(); + } + mask_layer_ = mask_layer; + if (mask_layer_.get()) { + DCHECK(!mask_layer_->parent()); + mask_layer_->RemoveFromParent(); + mask_layer_->SetParent(this); + mask_layer_->SetIsMask(true); + } + SetNeedsFullTreeSync(); +} + +void Layer::SetReplicaLayer(Layer* layer) { + DCHECK(IsPropertyChangeAllowed()); + if (replica_layer_.get() == layer) + return; + if (replica_layer_.get()) { + DCHECK_EQ(this, replica_layer_->parent()); + replica_layer_->RemoveFromParent(); + } + replica_layer_ = layer; + if (replica_layer_.get()) { + DCHECK(!replica_layer_->parent()); + replica_layer_->RemoveFromParent(); + replica_layer_->SetParent(this); + } + SetNeedsFullTreeSync(); +} + +void Layer::SetFilters(const FilterOperations& filters) { + DCHECK(IsPropertyChangeAllowed()); + if (filters_ == filters) + return; + DCHECK(!filter_); + filters_ = filters; + SetNeedsCommit(); + if (!filters.IsEmpty() && layer_tree_host_) + layer_tree_host_->set_needs_filter_context(); +} + +void Layer::SetFilter(const skia::RefPtr<SkImageFilter>& filter) { + DCHECK(IsPropertyChangeAllowed()); + if (filter_.get() == filter.get()) + return; + DCHECK(filters_.IsEmpty()); + filter_ = filter; + SetNeedsCommit(); + if (filter && layer_tree_host_) + layer_tree_host_->set_needs_filter_context(); +} + +void Layer::SetBackgroundFilters(const FilterOperations& filters) { + DCHECK(IsPropertyChangeAllowed()); + if (background_filters_ == filters) + return; + background_filters_ = filters; + SetNeedsCommit(); + if (!filters.IsEmpty() && layer_tree_host_) + layer_tree_host_->set_needs_filter_context(); +} + +void Layer::SetOpacity(float opacity) { + DCHECK(IsPropertyChangeAllowed()); + if (opacity_ == opacity) + return; + opacity_ = opacity; + SetNeedsCommit(); +} + +bool Layer::OpacityIsAnimating() const { + return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity); +} + +bool Layer::OpacityCanAnimateOnImplThread() const { + return false; +} + +void Layer::SetContentsOpaque(bool opaque) { + DCHECK(IsPropertyChangeAllowed()); + if (contents_opaque_ == opaque) + return; + contents_opaque_ = opaque; + SetNeedsCommit(); +} + +void Layer::SetPosition(gfx::PointF position) { + DCHECK(IsPropertyChangeAllowed()); + if (position_ == position) + return; + position_ = position; + SetNeedsCommit(); +} + +bool Layer::IsContainerForFixedPositionLayers() const { + if (!transform_.IsIdentityOrTranslation()) + return true; + if (parent_ && !parent_->sublayer_transform_.IsIdentityOrTranslation()) + return true; + return is_container_for_fixed_position_layers_; +} + +void Layer::SetSublayerTransform(const gfx::Transform& sublayer_transform) { + DCHECK(IsPropertyChangeAllowed()); + if (sublayer_transform_ == sublayer_transform) + return; + sublayer_transform_ = sublayer_transform; + SetNeedsCommit(); +} + +void Layer::SetTransform(const gfx::Transform& transform) { + DCHECK(IsPropertyChangeAllowed()); + if (transform_ == transform) + return; + transform_ = transform; + SetNeedsCommit(); +} + +bool Layer::TransformIsAnimating() const { + return layer_animation_controller_->IsAnimatingProperty(Animation::Transform); +} + +void Layer::SetScrollOffset(gfx::Vector2d scroll_offset) { + DCHECK(IsPropertyChangeAllowed()); + if (scroll_offset_ == scroll_offset) + return; + scroll_offset_ = scroll_offset; + SetNeedsCommit(); +} + +void Layer::SetScrollOffsetFromImplSide(gfx::Vector2d scroll_offset) { + DCHECK(IsPropertyChangeAllowed()); + // This function only gets called during a begin frame, so there + // is no need to call SetNeedsUpdate here. + DCHECK(layer_tree_host_ && layer_tree_host_->CommitRequested()); + if (scroll_offset_ == scroll_offset) + return; + scroll_offset_ = scroll_offset; + SetNeedsPushProperties(); + if (!did_scroll_callback_.is_null()) + did_scroll_callback_.Run(); + // The callback could potentially change the layer structure: + // "this" may have been destroyed during the process. +} + +void Layer::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) { + DCHECK(IsPropertyChangeAllowed()); + if (max_scroll_offset_ == max_scroll_offset) + return; + max_scroll_offset_ = max_scroll_offset; + SetNeedsCommit(); +} + +void Layer::SetScrollable(bool scrollable) { + DCHECK(IsPropertyChangeAllowed()); + if (scrollable_ == scrollable) + return; + scrollable_ = scrollable; + SetNeedsCommit(); +} + +void Layer::SetShouldScrollOnMainThread(bool should_scroll_on_main_thread) { + DCHECK(IsPropertyChangeAllowed()); + if (should_scroll_on_main_thread_ == should_scroll_on_main_thread) + return; + should_scroll_on_main_thread_ = should_scroll_on_main_thread; + SetNeedsCommit(); +} + +void Layer::SetHaveWheelEventHandlers(bool have_wheel_event_handlers) { + DCHECK(IsPropertyChangeAllowed()); + if (have_wheel_event_handlers_ == have_wheel_event_handlers) + return; + have_wheel_event_handlers_ = have_wheel_event_handlers; + SetNeedsCommit(); +} + +void Layer::SetNonFastScrollableRegion(const Region& region) { + DCHECK(IsPropertyChangeAllowed()); + if (non_fast_scrollable_region_ == region) + return; + non_fast_scrollable_region_ = region; + SetNeedsCommit(); +} + +void Layer::SetTouchEventHandlerRegion(const Region& region) { + DCHECK(IsPropertyChangeAllowed()); + if (touch_event_handler_region_ == region) + return; + touch_event_handler_region_ = region; +} + +void Layer::SetDrawCheckerboardForMissingTiles(bool checkerboard) { + DCHECK(IsPropertyChangeAllowed()); + if (draw_checkerboard_for_missing_tiles_ == checkerboard) + return; + draw_checkerboard_for_missing_tiles_ = checkerboard; + SetNeedsCommit(); +} + +void Layer::SetForceRenderSurface(bool force) { + DCHECK(IsPropertyChangeAllowed()); + if (force_render_surface_ == force) + return; + force_render_surface_ = force; + SetNeedsCommit(); +} + +void Layer::SetDoubleSided(bool double_sided) { + DCHECK(IsPropertyChangeAllowed()); + if (double_sided_ == double_sided) + return; + double_sided_ = double_sided; + SetNeedsCommit(); +} + +void Layer::SetIsDrawable(bool is_drawable) { + DCHECK(IsPropertyChangeAllowed()); + if (is_drawable_ == is_drawable) + return; + + is_drawable_ = is_drawable; + SetNeedsCommit(); +} + +void Layer::SetHideLayerAndSubtree(bool hide) { + DCHECK(IsPropertyChangeAllowed()); + if (hide_layer_and_subtree_ == hide) + return; + + hide_layer_and_subtree_ = hide; + SetNeedsCommit(); +} + +void Layer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) { + if (dirty_rect.IsEmpty()) + return; + + SetNeedsPushProperties(); + update_rect_.Union(dirty_rect); + + if (DrawsContent()) + SetNeedsUpdate(); +} + +bool Layer::DescendantIsFixedToContainerLayer() const { + for (size_t i = 0; i < children_.size(); ++i) { + if (children_[i]->position_constraint_.is_fixed_position() || + children_[i]->DescendantIsFixedToContainerLayer()) + return true; + } + return false; +} + +void Layer::SetIsContainerForFixedPositionLayers(bool container) { + if (is_container_for_fixed_position_layers_ == container) + return; + is_container_for_fixed_position_layers_ = container; + + if (layer_tree_host_ && layer_tree_host_->CommitRequested()) + return; + + // Only request a commit if we have a fixed positioned descendant. + if (DescendantIsFixedToContainerLayer()) + SetNeedsCommit(); +} + +void Layer::SetPositionConstraint(const LayerPositionConstraint& constraint) { + DCHECK(IsPropertyChangeAllowed()); + if (position_constraint_ == constraint) + return; + position_constraint_ = constraint; + SetNeedsCommit(); +} + +static void RunCopyCallbackOnMainThread(scoped_ptr<CopyOutputRequest> request, + scoped_ptr<CopyOutputResult> result) { + request->SendResult(result.Pass()); +} + +static void PostCopyCallbackToMainThread( + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + scoped_ptr<CopyOutputRequest> request, + scoped_ptr<CopyOutputResult> result) { + main_thread_task_runner->PostTask(FROM_HERE, + base::Bind(&RunCopyCallbackOnMainThread, + base::Passed(&request), + base::Passed(&result))); +} + +void Layer::PushPropertiesTo(LayerImpl* layer) { + DCHECK(layer_tree_host_); + + // If we did not SavePaintProperties() for the layer this frame, then push the + // real property values, not the paint property values. + bool use_paint_properties = paint_properties_.source_frame_number == + layer_tree_host_->source_frame_number(); + + layer->SetAnchorPoint(anchor_point_); + layer->SetAnchorPointZ(anchor_point_z_); + layer->SetBackgroundColor(background_color_); + layer->SetBounds(use_paint_properties ? paint_properties_.bounds + : bounds_); + layer->SetContentBounds(content_bounds()); + layer->SetContentsScale(contents_scale_x(), contents_scale_y()); + layer->SetDebugName(debug_name_); + layer->SetCompositingReasons(compositing_reasons_); + layer->SetDoubleSided(double_sided_); + layer->SetDrawCheckerboardForMissingTiles( + draw_checkerboard_for_missing_tiles_); + layer->SetForceRenderSurface(force_render_surface_); + layer->SetDrawsContent(DrawsContent()); + layer->SetHideLayerAndSubtree(hide_layer_and_subtree_); + layer->SetFilters(filters()); + layer->SetFilter(filter()); + layer->SetBackgroundFilters(background_filters()); + layer->SetMasksToBounds(masks_to_bounds_); + layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); + layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_); + layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); + layer->SetTouchEventHandlerRegion(touch_event_handler_region_); + layer->SetContentsOpaque(contents_opaque_); + if (!layer->OpacityIsAnimatingOnImplOnly() && !OpacityIsAnimating()) + layer->SetOpacity(opacity_); + DCHECK(!(OpacityIsAnimating() && layer->OpacityIsAnimatingOnImplOnly())); + layer->SetPosition(position_); + layer->SetIsContainerForFixedPositionLayers( + IsContainerForFixedPositionLayers()); + layer->SetFixedContainerSizeDelta(gfx::Vector2dF()); + layer->SetPositionConstraint(position_constraint_); + layer->SetPreserves3d(preserves_3d()); + layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); + layer->SetSublayerTransform(sublayer_transform_); + if (!layer->TransformIsAnimatingOnImplOnly() && !TransformIsAnimating()) + layer->SetTransform(transform_); + DCHECK(!(TransformIsAnimating() && layer->TransformIsAnimatingOnImplOnly())); + + layer->SetScrollable(scrollable_); + layer->SetScrollOffset(scroll_offset_); + layer->SetMaxScrollOffset(max_scroll_offset_); + + // Wrap the copy_requests_ in a PostTask to the main thread. + ScopedPtrVector<CopyOutputRequest> main_thread_copy_requests; + for (ScopedPtrVector<CopyOutputRequest>::iterator it = copy_requests_.begin(); + it != copy_requests_.end(); + ++it) { + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner = + layer_tree_host()->proxy()->MainThreadTaskRunner(); + scoped_ptr<CopyOutputRequest> original_request = copy_requests_.take(it); + const CopyOutputRequest& original_request_ref = *original_request; + scoped_ptr<CopyOutputRequest> main_thread_request = + CopyOutputRequest::CreateRelayRequest( + original_request_ref, + base::Bind(&PostCopyCallbackToMainThread, + main_thread_task_runner, + base::Passed(&original_request))); + main_thread_copy_requests.push_back(main_thread_request.Pass()); + } + copy_requests_.clear(); + layer->PassCopyRequests(&main_thread_copy_requests); + + // If the main thread commits multiple times before the impl thread actually + // draws, then damage tracking will become incorrect if we simply clobber the + // update_rect here. The LayerImpl's update_rect needs to accumulate (i.e. + // union) any update changes that have occurred on the main thread. + update_rect_.Union(layer->update_rect()); + layer->set_update_rect(update_rect_); + + if (layer->layer_tree_impl()->settings().impl_side_painting) { + DCHECK(layer->layer_tree_impl()->IsPendingTree()); + LayerImpl* active_twin = + layer->layer_tree_impl()->FindActiveTreeLayerById(id()); + // Update the scroll delta from the active layer, which may have + // adjusted its scroll delta prior to this pending layer being created. + // This code is identical to that in LayerImpl::SetScrollDelta. + if (active_twin) { + DCHECK(layer->sent_scroll_delta().IsZero()); + layer->SetScrollDelta(active_twin->ScrollDelta() - + active_twin->sent_scroll_delta()); + } + } else { + layer->SetScrollDelta(layer->ScrollDelta() - layer->sent_scroll_delta()); + layer->SetSentScrollDelta(gfx::Vector2d()); + } + + layer->SetStackingOrderChanged(stacking_order_changed_); + + layer_animation_controller_->PushAnimationUpdatesTo( + layer->layer_animation_controller()); + + // Reset any state that should be cleared for the next update. + stacking_order_changed_ = false; + update_rect_ = gfx::RectF(); + + // Animating layers require further push properties to clean up the animation. + // crbug.com/259088 + needs_push_properties_ = layer_animation_controller_->has_any_animation(); + num_dependents_need_push_properties_ = 0; +} + +scoped_ptr<LayerImpl> Layer::CreateLayerImpl(LayerTreeImpl* tree_impl) { + return LayerImpl::Create(tree_impl, layer_id_); +} + +bool Layer::DrawsContent() const { + return is_drawable_; +} + +void Layer::SavePaintProperties() { + DCHECK(layer_tree_host_); + + // TODO(reveman): Save all layer properties that we depend on not + // changing until PushProperties() has been called. crbug.com/231016 + paint_properties_.bounds = bounds_; + paint_properties_.source_frame_number = + layer_tree_host_->source_frame_number(); +} + +bool Layer::Update(ResourceUpdateQueue* queue, + const OcclusionTracker* occlusion) { + DCHECK(layer_tree_host_); + DCHECK_EQ(layer_tree_host_->source_frame_number(), + paint_properties_.source_frame_number) << + "SavePaintProperties must be called for any layer that is painted."; + return false; +} + +bool Layer::NeedMoreUpdates() { + return false; +} + +void Layer::SetDebugName(const std::string& debug_name) { + debug_name_ = debug_name; + SetNeedsCommit(); +} + +void Layer::SetCompositingReasons(CompositingReasons reasons) { + compositing_reasons_ = reasons; +} + +void Layer::CreateRenderSurface() { + DCHECK(!draw_properties_.render_surface); + draw_properties_.render_surface = make_scoped_ptr(new RenderSurface(this)); + draw_properties_.render_target = this; +} + +void Layer::ClearRenderSurface() { + draw_properties_.render_surface.reset(); +} + +void Layer::OnOpacityAnimated(float opacity) { + // This is called due to an ongoing accelerated animation. Since this + // animation is also being run on the impl thread, there is no need to request + // a commit to push this value over, so set the value directly rather than + // calling SetOpacity. + opacity_ = opacity; +} + +void Layer::OnTransformAnimated(const gfx::Transform& transform) { + // This is called due to an ongoing accelerated animation. Since this + // animation is also being run on the impl thread, there is no need to request + // a commit to push this value over, so set this value directly rather than + // calling SetTransform. + transform_ = transform; +} + +bool Layer::IsActive() const { + return true; +} + +bool Layer::AddAnimation(scoped_ptr <Animation> animation) { + if (!layer_animation_controller_->animation_registrar()) + return false; + + UMA_HISTOGRAM_BOOLEAN("Renderer.AnimationAddedToOrphanLayer", + !layer_tree_host_); + layer_animation_controller_->AddAnimation(animation.Pass()); + SetNeedsCommit(); + return true; +} + +void Layer::PauseAnimation(int animation_id, double time_offset) { + layer_animation_controller_->PauseAnimation(animation_id, time_offset); + SetNeedsCommit(); +} + +void Layer::RemoveAnimation(int animation_id) { + layer_animation_controller_->RemoveAnimation(animation_id); + SetNeedsCommit(); +} + +void Layer::SuspendAnimations(double monotonic_time) { + layer_animation_controller_->SuspendAnimations(monotonic_time); + SetNeedsCommit(); +} + +void Layer::ResumeAnimations(double monotonic_time) { + layer_animation_controller_->ResumeAnimations(monotonic_time); + SetNeedsCommit(); +} + +void Layer::SetLayerAnimationControllerForTest( + scoped_refptr<LayerAnimationController> controller) { + layer_animation_controller_->RemoveValueObserver(this); + layer_animation_controller_ = controller; + layer_animation_controller_->set_force_sync(); + layer_animation_controller_->AddValueObserver(this); + SetNeedsCommit(); +} + +bool Layer::HasActiveAnimation() const { + return layer_animation_controller_->HasActiveAnimation(); +} + +void Layer::AddLayerAnimationEventObserver( + LayerAnimationEventObserver* animation_observer) { + layer_animation_controller_->AddEventObserver(animation_observer); +} + +void Layer::RemoveLayerAnimationEventObserver( + LayerAnimationEventObserver* animation_observer) { + layer_animation_controller_->RemoveEventObserver(animation_observer); +} + +Region Layer::VisibleContentOpaqueRegion() const { + if (contents_opaque()) + return visible_content_rect(); + return Region(); +} + +ScrollbarLayer* Layer::ToScrollbarLayer() { + return NULL; +} + +RenderingStatsInstrumentation* Layer::rendering_stats_instrumentation() const { + return layer_tree_host_->rendering_stats_instrumentation(); +} + +bool Layer::SupportsLCDText() const { + return false; +} + +} // namespace cc |