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

#include "cc/layers/picture_layer_impl.h"

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

#include <algorithm>
#include <cmath>
#include <limits>
#include <set>

#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/benchmarks/micro_benchmark_impl.h"
#include "cc/debug/debug_colors.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/solid_color_layer_impl.h"
#include "cc/paint/display_item_list.h"
#include "cc/tiles/tile_manager.h"
#include "cc/tiles/tiling_set_raster_queue_all.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/occlusion.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/picture_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/traced_value.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"

namespace cc {
namespace {
// This must be > 1 as we multiply or divide by this to find a new raster
// scale during pinch.
const float kMaxScaleRatioDuringPinch = 2.0f;

// When creating a new tiling during pinch, snap to an existing
// tiling's scale if the desired scale is within this ratio.
const float kSnapToExistingTilingRatio = 1.2f;

// Even for really wide viewports, at some point GPU raster should use
// less than 4 tiles to fill the viewport. This is set to 256 as a
// sane minimum for now, but we might want to tune this for low-end.
const int kMinHeightForGpuRasteredTile = 256;

// When making odd-sized tiles, round them up to increase the chances
// of using the same tile size.
const int kTileRoundUp = 64;

// Round GPU default tile sizes to a multiple of 32. This helps prevent
// rounding errors during compositing.
const int kGpuDefaultTileRoundUp = 32;

// For performance reasons and to support compressed tile textures, tile
// width and height should be an even multiple of 4 in size.
const int kTileMinimalAlignment = 4;

// Large contents scale can cause overflow issues. Cap the ideal contents scale
// by this constant, since scales larger than this are usually not correct or
// their scale doesn't matter as long as it's large. Content scales usually
// closely match the default device-scale factor (so it's usually <= 5). See
// Renderer4.IdealContentsScale UMA (deprecated) for distribution of content
// scales.
const float kMaxIdealContentsScale = 10000.f;

// Intersect rects which may have right() and bottom() that overflow integer
// boundaries. This code is similar to gfx::Rect::Intersect with the exception
// that the types are promoted to int64_t when there is a chance of overflow.
gfx::Rect SafeIntersectRects(const gfx::Rect& one, const gfx::Rect& two) {
  if (one.IsEmpty() || two.IsEmpty())
    return gfx::Rect();

  int rx = std::max(one.x(), two.x());
  int ry = std::max(one.y(), two.y());
  int64_t rr = std::min(static_cast<int64_t>(one.x()) + one.width(),
                        static_cast<int64_t>(two.x()) + two.width());
  int64_t rb = std::min(static_cast<int64_t>(one.y()) + one.height(),
                        static_cast<int64_t>(two.y()) + two.height());
  if (rx > rr || ry > rb)
    return gfx::Rect();
  return gfx::Rect(rx, ry, static_cast<int>(rr - rx),
                   static_cast<int>(rb - ry));
}

// This function converts the given |device_pixels_size| to the expected size
// of content which was generated to fill it at 100%.  This takes into account
// the ceil operations that occur as device pixels are converted to/from DIPs
// (content size must be a whole number of DIPs).
gfx::Size ApplyDsfAdjustment(gfx::Size device_pixels_size, float dsf) {
  gfx::Size content_size_in_dips =
      gfx::ScaleToCeiledSize(device_pixels_size, 1.0f / dsf);
  gfx::Size content_size_in_dps =
      gfx::ScaleToCeiledSize(content_size_in_dips, dsf);
  return content_size_in_dps;
}

// For GPU rasterization, we pick an ideal tile size using the viewport so we
// don't need any settings. The current approach uses 4 tiles to cover the
// viewport vertically.
gfx::Size CalculateGpuTileSize(const gfx::Size& base_tile_size,
                               const gfx::Size& content_bounds,
                               const gfx::Size& max_tile_size) {
  int tile_width = base_tile_size.width();

  // Increase the height proportionally as the width decreases, and pad by our
  // border texels to make the tiles exactly match the viewport.
  int divisor = 4;
  if (content_bounds.width() <= base_tile_size.width() / 2)
    divisor = 2;
  if (content_bounds.width() <= base_tile_size.width() / 4)
    divisor = 1;
  int tile_height =
      MathUtil::UncheckedRoundUp(base_tile_size.height(), divisor) / divisor;

  // Grow default sizes to account for overlapping border texels.
  tile_width += 2 * PictureLayerTiling::kBorderTexels;
  tile_height += 2 * PictureLayerTiling::kBorderTexels;

  // Round GPU default tile sizes to a multiple of kGpuDefaultTileAlignment.
  // This helps prevent rounding errors in our CA path. https://crbug.com/632274
  tile_width = MathUtil::UncheckedRoundUp(tile_width, kGpuDefaultTileRoundUp);
  tile_height = MathUtil::UncheckedRoundUp(tile_height, kGpuDefaultTileRoundUp);

  tile_height = std::max(tile_height, kMinHeightForGpuRasteredTile);

  if (!max_tile_size.IsEmpty()) {
    tile_width = std::min(tile_width, max_tile_size.width());
    tile_height = std::min(tile_height, max_tile_size.height());
  }

  return gfx::Size(tile_width, tile_height);
}

}  // namespace

PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl,
                                   int id,
                                   Layer::LayerMaskType mask_type)
    : LayerImpl(tree_impl, id),
      twin_layer_(nullptr),
      tilings_(CreatePictureLayerTilingSet()),
      ideal_page_scale_(0.f),
      ideal_device_scale_(0.f),
      ideal_source_scale_(0.f),
      ideal_contents_scale_(0.f),
      raster_page_scale_(0.f),
      raster_device_scale_(0.f),
      raster_source_scale_(0.f),
      raster_contents_scale_(0.f),
      low_res_raster_contents_scale_(0.f),
      mask_type_(mask_type),
      was_screen_space_transform_animating_(false),
      only_used_low_res_last_append_quads_(false),
      nearest_neighbor_(false),
      use_transformed_rasterization_(false),
      is_directly_composited_image_(false),
      can_use_lcd_text_(true) {
  layer_tree_impl()->RegisterPictureLayerImpl(this);
}

PictureLayerImpl::~PictureLayerImpl() {
  if (twin_layer_)
    twin_layer_->twin_layer_ = nullptr;
  layer_tree_impl()->UnregisterPictureLayerImpl(this);

  // Unregister for all images on the current raster source.
  UnregisterAnimatedImages();
}

void PictureLayerImpl::SetLayerMaskType(Layer::LayerMaskType mask_type) {
  if (mask_type_ == mask_type)
    return;
  // It is expected that a layer can never change from being a mask to not being
  // one and vice versa. Only changes that make mask layer single <-> multi are
  // expected.
  DCHECK(mask_type_ != Layer::LayerMaskType::NOT_MASK &&
         mask_type != Layer::LayerMaskType::NOT_MASK);
  mask_type_ = mask_type;
}

const char* PictureLayerImpl::LayerTypeAsString() const {
  return "cc::PictureLayerImpl";
}

std::unique_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl(
    LayerTreeImpl* tree_impl) {
  return PictureLayerImpl::Create(tree_impl, id(), mask_type());
}

void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) {
  PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);

  LayerImpl::PushPropertiesTo(base_layer);

  layer_impl->SetLayerMaskType(mask_type());
  // Twin relationships should never change once established.
  DCHECK(!twin_layer_ || twin_layer_ == layer_impl);
  DCHECK(!twin_layer_ || layer_impl->twin_layer_ == this);
  // The twin relationship does not need to exist before the first
  // PushPropertiesTo from pending to active layer since before that the active
  // layer can not have a pile or tilings, it has only been created and inserted
  // into the tree at that point.
  twin_layer_ = layer_impl;
  layer_impl->twin_layer_ = this;

  layer_impl->SetNearestNeighbor(nearest_neighbor_);
  layer_impl->SetUseTransformedRasterization(use_transformed_rasterization_);

  // Solid color layers have no tilings.
  DCHECK(!raster_source_->IsSolidColor() || tilings_->num_tilings() == 0);
  // The pending tree should only have a high res (and possibly low res) tiling.
  DCHECK_LE(tilings_->num_tilings(),
            layer_tree_impl()->create_low_res_tiling() ? 2u : 1u);

  layer_impl->set_gpu_raster_max_texture_size(gpu_raster_max_texture_size_);
  layer_impl->UpdateRasterSource(raster_source_, &invalidation_,
                                 tilings_.get());
  DCHECK(invalidation_.IsEmpty());

  // After syncing a solid color layer, the active layer has no tilings.
  DCHECK(!raster_source_->IsSolidColor() ||
         layer_impl->tilings_->num_tilings() == 0);

  layer_impl->raster_page_scale_ = raster_page_scale_;
  layer_impl->raster_device_scale_ = raster_device_scale_;
  layer_impl->raster_source_scale_ = raster_source_scale_;
  layer_impl->raster_contents_scale_ = raster_contents_scale_;
  layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_;
  layer_impl->is_directly_composited_image_ = is_directly_composited_image_;
  // Simply push the value to the active tree without any extra invalidations,
  // since the pending tree tiles would have this handled. This is here to
  // ensure the state is consistent for future raster.
  layer_impl->can_use_lcd_text_ = can_use_lcd_text_;

  layer_impl->SanityCheckTilingState();

  // We always need to push properties.
  // See http://crbug.com/303943
  // TODO(danakj): Stop always pushing properties since we don't swap tilings.
  layer_tree_impl()->AddLayerShouldPushProperties(this);
}

