// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/tiles/tile_manager.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <string>

#include <optional>
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/traced_value.h"
#include "cc/base/devtools_instrumentation.h"
#include "cc/base/features.h"
#include "cc/base/histograms.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/paint/display_item_list.h"
#include "cc/raster/paint_worklet_image_provider.h"
#include "cc/raster/playback_image_provider.h"
#include "cc/raster/raster_buffer.h"
#include "cc/raster/task_category.h"
#include "cc/tiles/frame_viewer_instrumentation.h"
#include "cc/tiles/tile.h"
#include "cc/tiles/tile_priority.h"
#include "cc/tiles/tiles_with_resource_iterator.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {
namespace {

// Flag to indicate whether we should try and detect that
// a tile is of solid color.
const bool kUseColorEstimator = true;

// This class is wrapper for both ImageProvider and PaintWorkletImageProvider,
// which is used in RasterSource::PlaybackSettings. It looks at the draw image
// and decides which one of the two providers to dispatch the request to.
class DispatchingImageProvider : public ImageProvider {
 public:
  DispatchingImageProvider(
      PlaybackImageProvider playback_image_provider,
      PaintWorkletImageProvider paint_worklet_image_provider)
      : playback_image_provider_(std::move(playback_image_provider)),
        paint_worklet_image_provider_(std::move(paint_worklet_image_provider)) {
  }
  DispatchingImageProvider(const DispatchingImageProvider&) = delete;
  ~DispatchingImageProvider() override = default;

  DispatchingImageProvider& operator=(const DispatchingImageProvider&) = delete;

  DispatchingImageProvider(DispatchingImageProvider&& other) = default;

  ImageProvider::ScopedResult GetRasterContent(
      const DrawImage& draw_image) override {
    return draw_image.paint_image().IsPaintWorklet()
               ? paint_worklet_image_provider_.GetPaintRecordResult(
                     draw_image.paint_image().paint_worklet_input())
               : playback_image_provider_.GetRasterContent(draw_image);
  }

 private:
  PlaybackImageProvider playback_image_provider_;
  PaintWorkletImageProvider paint_worklet_image_provider_;
};

class RasterTaskImpl : public TileTask {
 public:
  RasterTaskImpl(TileManager* tile_manager,
                 Tile* tile,
                 ResourcePool::InUsePoolResource resource,
                 scoped_refptr<RasterSource> raster_source,
                 const RasterSource::PlaybackSettings& playback_settings,
                 TileResolution tile_resolution,
                 gfx::Rect invalidated_rect,
                 uint64_t source_prepare_tiles_id,
                 std::unique_ptr<RasterBuffer> raster_buffer,
                 TileTask::Vector* dependencies,
                 bool is_gpu_rasterization,
                 DispatchingImageProvider image_provider,
                 GURL url)
      : TileTask(
            is_gpu_rasterization ? TileTask::SupportsConcurrentExecution::kNo
                                 : TileTask::SupportsConcurrentExecution::kYes,
            raster_buffer && raster_buffer->SupportsBackgroundThreadPriority()
                ? TileTask::SupportsBackgroundThreadPriority::kYes
                : TileTask::SupportsBackgroundThreadPriority::kNo,
            dependencies),
        tile_manager_(tile_manager),
        tile_id_(tile->id()),
        resource_(std::move(resource)),
        raster_source_(std::move(raster_source)),
        content_rect_(tile->content_rect()),
        invalid_content_rect_(invalidated_rect),
        raster_transform_(tile->raster_transform()),
        playback_settings_(playback_settings),
        tile_resolution_(tile_resolution),
        layer_id_(tile->layer_id()),
        source_prepare_tiles_id_(source_prepare_tiles_id),
        tile_tracing_id_(static_cast<void*>(tile)),
        new_content_id_(tile->id()),
        source_frame_number_(tile->source_frame_number()),
        raster_buffer_(std::move(raster_buffer)),
        image_provider_(std::move(image_provider)),
        url_(std::move(url)) {
    DCHECK(origin_thread_checker_.CalledOnValidThread());
    playback_settings_.image_provider = &image_provider_;
  }
  RasterTaskImpl(const RasterTaskImpl&) = delete;
  RasterTaskImpl& operator=(const RasterTaskImpl&) = delete;

  // Overridden from Task:
  void RunOnWorkerThread() override {
    TRACE_EVENT1("cc", "RasterizerTaskImpl::RunOnWorkerThread",
                 "source_prepare_tiles_id", source_prepare_tiles_id_);

    DCHECK(raster_source_.get());
    DCHECK(raster_buffer_);

    frame_viewer_instrumentation::ScopedRasterTask raster_task(
        tile_tracing_id_, tile_resolution_, source_frame_number_, layer_id_);

    DCHECK(raster_source_);

    raster_buffer_->Playback(raster_source_.get(), content_rect_,
                             invalid_content_rect_, new_content_id_,
                             raster_transform_, playback_settings_, url_);
  }

  // Overridden from TileTask:
  void OnTaskCompleted() override {
    DCHECK(origin_thread_checker_.CalledOnValidThread());

    // Here calling state().IsCanceled() is thread-safe, because this task is
    // already concluded as FINISHED or CANCELLED and no longer will be worked
    // upon by task graph runner.
    raster_buffer_ = nullptr;
    tile_manager_->OnRasterTaskCompleted(tile_id_, std::move(resource_),
                                         state().IsCanceled());
  }

 protected:
  ~RasterTaskImpl() override {
    DCHECK(origin_thread_checker_.CalledOnValidThread());
    DCHECK(!raster_buffer_);
    DCHECK(!resource_);
  }

 private:
  base::ThreadChecker origin_thread_checker_;

  // The following members are needed for processing completion of this task on
  // origin thread. These are not thread-safe and should be accessed only in
  // origin thread. Ensure their access by checking CalledOnValidThread().
  raw_ptr<TileManager> tile_manager_;
  Tile::Id tile_id_;
  ResourcePool::InUsePoolResource resource_;

  // The following members should be used for running the task.
  scoped_refptr<RasterSource> raster_source_;
  gfx::Rect content_rect_;
  gfx::Rect invalid_content_rect_;
  gfx::AxisTransform2d raster_transform_;
  RasterSource::PlaybackSettings playback_settings_;
  TileResolution tile_resolution_;
  int layer_id_;
  uint64_t source_prepare_tiles_id_;
  raw_ptr<void, AcrossTasksDanglingUntriaged> tile_tracing_id_;
  uint64_t new_content_id_;
  int source_frame_number_;
  std::unique_ptr<RasterBuffer> raster_buffer_;
  DispatchingImageProvider image_provider_;
  GURL url_;
};

TaskCategory TaskCategoryForTileTask(TileTask* task,
                                     bool use_foreground_category) {
  if (!task->supports_concurrent_execution())
    return TASK_CATEGORY_NONCONCURRENT_FOREGROUND;

  if (use_foreground_category)
    return TASK_CATEGORY_FOREGROUND;

  if (!task->supports_background_thread_priority())
    return TASK_CATEGORY_BACKGROUND_WITH_NORMAL_THREAD_PRIORITY;

  return TASK_CATEGORY_BACKGROUND;
}

bool IsForegroundCategory(uint16_t category) {
  TaskCategory enum_category = static_cast<TaskCategory>(category);
  switch (enum_category) {
    case TASK_CATEGORY_NONCONCURRENT_FOREGROUND:
    case TASK_CATEGORY_FOREGROUND:
      return true;
    case TASK_CATEGORY_BACKGROUND:
    case TASK_CATEGORY_BACKGROUND_WITH_NORMAL_THREAD_PRIORITY:
      return false;
  }

  NOTREACHED();
  return false;
}

// Task priorities that make sure that the task set done tasks run before any
// other remaining tasks.
const size_t kRequiredForActivationDoneTaskPriority = 1u;
const size_t kRequiredForDrawDoneTaskPriority = 2u;
const size_t kAllDoneTaskPriority = 3u;

// For correctness, |kTileTaskPriorityBase| must be greater than
// all task set done task priorities.
size_t kTileTaskPriorityBase = 10u;

void InsertNodeForTask(TaskGraph* graph,
                       TileTask* task,
                       uint16_t category,
                       uint16_t priority,
                       size_t dependencies) {
  DCHECK(!base::Contains(graph->nodes, task, &TaskGraph::Node::task));
  graph->nodes.emplace_back(task, category, priority, dependencies);
}

void InsertNodeForDecodeTask(TaskGraph* graph,
                             TileTask* task,
                             bool use_foreground_category,
                             uint16_t priority) {
  uint32_t dependency_count = 0u;
  if (task->dependencies().size()) {
    DCHECK_EQ(task->dependencies().size(), 1u);
    auto* dependency = task->dependencies()[0].get();
    if (!dependency->HasCompleted()) {
      InsertNodeForDecodeTask(graph, dependency, use_foreground_category,
                              priority);
      graph->edges.emplace_back(dependency, task);
      dependency_count = 1u;
    }
  }
  InsertNodeForTask(graph, task,
                    TaskCategoryForTileTask(task, use_foreground_category),
                    priority, dependency_count);
}

void InsertNodesForRasterTask(TaskGraph* graph,
                              TileTask* raster_task,
                              const TileTask::Vector& decode_tasks,
                              size_t priority,
                              bool use_foreground_category) {
  size_t dependencies = 0u;

  // Insert image decode tasks.
  for (auto it = decode_tasks.begin(); it != decode_tasks.end(); ++it) {
    TileTask* decode_task = it->get();

    // Skip if already decoded.
    if (decode_task->HasCompleted())
      continue;

    dependencies++;

    // Add decode task if it doesn't already exist in graph.
    auto decode_it =
        base::ranges::find(graph->nodes, decode_task, &TaskGraph::Node::task);

    // In rare circumstances, a background category task may come in before a
    // foreground category task. In these cases, upgrade any background category
    // dependencies of the current task.
    // TODO(ericrk): Task iterators should be updated to avoid this.
    // crbug.com/594851
    // TODO(ericrk): This should handle dependencies recursively.
    // crbug.com/605234
    if (decode_it != graph->nodes.end() && use_foreground_category &&
        !IsForegroundCategory(decode_it->category)) {
      decode_it->category = TASK_CATEGORY_FOREGROUND;
    }

    if (decode_it == graph->nodes.end()) {
      InsertNodeForDecodeTask(graph, decode_task, use_foreground_category,
                              priority);
    }

    graph->edges.emplace_back(decode_task, raster_task);
  }

  InsertNodeForTask(
      graph, raster_task,
      TaskCategoryForTileTask(raster_task, use_foreground_category), priority,
      dependencies);
}

class TaskSetFinishedTaskImpl : public TileTask {
 public:
  explicit TaskSetFinishedTaskImpl(
      base::SequencedTaskRunner* task_runner,
      base::RepeatingClosure on_task_set_finished_callback)
      : TileTask(TileTask::SupportsConcurrentExecution::kYes,
                 TileTask::SupportsBackgroundThreadPriority::kYes),
        task_runner_(task_runner),
        on_task_set_finished_callback_(
            std::move(on_task_set_finished_callback)) {}
  TaskSetFinishedTaskImpl(const TaskSetFinishedTaskImpl&) = delete;
  TaskSetFinishedTaskImpl& operator=(const TaskSetFinishedTaskImpl&) = delete;

