summaryrefslogtreecommitdiffstats
path: root/chromium/cc/trees/layer_tree_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/trees/layer_tree_impl.cc')
-rw-r--r--chromium/cc/trees/layer_tree_impl.cc885
1 files changed, 692 insertions, 193 deletions
diff --git a/chromium/cc/trees/layer_tree_impl.cc b/chromium/cc/trees/layer_tree_impl.cc
index 9f181cda458..d5ec804eaa9 100644
--- a/chromium/cc/trees/layer_tree_impl.cc
+++ b/chromium/cc/trees/layer_tree_impl.cc
@@ -4,29 +4,72 @@
#include "cc/trees/layer_tree_impl.h"
+#include <limits>
+#include <set>
+
#include "base/debug/trace_event.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/scrollbar_animation_controller.h"
+#include "cc/animation/scrollbar_animation_controller_linear_fade.h"
+#include "cc/animation/scrollbar_animation_controller_thinning.h"
#include "cc/base/math_util.h"
#include "cc/base/util.h"
+#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
+#include "cc/layers/layer_iterator.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/layers/scrollbar_layer_impl_base.h"
#include "cc/resources/ui_resource_request.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
+#include "ui/gfx/point_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"
namespace cc {
+// This class exists to split the LayerScrollOffsetDelegate between the
+// InnerViewportScrollLayer and the OuterViewportScrollLayer in a manner
+// that never requires the embedder or LayerImpl to know about.
+class LayerScrollOffsetDelegateProxy : public LayerImpl::ScrollOffsetDelegate {
+ public:
+ LayerScrollOffsetDelegateProxy(LayerImpl* layer,
+ LayerScrollOffsetDelegate* delegate,
+ LayerTreeImpl* layer_tree)
+ : layer_(layer), delegate_(delegate), layer_tree_impl_(layer_tree) {}
+ virtual ~LayerScrollOffsetDelegateProxy() {}
+
+ gfx::Vector2dF last_set_scroll_offset() const {
+ return last_set_scroll_offset_;
+ }
+
+ // LayerScrollOffsetDelegate implementation.
+ virtual void SetTotalScrollOffset(const gfx::Vector2dF& new_offset) OVERRIDE {
+ last_set_scroll_offset_ = new_offset;
+ layer_tree_impl_->UpdateScrollOffsetDelegate();
+ }
+
+ virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
+ return layer_tree_impl_->GetDelegatedScrollOffset(layer_);
+ }
+
+ virtual bool IsExternalFlingActive() const OVERRIDE {
+ return delegate_->IsExternalFlingActive();
+ }
+
+ private:
+ LayerImpl* layer_;
+ LayerScrollOffsetDelegate* delegate_;
+ LayerTreeImpl* layer_tree_impl_;
+ gfx::Vector2dF last_set_scroll_offset_;
+};
+
LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl)
: layer_tree_host_impl_(layer_tree_host_impl),
source_frame_number_(-1),
hud_layer_(0),
- root_scroll_layer_(NULL),
currently_scrolling_layer_(NULL),
root_layer_scroll_offset_delegate_(NULL),
background_color_(0),
@@ -41,69 +84,99 @@ LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl)
max_page_scale_factor_(0),
scrolling_layer_id_from_previous_tree_(0),
contents_textures_purged_(false),
+ requires_high_res_to_draw_(false),
viewport_size_invalid_(false),
needs_update_draw_properties_(true),
needs_full_tree_sync_(true),
- next_activation_forces_redraw_(false) {
+ next_activation_forces_redraw_(false),
+ render_surface_layer_list_id_(0) {
}
LayerTreeImpl::~LayerTreeImpl() {
// Need to explicitly clear the tree prior to destroying this so that
// the LayerTreeImpl pointer is still valid in the LayerImpl dtor.
- root_layer_.reset();
+ DCHECK(!root_layer_);
+ DCHECK(layers_with_copy_output_request_.empty());
}
-static LayerImpl* FindRootScrollLayerRecursive(LayerImpl* layer) {
- if (!layer)
- return NULL;
-
- if (layer->scrollable())
- return layer;
-
- for (size_t i = 0; i < layer->children().size(); ++i) {
- LayerImpl* found = FindRootScrollLayerRecursive(layer->children()[i]);
- if (found)
- return found;
- }
+void LayerTreeImpl::Shutdown() { root_layer_.reset(); }
- return NULL;
+void LayerTreeImpl::ReleaseResources() {
+ if (root_layer_)
+ ReleaseResourcesRecursive(root_layer_.get());
}
void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
- if (root_scroll_layer_)
- root_scroll_layer_->SetScrollOffsetDelegate(NULL);
+ if (inner_viewport_scroll_layer_)
+ inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
+ if (outer_viewport_scroll_layer_)
+ outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
+ inner_viewport_scroll_delegate_proxy_.reset();
+ outer_viewport_scroll_delegate_proxy_.reset();
+
root_layer_ = layer.Pass();
currently_scrolling_layer_ = NULL;
- root_scroll_layer_ = NULL;
+ inner_viewport_scroll_layer_ = NULL;
+ outer_viewport_scroll_layer_ = NULL;
+ page_scale_layer_ = NULL;
layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}
-void LayerTreeImpl::FindRootScrollLayer() {
- root_scroll_layer_ = FindRootScrollLayerRecursive(root_layer_.get());
+LayerImpl* LayerTreeImpl::InnerViewportScrollLayer() const {
+ return inner_viewport_scroll_layer_;
+}
- if (root_scroll_layer_) {
- UpdateMaxScrollOffset();
- root_scroll_layer_->SetScrollOffsetDelegate(
- root_layer_scroll_offset_delegate_);
- }
+LayerImpl* LayerTreeImpl::OuterViewportScrollLayer() const {
+ return outer_viewport_scroll_layer_;
+}
- if (scrolling_layer_id_from_previous_tree_) {
- currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree(
- root_layer_.get(),
- scrolling_layer_id_from_previous_tree_);
- }
+gfx::Vector2dF LayerTreeImpl::TotalScrollOffset() const {
+ gfx::Vector2dF offset;
- scrolling_layer_id_from_previous_tree_ = 0;
+ if (inner_viewport_scroll_layer_)
+ offset += inner_viewport_scroll_layer_->TotalScrollOffset();
+
+ if (outer_viewport_scroll_layer_)
+ offset += outer_viewport_scroll_layer_->TotalScrollOffset();
+
+ return offset;
+}
+
+gfx::Vector2dF LayerTreeImpl::TotalMaxScrollOffset() const {
+ gfx::Vector2dF offset;
+
+ if (inner_viewport_scroll_layer_)
+ offset += inner_viewport_scroll_layer_->MaxScrollOffset();
+
+ if (outer_viewport_scroll_layer_)
+ offset += outer_viewport_scroll_layer_->MaxScrollOffset();
+
+ return offset;
+}
+gfx::Vector2dF LayerTreeImpl::TotalScrollDelta() const {
+ DCHECK(inner_viewport_scroll_layer_);
+ gfx::Vector2dF delta = inner_viewport_scroll_layer_->ScrollDelta();
+
+ if (outer_viewport_scroll_layer_)
+ delta += outer_viewport_scroll_layer_->ScrollDelta();
+
+ return delta;
}
scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
// Clear all data structures that have direct references to the layer tree.
scrolling_layer_id_from_previous_tree_ =
currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
- if (root_scroll_layer_)
- root_scroll_layer_->SetScrollOffsetDelegate(NULL);
- root_scroll_layer_ = NULL;
+ if (inner_viewport_scroll_layer_)
+ inner_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
+ if (outer_viewport_scroll_layer_)
+ outer_viewport_scroll_layer_->SetScrollOffsetDelegate(NULL);
+ inner_viewport_scroll_delegate_proxy_.reset();
+ outer_viewport_scroll_delegate_proxy_.reset();
+ inner_viewport_scroll_layer_ = NULL;
+ outer_viewport_scroll_layer_ = NULL;
+ page_scale_layer_ = NULL;
currently_scrolling_layer_ = NULL;
render_surface_layer_list_.clear();
@@ -116,24 +189,25 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
DCHECK_EQ(ui_resource_request_queue_.size(), 0u);
if (next_activation_forces_redraw_) {
- layer_tree_host_impl_->SetFullRootLayerDamage();
+ target_tree->ForceRedrawNextActivation();
next_activation_forces_redraw_ = false;
}
target_tree->PassSwapPromises(&swap_promise_list_);
- target_tree->SetPageScaleFactorAndLimits(
- page_scale_factor(), min_page_scale_factor(), max_page_scale_factor());
- target_tree->SetPageScaleDelta(
+ target_tree->SetPageScaleValues(
+ page_scale_factor(), min_page_scale_factor(), max_page_scale_factor(),
target_tree->page_scale_delta() / target_tree->sent_page_scale_delta());
target_tree->set_sent_page_scale_delta(1);
- if (settings().use_pinch_virtual_viewport) {
+ if (page_scale_layer_ && inner_viewport_scroll_layer_) {
target_tree->SetViewportLayersFromIds(
page_scale_layer_->id(),
inner_viewport_scroll_layer_->id(),
outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
: Layer::INVALID_ID);
+ } else {
+ target_tree->ClearViewportLayers();
}
// This should match the property synchronization in
// LayerTreeHost::finishCommitOnImplThread().
@@ -146,6 +220,10 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
else
target_tree->ResetContentsTexturesPurged();
+ // Always reset this flag on activation, as we would only have activated
+ // if we were in a good state.
+ target_tree->ResetRequiresHighResToDraw();
+
if (ViewportSizeInvalid())
target_tree->SetViewportSizeInvalid();
else
@@ -159,12 +237,10 @@ void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
target_tree->set_hud_layer(NULL);
}
-LayerImpl* LayerTreeImpl::RootScrollLayer() const {
- return root_scroll_layer_;
-}
-
-LayerImpl* LayerTreeImpl::RootContainerLayer() const {
- return root_scroll_layer_ ? root_scroll_layer_->parent() : NULL;
+LayerImpl* LayerTreeImpl::InnerViewportContainerLayer() const {
+ return inner_viewport_scroll_layer_
+ ? inner_viewport_scroll_layer_->scroll_clip_layer()
+ : NULL;
}
LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const {
@@ -178,11 +254,11 @@ void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) {
if (currently_scrolling_layer_ &&
currently_scrolling_layer_->scrollbar_animation_controller())
- currently_scrolling_layer_->scrollbar_animation_controller()->
- DidScrollGestureEnd(CurrentPhysicalTimeTicks());
+ currently_scrolling_layer_->scrollbar_animation_controller()
+ ->DidScrollEnd();
currently_scrolling_layer_ = layer;
if (layer && layer->scrollbar_animation_controller())
- layer->scrollbar_animation_controller()->DidScrollGestureBegin();
+ layer->scrollbar_animation_controller()->DidScrollBegin();
}
void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
@@ -190,79 +266,106 @@ void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
scrolling_layer_id_from_previous_tree_ = 0;
}
+float LayerTreeImpl::VerticalAdjust(const int clip_layer_id) const {
+ LayerImpl* container_layer = InnerViewportContainerLayer();
+ if (!container_layer || clip_layer_id != container_layer->id())
+ return 0.f;
+
+ return layer_tree_host_impl_->VerticalAdjust();
+}
+
+namespace {
+
+void ForceScrollbarParameterUpdateAfterScaleChange(LayerImpl* current_layer) {
+ if (!current_layer)
+ return;
+
+ while (current_layer) {
+ current_layer->ScrollbarParametersDidChange();
+ current_layer = current_layer->parent();
+ }
+}
+
+} // namespace
+
void LayerTreeImpl::SetPageScaleFactorAndLimits(float page_scale_factor,
float min_page_scale_factor, float max_page_scale_factor) {
- if (!page_scale_factor)
- return;
+ SetPageScaleValues(page_scale_factor, min_page_scale_factor,
+ max_page_scale_factor, page_scale_delta_);
+}
+
+void LayerTreeImpl::SetPageScaleDelta(float delta) {
+ SetPageScaleValues(page_scale_factor_, min_page_scale_factor_,
+ max_page_scale_factor_, delta);
+}
+
+void LayerTreeImpl::SetPageScaleValues(float page_scale_factor,
+ float min_page_scale_factor, float max_page_scale_factor,
+ float page_scale_delta) {
+ bool page_scale_changed =
+ min_page_scale_factor != min_page_scale_factor_ ||
+ max_page_scale_factor != max_page_scale_factor_ ||
+ page_scale_factor != page_scale_factor_;
min_page_scale_factor_ = min_page_scale_factor;
max_page_scale_factor_ = max_page_scale_factor;
page_scale_factor_ = page_scale_factor;
- if (root_layer_scroll_offset_delegate_) {
- root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
- total_page_scale_factor());
- }
-}
-
-void LayerTreeImpl::SetPageScaleDelta(float delta) {
- // Clamp to the current min/max limits.
- float total = page_scale_factor_ * delta;
+ float total = page_scale_factor_ * page_scale_delta;
if (min_page_scale_factor_ && total < min_page_scale_factor_)
- delta = min_page_scale_factor_ / page_scale_factor_;
+ page_scale_delta = min_page_scale_factor_ / page_scale_factor_;
else if (max_page_scale_factor_ && total > max_page_scale_factor_)
- delta = max_page_scale_factor_ / page_scale_factor_;
+ page_scale_delta = max_page_scale_factor_ / page_scale_factor_;
- if (delta == page_scale_delta_)
+ if (page_scale_delta_ == page_scale_delta && !page_scale_changed)
return;
- page_scale_delta_ = delta;
+ if (page_scale_delta_ != page_scale_delta) {
+ page_scale_delta_ = page_scale_delta;
- if (IsActiveTree()) {
- LayerTreeImpl* pending_tree = layer_tree_host_impl_->pending_tree();
- if (pending_tree) {
- DCHECK_EQ(1, pending_tree->sent_page_scale_delta());
- pending_tree->SetPageScaleDelta(
- page_scale_delta_ / sent_page_scale_delta_);
+ if (IsActiveTree()) {
+ LayerTreeImpl* pending_tree = layer_tree_host_impl_->pending_tree();
+ if (pending_tree) {
+ DCHECK_EQ(1, pending_tree->sent_page_scale_delta());
+ pending_tree->SetPageScaleDelta(
+ page_scale_delta_ / sent_page_scale_delta_);
+ }
}
- }
- UpdateMaxScrollOffset();
- set_needs_update_draw_properties();
+ set_needs_update_draw_properties();
+ }
if (root_layer_scroll_offset_delegate_) {
- root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
- total_page_scale_factor());
+ root_layer_scroll_offset_delegate_->UpdateRootLayerState(
+ TotalScrollOffset(),
+ TotalMaxScrollOffset(),
+ ScrollableSize(),
+ total_page_scale_factor(),
+ min_page_scale_factor_,
+ max_page_scale_factor_);
}
+
+ ForceScrollbarParameterUpdateAfterScaleChange(page_scale_layer());
}
gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
- return gfx::ScaleSize(layer_tree_host_impl_->UnscaledScrollableViewportSize(),
- 1.0f / total_page_scale_factor());
+ if (outer_viewport_scroll_layer_)
+ return layer_tree_host_impl_->UnscaledScrollableViewportSize();
+ else
+ return gfx::ScaleSize(
+ layer_tree_host_impl_->UnscaledScrollableViewportSize(),
+ 1.0f / total_page_scale_factor());
}
gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const {
- if (!root_scroll_layer_ || root_scroll_layer_->children().empty())
+ LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
+ ? OuterViewportScrollLayer()
+ : InnerViewportScrollLayer();
+ if (!root_scroll_layer || root_scroll_layer->children().empty())
return gfx::Rect();
- LayerImpl* layer = root_scroll_layer_->children()[0];
- return MathUtil::MapClippedRect(
- layer->screen_space_transform(),
- gfx::Rect(layer->content_bounds()));
-}
-
-void LayerTreeImpl::UpdateMaxScrollOffset() {
- LayerImpl* root_scroll = RootScrollLayer();
- if (!root_scroll || !root_scroll->children().size())
- return;
-
- gfx::Vector2dF max_scroll = gfx::Rect(ScrollableSize()).bottom_right() -
- gfx::RectF(ScrollableViewportSize()).bottom_right();
-
- // The viewport may be larger than the contents in some cases, such as
- // having a vertical scrollbar but no horizontal overflow.
- max_scroll.SetToMax(gfx::Vector2dF());
-
- root_scroll_layer_->SetMaxScrollOffset(gfx::ToFlooredVector2d(max_scroll));
+ LayerImpl* layer = root_scroll_layer->children()[0];
+ return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(),
+ gfx::Rect(layer->content_bounds()));
}
static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) {
@@ -311,6 +414,20 @@ void LayerTreeImpl::SetViewportLayersFromIds(
LayerById(outer_viewport_scroll_layer_id);
DCHECK(outer_viewport_scroll_layer_ ||
outer_viewport_scroll_layer_id == Layer::INVALID_ID);
+
+ if (!root_layer_scroll_offset_delegate_)
+ return;
+
+ inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
+ new LayerScrollOffsetDelegateProxy(inner_viewport_scroll_layer_,
+ root_layer_scroll_offset_delegate_,
+ this));
+
+ if (outer_viewport_scroll_layer_)
+ outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
+ new LayerScrollOffsetDelegateProxy(outer_viewport_scroll_layer_,
+ root_layer_scroll_offset_delegate_,
+ this));
}
void LayerTreeImpl::ClearViewportLayers() {
@@ -319,55 +436,19 @@ void LayerTreeImpl::ClearViewportLayers() {
outer_viewport_scroll_layer_ = NULL;
}
-// TODO(wjmaclean) This needs to go away, and be replaced with a single core
-// of login that works for both scrollbar layer types. This is already planned
-// as part of the larger pinch-zoom re-factoring viewport.
-void LayerTreeImpl::UpdateSolidColorScrollbars() {
- LayerImpl* root_scroll = RootScrollLayer();
- DCHECK(root_scroll);
- DCHECK(IsActiveTree());
-
- gfx::RectF scrollable_viewport(
- gfx::PointAtOffsetFromOrigin(root_scroll->TotalScrollOffset()),
- ScrollableViewportSize());
- float vertical_adjust = 0.0f;
- if (RootContainerLayer())
- vertical_adjust =
- layer_tree_host_impl_->UnscaledScrollableViewportSize().height() -
- RootContainerLayer()->bounds().height();
- if (ScrollbarLayerImplBase* horiz =
- root_scroll->horizontal_scrollbar_layer()) {
- horiz->SetVerticalAdjust(vertical_adjust);
- horiz->SetVisibleToTotalLengthRatio(
- scrollable_viewport.width() / ScrollableSize().width());
- }
- if (ScrollbarLayerImplBase* vertical =
- root_scroll->vertical_scrollbar_layer()) {
- vertical->SetVerticalAdjust(vertical_adjust);
- vertical->SetVisibleToTotalLengthRatio(
- scrollable_viewport.height() / ScrollableSize().height());
- }
-}
-
-void LayerTreeImpl::UpdateDrawProperties() {
- if (IsActiveTree() && RootScrollLayer() && RootContainerLayer())
- UpdateRootScrollLayerSizeDelta();
-
- if (IsActiveTree() &&
- RootContainerLayer()
- && !RootContainerLayer()->masks_to_bounds()) {
- UpdateSolidColorScrollbars();
- }
-
- needs_update_draw_properties_ = false;
- render_surface_layer_list_.clear();
+bool LayerTreeImpl::UpdateDrawProperties() {
+ if (!needs_update_draw_properties_)
+ return true;
// For max_texture_size.
if (!layer_tree_host_impl_->renderer())
- return;
+ return false;
if (!root_layer())
- return;
+ return false;
+
+ needs_update_draw_properties_ = false;
+ render_surface_layer_list_.clear();
{
TRACE_EVENT2("cc",
@@ -377,9 +458,11 @@ void LayerTreeImpl::UpdateDrawProperties() {
"SourceFrameNumber",
source_frame_number_);
LayerImpl* page_scale_layer =
- page_scale_layer_ ? page_scale_layer_ : RootContainerLayer();
+ page_scale_layer_ ? page_scale_layer_ : InnerViewportContainerLayer();
bool can_render_to_separate_surface =
!output_surface()->ForcedDrawToSoftwareDevice();
+
+ ++render_surface_layer_list_id_;
LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
root_layer(),
DrawViewportSize(),
@@ -391,7 +474,8 @@ void LayerTreeImpl::UpdateDrawProperties() {
settings().can_use_lcd_text,
can_render_to_separate_surface,
settings().layer_transforms_should_scale_layer_contents,
- &render_surface_layer_list_);
+ &render_surface_layer_list_,
+ render_surface_layer_list_id_);
LayerTreeHostCommon::CalculateDrawProperties(&inputs);
}
@@ -405,29 +489,29 @@ void LayerTreeImpl::UpdateDrawProperties() {
// LayerIterator is used here instead of CallFunctionForSubtree to only
// UpdateTilePriorities on layers that will be visible (and thus have valid
// draw properties) and not because any ordering is required.
- typedef LayerIterator<LayerImpl,
- LayerImplList,
- RenderSurfaceImpl,
- LayerIteratorActions::FrontToBack> LayerIteratorType;
+ typedef LayerIterator<LayerImpl> LayerIteratorType;
LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
for (LayerIteratorType it =
LayerIteratorType::Begin(&render_surface_layer_list_);
it != end;
++it) {
- if (!it.represents_itself())
- continue;
LayerImpl* layer = *it;
+ if (it.represents_itself())
+ layer->UpdateTiles();
+
+ if (!it.represents_contributing_render_surface())
+ continue;
- layer->UpdateTilePriorities();
if (layer->mask_layer())
- layer->mask_layer()->UpdateTilePriorities();
+ layer->mask_layer()->UpdateTiles();
if (layer->replica_layer() && layer->replica_layer()->mask_layer())
- layer->replica_layer()->mask_layer()->UpdateTilePriorities();
+ layer->replica_layer()->mask_layer()->UpdateTiles();
}
}
DCHECK(!needs_update_draw_properties_) <<
"CalcDrawProperties should not set_needs_update_draw_properties()";
+ return true;
}
const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const {
@@ -437,9 +521,12 @@ const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const {
}
gfx::Size LayerTreeImpl::ScrollableSize() const {
- if (!root_scroll_layer_ || root_scroll_layer_->children().empty())
+ LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
+ ? OuterViewportScrollLayer()
+ : InnerViewportScrollLayer();
+ if (!root_scroll_layer || root_scroll_layer->children().empty())
return gfx::Size();
- return root_scroll_layer_->children()[0]->bounds();
+ return root_scroll_layer->children()[0]->bounds();
}
LayerImpl* LayerTreeImpl::LayerById(int id) {
@@ -473,8 +560,19 @@ void LayerTreeImpl::DidBecomeActive() {
if (!root_layer())
return;
+ if (next_activation_forces_redraw_) {
+ layer_tree_host_impl_->SetFullRootLayerDamage();
+ next_activation_forces_redraw_ = false;
+ }
+
+ if (scrolling_layer_id_from_previous_tree_) {
+ currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree(
+ root_layer_.get(), scrolling_layer_id_from_previous_tree_);
+ }
+
DidBecomeActiveRecursive(root_layer());
- FindRootScrollLayer();
+ devtools_instrumentation::DidActivateLayerTree(layer_tree_host_impl_->id(),
+ source_frame_number_);
}
bool LayerTreeImpl::ContentsTexturesPurged() const {
@@ -495,6 +593,18 @@ void LayerTreeImpl::ResetContentsTexturesPurged() {
layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}
+void LayerTreeImpl::SetRequiresHighResToDraw() {
+ requires_high_res_to_draw_ = true;
+}
+
+void LayerTreeImpl::ResetRequiresHighResToDraw() {
+ requires_high_res_to_draw_ = false;
+}
+
+bool LayerTreeImpl::RequiresHighResToDraw() const {
+ return requires_high_res_to_draw_;
+}
+
bool LayerTreeImpl::ViewportSizeInvalid() const {
return viewport_size_invalid_;
}
@@ -517,7 +627,7 @@ const LayerTreeSettings& LayerTreeImpl::settings() const {
return layer_tree_host_impl_->settings();
}
-const RendererCapabilities& LayerTreeImpl::GetRendererCapabilities() const {
+const RendererCapabilitiesImpl& LayerTreeImpl::GetRendererCapabilities() const {
return layer_tree_host_impl_->GetRendererCapabilities();
}
@@ -553,6 +663,10 @@ bool LayerTreeImpl::device_viewport_valid_for_tile_management() const {
return layer_tree_host_impl_->device_viewport_valid_for_tile_management();
}
+gfx::Size LayerTreeImpl::device_viewport_size() const {
+ return layer_tree_host_impl_->device_viewport_size();
+}
+
bool LayerTreeImpl::IsActiveTree() const {
return layer_tree_host_impl_->active_tree() == this;
}
@@ -591,12 +705,8 @@ base::TimeTicks LayerTreeImpl::CurrentFrameTimeTicks() const {
return layer_tree_host_impl_->CurrentFrameTimeTicks();
}
-base::Time LayerTreeImpl::CurrentFrameTime() const {
- return layer_tree_host_impl_->CurrentFrameTime();
-}
-
-base::TimeTicks LayerTreeImpl::CurrentPhysicalTimeTicks() const {
- return layer_tree_host_impl_->CurrentPhysicalTimeTicks();
+base::TimeDelta LayerTreeImpl::begin_impl_frame_interval() const {
+ return layer_tree_host_impl_->begin_impl_frame_interval();
}
void LayerTreeImpl::SetNeedsCommit() {
@@ -607,14 +717,44 @@ gfx::Size LayerTreeImpl::DrawViewportSize() const {
return layer_tree_host_impl_->DrawViewportSize();
}
-void LayerTreeImpl::StartScrollbarAnimation() {
- layer_tree_host_impl_->StartScrollbarAnimation();
+scoped_ptr<ScrollbarAnimationController>
+LayerTreeImpl::CreateScrollbarAnimationController(LayerImpl* scrolling_layer) {
+ DCHECK(settings().scrollbar_fade_delay_ms);
+ DCHECK(settings().scrollbar_fade_duration_ms);
+ base::TimeDelta delay =
+ base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_delay_ms);
+ base::TimeDelta duration =
+ base::TimeDelta::FromMilliseconds(settings().scrollbar_fade_duration_ms);
+ switch (settings().scrollbar_animator) {
+ case LayerTreeSettings::LinearFade: {
+ return ScrollbarAnimationControllerLinearFade::Create(
+ scrolling_layer, layer_tree_host_impl_, delay, duration)
+ .PassAs<ScrollbarAnimationController>();
+ }
+ case LayerTreeSettings::Thinning: {
+ return ScrollbarAnimationControllerThinning::Create(
+ scrolling_layer, layer_tree_host_impl_, delay, duration)
+ .PassAs<ScrollbarAnimationController>();
+ }
+ case LayerTreeSettings::NoAnimator:
+ NOTREACHED();
+ break;
+ }
+ return scoped_ptr<ScrollbarAnimationController>();
}
void LayerTreeImpl::DidAnimateScrollOffset() {
layer_tree_host_impl_->DidAnimateScrollOffset();
}
+bool LayerTreeImpl::use_gpu_rasterization() const {
+ return layer_tree_host_impl_->use_gpu_rasterization();
+}
+
+bool LayerTreeImpl::create_low_res_tiling() const {
+ return layer_tree_host_impl_->create_low_res_tiling();
+}
+
void LayerTreeImpl::SetNeedsRedraw() {
layer_tree_host_impl_->SetNeedsRedraw();
}
@@ -643,10 +783,7 @@ scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
state->Set("root_layer", root_layer_->AsValue().release());
scoped_ptr<base::ListValue> render_surface_layer_list(new base::ListValue());
- typedef LayerIterator<LayerImpl,
- LayerImplList,
- RenderSurfaceImpl,
- LayerIteratorActions::FrontToBack> LayerIteratorType;
+ typedef LayerIterator<LayerImpl> LayerIteratorType;
LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
for (LayerIteratorType it = LayerIteratorType::Begin(
&render_surface_layer_list_); it != end; ++it) {
@@ -665,37 +802,105 @@ void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
if (root_layer_scroll_offset_delegate_ == root_layer_scroll_offset_delegate)
return;
- root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
-
- if (root_scroll_layer_) {
- root_scroll_layer_->SetScrollOffsetDelegate(
- root_layer_scroll_offset_delegate_);
+ if (!root_layer_scroll_offset_delegate) {
+ // Make sure we remove the proxies from their layers before
+ // releasing them.
+ if (InnerViewportScrollLayer())
+ InnerViewportScrollLayer()->SetScrollOffsetDelegate(NULL);
+ if (OuterViewportScrollLayer())
+ OuterViewportScrollLayer()->SetScrollOffsetDelegate(NULL);
+ inner_viewport_scroll_delegate_proxy_.reset();
+ outer_viewport_scroll_delegate_proxy_.reset();
}
+ root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
+
if (root_layer_scroll_offset_delegate_) {
- root_layer_scroll_offset_delegate_->SetScrollableSize(ScrollableSize());
- root_layer_scroll_offset_delegate_->SetTotalPageScaleFactor(
- total_page_scale_factor());
+ root_layer_scroll_offset_delegate_->UpdateRootLayerState(
+ TotalScrollOffset(),
+ TotalMaxScrollOffset(),
+ ScrollableSize(),
+ total_page_scale_factor(),
+ min_page_scale_factor(),
+ max_page_scale_factor());
+
+ if (inner_viewport_scroll_layer_) {
+ inner_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
+ new LayerScrollOffsetDelegateProxy(InnerViewportScrollLayer(),
+ root_layer_scroll_offset_delegate_,
+ this));
+ inner_viewport_scroll_layer_->SetScrollOffsetDelegate(
+ inner_viewport_scroll_delegate_proxy_.get());
+ }
+
+ if (outer_viewport_scroll_layer_) {
+ outer_viewport_scroll_delegate_proxy_ = make_scoped_ptr(
+ new LayerScrollOffsetDelegateProxy(OuterViewportScrollLayer(),
+ root_layer_scroll_offset_delegate_,
+ this));
+ outer_viewport_scroll_layer_->SetScrollOffsetDelegate(
+ outer_viewport_scroll_delegate_proxy_.get());
+ }
}
}
-void LayerTreeImpl::UpdateRootScrollLayerSizeDelta() {
- LayerImpl* root_scroll = RootScrollLayer();
- LayerImpl* root_container = RootContainerLayer();
- DCHECK(root_scroll);
- DCHECK(root_container);
- DCHECK(IsActiveTree());
+void LayerTreeImpl::UpdateScrollOffsetDelegate() {
+ DCHECK(InnerViewportScrollLayer());
+ DCHECK(root_layer_scroll_offset_delegate_);
+
+ gfx::Vector2dF offset =
+ inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+
+ if (OuterViewportScrollLayer())
+ offset += outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+
+ root_layer_scroll_offset_delegate_->UpdateRootLayerState(
+ offset,
+ TotalMaxScrollOffset(),
+ ScrollableSize(),
+ total_page_scale_factor(),
+ min_page_scale_factor(),
+ max_page_scale_factor());
+}
+
+gfx::Vector2dF LayerTreeImpl::GetDelegatedScrollOffset(LayerImpl* layer) {
+ DCHECK(root_layer_scroll_offset_delegate_);
+ DCHECK(InnerViewportScrollLayer());
+ if (layer == InnerViewportScrollLayer() && !OuterViewportScrollLayer())
+ return root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
+
+ // If we get here, we have both inner/outer viewports, and need to distribute
+ // the scroll offset between them.
+ DCHECK(inner_viewport_scroll_delegate_proxy_);
+ DCHECK(outer_viewport_scroll_delegate_proxy_);
+ gfx::Vector2dF inner_viewport_offset =
+ inner_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+ gfx::Vector2dF outer_viewport_offset =
+ outer_viewport_scroll_delegate_proxy_->last_set_scroll_offset();
+
+ // It may be nothing has changed.
+ gfx::Vector2dF delegate_offset =
+ root_layer_scroll_offset_delegate_->GetTotalScrollOffset();
+ if (inner_viewport_offset + outer_viewport_offset == delegate_offset) {
+ if (layer == InnerViewportScrollLayer())
+ return inner_viewport_offset;
+ else
+ return outer_viewport_offset;
+ }
+
+ gfx::Vector2d max_outer_viewport_scroll_offset =
+ OuterViewportScrollLayer()->MaxScrollOffset();
- gfx::Vector2dF scrollable_viewport_size =
- gfx::RectF(ScrollableViewportSize()).bottom_right() - gfx::PointF();
+ outer_viewport_offset = delegate_offset - inner_viewport_offset;
+ outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset);
+ outer_viewport_offset.SetToMax(gfx::Vector2d());
- gfx::Vector2dF original_viewport_size =
- gfx::RectF(root_container->bounds()).bottom_right() -
- gfx::PointF();
- original_viewport_size.Scale(1 / page_scale_factor());
+ if (layer == OuterViewportScrollLayer())
+ return outer_viewport_offset;
- root_scroll->SetFixedContainerSizeDelta(
- scrollable_viewport_size - original_viewport_size);
+ inner_viewport_offset = delegate_offset - outer_viewport_offset;
+
+ return inner_viewport_offset;
}
void LayerTreeImpl::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
@@ -771,9 +976,14 @@ void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) {
// they are aborted if not serviced during draw.
DCHECK(IsActiveTree());
- DCHECK(std::find(layers_with_copy_output_request_.begin(),
- layers_with_copy_output_request_.end(),
- layer) == layers_with_copy_output_request_.end());
+ // DCHECK(std::find(layers_with_copy_output_request_.begin(),
+ // layers_with_copy_output_request_.end(),
+ // layer) == layers_with_copy_output_request_.end());
+ // TODO(danakj): Remove this once crash is found crbug.com/309777
+ for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) {
+ CHECK(layers_with_copy_output_request_[i] != layer)
+ << i << " of " << layers_with_copy_output_request_.size();
+ }
layers_with_copy_output_request_.push_back(layer);
}
@@ -788,6 +998,12 @@ void LayerTreeImpl::RemoveLayerWithCopyOutputRequest(LayerImpl* layer) {
layer);
DCHECK(it != layers_with_copy_output_request_.end());
layers_with_copy_output_request_.erase(it);
+
+ // TODO(danakj): Remove this once crash is found crbug.com/309777
+ for (size_t i = 0; i < layers_with_copy_output_request_.size(); ++i) {
+ CHECK(layers_with_copy_output_request_[i] != layer)
+ << i << " of " << layers_with_copy_output_request_.size();
+ }
}
const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest()
@@ -799,4 +1015,287 @@ const std::vector<LayerImpl*>& LayerTreeImpl::LayersWithCopyOutputRequest()
return layers_with_copy_output_request_;
}
+void LayerTreeImpl::ReleaseResourcesRecursive(LayerImpl* current) {
+ DCHECK(current);
+ current->ReleaseResources();
+ if (current->mask_layer())
+ ReleaseResourcesRecursive(current->mask_layer());
+ if (current->replica_layer())
+ ReleaseResourcesRecursive(current->replica_layer());
+ for (size_t i = 0; i < current->children().size(); ++i)
+ ReleaseResourcesRecursive(current->children()[i]);
+}
+
+template <typename LayerType>
+static inline bool LayerClipsSubtree(LayerType* layer) {
+ return layer->masks_to_bounds() || layer->mask_layer();
+}
+
+static bool PointHitsRect(
+ const gfx::PointF& screen_space_point,
+ const gfx::Transform& local_space_to_screen_space_transform,
+ const gfx::RectF& local_space_rect,
+ float* distance_to_camera) {
+ // If the transform is not invertible, then assume that this point doesn't hit
+ // this rect.
+ gfx::Transform inverse_local_space_to_screen_space(
+ gfx::Transform::kSkipInitialization);
+ if (!local_space_to_screen_space_transform.GetInverse(
+ &inverse_local_space_to_screen_space))
+ return false;
+
+ // Transform the hit test point from screen space to the local space of the
+ // given rect.
+ bool clipped = false;
+ gfx::Point3F planar_point = MathUtil::ProjectPoint3D(
+ inverse_local_space_to_screen_space, screen_space_point, &clipped);
+ gfx::PointF hit_test_point_in_local_space =
+ gfx::PointF(planar_point.x(), planar_point.y());
+
+ // If ProjectPoint could not project to a valid value, then we assume that
+ // this point doesn't hit this rect.
+ if (clipped)
+ return false;
+
+ if (!local_space_rect.Contains(hit_test_point_in_local_space))
+ return false;
+
+ if (distance_to_camera) {
+ // To compute the distance to the camera, we have to take the planar point
+ // and pull it back to world space and compute the displacement along the
+ // z-axis.
+ gfx::Point3F planar_point_in_screen_space(planar_point);
+ local_space_to_screen_space_transform.TransformPoint(
+ &planar_point_in_screen_space);
+ *distance_to_camera = planar_point_in_screen_space.z();
+ }
+
+ return true;
+}
+
+static bool PointHitsRegion(const gfx::PointF& screen_space_point,
+ const gfx::Transform& screen_space_transform,
+ const Region& layer_space_region,
+ float layer_content_scale_x,
+ float layer_content_scale_y) {
+ // If the transform is not invertible, then assume that this point doesn't hit
+ // this region.
+ gfx::Transform inverse_screen_space_transform(
+ gfx::Transform::kSkipInitialization);
+ if (!screen_space_transform.GetInverse(&inverse_screen_space_transform))
+ return false;
+
+ // Transform the hit test point from screen space to the local space of the
+ // given region.
+ bool clipped = false;
+ gfx::PointF hit_test_point_in_content_space = MathUtil::ProjectPoint(
+ inverse_screen_space_transform, screen_space_point, &clipped);
+ gfx::PointF hit_test_point_in_layer_space =
+ gfx::ScalePoint(hit_test_point_in_content_space,
+ 1.f / layer_content_scale_x,
+ 1.f / layer_content_scale_y);
+
+ // If ProjectPoint could not project to a valid value, then we assume that
+ // this point doesn't hit this region.
+ if (clipped)
+ return false;
+
+ return layer_space_region.Contains(
+ gfx::ToRoundedPoint(hit_test_point_in_layer_space));
+}
+
+static LayerImpl* GetNextClippingLayer(LayerImpl* layer) {
+ if (layer->scroll_parent())
+ return layer->scroll_parent();
+ if (layer->clip_parent())
+ return layer->clip_parent();
+ return layer->parent();
+}
+
+static bool PointIsClippedBySurfaceOrClipRect(
+ const gfx::PointF& screen_space_point,
+ LayerImpl* layer) {
+ // Walk up the layer tree and hit-test any render_surfaces and any layer
+ // clip rects that are active.
+ for (; layer; layer = GetNextClippingLayer(layer)) {
+ if (layer->render_surface() &&
+ !PointHitsRect(screen_space_point,
+ layer->render_surface()->screen_space_transform(),
+ layer->render_surface()->content_rect(),
+ NULL))
+ return true;
+
+ if (LayerClipsSubtree(layer) &&
+ !PointHitsRect(screen_space_point,
+ layer->screen_space_transform(),
+ gfx::Rect(layer->content_bounds()),
+ NULL))
+ return true;
+ }
+
+ // If we have finished walking all ancestors without having already exited,
+ // then the point is not clipped by any ancestors.
+ return false;
+}
+
+static bool PointHitsLayer(LayerImpl* layer,
+ const gfx::PointF& screen_space_point,
+ float* distance_to_intersection) {
+ gfx::RectF content_rect(layer->content_bounds());
+ if (!PointHitsRect(screen_space_point,
+ layer->screen_space_transform(),
+ content_rect,
+ distance_to_intersection))
+ return false;
+
+ // At this point, we think the point does hit the layer, but we need to walk
+ // up the parents to ensure that the layer was not clipped in such a way
+ // that the hit point actually should not hit the layer.
+ if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer))
+ return false;
+
+ // Skip the HUD layer.
+ if (layer == layer->layer_tree_impl()->hud_layer())
+ return false;
+
+ return true;
+}
+
+struct FindClosestMatchingLayerDataForRecursion {
+ FindClosestMatchingLayerDataForRecursion()
+ : closest_match(NULL),
+ closest_distance(-std::numeric_limits<float>::infinity()) {}
+ LayerImpl* closest_match;
+ // Note that the positive z-axis points towards the camera, so bigger means
+ // closer in this case, counterintuitively.
+ float closest_distance;
+};
+
+template <typename Functor>
+static void FindClosestMatchingLayer(
+ const gfx::PointF& screen_space_point,
+ LayerImpl* layer,
+ const Functor& func,
+ FindClosestMatchingLayerDataForRecursion* data_for_recursion) {
+ for (int i = layer->children().size() - 1; i >= 0; --i) {
+ FindClosestMatchingLayer(
+ screen_space_point, layer->children()[i], func, data_for_recursion);
+ }
+
+ float distance_to_intersection = 0.f;
+ if (func(layer) &&
+ PointHitsLayer(layer, screen_space_point, &distance_to_intersection) &&
+ ((!data_for_recursion->closest_match ||
+ distance_to_intersection > data_for_recursion->closest_distance))) {
+ data_for_recursion->closest_distance = distance_to_intersection;
+ data_for_recursion->closest_match = layer;
+ }
+}
+
+static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) {
+ if (!layer->scrollable())
+ return false;
+ if (layer->IsDrawnRenderSurfaceLayerListMember())
+ return true;
+ if (!layer->scroll_children())
+ return false;
+ for (std::set<LayerImpl*>::const_iterator it =
+ layer->scroll_children()->begin();
+ it != layer->scroll_children()->end();
+ ++it) {
+ if ((*it)->IsDrawnRenderSurfaceLayerListMember())
+ return true;
+ }
+ return false;
+}
+
+struct FindScrollingLayerFunctor {
+ bool operator()(LayerImpl* layer) const {
+ return ScrollsAnyDrawnRenderSurfaceLayerListMember(layer);
+ }
+};
+
+LayerImpl* LayerTreeImpl::FindFirstScrollingLayerThatIsHitByPoint(
+ const gfx::PointF& screen_space_point) {
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(screen_space_point,
+ root_layer(),
+ FindScrollingLayerFunctor(),
+ &data_for_recursion);
+ return data_for_recursion.closest_match;
+}
+
+struct HitTestVisibleScrollableOrTouchableFunctor {
+ bool operator()(LayerImpl* layer) const {
+ return layer->IsDrawnRenderSurfaceLayerListMember() ||
+ ScrollsAnyDrawnRenderSurfaceLayerListMember(layer) ||
+ !layer->touch_event_handler_region().IsEmpty() ||
+ layer->have_wheel_event_handlers();
+ }
+};
+
+LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPoint(
+ const gfx::PointF& screen_space_point) {
+ if (!root_layer())
+ return NULL;
+ if (!UpdateDrawProperties())
+ return NULL;
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(screen_space_point,
+ root_layer(),
+ HitTestVisibleScrollableOrTouchableFunctor(),
+ &data_for_recursion);
+ return data_for_recursion.closest_match;
+}
+
+static bool LayerHasTouchEventHandlersAt(const gfx::PointF& screen_space_point,
+ LayerImpl* layer_impl) {
+ if (layer_impl->touch_event_handler_region().IsEmpty())
+ return false;
+
+ if (!PointHitsRegion(screen_space_point,
+ layer_impl->screen_space_transform(),
+ layer_impl->touch_event_handler_region(),
+ layer_impl->contents_scale_x(),
+ layer_impl->contents_scale_y()))
+ return false;
+
+ // At this point, we think the point does hit the touch event handler region
+ // on the layer, but we need to walk up the parents to ensure that the layer
+ // was not clipped in such a way that the hit point actually should not hit
+ // the layer.
+ if (PointIsClippedBySurfaceOrClipRect(screen_space_point, layer_impl))
+ return false;
+
+ return true;
+}
+
+struct FindTouchEventLayerFunctor {
+ bool operator()(LayerImpl* layer) const {
+ return LayerHasTouchEventHandlersAt(screen_space_point, layer);
+ }
+ const gfx::PointF screen_space_point;
+};
+
+LayerImpl* LayerTreeImpl::FindLayerThatIsHitByPointInTouchHandlerRegion(
+ const gfx::PointF& screen_space_point) {
+ if (!root_layer())
+ return NULL;
+ if (!UpdateDrawProperties())
+ return NULL;
+ FindTouchEventLayerFunctor func = {screen_space_point};
+ FindClosestMatchingLayerDataForRecursion data_for_recursion;
+ FindClosestMatchingLayer(
+ screen_space_point, root_layer(), func, &data_for_recursion);
+ return data_for_recursion.closest_match;
+}
+
+void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
+ layer_tree_host_impl_->RegisterPictureLayerImpl(layer);
+}
+
+void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
+ layer_tree_host_impl_->UnregisterPictureLayerImpl(layer);
+}
+
} // namespace cc