void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass,
                                   AppendQuadsData* append_quads_data) {
  // The bounds and the pile size may differ if the pile wasn't updated (ie.
  // PictureLayer::Update didn't happen). In that case the pile will be empty.
  DCHECK(raster_source_->GetSize().IsEmpty() ||
         bounds() == raster_source_->GetSize())
      << " bounds " << bounds().ToString() << " pile "
      << raster_source_->GetSize().ToString();

  viz::SharedQuadState* shared_quad_state =
      render_pass->CreateAndAppendSharedQuadState();

  if (raster_source_->IsSolidColor()) {
    // TODO(sunxd): Solid color non-mask layers are forced to have contents
    // scale = 1. This is a workaround to temperarily fix
    // https://crbug.com/796558.
    // We need to investigate into the ca layers logic and remove this
    // workaround after fixing the bug.
    float max_contents_scale =
        !(mask_type_ == Layer::LayerMaskType::MULTI_TEXTURE_MASK)
            ? 1
            : CanHaveTilings() ? ideal_contents_scale_
                               : std::min(kMaxIdealContentsScale,
                                          std::max(GetIdealContentsScale(),
                                                   MinimumContentsScale()));

    // The downstream CA layers use shared_quad_state to generate resources of
    // the right size even if it is a solid color picture layer.
    PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
                                  max_contents_scale, contents_opaque());

    AppendDebugBorderQuad(render_pass, gfx::Rect(bounds()), shared_quad_state,
                          append_quads_data);

    gfx::Rect scaled_visible_layer_rect =
        shared_quad_state->visible_quad_layer_rect;
    Occlusion occlusion;
    // TODO(sunxd): Compute the correct occlusion for mask layers.
    if (mask_type_ == Layer::LayerMaskType::NOT_MASK) {
      occlusion = draw_properties().occlusion_in_content_space;
    }
    SolidColorLayerImpl::AppendSolidQuads(
        render_pass, occlusion, shared_quad_state, scaled_visible_layer_rect,
        raster_source_->GetSolidColor(),
        !layer_tree_impl()->settings().enable_edge_anti_aliasing,
        append_quads_data);
    return;
  }

  float device_scale_factor = layer_tree_impl()->device_scale_factor();
  float max_contents_scale = MaximumTilingContentsScale();
  PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale,
                                max_contents_scale, contents_opaque());
  Occlusion scaled_occlusion;
  if (mask_type_ == Layer::LayerMaskType::NOT_MASK) {
    scaled_occlusion =
        draw_properties()
            .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
                shared_quad_state->quad_to_target_transform);
  }

  if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
    DCHECK(shared_quad_state->quad_layer_rect.origin() == gfx::Point(0, 0));
    AppendDebugBorderQuad(
        render_pass, shared_quad_state->quad_layer_rect, shared_quad_state,
        append_quads_data, DebugColors::DirectPictureBorderColor(),
        DebugColors::DirectPictureBorderWidth(device_scale_factor));

    gfx::Rect geometry_rect = shared_quad_state->visible_quad_layer_rect;
    gfx::Rect visible_geometry_rect =
        scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
    bool needs_blending = !contents_opaque();

    // The raster source may not be valid over the entire visible rect,
    // and rastering outside of that may cause incorrect pixels.
    gfx::Rect scaled_recorded_viewport = gfx::ScaleToEnclosingRect(
        raster_source_->RecordedViewport(), max_contents_scale);
    geometry_rect.Intersect(scaled_recorded_viewport);
    visible_geometry_rect.Intersect(scaled_recorded_viewport);

    if (visible_geometry_rect.IsEmpty())
      return;

    DCHECK(raster_source_->HasRecordings());
    gfx::Rect quad_content_rect = shared_quad_state->visible_quad_layer_rect;
    gfx::Size texture_size = quad_content_rect.size();
    gfx::RectF texture_rect = gfx::RectF(gfx::SizeF(texture_size));

    viz::PictureDrawQuad::ImageAnimationMap image_animation_map;
    const auto* controller = layer_tree_impl()->image_animation_controller();
    WhichTree tree = layer_tree_impl()->IsPendingTree()
                         ? WhichTree::PENDING_TREE
                         : WhichTree::ACTIVE_TREE;
    for (const auto& image_data : raster_source_->GetDisplayItemList()
                                      ->discardable_image_map()
                                      .animated_images_metadata()) {
      image_animation_map[image_data.paint_image_id] =
          controller->GetFrameIndexForImage(image_data.paint_image_id, tree);
    }

    auto* quad = render_pass->CreateAndAppendDrawQuad<viz::PictureDrawQuad>();
    quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
                 needs_blending, texture_rect, texture_size, nearest_neighbor_,
                 viz::RGBA_8888, quad_content_rect, max_contents_scale,
                 std::move(image_animation_map),
                 raster_source_->GetDisplayItemList());
    ValidateQuadResources(quad);
    return;
  }

  // If we're doing a regular AppendQuads (ie, not solid color or resourceless
  // software draw, and if the visible rect is scrolled far enough away, then we
  // may run into a floating point precision in AA calculations in the renderer.
  // See crbug.com/765297. In order to avoid this, we shift the quads up from
  // where they logically reside and adjust the shared_quad_state's transform
  // instead. We only do this in a scale/translate matrices to ensure the math
  // is correct.
  gfx::Vector2d quad_offset;
  if (shared_quad_state->quad_to_target_transform.IsScaleOrTranslation()) {
    const auto& visible_rect = shared_quad_state->visible_quad_layer_rect;
    quad_offset = gfx::Vector2d(-visible_rect.x(), -visible_rect.y());
  }

  gfx::Rect debug_border_rect(shared_quad_state->quad_layer_rect);
  debug_border_rect.Offset(quad_offset);
  AppendDebugBorderQuad(render_pass, debug_border_rect, shared_quad_state,
                        append_quads_data);

  if (ShowDebugBorders(DebugBorderType::LAYER)) {
    for (PictureLayerTilingSet::CoverageIterator iter(
             tilings_.get(), max_contents_scale,
             shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_);
         iter; ++iter) {
      SkColor color;
      float width;
      if (*iter && iter->draw_info().IsReadyToDraw()) {
        TileDrawInfo::Mode mode = iter->draw_info().mode();
        if (mode == TileDrawInfo::SOLID_COLOR_MODE) {
          color = DebugColors::SolidColorTileBorderColor();
          width = DebugColors::SolidColorTileBorderWidth(device_scale_factor);
        } else if (mode == TileDrawInfo::OOM_MODE) {
          color = DebugColors::OOMTileBorderColor();
          width = DebugColors::OOMTileBorderWidth(device_scale_factor);
        } else if (iter->draw_info().has_compressed_resource()) {
          color = DebugColors::CompressedTileBorderColor();
          width = DebugColors::CompressedTileBorderWidth(device_scale_factor);
        } else if (iter.resolution() == HIGH_RESOLUTION) {
          color = DebugColors::HighResTileBorderColor();
          width = DebugColors::HighResTileBorderWidth(device_scale_factor);
        } else if (iter.resolution() == LOW_RESOLUTION) {
          color = DebugColors::LowResTileBorderColor();
          width = DebugColors::LowResTileBorderWidth(device_scale_factor);
        } else if (iter->contents_scale_key() > max_contents_scale) {
          color = DebugColors::ExtraHighResTileBorderColor();
          width = DebugColors::ExtraHighResTileBorderWidth(device_scale_factor);
        } else {
          color = DebugColors::ExtraLowResTileBorderColor();
          width = DebugColors::ExtraLowResTileBorderWidth(device_scale_factor);
        }
      } else {
        color = DebugColors::MissingTileBorderColor();
        width = DebugColors::MissingTileBorderWidth(device_scale_factor);
      }

      auto* debug_border_quad =
          render_pass->CreateAndAppendDrawQuad<viz::DebugBorderDrawQuad>();
      gfx::Rect geometry_rect = iter.geometry_rect();
      geometry_rect.Offset(quad_offset);
      gfx::Rect visible_geometry_rect = geometry_rect;
      debug_border_quad->SetNew(shared_quad_state,
                                geometry_rect,
                                visible_geometry_rect,
                                color,
                                width);
    }
  }

  // Keep track of the tilings that were used so that tilings that are
  // unused can be considered for removal.
  last_append_quads_tilings_.clear();

  // Ignore missing tiles outside of viewport for tile priority. This is
  // normally the same as draw viewport but can be independently overridden by
  // embedders like Android WebView with SetExternalTilePriorityConstraints.
  gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect(
      viewport_rect_for_tile_priority_in_content_space_, max_contents_scale);

  size_t missing_tile_count = 0u;
  size_t on_demand_missing_tile_count = 0u;
  only_used_low_res_last_append_quads_ = true;
  gfx::Rect scaled_recorded_viewport = gfx::ScaleToEnclosingRect(
      raster_source_->RecordedViewport(), max_contents_scale);
  for (PictureLayerTilingSet::CoverageIterator iter(
           tilings_.get(), max_contents_scale,
           shared_quad_state->visible_quad_layer_rect, ideal_contents_scale_);
       iter; ++iter) {
    gfx::Rect geometry_rect = iter.geometry_rect();
    gfx::Rect visible_geometry_rect =
        scaled_occlusion.GetUnoccludedContentRect(geometry_rect);

    gfx::Rect offset_geometry_rect = geometry_rect;
    offset_geometry_rect.Offset(quad_offset);
    gfx::Rect offset_visible_geometry_rect = visible_geometry_rect;
    offset_visible_geometry_rect.Offset(quad_offset);

    bool needs_blending = !contents_opaque();
    if (visible_geometry_rect.IsEmpty())
      continue;

    int64_t visible_geometry_area =
        static_cast<int64_t>(visible_geometry_rect.width()) *
        visible_geometry_rect.height();
    append_quads_data->visible_layer_area += visible_geometry_area;

    bool has_draw_quad = false;
    if (*iter && iter->draw_info().IsReadyToDraw()) {
      const TileDrawInfo& draw_info = iter->draw_info();

      switch (draw_info.mode()) {
        case TileDrawInfo::RESOURCE_MODE: {
          gfx::RectF texture_rect = iter.texture_rect();

          // The raster_contents_scale_ is the best scale that the layer is
          // trying to produce, even though it may not be ideal. Since that's
          // the best the layer can promise in the future, consider those as
          // complete. But if a tile is ideal scale, we don't want to consider
          // it incomplete and trying to replace it with a tile at a worse
          // scale.
          if (iter->contents_scale_key() != raster_contents_scale_ &&
              iter->contents_scale_key() != ideal_contents_scale_ &&
              geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
            append_quads_data->num_incomplete_tiles++;
          }

          auto* quad =
              render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
          quad->SetNew(
              shared_quad_state, offset_geometry_rect,
              offset_visible_geometry_rect, needs_blending,
              draw_info.resource_id_for_export(), texture_rect,
              draw_info.resource_size(), draw_info.contents_swizzled(),
              draw_info.is_premultiplied(), nearest_neighbor_,
              !layer_tree_impl()->settings().enable_edge_anti_aliasing);
          ValidateQuadResources(quad);
          has_draw_quad = true;
          break;
        }
        case TileDrawInfo::SOLID_COLOR_MODE: {
          float alpha =
              (SkColorGetA(draw_info.solid_color()) * (1.0f / 255.0f)) *
              shared_quad_state->opacity;
          if (mask_type_ == Layer::LayerMaskType::MULTI_TEXTURE_MASK ||
              alpha >= std::numeric_limits<float>::epsilon()) {
            auto* quad =
                render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
            quad->SetNew(
                shared_quad_state, offset_geometry_rect,
                offset_visible_geometry_rect, draw_info.solid_color(),
                !layer_tree_impl()->settings().enable_edge_anti_aliasing);
            ValidateQuadResources(quad);
          }
          has_draw_quad = true;
          break;
        }
        case TileDrawInfo::OOM_MODE:
          break;  // Checkerboard.
      }
    }

    if (!has_draw_quad) {
      // Checkerboard.
      SkColor color = SafeOpaqueBackgroundColor();
      if (ShowDebugBorders(DebugBorderType::LAYER)) {
        // Fill the whole tile with the missing tile color.
        color = DebugColors::OOMTileBorderColor();
      }
      auto* quad =
          render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
      quad->SetNew(shared_quad_state, offset_geometry_rect,
                   offset_visible_geometry_rect, color, false);
      ValidateQuadResources(quad);

      if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
        append_quads_data->num_missing_tiles++;
        ++missing_tile_count;
      }
      append_quads_data->checkerboarded_visible_content_area +=
          visible_geometry_area;
      // Intersect checkerboard rect with interest rect to generate rect where
      // we checkerboarded and has recording. The area where we don't have
      // recording is not necessarily a Rect, and its area is calculated using
      // subtraction.
      gfx::Rect visible_rect_has_recording = visible_geometry_rect;
      visible_rect_has_recording.Intersect(scaled_recorded_viewport);
      int64_t checkerboarded_has_recording_area =
          static_cast<int64_t>(visible_rect_has_recording.width()) *
          visible_rect_has_recording.height();
      append_quads_data->checkerboarded_needs_raster_content_area +=
          checkerboarded_has_recording_area;
      append_quads_data->checkerboarded_no_recording_content_area +=
          visible_geometry_area - checkerboarded_has_recording_area;
      continue;
    }

    if (iter.resolution() != HIGH_RESOLUTION) {
      append_quads_data->approximated_visible_content_area +=
          visible_geometry_area;
    }

    // If we have a draw quad, but it's not low resolution, then
    // mark that we've used something other than low res to draw.
    if (iter.resolution() != LOW_RESOLUTION)
      only_used_low_res_last_append_quads_ = false;

    if (last_append_quads_tilings_.empty() ||
        last_append_quads_tilings_.back() != iter.CurrentTiling()) {
      last_append_quads_tilings_.push_back(iter.CurrentTiling());
    }
  }

  // Adjust shared_quad_state with the quad_offset, since we've adjusted each
  // quad we've appended by it.
  shared_quad_state->quad_to_target_transform.Translate(-quad_offset);
  shared_quad_state->quad_layer_rect.Offset(quad_offset);
  shared_quad_state->visible_quad_layer_rect.Offset(quad_offset);

  if (missing_tile_count) {
    TRACE_EVENT_INSTANT2("cc",
                         "PictureLayerImpl::AppendQuads checkerboard",
                         TRACE_EVENT_SCOPE_THREAD,
                         "missing_tile_count",
                         missing_tile_count,
                         "on_demand_missing_tile_count",
                         on_demand_missing_tile_count);
  }

  // Aggressively remove any tilings that are not seen to save memory. Note
  // that this is at the expense of doing cause more frequent re-painting. A
  // better scheme would be to maintain a tighter visible_layer_rect for the
  // finer tilings.
  CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
}