  // Overridden from Task:
  void RunOnWorkerThread() override {
    TRACE_EVENT0("cc", "TaskSetFinishedTaskImpl::RunOnWorkerThread");
    TaskSetFinished();
  }

  // Overridden from TileTask:
  void OnTaskCompleted() override {}

 protected:
  ~TaskSetFinishedTaskImpl() override = default;

  void TaskSetFinished() {
    task_runner_->PostTask(FROM_HERE, on_task_set_finished_callback_);
  }

 private:
  raw_ptr<base::SequencedTaskRunner> task_runner_;
  const base::RepeatingClosure on_task_set_finished_callback_;
};

class DidFinishRunningAllTilesTask : public TileTask {
 public:
  using CompletionCb = base::OnceCallback<void(bool has_pending_queries)>;
  DidFinishRunningAllTilesTask(base::SequencedTaskRunner* task_runner,
                               RasterQueryQueue* pending_raster_queries,
                               CompletionCb completion_cb)
      : TileTask(TileTask::SupportsConcurrentExecution::kNo,
                 TileTask::SupportsBackgroundThreadPriority::kYes),
        task_runner_(task_runner),
        pending_raster_queries_(pending_raster_queries),
        completion_cb_(std::move(completion_cb)) {}

  void RunOnWorkerThread() override {
    TRACE_EVENT0("cc", "TaskSetFinishedTaskImpl::RunOnWorkerThread");
    bool has_pending_queries = false;
    if (pending_raster_queries_) {
      has_pending_queries =
          pending_raster_queries_->CheckRasterFinishedQueries();
    }
    task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(completion_cb_),
                                                     has_pending_queries));
  }

  void OnTaskCompleted() override {}

 protected:
  ~DidFinishRunningAllTilesTask() override = default;

 private:
  raw_ptr<base::SequencedTaskRunner> task_runner_;
  raw_ptr<RasterQueryQueue, AcrossTasksDanglingUntriaged>
      pending_raster_queries_;
  CompletionCb completion_cb_;
};

gfx::ContentColorUsage GetContentColorUsageForPrioritizedTile(
    const PrioritizedTile& prioritized_tile) {
  return prioritized_tile.raster_source()
      ->GetDisplayItemList()
      ->discardable_image_map()
      .content_color_usage();
}

}  // namespace

RasterTaskCompletionStats::RasterTaskCompletionStats()
    : completed_count(0u), canceled_count(0u) {}

std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
  std::unique_ptr<base::trace_event::TracedValue> state(
      new base::trace_event::TracedValue());
  state->SetInteger("completed_count",
                    base::saturated_cast<int>(stats.completed_count));
  state->SetInteger("canceled_count",
                    base::saturated_cast<int>(stats.canceled_count));
  return std::move(state);
}

TileManager::TileManager(
    TileManagerClient* client,
    base::SequencedTaskRunner* origin_task_runner,
    scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner,
    size_t scheduled_raster_task_limit,
    const TileManagerSettings& tile_manager_settings)
    : client_(client),
      task_runner_(origin_task_runner),
      resource_pool_(nullptr),
      tile_task_manager_(nullptr),
      scheduled_raster_task_limit_(scheduled_raster_task_limit),
      tile_manager_settings_(tile_manager_settings),
      use_gpu_rasterization_(false),
      all_tiles_that_need_to_be_rasterized_are_scheduled_(true),
      did_check_for_completed_tasks_since_last_schedule_tasks_(true),
      did_oom_on_last_assign_(false),
      image_controller_(origin_task_runner,
                        std::move(image_worker_task_runner)),
      decoded_image_tracker_(&image_controller_, origin_task_runner),
      checker_image_tracker_(&image_controller_,
                             this,
                             tile_manager_settings_.enable_checker_imaging,
                             tile_manager_settings_.min_image_bytes_to_checker),
      more_tiles_need_prepare_check_notifier_(
          task_runner_,
          base::BindRepeating(&TileManager::CheckIfMoreTilesNeedToBePrepared,
                              base::Unretained(this))),
      signals_check_notifier_(
          task_runner_,
          base::BindRepeating(
              &TileManager::CheckForCompletedTasksAndIssueSignals,
              base::Unretained(this))),
      has_scheduled_tile_tasks_(false),
      prepare_tiles_count_(0u),
      next_tile_id_(0u) {
  if (base::SingleThreadTaskRunner::HasCurrentDefault()) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "TileManager", base::SingleThreadTaskRunner::GetCurrentDefault());
  }
}

TileManager::~TileManager() {
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
  FinishTasksAndCleanUp();
}

void TileManager::FinishTasksAndCleanUp() {
  if (!tile_task_manager_)
    return;

  global_state_ = GlobalStateThatImpactsTilePriority();

  // This must be signalled before the Shutdown call below so that if there are
  // any pending tasks on the worker thread that might be waiting on tasks
  // posted to this thread they are cancelled.
  shutdown_event_.Signal();

  // This cancels tasks if possible, finishes pending tasks, and release any
  // uninitialized resources.
  tile_task_manager_->Shutdown();

  // Reset the signal since SetResources() might be called later.
  shutdown_event_.Reset();

  raster_buffer_provider_->Shutdown();

  tile_task_manager_->CheckForCompletedTasks();

  tile_task_manager_ = nullptr;
  resource_pool_ = nullptr;
  pending_raster_queries_ = nullptr;
  more_tiles_need_prepare_check_notifier_.Cancel();
  signals_check_notifier_.Cancel();
  task_set_finished_weak_ptr_factory_.InvalidateWeakPtrs();
  ready_to_draw_callback_weak_ptr_factory_.InvalidateWeakPtrs();
  check_pending_tile_queries_callback_.Cancel();
  raster_buffer_provider_ = nullptr;

  // Ask the tracker to drop any locked decodes since we will be destroying the
  // decode cache.
  bool can_clear_decode_policy_tracking = false;
  checker_image_tracker_.ClearTracker(can_clear_decode_policy_tracking);
  image_controller_.SetImageDecodeCache(nullptr);
  locked_image_tasks_.clear();
}

void TileManager::ScheduleReduceTileMemoryWhenIdle(
    base::TimeDelta time_since_last_active) {
  if (!base::FeatureList::IsEnabled(features::kReclaimPrepaintTilesWhenIdle) ||
      has_pending_idle_task_) {
    return;
  }

  has_pending_idle_task_ = true;
  base::TimeDelta delay = kDelayBeforeTimeReclaim - time_since_last_active;

  TaskRunnerWithOverride()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&TileManager::ReduceTileMemoryWhenIdle,
                     ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()),
      delay);
}

// static
base::TimeDelta TileManager::GetTrimPrepaintTilesDelay() {
  return base::Seconds(::features::kReclaimDelayInSeconds.Get());
}

void TileManager::ScheduleTrimPrepaintTiles() {
  if (!base::FeatureList::IsEnabled(features::kReclaimOldPrepaintTiles) ||
      has_pending_tile_trimming_task_) {
    return;
  }

  has_pending_tile_trimming_task_ = true;
  TaskRunnerWithOverride()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&TileManager::TrimPrepaintTiles,
                     ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()),
      GetTrimPrepaintTilesDelay());
}

void TileManager::ReduceTileMemoryWhenIdle() {
  has_pending_idle_task_ = false;

  base::TimeDelta time_since_last_active =
      NowWithOverride() - last_active_time_;

  if (time_since_last_active < kDelayBeforeTimeReclaim) {
    ScheduleReduceTileMemoryWhenIdle(time_since_last_active);
    return;
  }

  MemoryUsage limit(0, 0);
  MemoryUsage usage(resource_pool_->memory_usage_bytes(),
                    resource_pool_->resource_count());

  // Ensures that all the resources that are not at least as important as this
  // one are evicted.
  constexpr TilePriority kVisiblePriority =
      TilePriority(HIGH_RESOLUTION, TilePriority::NOW, 0);
  // Note: we don't need to flush anything here, even though this is a case
  // where frames are not being produced. The resource pool will itself issue a
  // flush after a few seconds when a resource becomes unused.
  FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
      nullptr, limit, kVisiblePriority, &usage);
}

void TileManager::TrimPrepaintTiles() {
  has_pending_tile_trimming_task_ = false;

  std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue =
      client_->BuildEvictionQueue(global_state_.tree_priority);
  bool has_eligible_used_tiles = false;
  for (; !eviction_priority_queue->IsEmpty(); eviction_priority_queue->Pop()) {
    const auto& prioritized_tile = eviction_priority_queue->Top();
    Tile* tile = prioritized_tile.tile();
    // Evict tiles that haven't been used in a while, that are not close to the
    // viewport or part of the skewport (the SOON tiles).
    //
    // The last part of the eligibility condition is to make sure that we are
    // not evicting a tile that would be re-rasterized at the next frame. Since
    // it violates the current memory policy, it will not get rasterized. In
    // practice, as of 2023, the memory policy generally doesn't allow tiles are
    // not in the SOON bin to be rasterized anyway, but this is to ensure that
    // we are not wasting CPU and GPU time.
    bool eligible =
        prioritized_tile.priority().priority_bin > TilePriority::SOON &&
        TilePriorityViolatesMemoryPolicy(prioritized_tile.priority());
    if (!eligible) {
      continue;
    }

    if (!tile->used()) {
      // Note: we may want to add `DCHECK(!tile->required_for_draw())` but it is
      // not possible, as some tiles in the EVENTUALLY priority bin are marked
      // as required for draw.
      //
      // This is the case if they are part of a non-drawing layer, in which case
      // PictureLayerTiling::ComputePriorityForTile() sets the bin to EVENTUALLY
      // regardless (because the client doesn't have valid priorities).
      // We don't want to keep these tiles, so no DCHECK() or exclusion here.
      FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
    } else {
      // Tile has been used recently, reset this so that if it's not used until
      // the next reclaim task, then we know it has been at least
      // `kPrepaintTilesTrimDelay` since the last time it was used, and thus can
      // be reclaimed.
      tile->clear_used();
      has_eligible_used_tiles = true;
    }
  }

  // Reschedule the task, since there are tiles that would be eligible to evict
  // if they were old enough. Note that we don't choose the smallest delay
  // possible to make progress, on purpose, resource reclaim can wait. Eligible
  // tiles are marked as "not used" above, so unless they are used before the
  // next scheduled task, they will be reclaimed then.
  if (has_eligible_used_tiles) {
    ScheduleTrimPrepaintTiles();
  }
}

