| Index: cc/resources/shared_tile_bundle.cc
 | 
| diff --git a/cc/resources/shared_tile_bundle.cc b/cc/resources/shared_tile_bundle.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..906346ba2ff3f5ee161ec699b7d5933563be8402
 | 
| --- /dev/null
 | 
| +++ b/cc/resources/shared_tile_bundle.cc
 | 
| @@ -0,0 +1,198 @@
 | 
| +// Copyright 2013 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/resources/shared_tile_bundle.h"
 | 
| +
 | 
| +namespace cc {
 | 
| +
 | 
| +SharedTileBundle::SharedTileBundle() {}
 | 
| +
 | 
| +SharedTileBundle::SharedTileBundle(const TilePriority& active_priority,
 | 
| +                                   const TilePriority& pending_priority)
 | 
| +    : active_priority_(active_priority), pending_priority_(pending_priority) {}
 | 
| +
 | 
| +void SharedTileBundle::AddTileAt(int x, int y, Tile* tile) {
 | 
| +  TileMapKey key(x, y);
 | 
| +  DCHECK(tiles_.find(key) == tiles_.end());
 | 
| +  tiles_[key] = tile;
 | 
| +}
 | 
| +
 | 
| +SharedTileBundle::Iterator::Iterator(SharedTileBundle* bundle)
 | 
| +    : bundle_(bundle), iterator_(bundle_->tiles_.begin()) {}
 | 
| +
 | 
| +SharedTileBundle::Iterator::~Iterator() {}
 | 
| +
 | 
| +BundleSetIterator::BundleSetIterator(TileBundleMap* bundles)
 | 
| +    : bundles_(bundles),
 | 
| +      current_bundle_iterator_(bundles_->begin()),
 | 
| +      current_bundle_type_(eActivePriorityOnly),
 | 
| +      active_bundle_(NULL),
 | 
| +      pending_bundle_(NULL) {
 | 
| +  if (current_bundle_iterator_ == bundles_->end())
 | 
| +    return;
 | 
| +
 | 
| +  bool success = InitializeSharedBundles();
 | 
| +  if (success)
 | 
| +    return;
 | 
| +
 | 
| +  AdvanceBundleIterator();
 | 
| +}
 | 
| +
 | 
| +BundleSetIterator::~BundleSetIterator() {}
 | 
| +
 | 
| +SharedTileBundle* BundleSetIterator::operator*() {
 | 
| +  return ¤t_bundle_;
 | 
| +}
 | 
| +
 | 
| +SharedTileBundle* BundleSetIterator::operator->() {
 | 
| +  return ¤t_bundle_;
 | 
| +}
 | 
| +
 | 
| +BundleSetIterator::operator bool() const {
 | 
| +  return current_bundle_iterator_ != bundles_->end();
 | 
| +}
 | 
| +
 | 
| +BundleSetIterator& BundleSetIterator::operator++() {
 | 
| +  DCHECK(current_bundle_type_ != eMaxSharedBundleTypes);
 | 
| +  DCHECK(current_bundle_iterator_ != bundles_->end());
 | 
| +
 | 
| +  current_bundle_type_ =
 | 
| +      static_cast<SharedBundleType>(current_bundle_type_ + 1);
 | 
| +  while (current_bundle_type_ != eMaxSharedBundleTypes) {
 | 
| +    bool success = InitializeSharedBundle(current_bundle_type_);
 | 
| +    if (success)
 | 
| +      return *this;
 | 
| +    current_bundle_type_ =
 | 
| +        static_cast<SharedBundleType>(current_bundle_type_ + 1);
 | 
| +  }
 | 
| +
 | 
| +  AdvanceBundleIterator();
 | 
| +  return *this;
 | 
| +}
 | 
| +
 | 
| +void BundleSetIterator::AdvanceBundleIterator() {
 | 
| +  DCHECK(current_bundle_iterator_ != bundles_->end());
 | 
| +
 | 
| +  ++current_bundle_iterator_;
 | 
| +  while (current_bundle_iterator_ != bundles_->end()) {
 | 
| +    bool success = InitializeSharedBundles();
 | 
| +    if (success)
 | 
| +      break;
 | 
| +    ++current_bundle_iterator_;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +bool BundleSetIterator::InitializeSharedBundles() {
 | 
| +  active_bundle_ = NULL;
 | 
| +  pending_bundle_ = NULL;
 | 
| +
 | 
| +  TileBundle* bundle = current_bundle_iterator_->second;
 | 
| +  if ((processed_bundles_.count(bundle->id()) != 0) || bundle->IsRecycled())
 | 
| +    return false;
 | 
| +
 | 
| +  DetermineActivePendingBundles(bundle, bundle->GetTwinBundle());
 | 
| +
 | 
| +  if (active_bundle_)
 | 
| +    processed_bundles_.insert(active_bundle_->id());
 | 
| +  if (pending_bundle_)
 | 
| +    processed_bundles_.insert(pending_bundle_->id());
 | 
| +
 | 
| +  bool success = InitializeSharedBundle(current_bundle_type_);
 | 
| +  if (success)
 | 
| +    return true;
 | 
| +
 | 
| +  current_bundle_type_ =
 | 
| +      static_cast<SharedBundleType>(current_bundle_type_ + 1);
 | 
| +  while (current_bundle_type_ != eMaxSharedBundleTypes) {
 | 
| +    success = InitializeSharedBundle(current_bundle_type_);
 | 
| +    if (success)
 | 
| +      return true;
 | 
| +    current_bundle_type_ =
 | 
| +        static_cast<SharedBundleType>(current_bundle_type_ + 1);
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +bool BundleSetIterator::InitializeSharedBundle(SharedBundleType type) {
 | 
| +  bool first_run = true;
 | 
| +  switch (type) {
 | 
| +    case eBothPriorities:
 | 
| +      if (!active_bundle_ || !pending_bundle_)
 | 
| +        return false;
 | 
| +
 | 
| +      for (TileBundle::Iterator it(active_bundle_); it; ++it) {
 | 
| +        Tile* tile = pending_bundle_->TileAt(it.index_x(), it.index_y());
 | 
| +        if (tile != *it)
 | 
| +          continue;
 | 
| +
 | 
| +        if (first_run) {
 | 
| +          current_bundle_ = SharedTileBundle(active_bundle_->GetPriority(),
 | 
| +                                             pending_bundle_->GetPriority());
 | 
| +          first_run = false;
 | 
| +        }
 | 
| +        current_bundle_.AddTileAt(it.index_x(), it.index_y(), tile);
 | 
| +      }
 | 
| +      break;
 | 
| +    case eActivePriorityOnly:
 | 
| +      if (!active_bundle_)
 | 
| +        return false;
 | 
| +
 | 
| +      for (TileBundle::Iterator it(active_bundle_); it; ++it) {
 | 
| +        if (pending_bundle_ &&
 | 
| +            pending_bundle_->TileAt(it.index_x(), it.index_y()) == *it)
 | 
| +          continue;
 | 
| +
 | 
| +        if (first_run) {
 | 
| +          current_bundle_ = SharedTileBundle(active_bundle_->GetPriority(),
 | 
| +                                             TilePriority());
 | 
| +          first_run = false;
 | 
| +        }
 | 
| +        current_bundle_.AddTileAt(it.index_x(), it.index_y(), *it);
 | 
| +      }
 | 
| +      break;
 | 
| +    case ePendingPriorityOnly:
 | 
| +      if (!pending_bundle_)
 | 
| +        return false;
 | 
| +
 | 
| +      for (TileBundle::Iterator it(pending_bundle_); it; ++it) {
 | 
| +        if (active_bundle_ &&
 | 
| +            active_bundle_->TileAt(it.index_x(), it.index_y()) == *it)
 | 
| +          continue;
 | 
| +
 | 
| +        if (first_run) {
 | 
| +          current_bundle_ = SharedTileBundle(TilePriority(),
 | 
| +                                             pending_bundle_->GetPriority());
 | 
| +          first_run = false;
 | 
| +        }
 | 
| +        current_bundle_.AddTileAt(it.index_x(), it.index_y(), *it);
 | 
| +      }
 | 
| +      break;
 | 
| +    case eMaxSharedBundleTypes:
 | 
| +      NOTREACHED();
 | 
| +      break;
 | 
| +  }
 | 
| +  return !first_run;
 | 
| +}
 | 
| +
 | 
| +void BundleSetIterator::DetermineActivePendingBundles(TileBundle* bundle,
 | 
| +                                                      TileBundle* twin_bundle) {
 | 
| +  if (twin_bundle && !twin_bundle->IsRecycled()) {
 | 
| +    if (bundle->IsActive()) {
 | 
| +      active_bundle_ = bundle;
 | 
| +      pending_bundle_ = twin_bundle;
 | 
| +    } else {
 | 
| +      active_bundle_ = twin_bundle;
 | 
| +      pending_bundle_ = bundle;
 | 
| +    }
 | 
| +    current_bundle_type_ = eBothPriorities;
 | 
| +  } else if (bundle->IsActive()) {
 | 
| +    active_bundle_ = bundle;
 | 
| +    current_bundle_type_ = eActivePriorityOnly;
 | 
| +  } else {
 | 
| +    pending_bundle_ = bundle;
 | 
| +    current_bundle_type_ = ePendingPriorityOnly;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace cc
 | 
| 
 |