bool PictureLayerImpl::UpdateTiles() {
  if (!CanHaveTilings()) {
    ideal_page_scale_ = 0.f;
    ideal_device_scale_ = 0.f;
    ideal_contents_scale_ = 0.f;
    ideal_source_scale_ = 0.f;
    SanityCheckTilingState();
    return false;
  }

  // Remove any non-ideal tilings that were not used last time we generated
  // quads to save memory and processing time. Note that pending tree should
  // only have one or two tilings (high and low res), so only clean up the
  // active layer. This cleans it up here in case AppendQuads didn't run.
  // If it did run, this would not remove any additional tilings.
  if (layer_tree_impl()->IsActiveTree())
    CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);

  UpdateIdealScales();

  if (!raster_contents_scale_ || ShouldAdjustRasterScale()) {
    RecalculateRasterScales();
    AddTilingsForRasterScale();
  }

  if (layer_tree_impl()->IsActiveTree())
    AddLowResolutionTilingIfNeeded();

  DCHECK(raster_page_scale_);
  DCHECK(raster_device_scale_);
  DCHECK(raster_source_scale_);
  DCHECK(raster_contents_scale_);
  DCHECK(low_res_raster_contents_scale_);

  was_screen_space_transform_animating_ =
      draw_properties().screen_space_transform_is_animating;

  double current_frame_time_in_seconds =
      (layer_tree_impl()->CurrentBeginFrameArgs().frame_time -
       base::TimeTicks()).InSecondsF();
  UpdateViewportRectForTilePriorityInContentSpace();

  // The tiling set can require tiles for activation any of the following
  // conditions are true:
  // - This layer produced a high-res or non-ideal-res tile last frame.
  // - We're in requires high res to draw mode.
  // - We're not in smoothness takes priority mode.
  // To put different, the tiling set can't require tiles for activation if
  // we're in smoothness mode and only used low-res or checkerboard to draw last
  // frame and we don't need high res to draw.
  //
  // The reason for this is that we should be able to activate sooner and get a
  // more up to date recording, so we don't run out of recording on the active
  // tree.
  // A layer must be a drawing layer for it to require tiles for activation.
  bool can_require_tiles_for_activation = false;
  if (contributes_to_drawn_render_surface()) {
    can_require_tiles_for_activation =
        !only_used_low_res_last_append_quads_ || RequiresHighResToDraw() ||
        !layer_tree_impl()->SmoothnessTakesPriority();
  }

  static const Occlusion kEmptyOcclusion;
  const Occlusion& occlusion_in_content_space =
      layer_tree_impl()->settings().use_occlusion_for_tile_prioritization
          ? draw_properties().occlusion_in_content_space
          : kEmptyOcclusion;

  // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
  // they are the same space in picture layer, as contents scale is always 1.
  bool updated = tilings_->UpdateTilePriorities(
      viewport_rect_for_tile_priority_in_content_space_, ideal_contents_scale_,
      current_frame_time_in_seconds, occlusion_in_content_space,
      can_require_tiles_for_activation);
  return updated;
}