void TileManager::SetResources(ResourcePool* resource_pool,
                               ImageDecodeCache* image_decode_cache,
                               TaskGraphRunner* task_graph_runner,
                               RasterBufferProvider* raster_buffer_provider,
                               bool use_gpu_rasterization,
                               RasterQueryQueue* pending_raster_queries) {
  DCHECK(!tile_task_manager_);
  DCHECK(task_graph_runner);

  use_gpu_rasterization_ = use_gpu_rasterization;
  pending_raster_queries_ = pending_raster_queries;
  resource_pool_ = resource_pool;
  image_controller_.SetImageDecodeCache(image_decode_cache);
  tile_task_manager_ = TileTaskManagerImpl::Create(task_graph_runner);
  raster_buffer_provider_ = raster_buffer_provider;

  raster_buffer_provider_->SetShutdownEvent(&shutdown_event_);
}

void TileManager::Release(Tile* tile) {
  if (tile->raster_task_scheduled_with_checker_images())
    num_of_tiles_with_checker_images_--;
  DCHECK_GE(num_of_tiles_with_checker_images_, 0);

  FreeResourcesForTile(tile);
  tiles_.erase(tile->id());
}

void TileManager::DidFinishRunningTileTasksRequiredForActivation() {
  TRACE_EVENT0("cc",
               "TileManager::DidFinishRunningTileTasksRequiredForActivation");
  TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("cc", "ScheduledTasksState",
                                      TRACE_ID_LOCAL(this), "state",
                                      ScheduledTasksStateAsValue());
  // TODO(vmpstr): Temporary check to debug crbug.com/642927.
  CHECK(tile_task_manager_);
  signals_.activate_tile_tasks_completed = true;
  signals_check_notifier_.Schedule();
}

void TileManager::DidFinishRunningTileTasksRequiredForDraw() {
  TRACE_EVENT0("cc", "TileManager::DidFinishRunningTileTasksRequiredForDraw");
  TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("cc", "ScheduledTasksState",
                                      TRACE_ID_LOCAL(this), "state",
                                      ScheduledTasksStateAsValue());
  // TODO(vmpstr): Temporary check to debug crbug.com/642927.
  CHECK(tile_task_manager_);
  signals_.draw_tile_tasks_completed = true;
  signals_check_notifier_.Schedule();
}

void TileManager::DidFinishRunningAllTileTasks(bool has_pending_queries) {
  TRACE_EVENT0("cc", "TileManager::DidFinishRunningAllTileTasks");
  TRACE_EVENT_NESTABLE_ASYNC_END0("cc", "ScheduledTasks", TRACE_ID_LOCAL(this));
  DCHECK(resource_pool_);
  DCHECK(tile_task_manager_);

  has_scheduled_tile_tasks_ = false;
  has_pending_queries_ = has_pending_queries;

  if (all_tiles_that_need_to_be_rasterized_are_scheduled_ &&
      !resource_pool_->ResourceUsageTooHigh()) {
    // TODO(ericrk): We should find a better way to safely handle re-entrant
    // notifications than always having to schedule a new task.
    // http://crbug.com/498439
    // TODO(vmpstr): Temporary check to debug crbug.com/642927.
    CHECK(tile_task_manager_);
    signals_.all_tile_tasks_completed = true;
    signals_check_notifier_.Schedule();
    return;
  }

  more_tiles_need_prepare_check_notifier_.Schedule();
}

bool TileManager::PrepareTiles(
    const GlobalStateThatImpactsTilePriority& state) {
  ++prepare_tiles_count_;
  last_active_time_ = NowWithOverride();
  ScheduleReduceTileMemoryWhenIdle(base::TimeDelta());
  ScheduleTrimPrepaintTiles();

  TRACE_EVENT1("cc,benchmark", "TileManager::PrepareTiles", "prepare_tiles_id",
               prepare_tiles_count_);

  if (!tile_task_manager_) {
    TRACE_EVENT_INSTANT0("cc", "PrepareTiles aborted",
                         TRACE_EVENT_SCOPE_THREAD);
    return false;
  }

  signals_ = Signals();
  global_state_ = state;

  // Ensure that we don't schedule any decode work for checkered images until
  // the raster work for visible tiles is complete. This is done in
  // CheckForCompletedTasksAndIssueSignals when the ready to activate/draw
  // signals are dispatched to the client.
  checker_image_tracker_.SetNoDecodesAllowed();

  // We need to call CheckForCompletedTasks() once in-between each call
  // to ScheduleTasks() to prevent canceled tasks from being scheduled.
  if (!did_check_for_completed_tasks_since_last_schedule_tasks_) {
    tile_task_manager_->CheckForCompletedTasks();
    did_check_for_completed_tasks_since_last_schedule_tasks_ = true;
  }

  if (!ShouldRasterOccludedTiles())
    FreeResourcesForOccludedTiles();

  PrioritizedWorkToSchedule prioritized_work = AssignGpuMemoryToTiles();

  // Inform the client that will likely require a draw if the highest priority
  // tile that will be rasterized is required for draw.
  client_->SetIsLikelyToRequireADraw(
      !prioritized_work.tiles_to_raster.empty() &&
      prioritized_work.tiles_to_raster.front().tile()->required_for_draw());

  // Schedule tile tasks.
  ScheduleTasks(std::move(prioritized_work));

  TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD,
                       "state", BasicStateAsValue());
  return true;
}

void TileManager::PrepareToDraw() {
  TRACE_EVENT0("cc", "TileManager::PrepareToDraw");

  if (!tile_task_manager_) {
    TRACE_EVENT_INSTANT0("cc", "TileManager::PrepareToDrawAborted",
                         TRACE_EVENT_SCOPE_THREAD);
    return;
  }

  tile_task_manager_->CheckForCompletedTasks();
  did_check_for_completed_tasks_since_last_schedule_tasks_ = true;

  CheckPendingGpuWorkAndIssueSignals();

  // We want to reset the flag back to false now that we're drawing. This may be
  // set to true again in future PrepareTiles calls.
  if (IsReadyToDraw()) {
    client_->SetIsLikelyToRequireADraw(false);
  }

  TRACE_EVENT_INSTANT1(
      "cc", "TileManager::PrepareToDrawFinished", TRACE_EVENT_SCOPE_THREAD,
      "stats", RasterTaskCompletionStatsAsValue(raster_task_completion_stats_));
  raster_task_completion_stats_ = RasterTaskCompletionStats();
}

void TileManager::DidModifyTilePriorities() {
  pending_tile_requirements_dirty_ = true;
}

std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
TileManager::BasicStateAsValue() const {
  std::unique_ptr<base::trace_event::TracedValue> value(
      new base::trace_event::TracedValue());
  BasicStateAsValueInto(value.get());
  return std::move(value);
}

void TileManager::BasicStateAsValueInto(
    base::trace_event::TracedValue* state) const {
  state->SetInteger("tile_count", base::saturated_cast<int>(tiles_.size()));
  state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_);
  state->BeginDictionary("global_state");
  global_state_.AsValueInto(state);
  state->EndDictionary();
}

std::unique_ptr<EvictionTilePriorityQueue>
TileManager::FreeTileResourcesUntilUsageIsWithinLimit(
    std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue,
    const MemoryUsage& limit,
    MemoryUsage* usage) {
  while (usage->Exceeds(limit)) {
    if (!eviction_priority_queue) {
      eviction_priority_queue =
          client_->BuildEvictionQueue(global_state_.tree_priority);
    }
    if (eviction_priority_queue->IsEmpty())
      break;

    Tile* tile = eviction_priority_queue->Top().tile();
    *usage -= MemoryUsage::FromTile(tile);
    FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
    eviction_priority_queue->Pop();
  }
  return eviction_priority_queue;
}

std::unique_ptr<EvictionTilePriorityQueue>
TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
    std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue,
    const MemoryUsage& limit,
    const TilePriority& other_priority,
    MemoryUsage* usage) {
  while (usage->Exceeds(limit)) {
    if (!eviction_priority_queue) {
      eviction_priority_queue =
          client_->BuildEvictionQueue(global_state_.tree_priority);
    }
    if (eviction_priority_queue->IsEmpty())
      break;

    const PrioritizedTile& prioritized_tile = eviction_priority_queue->Top();
    if (!other_priority.IsHigherPriorityThan(prioritized_tile.priority()))
      break;

    Tile* tile = prioritized_tile.tile();
    *usage -= MemoryUsage::FromTile(tile);
    FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile);
    eviction_priority_queue->Pop();
  }
  return eviction_priority_queue;
}

bool TileManager::TilePriorityViolatesMemoryPolicy(
    const TilePriority& priority) {
  switch (global_state_.memory_limit_policy) {
    case ALLOW_NOTHING:
      return true;
    case ALLOW_ABSOLUTE_MINIMUM:
      return priority.priority_bin > TilePriority::NOW;
    case ALLOW_PREPAINT_ONLY:
      return priority.priority_bin > TilePriority::SOON;
    case ALLOW_ANYTHING:
      return priority.distance_to_visible ==
             std::numeric_limits<float>::infinity();
  }
  NOTREACHED();
  return true;
}

