| Index: cc/layers/picture_layer_impl.cc
 | 
| diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
 | 
| index 965a6129e66322a4bfb7bf04694d19eca580e46b..aacabde2c4effca2dc505f9ea303f6231d84ad1c 100644
 | 
| --- a/cc/layers/picture_layer_impl.cc
 | 
| +++ b/cc/layers/picture_layer_impl.cc
 | 
| @@ -90,6 +90,8 @@ PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id)
 | 
|  }
 | 
|  
 | 
|  PictureLayerImpl::~PictureLayerImpl() {
 | 
| +  if (twin_layer_)
 | 
| +    twin_layer_->twin_layer_ = nullptr;
 | 
|    layer_tree_impl()->UnregisterPictureLayerImpl(this);
 | 
|  }
 | 
|  
 | 
| @@ -110,10 +112,15 @@ void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
 | 
|  
 | 
|    LayerImpl::PushPropertiesTo(base_layer);
 | 
|  
 | 
| -  // When the pending tree pushes to the active tree, the pending twin
 | 
| -  // becomes recycled.
 | 
| -  layer_impl->twin_layer_ = nullptr;
 | 
| -  twin_layer_ = nullptr;
 | 
| +  // Twin relationships should never change once established.
 | 
| +  DCHECK_IMPLIES(twin_layer_, twin_layer_ == layer_impl);
 | 
| +  DCHECK_IMPLIES(twin_layer_, layer_impl->twin_layer_ == this);
 | 
| +  // The twin relationship does not need to exist before the first
 | 
| +  // PushPropertiesTo from pending to active layer since before that the active
 | 
| +  // layer can not have a pile or tilings, it has only been created and inserted
 | 
| +  // into the tree at that point.
 | 
| +  twin_layer_ = layer_impl;
 | 
| +  layer_impl->twin_layer_ = this;
 | 
|  
 | 
|    layer_impl->pile_ = pile_;
 | 
|  
 | 
| @@ -566,10 +573,16 @@ gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const {
 | 
|    return visible_rect_in_content_space;
 | 
|  }
 | 
|  
 | 
| -PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() {
 | 
| -  // TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418
 | 
| -  return static_cast<PictureLayerImpl*>(
 | 
| -      layer_tree_impl()->FindRecycleTreeLayerById(id()));
 | 
| +PictureLayerImpl* PictureLayerImpl::GetPendingOrActiveTwinLayer() const {
 | 
| +  if (!twin_layer_ || !twin_layer_->IsOnActiveOrPendingTree())
 | 
| +    return nullptr;
 | 
| +  return twin_layer_;
 | 
| +}
 | 
| +
 | 
| +PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() const {
 | 
| +  if (!twin_layer_ || twin_layer_->IsOnActiveOrPendingTree())
 | 
| +    return nullptr;
 | 
| +  return twin_layer_;
 | 
|  }
 | 
|  
 | 
|  void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
 | 
| @@ -641,16 +654,20 @@ const Region* PictureLayerImpl::GetPendingInvalidation() {
 | 
|    if (layer_tree_impl()->IsPendingTree())
 | 
|      return &invalidation_;
 | 
|    DCHECK(layer_tree_impl()->IsActiveTree());
 | 
| -  if (PictureLayerImpl* twin_layer = GetTwinLayer())
 | 
| +  if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer())
 | 
|      return &twin_layer->invalidation_;
 | 
|    return nullptr;
 | 
|  }
 | 
|  
 | 
| -const PictureLayerTiling* PictureLayerImpl::GetTwinTiling(
 | 
| +const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling(
 | 
|      const PictureLayerTiling* tiling) const {
 | 
| -  if (!twin_layer_)
 | 
| +  PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer();
 | 
| +  if (!twin_layer)
 | 
|      return nullptr;
 | 
| -  return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale());
 | 
| +  // TODO(danakj): Remove this when no longer swapping tilings.
 | 
| +  if (!twin_layer->tilings_)
 | 
| +    return nullptr;
 | 
| +  return twin_layer->tilings_->TilingAtScale(tiling->contents_scale());
 | 
|  }
 | 
|  
 | 