void PictureLayerImpl::UpdateViewportRectForTilePriorityInContentSpace() {
  // If visible_layer_rect() is empty or viewport_rect_for_tile_priority is
  // set to be different from the device viewport, try to inverse project the
  // viewport into layer space and use that. Otherwise just use
  // visible_layer_rect().
  gfx::Rect visible_rect_in_content_space = visible_layer_rect();
  gfx::Rect viewport_rect_for_tile_priority =
      layer_tree_impl()->ViewportRectForTilePriority();
  if (visible_rect_in_content_space.IsEmpty() ||
      layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority) {
    gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
    if (ScreenSpaceTransform().GetInverse(&view_to_layer)) {
      // Transform from view space to content space.
      visible_rect_in_content_space = MathUtil::ProjectEnclosingClippedRect(
          view_to_layer, viewport_rect_for_tile_priority);

      // We have to allow for a viewport that is outside of the layer bounds in
      // order to compute tile priorities correctly for offscreen content that
      // is going to make it on screen. However, we also have to limit the
      // viewport since it can be very large due to screen_space_transforms. As
      // a heuristic, we clip to bounds padded by skewport_extrapolation_limit *
      // maximum tiling scale, since this should allow sufficient room for
      // skewport calculations.
      gfx::Rect padded_bounds(bounds());
      int padding_amount = layer_tree_impl()
                               ->settings()
                               .skewport_extrapolation_limit_in_screen_pixels *
                           MaximumTilingContentsScale();
      padded_bounds.Inset(-padding_amount, -padding_amount);
      visible_rect_in_content_space =
          SafeIntersectRects(visible_rect_in_content_space, padded_bounds);
    }
  }
  viewport_rect_for_tile_priority_in_content_space_ =
      visible_rect_in_content_space;
#if defined(OS_ANDROID)
  // On android, if we're in a scrolling gesture, the pending tree does not
  // reflect the fact that we may be hiding the top or bottom controls. Thus,
  // it would believe that the viewport is smaller than it actually is which
  // can cause activation flickering issues. So, if we're in this situation
  // adjust the visible rect by the top/bottom controls height. This isn't
  // ideal since we're not always in this case, but since we should be
  // prioritizing the active tree anyway, it doesn't cause any serious issues.
  // https://crbug.com/794456.
  if (layer_tree_impl()->IsPendingTree() &&
      layer_tree_impl()->IsActivelyScrolling()) {
    float total_controls_height = layer_tree_impl()->top_controls_height() +
                                  layer_tree_impl()->bottom_controls_height();
    viewport_rect_for_tile_priority_in_content_space_.Inset(
        0,                        // left
        0,                        // top,
        0,                        // right,
        -total_controls_height);  // bottom
  }
#endif
}

PictureLayerImpl* PictureLayerImpl::GetPendingOrActiveTwinLayer() const {
  if (!twin_layer_ || !twin_layer_->IsOnActiveOrPendingTree())
    return nullptr;
  return twin_layer_;
}

void PictureLayerImpl::UpdateRasterSource(
    scoped_refptr<RasterSource> raster_source,
    Region* new_invalidation,
    const PictureLayerTilingSet* pending_set) {
  // The bounds and the pile size may differ if the pile wasn't updated (ie.
  // PictureLayer::Update didn't happen). In that case the pile will be empty.
  DCHECK(raster_source->GetSize().IsEmpty() ||
         bounds() == raster_source->GetSize())
      << " bounds " << bounds().ToString() << " pile "
      << raster_source->GetSize().ToString();

  // We have an updated recording if the DisplayItemList in the new RasterSource
  // is different.
  const bool recording_updated =
      !raster_source_ || raster_source_->GetDisplayItemList() !=
                             raster_source->GetDisplayItemList();

  // Unregister for all images on the current raster source, if the recording
  // was updated.
  if (recording_updated)
    UnregisterAnimatedImages();

  // The |raster_source_| is initially null, so have to check for that for the
  // first frame.
  bool could_have_tilings = raster_source_.get() && CanHaveTilings();
  raster_source_.swap(raster_source);

  // Register images from the new raster source, if the recording was updated.
  // TODO(khushalsagar): UMA the number of animated images in layer?
  if (recording_updated)
    RegisterAnimatedImages();

  // The |new_invalidation| must be cleared before updating tilings since they
  // access the invalidation through the PictureLayerTilingClient interface.
  invalidation_.Clear();
  invalidation_.Swap(new_invalidation);

  bool can_have_tilings = CanHaveTilings();
  DCHECK(!pending_set ||
         can_have_tilings == GetPendingOrActiveTwinLayer()->CanHaveTilings());

  // Need to call UpdateTiles again if CanHaveTilings changed.
  if (could_have_tilings != can_have_tilings)
    layer_tree_impl()->set_needs_update_draw_properties();

  if (!can_have_tilings) {
    RemoveAllTilings();
    return;
  }

  // We could do this after doing UpdateTiles, which would avoid doing this for
  // tilings that are going to disappear on the pending tree (if scale changed).
  // But that would also be more complicated, so we just do it here for now.
  //
  // TODO(crbug.com/843787): If the LayerTreeFrameSink is lost, and we activate,
  // this ends up running with the old LayerTreeFrameSink, or possibly with a
  // null LayerTreeFrameSink, which can give incorrect results or maybe crash.
  if (pending_set) {
    tilings_->UpdateTilingsToCurrentRasterSourceForActivation(
        raster_source_, pending_set, invalidation_, MinimumContentsScale(),
        MaximumContentsScale());
  } else {
    tilings_->UpdateTilingsToCurrentRasterSourceForCommit(
        raster_source_, invalidation_, MinimumContentsScale(),
        MaximumContentsScale());
    // We're in a commit, make sure to update the state of the checker image
    // tracker with the new async attribute data.
    layer_tree_impl()->UpdateImageDecodingHints(
        raster_source_->TakeDecodingModeMap());
  }
}

bool PictureLayerImpl::UpdateCanUseLCDTextAfterCommit() {
  DCHECK(layer_tree_impl()->IsSyncTree());

  // Once we disable lcd text, we don't re-enable it.
  if (!can_use_lcd_text_)
    return false;

  if (can_use_lcd_text_ == CanUseLCDText())
    return false;

  can_use_lcd_text_ = CanUseLCDText();
  // Synthetically invalidate everything.
  gfx::Rect bounds_rect(bounds());
  invalidation_ = Region(bounds_rect);
  tilings_->Invalidate(invalidation_);
  SetUpdateRect(bounds_rect);
  return true;
}

void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) {
  if (layer_tree_impl()->IsActiveTree())
    AddDamageRect(tile->enclosing_layer_rect());
  if (tile->draw_info().NeedsRaster()) {
    PictureLayerTiling* tiling =
        tilings_->FindTilingWithScaleKey(tile->contents_scale_key());
    if (tiling)
      tiling->set_all_tiles_done(false);
  }
}

void PictureLayerImpl::DidBeginTracing() {
  raster_source_->DidBeginTracing();
}

void PictureLayerImpl::ReleaseResources() {
  tilings_->ReleaseAllResources();
  ResetRasterScale();
}

void PictureLayerImpl::ReleaseTileResources() {
  // All resources are tile resources.
  ReleaseResources();
}

void PictureLayerImpl::RecreateTileResources() {
  // Recreate tilings with new settings, since some of those might change when
  // we release resources.
  tilings_ = CreatePictureLayerTilingSet();
}

Region PictureLayerImpl::GetInvalidationRegionForDebugging() {
  // |invalidation_| gives the invalidation contained in the source frame, but
  // is not cleared after drawing from the layer. However, update_rect() is
  // cleared once the invalidation is drawn, which is useful for debugging
  // visualizations. This method intersects the two to give a more exact
  // representation of what was invalidated that is cleared after drawing.
  return IntersectRegions(invalidation_, update_rect());
}