TileManager::PrioritizedWorkToSchedule TileManager::AssignGpuMemoryToTiles() {
  TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles");

  DCHECK(resource_pool_);
  DCHECK(tile_task_manager_);

  // Now give memory out to the tiles until we're out, and build
  // the needs-to-be-rasterized queue.
  unsigned schedule_priority = 1u;
  all_tiles_that_need_to_be_rasterized_are_scheduled_ = true;
  bool had_enough_memory_to_schedule_tiles_needed_now = true;

  MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes,
                                global_state_.num_resources_limit);
  MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes,
                                global_state_.num_resources_limit);
  MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(),
                           resource_pool_->resource_count());

  std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
      client_->BuildRasterQueue(global_state_.tree_priority,
                                RasterTilePriorityQueue::Type::ALL));
  std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue;
  PrioritizedWorkToSchedule work_to_schedule;
  const bool raster_occluded_tiles = ShouldRasterOccludedTiles();
  for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
    const PrioritizedTile& prioritized_tile = raster_priority_queue->Top();
    Tile* tile = prioritized_tile.tile();
    TilePriority priority = prioritized_tile.priority();

    if (TilePriorityViolatesMemoryPolicy(priority)) {
      TRACE_EVENT_INSTANT0(
          "cc", "TileManager::AssignGpuMemory tile violates memory policy",
          TRACE_EVENT_SCOPE_THREAD);
      break;
    }

    DCHECK(!prioritized_tile.is_occluded() || raster_occluded_tiles);

    if (!tile->is_solid_color_analysis_performed() &&
        tile->use_picture_analysis() && kUseColorEstimator) {
      // We analyze for solid color here, to decide to continue
      // or drop the tile for scheduling and raster.
      tile->set_solid_color_analysis_performed(true);
      SkColor4f color = SkColors::kTransparent;

      // 5 operations is an arbitrary amount. Was picked in 2023 because the
      // paint op list generated for solid colored tiles in Views contained 3
      // entries: DrawRecord, Save, Restore. 5 was picked to provide some margin
      // in case other operations creep in, while being low enough that
      // performing the analysis is not too costly (and besides, long paint op
      // lists are unlikely to result in easily identifiable solid colored
      // tiles). This was shows to improve memory usage without regressing
      // performance.
      int max_ops_to_analyze = base::FeatureList::IsEnabled(
                                   features::kMoreAggressiveSolidColorDetection)
                                   ? 5
                                   : RasterSource::kDefault;
      bool is_solid_color =
          prioritized_tile.raster_source()->PerformSolidColorAnalysis(
              tile->enclosing_layer_rect(), &color, max_ops_to_analyze);
      if (is_solid_color) {
        tile->draw_info().set_solid_color(color);
        client_->NotifyTileStateChanged(tile);
        continue;
      }
    }

    // Prepaint tiles that are far away are only processed for images.
    if (tile->is_prepaint() && prioritized_tile.is_process_for_images_only()) {
      work_to_schedule.tiles_to_process_for_images.push_back(prioritized_tile);
      continue;
    }

    auto content_color_usage =
        GetContentColorUsageForPrioritizedTile(prioritized_tile);
    const auto target_color_params =
        client_->GetTargetColorParams(content_color_usage);

    // Tiles in the raster queue should either require raster or decode for
    // checker-images. If this tile does not need raster, process it only to
    // build the decode queue for checkered images.
    // Note that performing this check after the solid color analysis is not
    // necessary for correctness.
    if (!tile->draw_info().NeedsRaster()) {
      DCHECK(tile->draw_info().is_checker_imaged());
      DCHECK(prioritized_tile.should_decode_checkered_images_for_tile());

      AddCheckeredImagesToDecodeQueue(
          prioritized_tile, target_color_params,
          CheckerImageTracker::DecodeType::kRaster,
          &work_to_schedule.checker_image_decode_queue);
      continue;
    }

    // We won't be able to schedule this tile, so break out early.
    if (work_to_schedule.tiles_to_raster.size() >=
        scheduled_raster_task_limit_) {
      all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
      break;
    }

    DCHECK(tile->draw_info().mode() == TileDrawInfo::OOM_MODE ||
           !tile->draw_info().IsReadyToDraw());

    // If the tile already has a raster_task, then the memory used by it is
    // already accounted for in memory_usage. Otherwise, we'll have to acquire
    // more memory to create a raster task.
    MemoryUsage memory_required_by_tile_to_be_scheduled;
    if (!tile->raster_task_.get()) {
      memory_required_by_tile_to_be_scheduled = MemoryUsage::FromConfig(
          tile->desired_texture_size(), DetermineFormat(tile));
    }

    bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW;
    // This is the memory limit that will be used by this tile. Depending on
    // the tile priority, it will be one of hard_memory_limit or
    // soft_memory_limit.
    MemoryUsage& tile_memory_limit =
        tile_is_needed_now ? hard_memory_limit : soft_memory_limit;

    const MemoryUsage& scheduled_tile_memory_limit =
        tile_memory_limit - memory_required_by_tile_to_be_scheduled;
    eviction_priority_queue =
        FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit(
            std::move(eviction_priority_queue), scheduled_tile_memory_limit,
            priority, &memory_usage);
    bool memory_usage_is_within_limit =
        !memory_usage.Exceeds(scheduled_tile_memory_limit);

    // If we couldn't fit the tile into our current memory limit, then we're
    // done.
    if (!memory_usage_is_within_limit) {
      if (tile_is_needed_now) {
        LOG(ERROR) << "WARNING: tile memory limits exceeded, some content may "
                      "not draw";

        had_enough_memory_to_schedule_tiles_needed_now = false;
      }
      all_tiles_that_need_to_be_rasterized_are_scheduled_ = false;
      break;
    }

    // If the tile has a scheduled task that will rasterize a resource with
    // checker-imaged content, add those images to the decode queue. Note that
    // we add all images as we process the raster priority queue to ensure that
    // images are added to the decode queue in raster priority order.
    if (tile->HasRasterTask()) {
      if (tile->raster_task_scheduled_with_checker_images() &&
          prioritized_tile.should_decode_checkered_images_for_tile()) {
        AddCheckeredImagesToDecodeQueue(
            prioritized_tile, target_color_params,
            CheckerImageTracker::DecodeType::kRaster,
            &work_to_schedule.checker_image_decode_queue);
      }
    } else {
      // Creating the raster task here will acquire resources, but
      // this resource usage has already been accounted for above.
      auto raster_task = CreateRasterTask(prioritized_tile, target_color_params,
                                          &work_to_schedule);
      if (!raster_task) {
        continue;
      }

      tile->raster_task_ = std::move(raster_task);
      // Even if the tile is pre-paint, mark it used here to make sure that the
      // next reclaim task doesn't evict it right away.
      tile->mark_used();
    }

    tile->scheduled_priority_ = schedule_priority++;
    memory_usage += memory_required_by_tile_to_be_scheduled;
    work_to_schedule.tiles_to_raster.push_back(prioritized_tile);
  }

  // Note that we should try and further reduce memory in case the above loop
  // didn't reduce memory. This ensures that we always release as many resources
  // as possible to stay within the memory limit.
  eviction_priority_queue = FreeTileResourcesUntilUsageIsWithinLimit(
      std::move(eviction_priority_queue), hard_memory_limit, &memory_usage);

  // At this point, if we ran out of memory when allocating resources and we
  // couldn't go past even the NOW bin, this means we have evicted resources
  // from all tiles with a lower priority while we still might have resources
  // holding checker-imaged content. The invalidations for these resources will
  // be generated only if the skipped images are decoded. So we must schedule
  // decodes for these tiles to update their content.
  if (!had_enough_memory_to_schedule_tiles_needed_now &&
      num_of_tiles_with_checker_images_ > 0) {
    for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
      const PrioritizedTile& prioritized_tile = raster_priority_queue->Top();

      if (prioritized_tile.priority().priority_bin > TilePriority::NOW)
        break;

      if (!prioritized_tile.should_decode_checkered_images_for_tile())
        continue;

      auto content_color_usage =
          GetContentColorUsageForPrioritizedTile(prioritized_tile);
      const auto target_color_params =
          client_->GetTargetColorParams(content_color_usage);

      Tile* tile = prioritized_tile.tile();
      if (tile->draw_info().is_checker_imaged() ||
          tile->raster_task_scheduled_with_checker_images()) {
        AddCheckeredImagesToDecodeQueue(
            prioritized_tile, target_color_params,
            CheckerImageTracker::DecodeType::kRaster,
            &work_to_schedule.checker_image_decode_queue);
      }
    }
  }

  did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now;
  // Since this is recorded once per frame, subsample these metrics.
  if (metrics_sub_sampler_.ShouldSample(0.01)) {
    UMA_HISTOGRAM_BOOLEAN("Compositing.TileManager.EnoughMemory",
                          had_enough_memory_to_schedule_tiles_needed_now);
    if (did_oom_on_last_assign_) {
      UMA_HISTOGRAM_MEMORY_MEDIUM_MB(
          "Compositing.TileManager.LimitWhenNotEnoughMemory",
          hard_memory_limit.memory_bytes() / (1024 * 1024));
    }
  }

  memory_stats_from_last_assign_.total_budget_in_bytes =
      global_state_.hard_memory_limit_in_bytes;
  memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes();
  DCHECK_GE(memory_stats_from_last_assign_.total_bytes_used, 0);
  memory_stats_from_last_assign_.had_enough_memory =
      had_enough_memory_to_schedule_tiles_needed_now;

  TRACE_EVENT_END2("cc", "TileManager::AssignGpuMemoryToTiles",
                   "all_tiles_that_need_to_be_rasterized_are_scheduled",
                   all_tiles_that_need_to_be_rasterized_are_scheduled_,
                   "had_enough_memory_to_schedule_tiles_needed_now",
                   had_enough_memory_to_schedule_tiles_needed_now);
  image_controller_.cache()->RecordStats();
  return work_to_schedule;
}

void TileManager::FreeResourcesForOccludedTiles() {
  std::unique_ptr<TilesWithResourceIterator> iterator =
      client_->CreateTilesWithResourceIterator();
  for (; !iterator->AtEnd(); iterator->Next()) {
    if (iterator->IsCurrentTileOccluded())
      FreeResourcesForTile(iterator->GetCurrent());
  }
}

void TileManager::FreeResourcesForTile(Tile* tile) {
  TileDrawInfo& draw_info = tile->draw_info();

  if (draw_info.is_checker_imaged())
    num_of_tiles_with_checker_images_--;
  DCHECK_GE(num_of_tiles_with_checker_images_, 0);

  if (draw_info.has_resource()) {
    resource_pool_->ReleaseResource(draw_info.TakeResource());
    pending_gpu_work_tiles_.erase(tile);
  }
}

void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(
    Tile* tile) {
  TRACE_EVENT0("viz", __PRETTY_FUNCTION__);
  bool was_ready_to_draw = tile->draw_info().IsReadyToDraw();
  FreeResourcesForTile(tile);
  if (was_ready_to_draw)
    client_->NotifyTileStateChanged(tile);
}

void TileManager::PartitionImagesForCheckering(
    const PrioritizedTile& prioritized_tile,
    const TargetColorParams& target_color_params,
    std::vector<DrawImage>* sync_decoded_images,
    std::vector<PaintImage>* checkered_images,
    const gfx::Rect* invalidated_rect,
    base::flat_map<PaintImage::Id, size_t>* image_to_frame_index) {
  Tile* tile = prioritized_tile.tile();
  std::vector<const DrawImage*> images_in_tile;
  gfx::Rect enclosing_rect = tile->enclosing_layer_rect();
  if (invalidated_rect) {
    enclosing_rect = ToEnclosingRect(
        tile->raster_transform().InverseMapRect(gfx::RectF(*invalidated_rect)));
  }
  prioritized_tile.raster_source()->GetDiscardableImagesInRect(enclosing_rect,
                                                               &images_in_tile);
  WhichTree tree = tile->tiling()->tree();

  for (const auto* original_draw_image : images_in_tile) {
    const auto& image = original_draw_image->paint_image();
    size_t frame_index = client_->GetFrameIndexForImage(image, tree);
    if (image_to_frame_index)
      (*image_to_frame_index)[image.stable_id()] = frame_index;

    DrawImage draw_image(*original_draw_image, tile->contents_scale_key(),
                         frame_index, target_color_params);
    if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree))
      checkered_images->push_back(draw_image.paint_image());
    else
      sync_decoded_images->push_back(std::move(draw_image));
  }
}