|  PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling(
 | 
| @@ -803,6 +820,8 @@ void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) {
 | 
|  
 | 
|  void PictureLayerImpl::SyncTiling(
 | 
|      const PictureLayerTiling* tiling) {
 | 
| +  if (!tilings_)
 | 
| +    return;
 | 
|    if (!CanHaveTilingWithScale(tiling->contents_scale()))
 | 
|      return;
 | 
|    tilings_->AddTiling(tiling->contents_scale(), pile_->tiling_size());
 | 
| @@ -858,16 +877,12 @@ void PictureLayerImpl::DoPostCommitInitialization() {
 | 
|    if (!tilings_)
 | 
|      tilings_ = make_scoped_ptr(new PictureLayerTilingSet(this));
 | 
|  
 | 
| -  DCHECK(!twin_layer_);
 | 
| -  twin_layer_ = static_cast<PictureLayerImpl*>(
 | 
| -      layer_tree_impl()->FindActiveTreeLayerById(id()));
 | 
| -  if (twin_layer_) {
 | 
| -    DCHECK(!twin_layer_->twin_layer_);
 | 
| -    twin_layer_->twin_layer_ = this;
 | 
| +  PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer();
 | 
| +  if (twin_layer) {
 | 
|      // If the twin has never been pushed to, do not sync from it.
 | 
|      // This can happen if this function is called during activation.
 | 
| -    if (!twin_layer_->needs_post_commit_initialization_)
 | 
| -      SyncFromActiveLayer(twin_layer_);
 | 
| +    if (!twin_layer->needs_post_commit_initialization_)
 | 
| +      SyncFromActiveLayer(twin_layer);
 | 
|    }
 | 
|  
 | 
|    needs_post_commit_initialization_ = false;
 | 
| @@ -882,8 +897,8 @@ PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) {
 | 
|  
 | 
|    DCHECK(pile_->HasRecordings());
 | 
|  
 | 
| -  if (twin_layer_)
 | 
| -    twin_layer_->SyncTiling(tiling);
 | 
| +  if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer())
 | 
| +    twin_layer->SyncTiling(tiling);
 | 
|  
 | 
|    return tiling;
 | 
|  }
 | 
| @@ -1127,7 +1142,7 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
 | 
|        raster_contents_scale_, ideal_contents_scale_);
 | 
|    float twin_low_res_scale = 0.f;
 | 
|  
 | 
| -  PictureLayerImpl* twin = twin_layer_;
 | 
| +  PictureLayerImpl* twin = GetPendingOrActiveTwinLayer();
 | 
|    if (twin && twin->CanHaveTilings()) {
 | 
|      min_acceptable_high_res_scale = std::min(
 | 
|          min_acceptable_high_res_scale,
 | 
| @@ -1136,10 +1151,14 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
 | 
|          max_acceptable_high_res_scale,
 | 
|          std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
 | 
|  
 | 
| -    for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
 | 
| -      PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
 | 
| -      if (tiling->resolution() == LOW_RESOLUTION)
 | 
| -        twin_low_res_scale = tiling->contents_scale();
 | 
| +    // TODO(danakj): Remove the tilings_ check when we create them in the
 | 
| +    // constructor.
 | 
| +    if (twin->tilings_) {
 | 
| +      for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) {
 | 
| +        PictureLayerTiling* tiling = twin->tilings_->tiling_at(i);
 | 
| +        if (tiling->resolution() == LOW_RESOLUTION)
 | 
| +          twin_low_res_scale = tiling->contents_scale();
 | 
| +      }
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -1174,7 +1193,8 @@ void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
 | 
|    PictureLayerImpl* recycled_twin = GetRecycledTwinLayer();
 | 
|    // Remove tilings on this tree and the twin tree.
 | 
|    for (size_t i = 0; i < to_remove.size(); ++i) {
 | 
| -    const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]);
 | 
| +    const PictureLayerTiling* twin_tiling =
 | 
| +        GetPendingOrActiveTwinTiling(to_remove[i]);
 | 
|      // Only remove tilings from the twin layer if they have
 | 
|      // NON_IDEAL_RESOLUTION.
 | 
|      if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION)
 | 
| 
 |