std::unique_ptr<Tile> PictureLayerImpl::CreateTile(
    const Tile::CreateInfo& info) {
  int flags = 0;

  // We don't handle solid color masks if mask tiling is disabled, we also don't
  // handle solid color single texture masks if the flag is enabled, so we
  // shouldn't bother analyzing those.
  // Otherwise, always analyze to maximize memory savings.
  if (mask_type_ != Layer::LayerMaskType::SINGLE_TEXTURE_MASK)
    flags = Tile::USE_PICTURE_ANALYSIS;

  if (contents_opaque())
    flags |= Tile::IS_OPAQUE;

  return layer_tree_impl()->tile_manager()->CreateTile(
      info, id(), layer_tree_impl()->source_frame_number(), flags,
      can_use_lcd_text_);
}

const Region* PictureLayerImpl::GetPendingInvalidation() {
  if (layer_tree_impl()->IsPendingTree())
    return &invalidation_;
  if (layer_tree_impl()->IsRecycleTree())
    return nullptr;
  DCHECK(layer_tree_impl()->IsActiveTree());
  if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer())
    return &twin_layer->invalidation_;
  return nullptr;
}

const PictureLayerTiling* PictureLayerImpl::GetPendingOrActiveTwinTiling(
    const PictureLayerTiling* tiling) const {
  PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer();
  if (!twin_layer)
    return nullptr;
  const PictureLayerTiling* twin_tiling =
      twin_layer->tilings_->FindTilingWithScaleKey(
          tiling->contents_scale_key());
  if (twin_tiling &&
      twin_tiling->raster_transform() == tiling->raster_transform())
    return twin_tiling;
  return nullptr;
}

bool PictureLayerImpl::RequiresHighResToDraw() const {
  return layer_tree_impl()->RequiresHighResToDraw();
}

gfx::Rect PictureLayerImpl::GetEnclosingRectInTargetSpace() const {
  return GetScaledEnclosingRectInTargetSpace(MaximumTilingContentsScale());
}

bool PictureLayerImpl::ShouldAnimate(PaintImage::Id paint_image_id) const {
  // If we are registered with the animation controller, which queries whether
  // the image should be animated, then we must have recordings with this image.
  DCHECK(raster_source_);
  DCHECK(raster_source_->GetDisplayItemList());
  DCHECK(
      !raster_source_->GetDisplayItemList()->discardable_image_map().empty());

  // Only animate images for layers which HasValidTilePriorities. This check is
  // important for 2 reasons:
  // 1) It avoids doing additional work for layers we don't plan to rasterize
  //    and/or draw. The updated state will be pulled by the animation system
  //    if the draw properties change.
  // 2) It eliminates considering layers on the recycle tree. Once the pending
  //    tree is activated, the layers on the recycle tree remain registered as
  //    animation drivers, but should not drive animations since they don't have
  //    updated draw properties.
  //
  //  Additionally only animate images which are on-screen, animations are
  //  paused once they are not visible.
  if (!HasValidTilePriorities())
    return false;

  const auto& rects = raster_source_->GetDisplayItemList()
                          ->discardable_image_map()
                          .GetRectsForImage(paint_image_id);
  for (const auto& r : rects.container()) {
    if (r.Intersects(visible_layer_rect()))
      return true;
  }
  return false;
}

gfx::Size PictureLayerImpl::CalculateTileSize(
    const gfx::Size& content_bounds) const {
  int max_texture_size = layer_tree_impl()->max_texture_size();

  if (mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK) {
    // Masks are not tiled, so if we can't cover the whole mask with one tile,
    // we shouldn't have such a tiling at all.
    DCHECK_LE(content_bounds.width(), max_texture_size);
    DCHECK_LE(content_bounds.height(), max_texture_size);
    return content_bounds;
  }

  int default_tile_width = 0;
  int default_tile_height = 0;
  if (layer_tree_impl()->use_gpu_rasterization()) {
    gfx::Size max_tile_size =
        layer_tree_impl()->settings().max_gpu_raster_tile_size;

    // Calculate |base_tile_size based| on |gpu_raster_max_texture_size_|,
    // adjusting for ceil operations that may occur due to DSF.
    gfx::Size base_tile_size = ApplyDsfAdjustment(
        gpu_raster_max_texture_size_, layer_tree_impl()->device_scale_factor());

    // Set our initial size assuming a |base_tile_size| equal to our
    // |viewport_size|.
    gfx::Size default_tile_size =
        CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size);

    // Use half-width GPU tiles when the content_width is greater than our
    // calculated tile size.
    if (content_bounds.width() > default_tile_size.width()) {
      // Divide width by 2 and round up.
      base_tile_size.set_width((base_tile_size.width() + 1) / 2);
      default_tile_size =
          CalculateGpuTileSize(base_tile_size, content_bounds, max_tile_size);
    }

    default_tile_width = default_tile_size.width();
    default_tile_height = default_tile_size.height();
  } else {
    // For CPU rasterization we use tile-size settings.
    const LayerTreeSettings& settings = layer_tree_impl()->settings();
    int max_untiled_content_width = settings.max_untiled_layer_size.width();
    int max_untiled_content_height = settings.max_untiled_layer_size.height();
    default_tile_width = settings.default_tile_size.width();
    default_tile_height = settings.default_tile_size.height();

    // If the content width is small, increase tile size vertically.
    // If the content height is small, increase tile size horizontally.
    // If both are less than the untiled-size, use a single tile.
    if (content_bounds.width() < default_tile_width)
      default_tile_height = max_untiled_content_height;
    if (content_bounds.height() < default_tile_height)
      default_tile_width = max_untiled_content_width;
    if (content_bounds.width() < max_untiled_content_width &&
        content_bounds.height() < max_untiled_content_height) {
      default_tile_height = max_untiled_content_height;
      default_tile_width = max_untiled_content_width;
    }
  }

  int tile_width = default_tile_width;
  int tile_height = default_tile_height;

  // Clamp the tile width/height to the content width/height to save space.
  if (content_bounds.width() < default_tile_width) {
    tile_width = std::min(tile_width, content_bounds.width());
    tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileRoundUp);
    tile_width = std::min(tile_width, default_tile_width);
  }
  if (content_bounds.height() < default_tile_height) {
    tile_height = std::min(tile_height, content_bounds.height());
    tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileRoundUp);
    tile_height = std::min(tile_height, default_tile_height);
  }

  // Ensure that tile width and height are properly aligned.
  tile_width = MathUtil::UncheckedRoundUp(tile_width, kTileMinimalAlignment);
  tile_height = MathUtil::UncheckedRoundUp(tile_height, kTileMinimalAlignment);

  // Under no circumstance should we be larger than the max texture size.
  tile_width = std::min(tile_width, max_texture_size);
  tile_height = std::min(tile_height, max_texture_size);
  return gfx::Size(tile_width, tile_height);
}

void PictureLayerImpl::GetContentsResourceId(
    viz::ResourceId* resource_id,
    gfx::Size* resource_size,
    gfx::SizeF* resource_uv_size) const {
  // The bounds and the pile size may differ if the pile wasn't updated (ie.
  // PictureLayer::Update didn't happen). In that case the pile will be empty.
  DCHECK(raster_source_->GetSize().IsEmpty() ||
         bounds() == raster_source_->GetSize())
      << " bounds " << bounds().ToString() << " pile "
      << raster_source_->GetSize().ToString();
  float dest_scale = MaximumTilingContentsScale();
  gfx::Rect content_rect =
      gfx::ScaleToEnclosingRect(gfx::Rect(bounds()), dest_scale);
  PictureLayerTilingSet::CoverageIterator iter(
      tilings_.get(), dest_scale, content_rect, ideal_contents_scale_);

  // Mask resource not ready yet.
  if (!iter || !*iter) {
    *resource_id = 0;
    return;
  }

  // Masks only supported if they fit on exactly one tile.
  DCHECK(iter.geometry_rect() == content_rect)
      << "iter rect " << iter.geometry_rect().ToString() << " content rect "
      << content_rect.ToString();

  const TileDrawInfo& draw_info = iter->draw_info();
  if (!draw_info.IsReadyToDraw() ||
      draw_info.mode() != TileDrawInfo::RESOURCE_MODE) {
    *resource_id = 0;
    return;
  }

  *resource_id = draw_info.resource_id_for_export();
  *resource_size = draw_info.resource_size();
  // |resource_uv_size| represents the range of UV coordinates that map to the
  // content being drawn. Typically, we draw to the entire texture, so these
  // coordinates are (1.0f, 1.0f). However, if we are rasterizing to an
  // over-large texture, this size will be smaller, mapping to the subset of the
  // texture being used.
  gfx::SizeF requested_tile_size =
      gfx::SizeF(iter->tiling()->tiling_data()->tiling_size());
  DCHECK_LE(requested_tile_size.width(), draw_info.resource_size().width());
  DCHECK_LE(requested_tile_size.height(), draw_info.resource_size().height());
  *resource_uv_size = gfx::SizeF(
      requested_tile_size.width() / draw_info.resource_size().width(),
      requested_tile_size.height() / draw_info.resource_size().height());
}