void TileManager::AddCheckeredImagesToDecodeQueue(
    const PrioritizedTile& prioritized_tile,
    const TargetColorParams& target_color_params,
    CheckerImageTracker::DecodeType decode_type,
    CheckerImageTracker::ImageDecodeQueue* image_decode_queue) {
  Tile* tile = prioritized_tile.tile();
  std::vector<const DrawImage*> images_in_tile;
  prioritized_tile.raster_source()->GetDiscardableImagesInRect(
      tile->enclosing_layer_rect(), &images_in_tile);
  WhichTree tree = tile->tiling()->tree();
  for (const auto* original_draw_image : images_in_tile) {
    size_t frame_index = client_->GetFrameIndexForImage(
        original_draw_image->paint_image(), tree);
    DrawImage draw_image(*original_draw_image, tile->contents_scale_key(),
                         frame_index, target_color_params);
    if (checker_image_tracker_.ShouldCheckerImage(draw_image, tree)) {
      image_decode_queue->emplace_back(draw_image.paint_image(), decode_type);
    }
  }
}

void TileManager::ScheduleTasks(PrioritizedWorkToSchedule work_to_schedule) {
  const std::vector<PrioritizedTile>& tiles_that_need_to_be_rasterized =
      work_to_schedule.tiles_to_raster;
  TRACE_EVENT1("cc", "TileManager::ScheduleTasks", "count",
               tiles_that_need_to_be_rasterized.size());

  DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_);

  if (!has_scheduled_tile_tasks_) {
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("cc", "ScheduledTasks",
                                      TRACE_ID_LOCAL(this));
  }

  // Cancel existing OnTaskSetFinished callbacks.
  task_set_finished_weak_ptr_factory_.InvalidateWeakPtrs();

  // Even when scheduling an empty set of tiles, the TTWP does some work, and
  // will always trigger a DidFinishRunningTileTasks notification. Because of
  // this we unconditionally set |has_scheduled_tile_tasks_| to true.
  has_scheduled_tile_tasks_ = true;

  // Track the number of dependents for each *_done task.
  size_t required_for_activate_count = 0;
  size_t required_for_draw_count = 0;
  size_t all_count = 0;

  size_t priority = kTileTaskPriorityBase;

  graph_.Reset();

  scoped_refptr<TileTask> required_for_activation_done_task =
      CreateTaskSetFinishedTask(
          &TileManager::DidFinishRunningTileTasksRequiredForActivation);
  scoped_refptr<TileTask> required_for_draw_done_task =
      CreateTaskSetFinishedTask(
          &TileManager::DidFinishRunningTileTasksRequiredForDraw);

  auto all_done_cb =
      base::BindOnce(&TileManager::DidFinishRunningAllTileTasks,
                     task_set_finished_weak_ptr_factory_.GetWeakPtr());
  scoped_refptr<TileTask> all_done_task =
      base::MakeRefCounted<DidFinishRunningAllTilesTask>(
          task_runner_, pending_raster_queries_, std::move(all_done_cb));

  // Build a new task queue containing all task currently needed. Tasks
  // are added in order of priority, highest priority task first.
  for (auto& prioritized_tile : tiles_that_need_to_be_rasterized) {
    Tile* tile = prioritized_tile.tile();

    DCHECK(tile->draw_info().requires_resource());
    DCHECK(!tile->draw_info().has_resource());
    DCHECK(tile->HasRasterTask());

    TileTask* task = tile->raster_task_.get();
    task->set_frame_number(tile->source_frame_number());

    DCHECK(!task->HasCompleted());

    if (tile->required_for_activation()) {
      required_for_activate_count++;
      graph_.edges.emplace_back(task, required_for_activation_done_task.get());
    }
    if (tile->required_for_draw()) {
      required_for_draw_count++;
      graph_.edges.emplace_back(task, required_for_draw_done_task.get());
    }
    all_count++;
    graph_.edges.emplace_back(task, all_done_task.get());

    // A tile should use a foreground task cateogry if it is either blocking
    // future compositing (required for draw or required for activation), or if
    // it has a priority bin of NOW for another reason (low resolution tiles).
    bool use_foreground_category =
        tile->required_for_draw() || tile->required_for_activation() ||
        prioritized_tile.priority().priority_bin == TilePriority::NOW;
    InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++,
                             use_foreground_category);
  }

  const std::vector<PrioritizedTile>& tiles_to_process_for_images =
      work_to_schedule.tiles_to_process_for_images;
  std::vector<DrawImage> new_locked_images;
  for (const PrioritizedTile& prioritized_tile : tiles_to_process_for_images) {
    auto content_color_usage =
        GetContentColorUsageForPrioritizedTile(prioritized_tile);
    const auto target_color_params =
        client_->GetTargetColorParams(content_color_usage);

    std::vector<DrawImage> sync_decoded_images;
    std::vector<PaintImage> checkered_images;
    PartitionImagesForCheckering(prioritized_tile, target_color_params,
                                 &sync_decoded_images, &checkered_images,
                                 nullptr);

    // Add the sync decoded images to |new_locked_images| so they can be added
    // to the task graph.
    new_locked_images.insert(
        new_locked_images.end(),
        std::make_move_iterator(sync_decoded_images.begin()),
        std::make_move_iterator(sync_decoded_images.end()));

    // For checkered-images, send them to the decode service.
    for (auto& image : checkered_images) {
      work_to_schedule.checker_image_decode_queue.emplace_back(
          std::move(image), CheckerImageTracker::DecodeType::kPreDecode);
    }
  }

  new_locked_images.insert(new_locked_images.end(),
                           work_to_schedule.extra_prepaint_images.begin(),
                           work_to_schedule.extra_prepaint_images.end());

  // TODO(vmpstr): SOON is misleading here, but these images can come from
  // several diffent tiles. Rethink what we actually want to trace here. Note
  // that I'm using SOON, since it can't be NOW (these are prepaint).
  ImageDecodeCache::TracingInfo tracing_info(
      prepare_tiles_count_, TilePriority::SOON,
      ImageDecodeCache::TaskType::kInRaster);
  std::vector<scoped_refptr<TileTask>> new_locked_image_tasks =
      image_controller_.SetPredecodeImages(new_locked_images, tracing_info);
  // Notify |decoded_image_tracker_| after |image_controller_| to ensure we've
  // taken new refs on the images before releasing the predecode API refs.
  decoded_image_tracker_.OnImagesUsedInDraw(new_locked_images);
  work_to_schedule.extra_prepaint_images.clear();

  for (auto& task : new_locked_image_tasks) {
    auto decode_it =
        base::ranges::find(graph_.nodes, task.get(), &TaskGraph::Node::task);
    // If this task is already in the graph, then we don't have to insert it.
    if (decode_it != graph_.nodes.end())
      continue;

    InsertNodeForDecodeTask(&graph_, task.get(), false, priority++);
    all_count++;
    graph_.edges.emplace_back(task.get(), all_done_task.get());
  }

  // The old locked images tasks have to stay around until past the
  // ScheduleTasks call below, so we do a swap instead of a move.
  // TODO(crbug.com/647402): Have the tile_task_manager keep a ref on the tasks,
  // since it makes it awkward for the callers to keep refs on tasks that only
  // exist within the task graph runner.
  locked_image_tasks_.swap(new_locked_image_tasks);

  // We must reduce the amount of unused resources before calling
  // ScheduleTasks to prevent usage from rising above limits.
  resource_pool_->ReduceResourceUsage();
  image_controller_.ReduceMemoryUsage();

  // Insert nodes for our task completion tasks. We enqueue these using
  // NONCONCURRENT_FOREGROUND category this is the highest priority category and
  // we'd like to run these tasks as soon as possible.
  InsertNodeForTask(&graph_, required_for_activation_done_task.get(),
                    TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
                    kRequiredForActivationDoneTaskPriority,
                    required_for_activate_count);
  InsertNodeForTask(&graph_, required_for_draw_done_task.get(),
                    TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
                    kRequiredForDrawDoneTaskPriority, required_for_draw_count);
  InsertNodeForTask(&graph_, all_done_task.get(),
                    TASK_CATEGORY_NONCONCURRENT_FOREGROUND,
                    kAllDoneTaskPriority, all_count);

  // Schedule running of |raster_queue_|. This replaces any previously
  // scheduled tasks and effectively cancels all tasks not present
  // in |raster_queue_|.
  tile_task_manager_->ScheduleTasks(&graph_);

  // Schedule running of the checker-image decode queue. This replaces the
  // previously scheduled queue and effectively cancels image decodes from the
  // previous queue, if not already started.
  checker_image_tracker_.ScheduleImageDecodeQueue(
      std::move(work_to_schedule.checker_image_decode_queue));

  did_check_for_completed_tasks_since_last_schedule_tasks_ = false;

  TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("cc", "ScheduledTasksState",
                                      TRACE_ID_LOCAL(this), "state",
                                      ScheduledTasksStateAsValue());
}

scoped_refptr<TileTask> TileManager::CreateRasterTask(
    const PrioritizedTile& prioritized_tile,
    const TargetColorParams& target_color_params,
    PrioritizedWorkToSchedule* work_to_schedule) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "TileManager::CreateRasterTask");
  Tile* tile = prioritized_tile.tile();
  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
               "TileManager::CreateRasterTask", "Tile", tile->id());

  const int msaa_sample_count = client_->GetMSAASampleCountForRaster(
      prioritized_tile.raster_source()->GetDisplayItemList());

  // When possible, rasterize HDR content into F16.
  //
  // TODO(crbug.com/1076568): Once we have access to the display's buffer format
  // via gfx::DisplayColorSpaces, we should also do this for HBD images.
  auto format = DetermineFormat(tile);
  if (target_color_params.color_space.IsHDR() &&
      GetContentColorUsageForPrioritizedTile(prioritized_tile) ==
          gfx::ContentColorUsage::kHDR) {
    format = viz::SinglePlaneFormat::kRGBA_F16;
  }

  // Get the resource.
  ResourcePool::InUsePoolResource resource;
  uint64_t resource_content_id = 0;
  gfx::Rect invalidated_rect = tile->invalidated_content_rect();
  if (UsePartialRaster(msaa_sample_count) && tile->invalidated_id()) {
    const std::string& debug_name =
        prioritized_tile.source_tiling()->raster_source()->debug_name();
    resource = resource_pool_->TryAcquireResourceForPartialRaster(
        tile->id(), tile->invalidated_content_rect(), tile->invalidated_id(),
        &invalidated_rect, target_color_params.color_space, debug_name);
  }

  bool partial_tile_decode = false;
  if (resource) {
    resource_content_id = tile->invalidated_id();
    DCHECK_EQ(format, resource.format());
    partial_tile_decode = true;
  } else {
    const std::string& debug_name =
        prioritized_tile.source_tiling()->raster_source()->debug_name();
    resource = resource_pool_->AcquireResource(
        tile->desired_texture_size(), format, target_color_params.color_space,
        debug_name);
    DCHECK(resource);
  }

  // For LOW_RESOLUTION tiles, we don't draw or predecode images.
  RasterSource::PlaybackSettings playback_settings;
  const bool skip_images =
      prioritized_tile.priority().resolution == LOW_RESOLUTION;
  playback_settings.use_lcd_text = tile->can_use_lcd_text();
  playback_settings.msaa_sample_count = msaa_sample_count;
  playback_settings.visible =
      tile->required_for_activation() || tile->required_for_draw();
  playback_settings.hdr_headroom =
      target_color_params.hdr_max_luminance_relative;

  // Create and queue all image decode tasks that this tile depends on. Note
  // that we need to store the images for decode tasks in
  // |scheduled_draw_images_| since the tile might have been destroyed by the
  // time the raster task finishes.
  TileTask::Vector decode_tasks;
  std::vector<DrawImage>& sync_decoded_images =
      scheduled_draw_images_[tile->id()];
  sync_decoded_images.clear();
  std::vector<PaintImage> checkered_images;
  base::flat_map<PaintImage::Id, size_t> image_id_to_current_frame_index;
  if (!skip_images) {
    PartitionImagesForCheckering(
        prioritized_tile, target_color_params, &sync_decoded_images,
        &checkered_images, partial_tile_decode ? &invalidated_rect : nullptr,
        &image_id_to_current_frame_index);
  }

  // Get the tasks for the required images.
  ImageDecodeCache::TracingInfo tracing_info(
      prepare_tiles_count_, prioritized_tile.priority().priority_bin,
      ImageDecodeCache::TaskType::kInRaster);
  bool has_at_raster_images = false;
  bool has_hardware_accelerated_jpeg_candidates = false;
  bool has_hardware_accelerated_webp_candidates = false;
  image_controller_.ConvertImagesToTasks(
      &sync_decoded_images, &decode_tasks, &has_at_raster_images,
      &has_hardware_accelerated_jpeg_candidates,
      &has_hardware_accelerated_webp_candidates, tracing_info);
  // Notify |decoded_image_tracker_| after |image_controller_| to ensure we've
  // taken new refs on the images before releasing the predecode API refs.
  decoded_image_tracker_.OnImagesUsedInDraw(sync_decoded_images);

  const bool has_checker_images = !checkered_images.empty();
  tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
  if (has_checker_images)
    num_of_tiles_with_checker_images_++;

  // Don't allow at-raster prepaint tiles, because they could be very slow
  // and block high-priority tasks.
  if (has_at_raster_images && tile->is_prepaint()) {
    work_to_schedule->extra_prepaint_images.insert(
        work_to_schedule->extra_prepaint_images.end(),
        sync_decoded_images.begin(), sync_decoded_images.end());
    // This will unref the images, but ScheduleTasks will schedule them
    // right away anyway.
    OnRasterTaskCompleted(tile->id(), std::move(resource),
                          true /* was_canceled */);
    return nullptr;
  }

  PaintImageIdFlatSet images_to_skip;
  for (const auto& image : checkered_images) {
    DCHECK(!image.ShouldAnimate());

    images_to_skip.insert(image.stable_id());

    // This can be the case for tiles on the active tree that will be replaced
    // or are occluded on the pending tree. While we still need to continue
    // skipping images for these tiles, we don't need to decode them since
    // they will not be required on the next active tree.
    if (prioritized_tile.should_decode_checkered_images_for_tile()) {
      work_to_schedule->checker_image_decode_queue.emplace_back(
          image, CheckerImageTracker::DecodeType::kRaster);
    }
  }

  std::unique_ptr<RasterBuffer> raster_buffer =
      raster_buffer_provider_->AcquireBufferForRaster(
          resource, resource_content_id, tile->invalidated_id(),
          has_at_raster_images, has_hardware_accelerated_jpeg_candidates,
          has_hardware_accelerated_webp_candidates);

  std::optional<PlaybackImageProvider::Settings> settings;
  if (!skip_images) {
    settings.emplace();
    settings->images_to_skip = std::move(images_to_skip);
    settings->image_to_current_frame_index =
        std::move(image_id_to_current_frame_index);
    if (use_gpu_rasterization_) {
      settings->raster_mode = PlaybackImageProvider::RasterMode::kOop;
    }
  }

  PlaybackImageProvider image_provider(
      image_controller_.cache(), target_color_params, std::move(settings));
  // We make a deliberate copy of the PaintWorklet map here, as the
  // PictureLayerImpl's map could be mutated or destroyed whilst raster from an
  // earlier snapshot is still ongoing on the raster worker threads.
  PaintWorkletRecordMap paint_worklet_records =
      prioritized_tile.GetPaintWorkletRecords();
  PaintWorkletImageProvider paint_worklet_image_provider(
      std::move(paint_worklet_records));
  DispatchingImageProvider dispatching_image_provider(
      std::move(image_provider), std::move(paint_worklet_image_provider));

  return base::MakeRefCounted<RasterTaskImpl>(
      this, tile, std::move(resource), prioritized_tile.raster_source(),
      playback_settings, prioritized_tile.priority().resolution,
      invalidated_rect, prepare_tiles_count_, std::move(raster_buffer),
      &decode_tasks, use_gpu_rasterization_,
      std::move(dispatching_image_provider), active_url_);
}

void TileManager::ResetSignalsForTesting() {
  signals_ = Signals();
}

void TileManager::OnRasterTaskCompleted(
    Tile::Id tile_id,
    ResourcePool::InUsePoolResource resource,
    bool was_canceled) {
  auto found = tiles_.find(tile_id);
  Tile* tile = nullptr;
  bool raster_task_was_scheduled_with_checker_images = false;
  if (found != tiles_.end()) {
    tile = found->second;
    tile->raster_task_ = nullptr;
    raster_task_was_scheduled_with_checker_images =
        tile->set_raster_task_scheduled_with_checker_images(false);
    if (raster_task_was_scheduled_with_checker_images)
      num_of_tiles_with_checker_images_--;
  }

  // Unref all the images.
  auto images_it = scheduled_draw_images_.find(tile_id);
  // Every raster task unconditionally creates sync_decoded_images_ entry in
  // CreateRasterTask. This is the only place it's cleared. So we should have
  // the images_it here that doesn't point to end. This check is here to debug
  // crbug.com/757049.
  CHECK(images_it != scheduled_draw_images_.end());
  image_controller_.UnrefImages(images_it->second);
  scheduled_draw_images_.erase(images_it);

  if (was_canceled) {
    ++raster_task_completion_stats_.canceled_count;
    resource_pool_->ReleaseResource(std::move(resource));
    return;
  }

  resource_pool_->OnContentReplaced(resource, tile_id);
  ++raster_task_completion_stats_.completed_count;

  if (!tile) {
    resource_pool_->ReleaseResource(std::move(resource));
    return;
  }

  raster_buffer_provider_->NotifyWorkSubmitted();

  // Once raster is done, allow the resource to be exported to the display
  // compositor, by giving it a ResourceId.
  bool exported = resource_pool_->PrepareForExport(
      resource, viz::TransferableResource::ResourceSource::kTileRasterTask);

  // In SMOOTHNESS_TAKES_PRIORITY mode, we wait for GPU work to complete for a
  // tile before setting it as ready to draw.
  bool is_ready_for_draw = true;
  if (global_state_.tree_priority == SMOOTHNESS_TAKES_PRIORITY) {
    is_ready_for_draw =
        raster_buffer_provider_->IsResourceReadyToDraw(resource);
  }

  TileDrawInfo& draw_info = tile->draw_info();
  if (exported) {
    bool is_premultiplied = raster_buffer_provider_->IsResourcePremultiplied();
    draw_info.SetResource(std::move(resource),
                          raster_task_was_scheduled_with_checker_images,
                          is_premultiplied);
  } else {
    resource_pool_->ReleaseResource(std::move(resource));
    draw_info.set_oom();
  }
  if (raster_task_was_scheduled_with_checker_images)
    num_of_tiles_with_checker_images_++;

  if (!is_ready_for_draw) {
    pending_gpu_work_tiles_.insert(tile);
  } else {
    draw_info.set_resource_ready_for_draw();
    client_->NotifyTileStateChanged(tile);
  }
}

std::unique_ptr<Tile> TileManager::CreateTile(const Tile::CreateInfo& info,
                                              int layer_id,
                                              int source_frame_number,
                                              int flags) {
  // We need to have a tile task worker pool to do anything meaningful with
  // tiles.
  DCHECK(tile_task_manager_);
  std::unique_ptr<Tile> tile(
      new Tile(this, info, layer_id, source_frame_number, flags));
  DCHECK(!base::Contains(tiles_, tile->id()));

  tiles_[tile->id()] = tile.get();
  return tile;
}

bool TileManager::AreRequiredTilesReadyToDraw(
    RasterTilePriorityQueue::Type type) const {
  std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
      client_->BuildRasterQueue(global_state_.tree_priority, type));
  // It is insufficient to check whether the raster queue we constructed is
  // empty. The reason for this is that there are situations (rasterize on
  // demand) when the tile both needs raster and it's ready to draw. Hence, we
  // have to iterate the queue to check whether the required tiles are ready to
  // draw.
  for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
    const auto& prioritized_tile = raster_priority_queue->Top();
    if (!prioritized_tile.tile()->draw_info().IsReadyToDraw())
      return false;
  }

#if DCHECK_IS_ON()
  std::unique_ptr<RasterTilePriorityQueue> all_queue(
      client_->BuildRasterQueue(global_state_.tree_priority, type));
  for (; !all_queue->IsEmpty(); all_queue->Pop()) {
    Tile* tile = all_queue->Top().tile();
    DCHECK(!tile->required_for_activation() ||
           tile->draw_info().IsReadyToDraw());
  }
#endif
  return true;
}

bool TileManager::IsReadyToActivate() const {
  TRACE_EVENT0("cc,benchmark", "TileManager::IsReadyToActivate");
  return pending_required_for_activation_callback_id_ == 0 &&
         AreRequiredTilesReadyToDraw(
             RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION);
}