void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) {
  if (nearest_neighbor_ == nearest_neighbor)
    return;

  nearest_neighbor_ = nearest_neighbor;
  NoteLayerPropertyChanged();
}

void PictureLayerImpl::SetUseTransformedRasterization(bool use) {
  if (use_transformed_rasterization_ == use)
    return;

  use_transformed_rasterization_ = use;
  NoteLayerPropertyChanged();
}

PictureLayerTiling* PictureLayerImpl::AddTiling(
    const gfx::AxisTransform2d& contents_transform) {
  DCHECK(CanHaveTilings());
  DCHECK_GE(contents_transform.scale(), MinimumContentsScale());
  DCHECK_LE(contents_transform.scale(), MaximumContentsScale());
  DCHECK(raster_source_->HasRecordings());
  return tilings_->AddTiling(contents_transform, raster_source_);
}

void PictureLayerImpl::RemoveAllTilings() {
  tilings_->RemoveAllTilings();
  // If there are no tilings, then raster scales are no longer meaningful.
  ResetRasterScale();
}

void PictureLayerImpl::AddTilingsForRasterScale() {
  // Reset all resolution enums on tilings, we'll be setting new values in this
  // function.
  tilings_->MarkAllTilingsNonIdeal();

  PictureLayerTiling* high_res =
      tilings_->FindTilingWithScaleKey(raster_contents_scale_);
  // Note: This function is always invoked when raster scale is recomputed,
  // but not necessarily changed. This means raster translation update is also
  // always done when there are significant changes that triggered raster scale
  // recomputation.
  gfx::Vector2dF raster_translation =
      CalculateRasterTranslation(raster_contents_scale_);
  if (high_res &&
      high_res->raster_transform().translation() != raster_translation) {
    tilings_->Remove(high_res);
    high_res = nullptr;
  }
  if (!high_res) {
    // We always need a high res tiling, so create one if it doesn't exist.
    high_res = AddTiling(
        gfx::AxisTransform2d(raster_contents_scale_, raster_translation));
  } else if (high_res->may_contain_low_resolution_tiles()) {
    // If the tiling we find here was LOW_RESOLUTION previously, it may not be
    // fully rastered, so destroy the old tiles.
    high_res->Reset();
    // Reset the flag now that we'll make it high res, it will have fully
    // rastered content.
    high_res->reset_may_contain_low_resolution_tiles();
  }
  high_res->set_resolution(HIGH_RESOLUTION);

  if (layer_tree_impl()->IsPendingTree()) {
    // On the pending tree, drop any tilings that are non-ideal since we don't
    // need them to activate anyway.
    tilings_->RemoveNonIdealTilings();
  }

  SanityCheckTilingState();
}

bool PictureLayerImpl::ShouldAdjustRasterScale() const {
  if (is_directly_composited_image_) {
    float max_scale = std::max(1.f, MinimumContentsScale());
    if (raster_source_scale_ < std::min(ideal_source_scale_, max_scale))
      return true;
    if (raster_source_scale_ > 4 * ideal_source_scale_)
      return true;
    return false;
  }

  if (was_screen_space_transform_animating_ !=
      draw_properties().screen_space_transform_is_animating)
    return true;

  bool is_pinching = layer_tree_impl()->PinchGestureActive();
  if (is_pinching && raster_page_scale_) {
    // We change our raster scale when it is:
    // - Higher than ideal (need a lower-res tiling available)
    // - Too far from ideal (need a higher-res tiling available)
    float ratio = ideal_page_scale_ / raster_page_scale_;
    if (raster_page_scale_ > ideal_page_scale_ ||
        ratio > kMaxScaleRatioDuringPinch)
      return true;
  }

  if (!is_pinching) {
    // When not pinching, match the ideal page scale factor.
    if (raster_page_scale_ != ideal_page_scale_)
      return true;
  }

  // Always match the ideal device scale factor.
  if (raster_device_scale_ != ideal_device_scale_)
    return true;

  if (raster_contents_scale_ > MaximumContentsScale())
    return true;
  if (raster_contents_scale_ < MinimumContentsScale())
    return true;

  // Don't change the raster scale if any of the following are true:
  //  - We have an animating transform.
  //  - The raster scale is already ideal.
  if (draw_properties().screen_space_transform_is_animating ||
      raster_source_scale_ == ideal_source_scale_) {
    return false;
  }

  // Don't update will-change: transform layers if the raster contents scale is
  // at least the native scale (otherwise, we'd need to clamp it).
  if (has_will_change_transform_hint() &&
      raster_contents_scale_ >= raster_page_scale_ * raster_device_scale_) {
    return false;
  }

  // Match the raster scale in all other cases.
  return true;
}

void PictureLayerImpl::AddLowResolutionTilingIfNeeded() {
  DCHECK(layer_tree_impl()->IsActiveTree());

  if (!layer_tree_impl()->create_low_res_tiling())
    return;

  // We should have a high resolution tiling at raster_contents_scale, so if the
  // low res one is the same then we shouldn't try to override this tiling by
  // marking it as a low res.
  if (raster_contents_scale_ == low_res_raster_contents_scale_)
    return;

  PictureLayerTiling* low_res =
      tilings_->FindTilingWithScaleKey(low_res_raster_contents_scale_);
  DCHECK(!low_res || low_res->resolution() != HIGH_RESOLUTION);

  // Only create new low res tilings when the transform is static.  This
  // prevents wastefully creating a paired low res tiling for every new high
  // res tiling during a pinch or a CSS animation.
  bool is_pinching = layer_tree_impl()->PinchGestureActive();
  bool is_animating = draw_properties().screen_space_transform_is_animating;
  if (!is_pinching && !is_animating) {
    if (!low_res)
      low_res = AddTiling(gfx::AxisTransform2d(low_res_raster_contents_scale_,
                                               gfx::Vector2dF()));
    low_res->set_resolution(LOW_RESOLUTION);
  }
}