bool TileManager::IsReadyToDraw() const {
  TRACE_EVENT0("cc,benchmark", "TileManager::IsReadyToDraw");
  return pending_required_for_draw_callback_id_ == 0 &&
         AreRequiredTilesReadyToDraw(
             RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW);
}

void TileManager::ScheduleCheckRasterFinishedQueries() {
  DCHECK(has_pending_queries_);

  if (!check_pending_tile_queries_callback_.IsCancelled())
    return;

  check_pending_tile_queries_callback_.Reset(base::BindOnce(
      &TileManager::CheckRasterFinishedQueries, base::Unretained(this)));
  task_runner_->PostDelayedTask(FROM_HERE,
                                check_pending_tile_queries_callback_.callback(),
                                base::Milliseconds(100));
}

void TileManager::CheckRasterFinishedQueries() {
  check_pending_tile_queries_callback_.Cancel();

  if (!has_pending_queries_)
    return;

  // Raster tasks are in progress. The queries will be polled once they finish.
  if (has_scheduled_tile_tasks_ || !signals_.all_tile_tasks_completed)
    return;

  has_pending_queries_ = false;
  if (pending_raster_queries_) {
    has_pending_queries_ =
        pending_raster_queries_->CheckRasterFinishedQueries();
  }
  if (has_pending_queries_)
    ScheduleCheckRasterFinishedQueries();
}

void TileManager::CheckForCompletedTasksAndIssueSignals() {
  TRACE_EVENT0("cc", "TileManager::CheckForCompletedTasksAndIssueSignals");
  tile_task_manager_->CheckForCompletedTasks();
  did_check_for_completed_tasks_since_last_schedule_tasks_ = true;

  CheckPendingGpuWorkAndIssueSignals();
}

void TileManager::IssueSignals() {
  // Ready to activate.
  if (signals_.activate_tile_tasks_completed &&
      signals_.activate_gpu_work_completed &&
      !signals_.did_notify_ready_to_activate) {
    // If commit_to_active_tree is true(no pending tree), NotifyReadyToActivate
    // isn't sent to client, so don't call IsReadyToActivate() to save CPU time
    if (client_->HasPendingTree() && IsReadyToActivate()) {
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                   "TileManager::IssueSignals - ready to activate");
      signals_.did_notify_ready_to_activate = true;
      client_->NotifyReadyToActivate();
    }
  }

  // Ready to draw.
  if (signals_.draw_tile_tasks_completed && signals_.draw_gpu_work_completed &&
      !signals_.did_notify_ready_to_draw) {
    if (tile_manager_settings_.needs_notify_ready_to_draw && IsReadyToDraw()) {
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                   "TileManager::IssueSignals - ready to draw");
      signals_.did_notify_ready_to_draw = true;
      client_->NotifyReadyToDraw();
    }
  }

  // All tile tasks completed.
  if (signals_.all_tile_tasks_completed &&
      !signals_.did_notify_all_tile_tasks_completed) {
    if (!has_scheduled_tile_tasks_) {
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                   "TileManager::IssueSignals - all tile tasks completed");

      if (has_pending_queries_)
        ScheduleCheckRasterFinishedQueries();

      signals_.did_notify_all_tile_tasks_completed = true;
      client_->NotifyAllTileTasksCompleted();
    }
  }

  bool notify_ready_to_activate_pending =
      client_->HasPendingTree() && !signals_.did_notify_ready_to_activate;
  bool notify_ready_to_draw_pending =
      tile_manager_settings_.needs_notify_ready_to_draw &&
      !signals_.did_notify_ready_to_draw;

  // Allow decodes for rasterized tiles if all required for draw/activate tiles
  // are done. And pre-decode tiles once all tile tasks are done.
  // Note that the order is important here, since all signals could have become
  // true and in that case we want to allow the most decodes.
  if (signals_.did_notify_all_tile_tasks_completed) {
    checker_image_tracker_.SetMaxDecodePriorityAllowed(
        CheckerImageTracker::DecodeType::kPreDecode);
  } else if (!notify_ready_to_activate_pending &&
             !notify_ready_to_draw_pending) {
    checker_image_tracker_.SetMaxDecodePriorityAllowed(
        CheckerImageTracker::DecodeType::kRaster);
  }
}

void TileManager::CheckIfMoreTilesNeedToBePrepared() {
  tile_task_manager_->CheckForCompletedTasks();
  did_check_for_completed_tasks_since_last_schedule_tasks_ = true;

  // When OOM, keep re-assigning memory until we reach a steady state
  // where top-priority tiles are initialized.
  PrioritizedWorkToSchedule work_to_schedule = AssignGpuMemoryToTiles();

  // Inform the client that will likely require a draw if the highest priority
  // tile that will be rasterized is required for draw.
  client_->SetIsLikelyToRequireADraw(
      !work_to_schedule.tiles_to_raster.empty() &&
      work_to_schedule.tiles_to_raster.front().tile()->required_for_draw());

  // |tiles_that_need_to_be_rasterized| will be empty when we reach a
  // steady memory state. Keep scheduling tasks until we reach this state.
  if (!work_to_schedule.tiles_to_raster.empty()) {
    ScheduleTasks(std::move(work_to_schedule));
    return;
  }

  // If we're not in SMOOTHNESS_TAKES_PRIORITY  mode, we should unlock all
  // images since we're technically going idle here at least for this frame.
  if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY) {
    image_controller_.SetPredecodeImages(std::vector<DrawImage>(),
                                         ImageDecodeCache::TracingInfo());
    locked_image_tasks_.clear();
  }

  resource_pool_->ReduceResourceUsage();
  image_controller_.ReduceMemoryUsage();

  // TODO(vmpstr): Temporary check to debug crbug.com/642927.
  CHECK(tile_task_manager_);

  // Schedule all checks in case we're left with solid color tiles only.
  signals_.activate_tile_tasks_completed = true;
  signals_.draw_tile_tasks_completed = true;
  signals_.all_tile_tasks_completed = true;
  signals_check_notifier_.Schedule();

  // We don't reserve memory for required-for-activation tiles during
  // accelerated gestures, so we just postpone activation when we don't
  // have these tiles, and activate after the accelerated gesture.
  // Likewise if we don't allow any tiles (as is the case when we're
  // invisible), if we have tiles that aren't ready, then we shouldn't
  // activate as activation can cause checkerboards.
  bool wait_for_all_required_tiles =
      global_state_.tree_priority == SMOOTHNESS_TAKES_PRIORITY ||
      global_state_.memory_limit_policy == ALLOW_NOTHING;

  // If we have tiles left to raster for activation, and we don't allow
  // activating without them, then skip activation and return early.
  if (wait_for_all_required_tiles)
    return;

  // Mark any required tiles that have not been been assigned memory after
  // reaching a steady memory state as OOM. This ensures that we activate/draw
  // even when OOM. Note that we can't reuse the queue we used for
  // AssignGpuMemoryToTiles, since the AssignGpuMemoryToTiles call could have
  // evicted some tiles that would not be picked up by the old raster queue.
  MarkTilesOutOfMemory(client_->BuildRasterQueue(
      global_state_.tree_priority,
      RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
  MarkTilesOutOfMemory(client_->BuildRasterQueue(
      global_state_.tree_priority,
      RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW));

  // TODO(vmpstr): Temporary check to debug crbug.com/642927.
  CHECK(tile_task_manager_);

  DCHECK(IsReadyToActivate());
  DCHECK(IsReadyToDraw());
}

void TileManager::MarkTilesOutOfMemory(
    std::unique_ptr<RasterTilePriorityQueue> queue) const {
  // Mark required tiles as OOM so that we can activate/draw without them.
  for (; !queue->IsEmpty(); queue->Pop()) {
    Tile* tile = queue->Top().tile();
    if (tile->draw_info().IsReadyToDraw())
      continue;
    tile->draw_info().set_oom();
    client_->NotifyTileStateChanged(tile);
  }
}

const PaintImageIdFlatSet& TileManager::TakeImagesToInvalidateOnSyncTree() {
  return checker_image_tracker_.TakeImagesToInvalidateOnSyncTree();
}

void TileManager::DidActivateSyncTree() {
  checker_image_tracker_.DidActivateSyncTree();
}

void TileManager::ClearCheckerImageTracking(
    bool can_clear_decode_policy_tracking) {
  checker_image_tracker_.ClearTracker(can_clear_decode_policy_tracking);
}

void TileManager::SetCheckerImagingForceDisabled(bool force_disable) {
  checker_image_tracker_.set_force_disabled(force_disable);
}

void TileManager::NeedsInvalidationForCheckerImagedTiles() {
  client_->RequestImplSideInvalidationForCheckerImagedTiles();
}

viz::SharedImageFormat TileManager::DetermineFormat(const Tile* tile) const {
  return raster_buffer_provider_->GetFormat();
}

std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
TileManager::ScheduledTasksStateAsValue() const {
  std::unique_ptr<base::trace_event::TracedValue> state(
      new base::trace_event::TracedValue());
  state->BeginDictionary("tasks_pending");
  state->SetBoolean("activate_tile_tasks_completed",
                    signals_.activate_tile_tasks_completed);
  state->SetBoolean("draw_tile_tasks_completed",
                    signals_.draw_tile_tasks_completed);
  state->SetBoolean("all_tile_tasks_completed",
                    signals_.all_tile_tasks_completed);
  state->EndDictionary();
  return std::move(state);
}

bool TileManager::UsePartialRaster(int msaa_sample_count) const {
  // Partial raster doesn't support MSAA, as the MSAA resolve is unaware of clip
  // rects.
  // TODO(crbug.com/629683): See if we can work around this limitation.
  return tile_manager_settings_.use_partial_raster &&
         raster_buffer_provider_->CanPartialRasterIntoProvidedResource() &&
         msaa_sample_count == 0;
}

void TileManager::CheckPendingGpuWorkAndIssueSignals() {
  TRACE_EVENT2("cc", "TileManager::CheckPendingGpuWorkAndIssueSignals",
               "pending_gpu_work_tiles", pending_gpu_work_tiles_.size(),
               "tree_priority",
               TreePriorityToString(global_state_.tree_priority));

  std::vector<const ResourcePool::InUsePoolResource*> required_for_activation;
  std::vector<const ResourcePool::InUsePoolResource*> required_for_draw;

  for (auto it = pending_gpu_work_tiles_.begin();
       it != pending_gpu_work_tiles_.end();) {
    Tile* tile = *it;
    DCHECK(tile->draw_info().has_resource());
    const ResourcePool::InUsePoolResource& resource =
        tile->draw_info().GetResource();

    // Update requirements first so that if the tile has become required
    // it will force a redraw.
    if (pending_tile_requirements_dirty_)
      tile->tiling()->UpdateRequiredStatesOnTile(tile);

    if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY ||
        raster_buffer_provider_->IsResourceReadyToDraw(resource)) {
      tile->draw_info().set_resource_ready_for_draw();
      client_->NotifyTileStateChanged(tile);
      it = pending_gpu_work_tiles_.erase(it);
      continue;
    }

    // TODO(ericrk): If a tile in our list no longer has valid tile priorities,
    // it may still report that it is required, and unnecessarily delay
    // activation. crbug.com/687265
    if (tile->required_for_activation())
      required_for_activation.push_back(&resource);
    if (tile->required_for_draw())
      required_for_draw.push_back(&resource);

    ++it;
  }

  if (required_for_activation.empty()) {
    pending_required_for_activation_callback_id_ = 0;
  } else {
    pending_required_for_activation_callback_id_ =
        raster_buffer_provider_->SetReadyToDrawCallback(
            required_for_activation,
            base::BindOnce(
                &TileManager::CheckPendingGpuWorkAndIssueSignals,
                ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()),
            pending_required_for_activation_callback_id_);
  }

  if (required_for_draw.empty()) {
    pending_required_for_draw_callback_id_ = 0;
  } else {
    pending_required_for_draw_callback_id_ =
        raster_buffer_provider_->SetReadyToDrawCallback(
            required_for_draw,
            base::BindOnce(
                &TileManager::CheckPendingGpuWorkAndIssueSignals,
                ready_to_draw_callback_weak_ptr_factory_.GetWeakPtr()),
            pending_required_for_draw_callback_id_);
  }

  // Update our signals now that we know whether we have pending resources.
  signals_.activate_gpu_work_completed =
      (pending_required_for_activation_callback_id_ == 0);
  signals_.draw_gpu_work_completed =
      (pending_required_for_draw_callback_id_ == 0);

  // We've just updated all pending tile requirements if necessary.
  pending_tile_requirements_dirty_ = false;

  IssueSignals();
}

// Utility function that can be used to create a "Task set finished" task that
// posts |callback| to |task_runner| when run.
scoped_refptr<TileTask> TileManager::CreateTaskSetFinishedTask(
    void (TileManager::*callback)()) {
  return base::MakeRefCounted<TaskSetFinishedTaskImpl>(
      task_runner_,
      base::BindRepeating(callback,
                          task_set_finished_weak_ptr_factory_.GetWeakPtr()));
}

std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
TileManager::ActivationStateAsValue() {
  auto state = std::make_unique<base::trace_event::TracedValue>();
  ActivationStateAsValueInto(state.get());
  return std::move(state);
}

void TileManager::ActivationStateAsValueInto(
    base::trace_event::TracedValue* state) const {
  state->SetString("tree_priority",
                   TreePriorityToString(global_state_.tree_priority));
  state->SetInteger("soft_memory_limit",
                    global_state_.soft_memory_limit_in_bytes);
  state->SetInteger("hard_memory_limit",
                    global_state_.hard_memory_limit_in_bytes);
  state->SetInteger("pending_required_for_activation_callback_id",
                    pending_required_for_activation_callback_id_);
  state->SetInteger("current_memory_usage",
                    resource_pool_->memory_usage_bytes());
  state->SetInteger("current_resource_usage", resource_pool_->resource_count());

  // Use a custom tile_as_value, instead of Tile::AsValueInto, since we don't
  // need all of the state that would be captured by other functions.
  auto tile_as_value = [](const PrioritizedTile& prioritized_tile,
                          base::trace_event::TracedValue* value) {
    Tile* tile = prioritized_tile.tile();
    TilePriority priority = prioritized_tile.priority();

    value->SetInteger("id", tile->id());
    value->SetString("content_rect", tile->content_rect().ToString());
    value->SetDouble("contents_scale", tile->contents_scale_key());
    value->SetBoolean("is_ready_to_draw", tile->draw_info().IsReadyToDraw());
    value->SetString("resolution", TileResolutionToString(priority.resolution));
    value->SetString("priority_bin",
                     TilePriorityBinToString(priority.priority_bin));
    value->SetDouble("distance_to_visible", priority.distance_to_visible);
    value->SetBoolean("required_for_activation",
                      tile->required_for_activation());
    value->SetBoolean("required_for_draw", tile->required_for_draw());
  };

  std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue(
      client_->BuildRasterQueue(global_state_.tree_priority,
                                RasterTilePriorityQueue::Type::ALL));
  state->BeginArray("raster_tiles");
  for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) {
    state->BeginDictionary();
    tile_as_value(raster_priority_queue->Top(), state);
    state->EndDictionary();
  }
  state->EndArray();

  std::unique_ptr<RasterTilePriorityQueue> required_priority_queue(
      client_->BuildRasterQueue(
          global_state_.tree_priority,
          RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION));
  state->BeginArray("activation_tiles");
  for (; !required_priority_queue->IsEmpty(); required_priority_queue->Pop()) {
    state->BeginDictionary();
    tile_as_value(required_priority_queue->Top(), state);
    state->EndDictionary();
  }
  state->EndArray();
}

void TileManager::SetOverridesForTesting(
    scoped_refptr<base::TaskRunner> task_runner_for_testing,
    const base::TickClock* clock) {
  task_runner_for_testing_ = task_runner_for_testing;
  tick_clock_for_testing_ = clock;
}

bool TileManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                               base::trace_event::ProcessMemoryDump* pmd) {
  if (args.level_of_detail !=
          base::trace_event::MemoryDumpLevelOfDetail::kDetailed ||
      !resource_pool_) {
    return true;
  }

  std::string manager_path =
      base::StringPrintf("cc/tile_manager_%d", resource_pool_->tracing_id());
  auto* dump = pmd->CreateAllocatorDump(manager_path);
  dump->AddString(
      "memory_policy", "",
      TileMemoryLimitPolicyToString(global_state_.memory_limit_policy));
  dump->AddScalar("soft_memory_limit", "bytes",
                  global_state_.soft_memory_limit_in_bytes);
  dump->AddScalar("hard_memory_limit", "bytes",
                  global_state_.hard_memory_limit_in_bytes);
  dump->AddScalar("num_resources_limit", "count",
                  global_state_.num_resources_limit);

  std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue(
      client_->BuildEvictionQueue(global_state_.tree_priority));
  std::set<Tile*> tiles_to_evict;
  while (!eviction_priority_queue->IsEmpty()) {
    const PrioritizedTile& tile = eviction_priority_queue->Top();

    std::string name =
        base::StringPrintf("%s/tile_%u", manager_path.c_str(),
                           static_cast<unsigned int>(tile.tile()->id()));
    auto* tile_dump = pmd->CreateAllocatorDump(name);
    tile_dump->AddString("priority", "",
                         TilePriorityBinToString(tile.priority().priority_bin));
    tile_dump->AddScalar("distance_to_visible", "px",
                         tile.priority().distance_to_visible);

    tile_dump->AddScalar("is_prepaint", "bool", tile.tile()->is_prepaint());
    tile_dump->AddScalar("gpu_memory", "bytes",
                         tile.tile()->GPUMemoryUsageInBytes());
    auto size = tile.tile()->desired_texture_size();
    tile_dump->AddScalar("width", "px", size.width());
    tile_dump->AddScalar("height", "px", size.height());
    tile_dump->AddScalar("young", "bool", tile.tile()->used());

    eviction_priority_queue->Pop();
  }

  return true;
}

bool TileManager::ShouldRasterOccludedTiles() const {
  return (global_state_.memory_limit_policy != ALLOW_NOTHING &&
          global_state_.memory_limit_policy != ALLOW_ABSOLUTE_MINIMUM);
}

base::TimeTicks TileManager::NowWithOverride() const {
  return tick_clock_for_testing_ ? tick_clock_for_testing_->NowTicks()
                                 : base::TimeTicks::Now();
}

base::TaskRunner* TileManager::TaskRunnerWithOverride() const {
  return task_runner_for_testing_ ? task_runner_for_testing_.get()
                                  : task_runner_;
}

TileManager::MemoryUsage::MemoryUsage()
    : memory_bytes_(0), resource_count_(0) {}

TileManager::MemoryUsage::MemoryUsage(size_t memory_bytes,
                                      size_t resource_count)
    : memory_bytes_(static_cast<int64_t>(memory_bytes)),
      resource_count_(static_cast<int>(resource_count)) {
  // MemoryUsage is constructed using size_ts, since it deals with memory and
  // the inputs are typically size_t. However, during the course of usage (in
  // particular operator-=) can cause internal values to become negative.
  // Thus, member variables are signed.
  DCHECK_LE(memory_bytes,
            static_cast<size_t>(std::numeric_limits<int64_t>::max()));
  DCHECK_LE(resource_count,
            static_cast<size_t>(std::numeric_limits<int>::max()));
}

// static
TileManager::MemoryUsage TileManager::MemoryUsage::FromConfig(
    const gfx::Size& size,
    viz::SharedImageFormat format) {
  // We don't need to validate the computed size since this is used with a tile
  // size which is determined by the compositor (it's at most max texture
  // size).
  return MemoryUsage(format.EstimatedSizeInBytes(size), 1);
}

// static
TileManager::MemoryUsage TileManager::MemoryUsage::FromTile(const Tile* tile) {
  const TileDrawInfo& draw_info = tile->draw_info();
  if (draw_info.has_resource()) {
    return MemoryUsage(draw_info.GetResource().memory_usage(), 1);
  }
  return MemoryUsage();
}

TileManager::MemoryUsage& TileManager::MemoryUsage::operator+=(
    const MemoryUsage& other) {
  memory_bytes_ += other.memory_bytes_;
  resource_count_ += other.resource_count_;
  return *this;
}

TileManager::MemoryUsage& TileManager::MemoryUsage::operator-=(
    const MemoryUsage& other) {
  memory_bytes_ -= other.memory_bytes_;
  resource_count_ -= other.resource_count_;
  return *this;
}

TileManager::MemoryUsage TileManager::MemoryUsage::operator-(
    const MemoryUsage& other) {
  MemoryUsage result = *this;
  result -= other;
  return result;
}

bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const {
  return memory_bytes_ > limit.memory_bytes_ ||
         resource_count_ > limit.resource_count_;
}

TileManager::PrioritizedWorkToSchedule::PrioritizedWorkToSchedule() = default;
TileManager::PrioritizedWorkToSchedule::PrioritizedWorkToSchedule(
    PrioritizedWorkToSchedule&& other) = default;
TileManager::PrioritizedWorkToSchedule::~PrioritizedWorkToSchedule() = default;

}  // namespace cc