void PictureLayerImpl::RecalculateRasterScales() {
  if (is_directly_composited_image_) {
    if (!raster_source_scale_)
      raster_source_scale_ = 1.f;

    float min_scale = MinimumContentsScale();
    float max_scale = std::max(1.f, MinimumContentsScale());
    float clamped_ideal_source_scale_ =
        std::max(min_scale, std::min(ideal_source_scale_, max_scale));

    while (raster_source_scale_ < clamped_ideal_source_scale_)
      raster_source_scale_ *= 2.f;
    while (raster_source_scale_ > 4 * clamped_ideal_source_scale_)
      raster_source_scale_ /= 2.f;

    raster_source_scale_ =
        std::max(min_scale, std::min(raster_source_scale_, max_scale));

    raster_page_scale_ = 1.f;
    raster_device_scale_ = 1.f;
    raster_contents_scale_ = raster_source_scale_;
    low_res_raster_contents_scale_ = raster_contents_scale_;
    return;
  }

  float old_raster_contents_scale = raster_contents_scale_;
  float old_raster_page_scale = raster_page_scale_;

  raster_device_scale_ = ideal_device_scale_;
  raster_page_scale_ = ideal_page_scale_;
  raster_source_scale_ = ideal_source_scale_;
  raster_contents_scale_ = ideal_contents_scale_;

  // During pinch we completely ignore the current ideal scale, and just use
  // a multiple of the previous scale.
  bool is_pinching = layer_tree_impl()->PinchGestureActive();
  if (is_pinching && old_raster_contents_scale) {
    // See ShouldAdjustRasterScale:
    // - When zooming out, preemptively create new tiling at lower resolution.
    // - When zooming in, approximate ideal using multiple of kMaxScaleRatio.
    bool zooming_out = old_raster_page_scale > ideal_page_scale_;
    float desired_contents_scale = old_raster_contents_scale;
    if (zooming_out) {
      while (desired_contents_scale > ideal_contents_scale_)
        desired_contents_scale /= kMaxScaleRatioDuringPinch;
    } else {
      while (desired_contents_scale < ideal_contents_scale_)
        desired_contents_scale *= kMaxScaleRatioDuringPinch;
    }
    raster_contents_scale_ = tilings_->GetSnappedContentsScaleKey(
        desired_contents_scale, kSnapToExistingTilingRatio);
    raster_page_scale_ =
        raster_contents_scale_ / raster_device_scale_ / raster_source_scale_;
  }

  // We rasterize at the maximum scale that will occur during the animation, if
  // the maximum scale is known. However we want to avoid excessive memory use.
  // If the scale is smaller than what we would choose otherwise, then it's
  // always better off for us memory-wise. But otherwise, we don't choose a
  // scale at which this layer's rastered content would become larger than the
  // viewport.
  if (draw_properties().screen_space_transform_is_animating) {
    bool can_raster_at_maximum_scale = false;
    bool should_raster_at_starting_scale = false;
    CombinedAnimationScale animation_scales =
        layer_tree_impl()->property_trees()->GetAnimationScales(
            transform_tree_index(), layer_tree_impl());
    float maximum_scale = animation_scales.maximum_animation_scale;
    float starting_scale = animation_scales.starting_animation_scale;
    if (maximum_scale) {
      gfx::Size bounds_at_maximum_scale =
          gfx::ScaleToCeiledSize(raster_source_->GetSize(), maximum_scale);
      int64_t maximum_area =
          static_cast<int64_t>(bounds_at_maximum_scale.width()) *
          static_cast<int64_t>(bounds_at_maximum_scale.height());
      gfx::Size viewport = layer_tree_impl()->device_viewport_size();

      // Use the square of the maximum viewport dimension direction, to
      // compensate for viewports with different aspect ratios.
      int64_t max_viewport_dimension =
          std::max(static_cast<int64_t>(viewport.width()),
                   static_cast<int64_t>(viewport.height()));
      int64_t squared_viewport_area =
          max_viewport_dimension * max_viewport_dimension;

      if (maximum_area <= squared_viewport_area)
        can_raster_at_maximum_scale = true;
    }
    if (starting_scale && starting_scale > maximum_scale) {
      gfx::Size bounds_at_starting_scale =
          gfx::ScaleToCeiledSize(raster_source_->GetSize(), starting_scale);
      int64_t start_area =
          static_cast<int64_t>(bounds_at_starting_scale.width()) *
          static_cast<int64_t>(bounds_at_starting_scale.height());
      gfx::Size viewport = layer_tree_impl()->device_viewport_size();
      int64_t viewport_area = static_cast<int64_t>(viewport.width()) *
                              static_cast<int64_t>(viewport.height());
      if (start_area <= viewport_area)
        should_raster_at_starting_scale = true;
    }
    // Use the computed scales for the raster scale directly, do not try to use
    // the ideal scale here. The current ideal scale may be way too large in the
    // case of an animation with scale, and will be constantly changing.
    if (should_raster_at_starting_scale)
      raster_contents_scale_ = starting_scale;
    else if (can_raster_at_maximum_scale)
      raster_contents_scale_ = maximum_scale;
    else
      raster_contents_scale_ = 1.f * ideal_page_scale_ * ideal_device_scale_;
  }

  // Clamp will-change: transform layers to be at least the native scale.
  if (has_will_change_transform_hint()) {
    float min_desired_scale = raster_device_scale_ * raster_page_scale_;
    if (raster_contents_scale_ < min_desired_scale) {
      raster_contents_scale_ = min_desired_scale;
      raster_page_scale_ = 1.f;
    }
  }

  raster_contents_scale_ =
      std::max(raster_contents_scale_, MinimumContentsScale());
  raster_contents_scale_ =
      std::min(raster_contents_scale_, MaximumContentsScale());
  DCHECK_GE(raster_contents_scale_, MinimumContentsScale());
  DCHECK_LE(raster_contents_scale_, MaximumContentsScale());

  // If this layer would create zero or one tiles at this content scale,
  // don't create a low res tiling.
  gfx::Size raster_bounds =
      gfx::ScaleToCeiledSize(raster_source_->GetSize(), raster_contents_scale_);
  gfx::Size tile_size = CalculateTileSize(raster_bounds);
  bool tile_covers_bounds = tile_size.width() >= raster_bounds.width() &&
                            tile_size.height() >= raster_bounds.height();
  if (tile_size.IsEmpty() || tile_covers_bounds) {
    low_res_raster_contents_scale_ = raster_contents_scale_;
    return;
  }

  float low_res_factor =
      layer_tree_impl()->settings().low_res_contents_scale_factor;
  low_res_raster_contents_scale_ =
      std::max(raster_contents_scale_ * low_res_factor, MinimumContentsScale());
  DCHECK_LE(low_res_raster_contents_scale_, raster_contents_scale_);
  DCHECK_GE(low_res_raster_contents_scale_, MinimumContentsScale());
  DCHECK_LE(low_res_raster_contents_scale_, MaximumContentsScale());
}

void PictureLayerImpl::CleanUpTilingsOnActiveLayer(
    const std::vector<PictureLayerTiling*>& used_tilings) {
  DCHECK(layer_tree_impl()->IsActiveTree());
  if (tilings_->num_tilings() == 0)
    return;

  float min_acceptable_high_res_scale = std::min(
      raster_contents_scale_, ideal_contents_scale_);
  float max_acceptable_high_res_scale = std::max(
      raster_contents_scale_, ideal_contents_scale_);

  PictureLayerImpl* twin = GetPendingOrActiveTwinLayer();
  if (twin && twin->CanHaveTilings()) {
    min_acceptable_high_res_scale = std::min(
        min_acceptable_high_res_scale,
        std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_));
    max_acceptable_high_res_scale = std::max(
        max_acceptable_high_res_scale,
        std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_));
  }

  PictureLayerTilingSet* twin_set = twin ? twin->tilings_.get() : nullptr;
  tilings_->CleanUpTilings(min_acceptable_high_res_scale,
                           max_acceptable_high_res_scale, used_tilings,
                           twin_set);
  DCHECK_GT(tilings_->num_tilings(), 0u);
  SanityCheckTilingState();
}

gfx::Vector2dF PictureLayerImpl::CalculateRasterTranslation(
    float raster_scale) {
  if (!use_transformed_rasterization_)
    return gfx::Vector2dF();

  DCHECK(!draw_properties().screen_space_transform_is_animating);
  gfx::Transform draw_transform = DrawTransform();
  DCHECK(draw_transform.IsScaleOrTranslation());

  // It is only useful to align the content space to the target space if their
  // relative pixel ratio is some small rational number. Currently we only
  // align if the relative pixel ratio is 1:1.
  // Good match if the maximum alignment error on a layer of size 10000px
  // does not exceed 0.001px.
  static constexpr float kErrorThreshold = 0.0000001f;
  if (std::abs(draw_transform.matrix().getFloat(0, 0) - raster_scale) >
          kErrorThreshold ||
      std::abs(draw_transform.matrix().getFloat(1, 1) - raster_scale) >
          kErrorThreshold)
    return gfx::Vector2dF();

  // Extract the fractional part of layer origin in the target space.
  float origin_x = draw_transform.matrix().getFloat(0, 3);
  float origin_y = draw_transform.matrix().getFloat(1, 3);
  return gfx::Vector2dF(origin_x - floorf(origin_x),
                        origin_y - floorf(origin_y));
}

float PictureLayerImpl::MinimumContentsScale() const {
  float setting_min = layer_tree_impl()->settings().minimum_contents_scale;

  // If the contents scale is less than 1 / width (also for height),
  // then it will end up having less than one pixel of content in that
  // dimension.  Bump the minimum contents scale up in this case to prevent
  // this from happening.
  int min_dimension = std::min(raster_source_->GetSize().width(),
                               raster_source_->GetSize().height());
  if (!min_dimension)
    return setting_min;

  return std::max(1.f / min_dimension, setting_min);
}

float PictureLayerImpl::MaximumContentsScale() const {
  // When mask tiling is disabled or the mask is single textured, masks can not
  // have tilings that would become larger than the max_texture_size since they
  // use a single tile for the entire tiling. Other layers can have tilings such
  // that dimension * scale does not overflow.
  float max_dimension =
      static_cast<float>(mask_type_ == Layer::LayerMaskType::SINGLE_TEXTURE_MASK
                             ? layer_tree_impl()->max_texture_size()
                             : std::numeric_limits<int>::max());
  float max_scale_width = max_dimension / bounds().width();
  float max_scale_height = max_dimension / bounds().height();
  float max_scale = std::min(max_scale_width, max_scale_height);

  // We require that multiplying the layer size by the contents scale and
  // ceiling produces a value <= |max_dimension|. Because for large layer
  // sizes floating point ambiguity may crop up, making the result larger or
  // smaller than expected, we use a slightly smaller floating point value for
  // the scale, to help ensure that the resulting content bounds will never end
  // up larger than |max_dimension|.
  return nextafterf(max_scale, 0.f);
}

void PictureLayerImpl::ResetRasterScale() {
  raster_page_scale_ = 0.f;
  raster_device_scale_ = 0.f;
  raster_source_scale_ = 0.f;
  raster_contents_scale_ = 0.f;
  low_res_raster_contents_scale_ = 0.f;
}

bool PictureLayerImpl::CanHaveTilings() const {
  if (raster_source_->IsSolidColor())
    return false;
  if (!DrawsContent())
    return false;
  if (!raster_source_->HasRecordings())
    return false;
  // If the |raster_source_| has a recording it should have non-empty bounds.
  DCHECK(!raster_source_->GetSize().IsEmpty());
  if (MaximumContentsScale() < MinimumContentsScale())
    return false;
  return true;
}

void PictureLayerImpl::SanityCheckTilingState() const {
#if DCHECK_IS_ON()
  if (!CanHaveTilings()) {
    DCHECK_EQ(0u, tilings_->num_tilings());
    return;
  }
  if (tilings_->num_tilings() == 0)
    return;

  // We should only have one high res tiling.
  DCHECK_EQ(1, tilings_->NumHighResTilings());
#endif
}

float PictureLayerImpl::MaximumTilingContentsScale() const {
  float max_contents_scale = tilings_->GetMaximumContentsScale();
  return std::max(max_contents_scale, MinimumContentsScale());
}

std::unique_ptr<PictureLayerTilingSet>
PictureLayerImpl::CreatePictureLayerTilingSet() {
  const LayerTreeSettings& settings = layer_tree_impl()->settings();
  return PictureLayerTilingSet::Create(
      IsActive() ? ACTIVE_TREE : PENDING_TREE, this,
      settings.tiling_interest_area_padding,
      layer_tree_impl()->use_gpu_rasterization()
          ? settings.gpu_rasterization_skewport_target_time_in_seconds
          : settings.skewport_target_time_in_seconds,
      settings.skewport_extrapolation_limit_in_screen_pixels,
      settings.max_preraster_distance_in_screen_pixels);
}

void PictureLayerImpl::UpdateIdealScales() {
  DCHECK(CanHaveTilings());

  float min_contents_scale = MinimumContentsScale();
  DCHECK_GT(min_contents_scale, 0.f);

  ideal_page_scale_ = IsAffectedByPageScale()
                          ? layer_tree_impl()->current_page_scale_factor()
                          : 1.f;
  ideal_device_scale_ = layer_tree_impl()->device_scale_factor();
  ideal_contents_scale_ =
      std::min(kMaxIdealContentsScale,
               std::max(GetIdealContentsScale(), min_contents_scale));
  ideal_source_scale_ =
      ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_;
}

void PictureLayerImpl::GetDebugBorderProperties(
    SkColor* color,
    float* width) const {
  float device_scale_factor =
      layer_tree_impl() ? layer_tree_impl()->device_scale_factor() : 1;

  if (is_directly_composited_image_) {
    *color = DebugColors::ImageLayerBorderColor();
    *width = DebugColors::ImageLayerBorderWidth(device_scale_factor);
  } else {
    *color = DebugColors::TiledContentLayerBorderColor();
    *width = DebugColors::TiledContentLayerBorderWidth(device_scale_factor);
  }
}

void PictureLayerImpl::GetAllPrioritizedTilesForTracing(
    std::vector<PrioritizedTile>* prioritized_tiles) const {
  if (!tilings_)
    return;
  tilings_->GetAllPrioritizedTilesForTracing(prioritized_tiles);
}

void PictureLayerImpl::AsValueInto(
    base::trace_event::TracedValue* state) const {
  LayerImpl::AsValueInto(state);
  state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
  state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
  state->BeginArray("tilings");
  tilings_->AsValueInto(state);
  state->EndArray();

  MathUtil::AddToTracedValue("tile_priority_rect",
                             viewport_rect_for_tile_priority_in_content_space_,
                             state);
  MathUtil::AddToTracedValue("visible_rect", visible_layer_rect(), state);

  state->BeginArray("pictures");
  raster_source_->AsValueInto(state);
  state->EndArray();

  state->BeginArray("invalidation");
  invalidation_.AsValueInto(state);
  state->EndArray();

  state->BeginArray("coverage_tiles");
  for (PictureLayerTilingSet::CoverageIterator iter(
           tilings_.get(), MaximumTilingContentsScale(),
           gfx::Rect(raster_source_->GetSize()), ideal_contents_scale_);
       iter; ++iter) {
    state->BeginDictionary();

    MathUtil::AddToTracedValue("geometry_rect", iter.geometry_rect(), state);

    if (*iter)
      viz::TracedValue::SetIDRef(*iter, state, "tile");

    state->EndDictionary();
  }
  state->EndArray();

  state->BeginDictionary("can_have_tilings_state");
  state->SetBoolean("can_have_tilings", CanHaveTilings());
  state->SetBoolean("raster_source_solid_color",
                    raster_source_->IsSolidColor());
  state->SetBoolean("draws_content", DrawsContent());
  state->SetBoolean("raster_source_has_recordings",
                    raster_source_->HasRecordings());
  state->SetDouble("max_contents_scale", MaximumTilingContentsScale());
  state->SetDouble("min_contents_scale", MinimumContentsScale());
  state->EndDictionary();

  state->BeginDictionary("raster_scales");
  state->SetDouble("page_scale", raster_page_scale_);
  state->SetDouble("device_scale", raster_device_scale_);
  state->SetDouble("source_scale", raster_source_scale_);
  state->SetDouble("contents_scale", raster_contents_scale_);
  state->SetDouble("low_res_contents_scale", low_res_raster_contents_scale_);
  state->EndDictionary();

  state->BeginDictionary("ideal_scales");
  state->SetDouble("page_scale", ideal_page_scale_);
  state->SetDouble("device_scale", ideal_device_scale_);
  state->SetDouble("source_scale", ideal_source_scale_);
  state->SetDouble("contents_scale", ideal_contents_scale_);
  state->EndDictionary();
}

size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
  return tilings_->GPUMemoryUsageInBytes();
}

void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
  benchmark->RunOnLayer(this);
}

bool PictureLayerImpl::IsOnActiveOrPendingTree() const {
  return !layer_tree_impl()->IsRecycleTree();
}

bool PictureLayerImpl::HasValidTilePriorities() const {
  return IsOnActiveOrPendingTree() &&
         (contributes_to_drawn_render_surface() || raster_even_if_not_drawn());
}

PictureLayerImpl::ImageInvalidationResult
PictureLayerImpl::InvalidateRegionForImages(
    const PaintImageIdFlatSet& images_to_invalidate) {
  if (!raster_source_ || !raster_source_->GetDisplayItemList() ||
      raster_source_->GetDisplayItemList()->discardable_image_map().empty()) {
    return ImageInvalidationResult::kNoImages;
  }

  InvalidationRegion image_invalidation;
  for (auto image_id : images_to_invalidate) {
    const auto& rects = raster_source_->GetDisplayItemList()
                            ->discardable_image_map()
                            .GetRectsForImage(image_id);
    for (const auto& r : rects.container())
      image_invalidation.Union(r);
  }
  Region invalidation;
  image_invalidation.Swap(&invalidation);

  if (invalidation.IsEmpty())
    return ImageInvalidationResult::kNoInvalidation;

  // Make sure to union the rect from this invalidation with the update_rect
  // instead of over-writing it. We don't want to reset the update that came
  // from the main thread.
  // Note: We can use a rect here since this is only used to track damage for a
  // frame and not raster invalidation.
  gfx::Rect new_update_rect = invalidation.bounds();
  new_update_rect.Union(update_rect());
  SetUpdateRect(new_update_rect);

  invalidation_.Union(invalidation);
  tilings_->Invalidate(invalidation);
  SetNeedsPushProperties();
  return ImageInvalidationResult::kInvalidated;
}

void PictureLayerImpl::RegisterAnimatedImages() {
  if (!raster_source_ || !raster_source_->GetDisplayItemList())
    return;

  auto* controller = layer_tree_impl()->image_animation_controller();
  const auto& metadata = raster_source_->GetDisplayItemList()
                             ->discardable_image_map()
                             .animated_images_metadata();
  for (const auto& data : metadata) {
    // Only update the metadata from updated recordings received from a commit.
    if (layer_tree_impl()->IsSyncTree())
      controller->UpdateAnimatedImage(data);
    controller->RegisterAnimationDriver(data.paint_image_id, this);
  }
}

void PictureLayerImpl::UnregisterAnimatedImages() {
  if (!raster_source_ || !raster_source_->GetDisplayItemList())
    return;

  auto* controller = layer_tree_impl()->image_animation_controller();
  const auto& metadata = raster_source_->GetDisplayItemList()
                             ->discardable_image_map()
                             .animated_images_metadata();
  for (const auto& data : metadata)
    controller->UnregisterAnimationDriver(data.paint_image_id, this);
}

}  // namespace cc
