// 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 "components/viz/service/display/skia_renderer.h"

#include <limits>
#include <string>
#include <utility>

#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/bits.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "cc/base/math_util.h"
#include "cc/debug/debug_colors.h"
#include "cc/paint/render_surface_filters.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.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/stream_video_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/skia_helper.h"
#include "components/viz/service/display/delegated_ink_handler.h"
#include "components/viz/service/display/delegated_ink_point_renderer_skia.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/renderer_utils.h"
#include "components/viz/service/display/resource_fence.h"
#include "components/viz/service/display/skia_output_surface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "skia/ext/opacity_filter_canvas.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkDeferredDisplayList.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/effects/SkColorMatrix.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
#include "third_party/skia/include/effects/SkOverdrawColorFilter.h"
#include "third_party/skia/include/effects/SkRuntimeEffect.h"
#include "third_party/skia/include/effects/SkShaderMaskFilter.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/third_party/skcms/skcms.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/color_transform.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/transform_util.h"
#include "ui/gfx/gpu_fence_handle.h"

namespace viz {

namespace {

// Smallest unit that impacts anti-aliasing output. We use this to determine
// when an exterior edge (with AA) has been clipped (no AA). The specific value
// was chosen to match that used by gl_renderer.
static const float kAAEpsilon = 1.0f / 1024.0f;

#if BUILDFLAG(IS_APPLE) || defined(USE_OZONE)
SkScalar remove_epsilon(SkScalar v) {
  return v < std::numeric_limits<SkScalar>::epsilon() &&
                 v > -std::numeric_limits<SkScalar>::epsilon()
             ? 0
             : v;
}
#endif  // BUILDFLAG(IS_APPLE) || defined(USE_OZONE)

// The gfx::QuadF draw_region passed to DoDrawQuad, converted to Skia types
struct SkDrawRegion {
  SkDrawRegion() = default;
  explicit SkDrawRegion(const gfx::QuadF& draw_region);

  SkPoint points[4];
};

// Additional YUV information to skia renderer to draw 9- and 10- bits color.
struct YUVInput {
  YUVInput() { memset(this, 0, sizeof(*this)); }
  float offset;
  float multiplier;
};

SkDrawRegion::SkDrawRegion(const gfx::QuadF& draw_region) {
  points[0] = gfx::PointFToSkPoint(draw_region.p1());
  points[1] = gfx::PointFToSkPoint(draw_region.p2());
  points[2] = gfx::PointFToSkPoint(draw_region.p3());
  points[3] = gfx::PointFToSkPoint(draw_region.p4());
}

bool IsTextureResource(DisplayResourceProviderSkia* resource_provider,
                       ResourceId resource_id) {
  return !resource_provider->IsResourceSoftwareBacked(resource_id);
}

unsigned GetCornerAAFlags(const DrawQuad* quad,
                          const SkPoint& vertex,
                          unsigned edge_mask) {
  // Returns mask of SkCanvas::QuadAAFlags, with bits set for each edge of the
  // shared quad state's quad_layer_rect that vertex is touching.

  unsigned mask = SkCanvas::kNone_QuadAAFlags;
  if (std::abs(vertex.x()) < kAAEpsilon)
    mask |= SkCanvas::kLeft_QuadAAFlag;
  if (std::abs(vertex.x() - quad->shared_quad_state->quad_layer_rect.width()) <
      kAAEpsilon)
    mask |= SkCanvas::kRight_QuadAAFlag;
  if (std::abs(vertex.y()) < kAAEpsilon)
    mask |= SkCanvas::kTop_QuadAAFlag;
  if (std::abs(vertex.y() - quad->shared_quad_state->quad_layer_rect.height()) <
      kAAEpsilon)
    mask |= SkCanvas::kBottom_QuadAAFlag;
  // & with the overall edge_mask to take into account edges that were clipped
  // by the visible rect.
  return mask & edge_mask;
}

bool IsExteriorEdge(unsigned corner_mask1, unsigned corner_mask2) {
  return (corner_mask1 & corner_mask2) != 0;
}

unsigned GetRectilinearEdgeFlags(const DrawQuad* quad) {
  // In the normal case, turn on AA for edges that represent the outside of
  // the layer, and that aren't clipped by the visible rect.
  unsigned mask = SkCanvas::kNone_QuadAAFlags;
  if (quad->IsLeftEdge() &&
      std::abs(quad->rect.x() - quad->visible_rect.x()) < kAAEpsilon)
    mask |= SkCanvas::kLeft_QuadAAFlag;
  if (quad->IsTopEdge() &&
      std::abs(quad->rect.y() - quad->visible_rect.y()) < kAAEpsilon)
    mask |= SkCanvas::kTop_QuadAAFlag;
  if (quad->IsRightEdge() &&
      std::abs(quad->rect.right() - quad->visible_rect.right()) < kAAEpsilon)
    mask |= SkCanvas::kRight_QuadAAFlag;
  if (quad->IsBottomEdge() &&
      std::abs(quad->rect.bottom() - quad->visible_rect.bottom()) < kAAEpsilon)
    mask |= SkCanvas::kBottom_QuadAAFlag;

  return mask;
}

// This also modifies draw_region to clean up any degeneracies
void GetClippedEdgeFlags(const DrawQuad* quad,
                         unsigned* edge_mask,
                         SkDrawRegion* draw_region) {
  // Instead of trying to rotate vertices of draw_region to align with Skia's
  // edge label conventions, turn on an edge's label if it is aligned to any
  // exterior edge.
  unsigned p0Mask = GetCornerAAFlags(quad, draw_region->points[0], *edge_mask);
  unsigned p1Mask = GetCornerAAFlags(quad, draw_region->points[1], *edge_mask);
  unsigned p2Mask = GetCornerAAFlags(quad, draw_region->points[2], *edge_mask);
  unsigned p3Mask = GetCornerAAFlags(quad, draw_region->points[3], *edge_mask);

  unsigned mask = SkCanvas::kNone_QuadAAFlags;
  // The "top" is p0 to p1
  if (IsExteriorEdge(p0Mask, p1Mask))
    mask |= SkCanvas::kTop_QuadAAFlag;
  // The "right" is p1 to p2
  if (IsExteriorEdge(p1Mask, p2Mask))
    mask |= SkCanvas::kRight_QuadAAFlag;
  // The "bottom" is p2 to p3
  if (IsExteriorEdge(p2Mask, p3Mask))
    mask |= SkCanvas::kBottom_QuadAAFlag;
  // The "left" is p3 to p0
  if (IsExteriorEdge(p3Mask, p0Mask))
    mask |= SkCanvas::kLeft_QuadAAFlag;

  // If the clipped draw_region has adjacent non-AA edges that touch the
  // exterior edge (which should be AA'ed), move the degenerate vertex to the
  // appropriate index so that Skia knows to construct a coverage ramp at that
  // corner. This is not an ideal solution, but is the best hint we can give,
  // given our limited information post-BSP splitting.
  if (draw_region->points[2] == draw_region->points[3]) {
    // The BSP splitting always creates degenerate quads with the duplicate
    // vertex in the last two indices.
    if (p0Mask && !(mask & SkCanvas::kLeft_QuadAAFlag) &&
        !(mask & SkCanvas::kTop_QuadAAFlag)) {
      // Rewrite draw_region from p0,p1,p2,p2 to p0,p1,p2,p0; top edge stays off
      // right edge is preserved, bottom edge turns off, left edge turns on
      draw_region->points[3] = draw_region->points[0];
      mask = SkCanvas::kLeft_QuadAAFlag | (mask & SkCanvas::kRight_QuadAAFlag);
    } else if (p1Mask && !(mask & SkCanvas::kTop_QuadAAFlag) &&
               !(mask & SkCanvas::kRight_QuadAAFlag)) {
      // Rewrite draw_region to p0,p1,p1,p2; top edge stays off, right edge
      // turns on, bottom edge turns off, left edge is preserved
      draw_region->points[2] = draw_region->points[1];
      mask = SkCanvas::kRight_QuadAAFlag | (mask & SkCanvas::kLeft_QuadAAFlag);
    }
    // p2 could follow the same process, but if its adjacent edges are AA
    // (skipping the degenerate edge to p3), it's actually already in the
    // desired vertex ordering; and since p3 is in the same location, it's
    // equivalent to p2 so it doesn't need checking either.
  }  // Else not degenerate, so can't to correct non-AA corners touching AA edge

  *edge_mask = mask;
}

bool IsAAForcedOff(const DrawQuad* quad) {
  switch (quad->material) {
    case DrawQuad::Material::kPictureContent:
      return PictureDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
    case DrawQuad::Material::kCompositorRenderPass:
      // We should not have compositor render passes here.
      NOTREACHED();
      return CompositorRenderPassDrawQuad::MaterialCast(quad)
          ->force_anti_aliasing_off;
    case DrawQuad::Material::kAggregatedRenderPass:
      return AggregatedRenderPassDrawQuad::MaterialCast(quad)
          ->force_anti_aliasing_off;
    case DrawQuad::Material::kSolidColor:
      return SolidColorDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
    case DrawQuad::Material::kTiledContent:
      return TileDrawQuad::MaterialCast(quad)->force_anti_aliasing_off;
    case DrawQuad::Material::kYuvVideoContent:
    case DrawQuad::Material::kStreamVideoContent:
    case DrawQuad::Material::kTextureContent:
      // This is done to match the behaviour of GLRenderer and we can revisit it
      // later.
      return true;
    default:
      return false;
  }
}

bool UseNearestNeighborSampling(const DrawQuad* quad) {
  switch (quad->material) {
    case DrawQuad::Material::kPictureContent:
      return PictureDrawQuad::MaterialCast(quad)->nearest_neighbor;
    case DrawQuad::Material::kTextureContent:
      return TextureDrawQuad::MaterialCast(quad)->nearest_neighbor;
    case DrawQuad::Material::kTiledContent:
      return TileDrawQuad::MaterialCast(quad)->nearest_neighbor;
    default:
      // Other quad types do not expose nearest_neighbor.
      return false;
  }
}

SkSamplingOptions GetSampling(const DrawQuad* quad) {
  if (UseNearestNeighborSampling(quad))
    return SkSamplingOptions(SkFilterMode::kNearest);

  // Default to bilinear if the quad doesn't specify nearest_neighbor.
  // TODO(penghuang): figure out how to set correct filter quality for YUV and
  // video stream quads.
  return SkSamplingOptions(SkFilterMode::kLinear);
}

// Returns kFast if sampling outside of vis_tex_coords due to AA or bilerp will
// not go outside of the content area, or if the content area is the full image
// (in which case hardware clamping handles it automatically). Different quad
// types have different rules for the content area within the image.
SkCanvas::SrcRectConstraint GetTextureConstraint(
    const SkImage* image,
    const gfx::RectF& vis_tex_coords,
    const gfx::RectF& valid_texel_bounds) {
  bool fills_left = valid_texel_bounds.x() <= 0.f;
  bool fills_right = valid_texel_bounds.right() >= image->width();
  bool fills_top = valid_texel_bounds.y() <= 0.f;
  bool fills_bottom = valid_texel_bounds.bottom() >= image->height();
  if (fills_left && fills_right && fills_top && fills_bottom) {
    // The entire image is contained in the content area, so hardware clamping
    // ensures only content texels are sampled
    return SkCanvas::kFast_SrcRectConstraint;
  }

  gfx::RectF safe_texels = valid_texel_bounds;
  safe_texels.Inset(0.5f, 0.5f);

  // Check each axis independently; tile quads may only need clamping on one
  // side (e.g. right or bottom) and this logic doesn't fully match a simple
  // contains() check.
  if ((!fills_left && vis_tex_coords.x() < safe_texels.x()) ||
      (!fills_right && vis_tex_coords.right() > safe_texels.right())) {
    return SkCanvas::kStrict_SrcRectConstraint;
  }
  if ((!fills_top && vis_tex_coords.y() < safe_texels.y()) ||
      (!fills_bottom && vis_tex_coords.bottom() > safe_texels.bottom())) {
    return SkCanvas::kStrict_SrcRectConstraint;
  }

  // The texture coordinates are far enough from the content area that even with
  // bilerp and AA, it won't sample outside the content area
  return SkCanvas::kFast_SrcRectConstraint;
}

// Return a color filter that multiplies the incoming color by the fixed alpha
sk_sp<SkColorFilter> MakeOpacityFilter(float alpha, sk_sp<SkColorFilter> in) {
  SkColor alpha_as_color = SkColorSetA(SK_ColorWHITE, 255 * alpha);
  // MakeModeFilter treats fixed color as src, and input color as dst.
  // kDstIn is (srcAlpha * dstColor, srcAlpha * dstAlpha) so this makes the
  // output color equal to input color * alpha.
  sk_sp<SkColorFilter> opacity =
      SkColorFilters::Blend(alpha_as_color, SkBlendMode::kDstIn);
  if (in) {
    return opacity->makeComposed(std::move(in));
  } else {
    return opacity;
  }
}

// Porter-Duff blend mode utility functions, where the final color is
// represented as a weighted sum of the incoming src and existing dst color.
// See [https://skia.org/user/api/SkBlendMode_Reference]

bool IsPorterDuffBlendMode(SkBlendMode blendMode) {
  return blendMode <= SkBlendMode::kLastCoeffMode;
}

// Returns true if drawing transparent black with |blendMode| would modify the
// destination buffer. If false is returned, the draw would have no discernible
// effect on the pixel color so the entire draw can be skipped.
bool TransparentBlackAffectsOutput(SkBlendMode blendMode) {
  SkBlendModeCoeff src, dst;
  if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) {
    // An advanced blend mode that can't be represented as coefficients, so
    // assume it modifies the output.
    return true;
  }
  // True when the dst coefficient is not equal to 1 (when src = (0,0,0,0))
  return dst != SkBlendModeCoeff::kOne && dst != SkBlendModeCoeff::kISA &&
         dst != SkBlendModeCoeff::kISC;
}

// Returns true if src content drawn with |blendMode| into a RenderPass would
// produce the exact same image as the original src content.
bool RenderPassPreservesContent(SkBlendMode blendMode) {
  SkBlendModeCoeff src, dst;
  if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) {
    return false;
  }
  // True when src coefficient is equal to 1 (when dst = (0,0,0,0))
  return src == SkBlendModeCoeff::kOne || src == SkBlendModeCoeff::kIDA ||
         src == SkBlendModeCoeff::kIDC;
}

// Returns true if src content draw with |blendMode| into an empty RenderPass
// would produce a transparent black image.
bool RenderPassRemainsTransparent(SkBlendMode blendMode) {
  SkBlendModeCoeff src, dst;
  if (!SkBlendMode_AsCoeff(blendMode, &src, &dst)) {
    return false;
  }

  // True when src coefficient is equal to 0 (when dst = (0,0,0,0))
  return src == SkBlendModeCoeff::kZero || src == SkBlendModeCoeff::kDA ||
         src == SkBlendModeCoeff::kDC;
}

SkYUVAInfo::Subsampling SubsamplingFromTextureSizes(gfx::Size ya_size,
                                                    gfx::Size uv_size) {
  if (uv_size.height() == ya_size.height()) {
    if (uv_size.width() == ya_size.width())
      return SkYUVAInfo::Subsampling::k444;
    if (uv_size.width() == (ya_size.width() + 1) / 2)
      return SkYUVAInfo::Subsampling::k422;
    if (uv_size.width() == (ya_size.width() + 3) / 4)
      return SkYUVAInfo::Subsampling::k411;
  } else if (uv_size.height() == (ya_size.height() + 1) / 2) {
    if (uv_size.width() == ya_size.width())
      return SkYUVAInfo::Subsampling::k440;
    if (uv_size.width() == (ya_size.width() + 1) / 2)
      return SkYUVAInfo::Subsampling::k420;
    if (uv_size.width() == (ya_size.width() + 3) / 4)
      return SkYUVAInfo::Subsampling::k410;
  }
  return SkYUVAInfo::Subsampling::kUnknown;
}

}  // namespace

// chrome style prevents this from going in skia_renderer.h, but since it
// uses absl::optional, the style also requires it to have a declared ctor
SkiaRenderer::BatchedQuadState::BatchedQuadState() = default;

// Parameters needed to draw a CompositorRenderPassDrawQuad.
struct SkiaRenderer::DrawRPDQParams {
  struct BypassGeometry {
    // The additional matrix to concatenate to the SkCanvas after image filters
    // have been configured so that the DrawQuadParams geometry is properly
    // mapped (i.e. when set, |visible_rect| and |draw_region| must be
    // pre-transformed by this before |content_device_transform|).
    SkMatrix transform;

    // `rect` from the bypassed RenderPassDrawQuad.
    gfx::RectF rect;

    // `visible_rect` from the bypassed RenderPassDrawQuad.
    gfx::RectF visible_rect;
  };

  explicit DrawRPDQParams(const gfx::RectF& visible_rect);

  // Root of the calculated image filter DAG to be applied to the render pass.
  sk_sp<SkImageFilter> image_filter = nullptr;
  // If |image_filter| can be represented as a single color filter, this will
  // be that filter. |image_filter| will still be non-null.
  sk_sp<SkColorFilter> color_filter = nullptr;
  // Root of the calculated backdrop filter DAG to be applied to the render pass
  sk_sp<SkImageFilter> backdrop_filter = nullptr;
  // Resolved mask image and calculated transform matrix baked into an SkShader,
  // which will be applied using SkCanvas::clipShader in RPDQ's coord space.
  sk_sp<SkShader> mask_shader = nullptr;
  // Backdrop border box for the render pass, to clip backdrop-filtered content
  absl::optional<gfx::RRectF> backdrop_filter_bounds;
  // The content space bounds that includes any filtered extents. If empty,
  // the draw can be skipped.
  gfx::Rect filter_bounds;

  // Geometry from the bypassed RenderPassDrawQuad.
  absl::optional<BypassGeometry> bypass_geometry;

  // True when there is an |image_filter| and it's not equivalent to
  // |color_filter|.
  bool has_complex_image_filter() const {
    return image_filter && !color_filter;
  }

  // True if the RenderPass's output rect would clip the visible contents that
  // are bypassing the renderpass' offscreen buffer.
  bool needs_bypass_clip(const gfx::RectF& content_rect) const {
    if (!bypass_geometry)
      return false;

    SkRect content_bounds =
        bypass_geometry->transform.mapRect(gfx::RectFToSkRect(content_rect));
    return !bypass_geometry->visible_rect.Contains(
        gfx::SkRectToRectF(content_bounds));
  }
};

SkiaRenderer::DrawRPDQParams::DrawRPDQParams(const gfx::RectF& visible_rect)
    : filter_bounds(gfx::ToEnclosingRect(visible_rect)) {}

// State calculated from a DrawQuad and current renderer state, that is common
// to all DrawQuad rendering.
struct SkiaRenderer::DrawQuadParams {
  DrawQuadParams() = default;
  DrawQuadParams(const gfx::Transform& cdt,
                 const gfx::RectF& rect,
                 const gfx::RectF& visible_rect,
                 unsigned aa_flags,
                 SkBlendMode blend_mode,
                 float opacity,
                 const SkSamplingOptions& sampling,
                 const gfx::QuadF* draw_region);

  // window_matrix * projection_matrix * quad_to_target_transform normally,
  // or quad_to_target_transform if the remaining device transform is held in
  // the DrawRPDQParams for a bypass quad.
  gfx::Transform content_device_transform;
  // The DrawQuad's rect.
  gfx::RectF rect;
  // The DrawQuad's visible_rect, possibly explicitly clipped by the scissor
  gfx::RectF visible_rect;
  // Initialized to the visible_rect, relevant quad types should updated based
  // on their specialized properties.
  gfx::RectF vis_tex_coords;
  // SkCanvas::QuadAAFlags, already taking into account settings
  // (but not certain quad type's force_antialias_off bit)
  unsigned aa_flags;
  // Final blend mode to use, respecting quad settings + opacity optimizations
  SkBlendMode blend_mode;
  // Final opacity of quad
  float opacity;
  // Resolved sampling from quad settings
  SkSamplingOptions sampling;
  // Optional restricted draw geometry, will point to a length 4 SkPoint array
  // with its points in CW order matching Skia's vertex/edge expectations.
  absl::optional<SkDrawRegion> draw_region;
  // Optional rounded corner clip to apply. If present, it will have been
  // transformed to device space and ShouldApplyRoundedCorner returns true.
  absl::optional<gfx::RRectF> rounded_corner_bounds;
  // Optional device space clip to apply. If present, it is equal to the current
  // |scissor_rect_| of the renderer.
  absl::optional<gfx::Rect> scissor_rect;

  SkPaint paint(sk_sp<SkColorFilter> color_filter) const {
    SkPaint p;
    if (color_filter) {
      p.setColorFilter(color_filter);
    }
    p.setBlendMode(blend_mode);
    p.setAlphaf(opacity);
    p.setAntiAlias(aa_flags != SkCanvas::kNone_QuadAAFlags);
    return p;
  }

  SkPath draw_region_in_path() const {
    if (draw_region) {
      return SkPath::Polygon(draw_region->points,
                             base::size(draw_region->points),
                             /*isClosed=*/true);
    }
    return SkPath();
  }

  void ApplyScissor(const SkiaRenderer* renderer,
                    const DrawQuad* quad,
                    const gfx::Rect* scissor_to_apply);
};

SkiaRenderer::DrawQuadParams::DrawQuadParams(const gfx::Transform& cdt,
                                             const gfx::RectF& rect,
                                             const gfx::RectF& visible_rect,
                                             unsigned aa_flags,
                                             SkBlendMode blend_mode,
                                             float opacity,
                                             const SkSamplingOptions& sampling,
                                             const gfx::QuadF* draw_region)
    : content_device_transform(cdt),
      rect(rect),
      visible_rect(visible_rect),
      vis_tex_coords(visible_rect),
      aa_flags(aa_flags),
      blend_mode(blend_mode),
      opacity(opacity),
      sampling(sampling) {
  if (draw_region) {
    this->draw_region.emplace(*draw_region);
  }
}

enum class SkiaRenderer::BypassMode {
  // The RenderPass's contents' blendmode would have made a transparent black
  // image and the RenderPass's own blend mode does not effect transparent black
  kSkip,
  // The renderPass's contents' creates a transparent image, but the
  // RenderPass's own blend mode must still process the transparent pixels (e.g.
  // certain filters affect transparent black).
  kDrawTransparentQuad,
  // Can draw the bypass quad with the modified parameters
  kDrawBypassQuad
};

// Scoped helper class for building SkImage from resource id.
class SkiaRenderer::ScopedSkImageBuilder {
 public:
  ScopedSkImageBuilder(SkiaRenderer* skia_renderer,
                       ResourceId resource_id,
                       bool maybe_concurrent_reads,
                       SkAlphaType alpha_type = kPremul_SkAlphaType,
                       GrSurfaceOrigin origin = kTopLeft_GrSurfaceOrigin,
                       const absl::optional<gfx::ColorSpace>&
                           override_colorspace = absl::nullopt,
                       bool raw_draw_if_possible = false);

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

  ~ScopedSkImageBuilder() = default;

  const SkImage* sk_image() const { return sk_image_; }
  const cc::PaintOpBuffer* paint_op_buffer() const { return paint_op_buffer_; }
  const absl::optional<SkColor>& clear_color() const { return clear_color_; }

 private:
  raw_ptr<const SkImage> sk_image_ = nullptr;
  raw_ptr<const cc::PaintOpBuffer> paint_op_buffer_ = nullptr;
  absl::optional<SkColor> clear_color_;
};

SkiaRenderer::ScopedSkImageBuilder::ScopedSkImageBuilder(
    SkiaRenderer* skia_renderer,
    ResourceId resource_id,
    bool maybe_concurrent_reads,
    SkAlphaType alpha_type,
    GrSurfaceOrigin origin,
    const absl::optional<gfx::ColorSpace>& override_color_space,
    bool raw_draw_if_possible) {
  if (!resource_id)
    return;
  auto* resource_provider = skia_renderer->resource_provider();
  DCHECK(IsTextureResource(resource_provider, resource_id));

  auto* image_context = skia_renderer->lock_set_for_external_use_->LockResource(
      resource_id, maybe_concurrent_reads, /*is_video_plane=*/false,
      override_color_space, raw_draw_if_possible);

  // |ImageContext::image| provides thread safety: (a) this ImageContext is
  // only accessed by GPU thread after |image| is set and (b) the fields of
  // ImageContext that are accessed by both compositor and GPU thread are no
  // longer modified after |image| is set.
  if (!image_context->has_image()) {
    image_context->set_alpha_type(alpha_type);
    image_context->set_origin(origin);
  }

  skia_renderer->skia_output_surface_->MakePromiseSkImage(image_context);
  paint_op_buffer_ = image_context->paint_op_buffer();
  clear_color_ = image_context->clear_color();
  sk_image_ = image_context->image().get();
  LOG_IF(ERROR, !image_context->has_image() && !paint_op_buffer_)
      << "Failed to create the promise sk image or get paint ops.";
}

class SkiaRenderer::ScopedYUVSkImageBuilder {
 public:
  ScopedYUVSkImageBuilder(SkiaRenderer* skia_renderer,
                          const YUVVideoDrawQuad* quad,
                          sk_sp<SkColorSpace> dst_color_space) {
    DCHECK(IsTextureResource(skia_renderer->resource_provider(),
                             quad->y_plane_resource_id()));
    DCHECK(IsTextureResource(skia_renderer->resource_provider(),
                             quad->u_plane_resource_id()));
    DCHECK(IsTextureResource(skia_renderer->resource_provider(),
                             quad->v_plane_resource_id()));
    DCHECK(quad->a_plane_resource_id() == kInvalidResourceId ||
           IsTextureResource(skia_renderer->resource_provider(),
                             quad->a_plane_resource_id()));

    // The image is always either NV12 or I420, possibly with a separate alpha
    // plane.
    SkYUVAInfo::PlaneConfig plane_config;
    if (quad->a_plane_resource_id() == kInvalidResourceId) {
      plane_config = quad->u_plane_resource_id() == quad->v_plane_resource_id()
                         ? SkYUVAInfo::PlaneConfig::kY_UV
                         : SkYUVAInfo::PlaneConfig::kY_U_V;
    } else {
      plane_config = quad->u_plane_resource_id() == quad->v_plane_resource_id()
                         ? SkYUVAInfo::PlaneConfig::kY_UV_A
                         : SkYUVAInfo::PlaneConfig::kY_U_V_A;
    }
    SkYUVAInfo::Subsampling subsampling =
        SubsamplingFromTextureSizes(quad->ya_tex_size, quad->uv_tex_size);
    const int number_of_textures = SkYUVAInfo::NumPlanes(plane_config);
    std::vector<ExternalUseClient::ImageContext*> contexts;
    contexts.reserve(number_of_textures);
    // Skia API ignores the color space information on the individual planes.
    // Dropping them here avoids some LOG spam.
    auto* y_context = skia_renderer->lock_set_for_external_use_->LockResource(
        quad->y_plane_resource_id(), /*maybe_concurrent_reads=*/true,
        /*is_video_plane=*/true);
    contexts.push_back(std::move(y_context));
    auto* u_context = skia_renderer->lock_set_for_external_use_->LockResource(
        quad->u_plane_resource_id(), /*maybe_concurrent_reads=*/true,
        /*is_video_plane=*/true);
    contexts.push_back(std::move(u_context));
    if (plane_config == SkYUVAInfo::PlaneConfig::kY_U_V ||
        plane_config == SkYUVAInfo::PlaneConfig::kY_U_V_A) {
      auto* v_context = skia_renderer->lock_set_for_external_use_->LockResource(
          quad->v_plane_resource_id(), /*maybe_concurrent_reads=*/true,
          /*is_video_plane=*/true);
      contexts.push_back(std::move(v_context));
    }

    if (SkYUVAInfo::HasAlpha(plane_config)) {
      auto* a_context = skia_renderer->lock_set_for_external_use_->LockResource(
          quad->a_plane_resource_id(), /*maybe_concurrent_reads=*/true,
          /*is_video_plane=*/true);
      contexts.push_back(std::move(a_context));
    }

    // Note: YUV to RGB and color conversion is handled by a color filter.
    sk_image_ = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
        std::move(contexts), dst_color_space, plane_config, subsampling);
    LOG_IF(ERROR, !sk_image_) << "Failed to create the promise sk yuva image.";
  }

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

  ~ScopedYUVSkImageBuilder() = default;

  const SkImage* sk_image() const { return sk_image_.get(); }

 private:
  sk_sp<SkImage> sk_image_;
};

class SkiaRenderer::FrameResourceFence : public ResourceFence {
 public:
  FrameResourceFence() = default;

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

  // ResourceFence implementation.
  void Set() override { set_ = true; }
  bool HasPassed() override { return event_.IsSignaled(); }

  bool WasSet() { return set_; }
  void Signal() { event_.Signal(); }

 private:
  ~FrameResourceFence() override = default;

  // Accessed only from compositor thread.
  bool set_ = false;

  base::WaitableEvent event_;
};

SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
                           const DebugRendererSettings* debug_settings,
                           OutputSurface* output_surface,
                           DisplayResourceProviderSkia* resource_provider,
                           OverlayProcessorInterface* overlay_processor,
                           SkiaOutputSurface* skia_output_surface)
    : DirectRenderer(settings,
                     debug_settings,
                     output_surface,
                     resource_provider,
                     overlay_processor),
      skia_output_surface_(skia_output_surface),
      is_using_raw_draw_(features::IsUsingRawDraw()) {
  DCHECK(skia_output_surface_);
  lock_set_for_external_use_.emplace(resource_provider, skia_output_surface_);

  current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>();
  this->resource_provider()->SetReadLockFence(
      current_frame_resource_fence_.get());

#if OS_ANDROID
  use_real_color_space_for_stream_video_ =
      features::UseRealVideoColorSpaceForDisplay();
#endif
}

SkiaRenderer::~SkiaRenderer() = default;

bool SkiaRenderer::CanPartialSwap() {
  return output_surface_->capabilities().supports_post_sub_buffer;
}

void SkiaRenderer::BeginDrawingFrame() {
  TRACE_EVENT0("viz", "SkiaRenderer::BeginDrawingFrame");

  DCHECK(!current_frame_resource_fence_->WasSet());
}

void SkiaRenderer::FinishDrawingFrame() {
  TRACE_EVENT0("viz", "SkiaRenderer::FinishDrawingFrame");
  current_canvas_ = nullptr;
  current_surface_ = nullptr;

  swap_buffer_rect_ = current_frame()->root_damage_rect;

  // TODO(weiliangc): Remove this once OverlayProcessor schedules overlays.
  if (current_frame()->output_surface_plane) {
    skia_output_surface_->ScheduleOutputSurfaceAsOverlay(
        current_frame()->output_surface_plane.value());
  }
  ScheduleOverlays();
  debug_tint_modulate_count_++;
}

void SkiaRenderer::SwapBuffers(SwapFrameData swap_frame_data) {
  DCHECK(visible_);
  TRACE_EVENT0("viz,benchmark", "SkiaRenderer::SwapBuffers");
  OutputSurfaceFrame output_frame;
  output_frame.latency_info = std::move(swap_frame_data.latency_info);
  output_frame.top_controls_visible_height_changed =
      swap_frame_data.top_controls_visible_height_changed;
  output_frame.size = surface_size_for_swap_buffers();
  if (use_partial_swap_) {
    swap_buffer_rect_.Intersect(gfx::Rect(surface_size_for_swap_buffers()));
    output_frame.sub_buffer_rect = swap_buffer_rect_;
  } else if (swap_buffer_rect_.IsEmpty() && allow_empty_swap_) {
    output_frame.sub_buffer_rect = gfx::Rect();
  }
  if (delegated_ink_handler_ && !UsingSkiaForDelegatedInk()) {
    output_frame.delegated_ink_metadata =
        delegated_ink_handler_->TakeMetadata();
  }
#if BUILDFLAG(IS_MAC)
  output_frame.ca_layer_error_code = swap_frame_data.ca_layer_error_code;
#endif
  skia_output_surface_->SwapBuffers(std::move(output_frame));
  swap_buffer_rect_ = gfx::Rect();

  FlushOutputSurface();
}

void SkiaRenderer::SwapBuffersSkipped() {
  gfx::Rect root_pass_damage_rect = gfx::Rect(surface_size_for_swap_buffers());
  if (use_partial_swap_)
    root_pass_damage_rect.Intersect(swap_buffer_rect_);

  skia_output_surface_->SwapBuffersSkipped(root_pass_damage_rect);
  swap_buffer_rect_ = gfx::Rect();

  FlushOutputSurface();
}

void SkiaRenderer::SwapBuffersComplete(gfx::GpuFenceHandle release_fence) {
  auto& read_lock_release_fence_overlay_locks =
      read_lock_release_fence_overlay_locks_.emplace_back();
  auto read_fence_lock_iter = committed_overlay_locks_.end();

  if (!release_fence.is_null()) {
    // Set release fences for returning for last frame overlay resources.
    for (auto& lock : committed_overlay_locks_) {
      lock.SetReleaseFence(release_fence.Clone());
    }
    // Find all locks that have a read-lock fence associated with them.
    // If we have a release fence, it's not safe to release them here.
    // Release them later in BuffersPresented.
    read_fence_lock_iter = std::partition(
        committed_overlay_locks_.begin(), committed_overlay_locks_.end(),
        [](auto& lock) { return !lock.HasReadLockFence(); });
    read_lock_release_fence_overlay_locks.insert(
        read_lock_release_fence_overlay_locks.end(),
        std::make_move_iterator(read_fence_lock_iter),
        std::make_move_iterator(committed_overlay_locks_.end()));
  }

  // Right now, only macOS and Ozone need to return mailboxes of released
  // overlays, so we should not release |committed_overlay_locks_| here. The
  // resources in it will be released by DidReceiveReleasedOverlays() later.
#if BUILDFLAG(IS_APPLE) || defined(USE_OZONE)
  for (auto lock_iter = committed_overlay_locks_.begin();
       lock_iter != read_fence_lock_iter; ++lock_iter) {
    awaiting_release_overlay_locks_.insert(std::move(*lock_iter));
  }
#endif  // BUILDFLAG(IS_APPLE) || defined(USE_OZONE)

  committed_overlay_locks_.clear();
  std::swap(committed_overlay_locks_, pending_overlay_locks_.front());
  pending_overlay_locks_.pop_front();
}

void SkiaRenderer::BuffersPresented() {
  DCHECK(!read_lock_release_fence_overlay_locks_.empty());
  read_lock_release_fence_overlay_locks_.pop_front();
}

void SkiaRenderer::DidReceiveReleasedOverlays(
    const std::vector<gpu::Mailbox>& released_overlays) {
  // This method is only called on macOS and Ozone right now.
#if BUILDFLAG(IS_APPLE) || defined(USE_OZONE)
  for (const auto& mailbox : released_overlays) {
    auto it = awaiting_release_overlay_locks_.find(mailbox);
    if (it == awaiting_release_overlay_locks_.end()) {
      DLOG(FATAL) << "Got an unexpected mailbox";
      continue;
    }
    awaiting_release_overlay_locks_.erase(it);
  }
#else
  NOTREACHED();
#endif  // !(BUILDFLAG(IS_APPLE) || defined (USE_OZONE))
}

bool SkiaRenderer::FlippedFramebuffer() const {
  // TODO(weiliangc): Make sure flipped correctly for Windows.
  // (crbug.com/644851)
  return false;
}

void SkiaRenderer::EnsureScissorTestEnabled() {
  is_scissor_enabled_ = true;
}

void SkiaRenderer::EnsureScissorTestDisabled() {
  is_scissor_enabled_ = false;
}

void SkiaRenderer::BindFramebufferToOutputSurface() {
  DCHECK(!output_surface_->HasExternalStencilTest());

  root_canvas_ = skia_output_surface_->BeginPaintCurrentFrame();
  current_canvas_ = root_canvas_;
  current_surface_ = root_surface_.get();
}

void SkiaRenderer::BindFramebufferToTexture(
    const AggregatedRenderPassId render_pass_id) {
  auto iter = render_pass_backings_.find(render_pass_id);
  DCHECK(render_pass_backings_.end() != iter);
  // This function is called after AllocateRenderPassResourceIfNeeded, so there
  // should be backing ready.
  RenderPassBacking& backing = iter->second;
  current_canvas_ = skia_output_surface_->BeginPaintRenderPass(
      render_pass_id, backing.size, backing.format, backing.generate_mipmap,
      backing.color_space.ToSkColorSpace(), backing.mailbox);
}

void SkiaRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) {
  is_scissor_enabled_ = true;
  scissor_rect_ = scissor_rect;
}

void SkiaRenderer::ClearCanvas(SkColor color) {
  if (!current_canvas_)
    return;

  if (is_scissor_enabled_) {
    // Limit the clear with the scissor rect.
    SkAutoCanvasRestore autoRestore(current_canvas_, true /* do_save */);
    current_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_));
    current_canvas_->clear(color);
  } else {
    current_canvas_->clear(color);
  }
}

void SkiaRenderer::ClearFramebuffer() {
  if (current_frame()->current_render_pass->has_transparent_background) {
    ClearCanvas(SkColorSetARGB(0, 0, 0, 0));
  } else {
#if DCHECK_IS_ON()
    // On DEBUG builds, opaque render passes are cleared to blue
    // to easily see regions that were not drawn on the screen.
    ClearCanvas(SkColorSetARGB(255, 0, 0, 255));
#endif
  }
}

void SkiaRenderer::PrepareSurfaceForPass(
    SurfaceInitializationMode initialization_mode,
    const gfx::Rect& render_pass_scissor) {
  switch (initialization_mode) {
    case SURFACE_INITIALIZATION_MODE_PRESERVE:
      EnsureScissorTestDisabled();
      return;
    case SURFACE_INITIALIZATION_MODE_FULL_SURFACE_CLEAR:
      EnsureScissorTestDisabled();
      ClearFramebuffer();
      break;
    case SURFACE_INITIALIZATION_MODE_SCISSORED_CLEAR:
      SetScissorTestRect(render_pass_scissor);
      ClearFramebuffer();
      break;
  }
}

void SkiaRenderer::DoDrawQuad(const DrawQuad* quad,
                              const gfx::QuadF* draw_region) {
  if (!current_canvas_)
    return;
  TRACE_EVENT0("viz", "SkiaRenderer::DoDrawQuad");
  gfx::Transform target_to_device =
      current_frame()->window_matrix * current_frame()->projection_matrix;
  const gfx::Rect* scissor = is_scissor_enabled_ ? &scissor_rect_ : nullptr;
  DrawQuadParams params =
      CalculateDrawQuadParams(target_to_device, scissor, quad, draw_region);
  // The outer DrawQuad will never have RPDQ params
  DrawQuadInternal(quad, /* rpdq */ nullptr, &params);
}

void SkiaRenderer::DrawQuadInternal(const DrawQuad* quad,
                                    const DrawRPDQParams* rpdq_params,
                                    DrawQuadParams* params) {
  if (MustFlushBatchedQuads(quad, rpdq_params, *params)) {
    FlushBatchedQuads();
  }

  switch (quad->material) {
    case DrawQuad::Material::kAggregatedRenderPass:
      // RPDQ should only ever be encountered as a top-level quad, not when
      // bypassing another renderpass
      DCHECK(rpdq_params == nullptr);
      DrawRenderPassQuad(AggregatedRenderPassDrawQuad::MaterialCast(quad),
                         params);
      break;
    case DrawQuad::Material::kDebugBorder:
      // DebugBorders draw directly into the device space, so are not compatible
      // with image filters, so should never have been promoted as a bypass quad
      DCHECK(rpdq_params == nullptr);
      DrawDebugBorderQuad(DebugBorderDrawQuad::MaterialCast(quad), params);
      break;
    case DrawQuad::Material::kPictureContent:
      // PictureQuads represent a collection of drawn elements that are
      // dynamically rasterized by Skia; bypassing a RenderPass to redraw the
      // N elements doesn't make much sense.
      DCHECK(rpdq_params == nullptr);
      DrawPictureQuad(PictureDrawQuad::MaterialCast(quad), params);
      break;
    case DrawQuad::Material::kCompositorRenderPass:
      // RenderPassDrawQuads should be converted to
      // AggregatedRenderPassDrawQuads at this point.
      DrawUnsupportedQuad(quad, rpdq_params, params);
      NOTREACHED();
      break;
    case DrawQuad::Material::kSolidColor:
      DrawSolidColorQuad(SolidColorDrawQuad::MaterialCast(quad), rpdq_params,
                         params);
      break;
    case DrawQuad::Material::kStreamVideoContent:
      DrawStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad), rpdq_params,
                          params);
      break;
    case DrawQuad::Material::kTextureContent:
      DrawTextureQuad(TextureDrawQuad::MaterialCast(quad), rpdq_params, params);
      break;
    case DrawQuad::Material::kTiledContent:
      DrawTileDrawQuad(TileDrawQuad::MaterialCast(quad), rpdq_params, params);
      break;
    case DrawQuad::Material::kSharedElement:
      DrawUnsupportedQuad(quad, rpdq_params, params);
      NOTREACHED();
      break;
    case DrawQuad::Material::kYuvVideoContent:
      DrawYUVVideoQuad(YUVVideoDrawQuad::MaterialCast(quad), rpdq_params,
                       params);
      break;
    case DrawQuad::Material::kInvalid:
      DrawUnsupportedQuad(quad, rpdq_params, params);
      NOTREACHED();
      break;
    case DrawQuad::Material::kVideoHole:
      // VideoHoleDrawQuad should only be used by Cast, and should
      // have been replaced by cast-specific OverlayProcessor before
      // reach here. In non-cast build, an untrusted render could send such
      // Quad and the quad would then reach here unexpectedly. Therefore
      // we should skip NOTREACHED() so an untrusted render is not capable
      // of causing a crash.
      DrawUnsupportedQuad(quad, rpdq_params, params);
      break;
    default:
      // If we've reached here, it's a new quad type that needs a
      // dedicated implementation
      DrawUnsupportedQuad(quad, rpdq_params, params);
      NOTREACHED();
      break;
  }
}

void SkiaRenderer::PrepareCanvas(
    const absl::optional<gfx::Rect>& scissor_rect,
    const absl::optional<gfx::RRectF>& rounded_corner_bounds,
    const gfx::Transform* cdt) {
  // Scissor is applied in the device space (CTM == I) and since no changes
  // to the canvas persist, CTM should already be the identity
  DCHECK(current_canvas_->getTotalMatrix() == SkMatrix::I());

  if (scissor_rect.has_value()) {
    current_canvas_->clipRect(gfx::RectToSkRect(*scissor_rect));
  }

  if (rounded_corner_bounds.has_value())
    current_canvas_->clipRRect(SkRRect(*rounded_corner_bounds), true /* AA */);

  if (cdt) {
    SkMatrix m;
    gfx::TransformToFlattenedSkMatrix(*cdt, &m);
    current_canvas_->concat(m);
  }
}

void SkiaRenderer::PrepareCanvasForRPDQ(const DrawRPDQParams& rpdq_params,
                                        DrawQuadParams* params) {
  // Clip to the filter bounds prior to saving the layer, which has been
  // constructed to contain the actual filtered contents (visually no
  // clipping effect, but lets Skia minimize internal layer size).
  bool aa = params->aa_flags != SkCanvas::kNone_QuadAAFlags;
  current_canvas_->clipRect(gfx::RectToSkRect(rpdq_params.filter_bounds), aa);

  SkPaint layer_paint = params->paint(nullptr /* color_filter */);
  // The layer always consumes the opacity, but its blend mode depends on if
  // it was initialized with backdrop content or not.
  params->opacity = 1.f;
  if (rpdq_params.backdrop_filter) {
    layer_paint.setBlendMode(SkBlendMode::kSrcOver);
  } else {
    params->blend_mode = SkBlendMode::kSrcOver;
  }

  if (rpdq_params.color_filter) {
    layer_paint.setColorFilter(rpdq_params.color_filter);
  } else if (rpdq_params.image_filter) {
    layer_paint.setImageFilter(rpdq_params.image_filter);
  }

  // Canocalize the backdrop bounds rrect type; if there's no backdrop filter or
  // filter bounds, this will be empty. If it's a rect or rrect, we must work
  // around Skia's background filter auto-expansion. If it's an rrect, we must
  // also clear out the rounded corners after filtering.
  gfx::RRectF::Type backdrop_bounds_type = gfx::RRectF::Type::kEmpty;
  if (rpdq_params.backdrop_filter &&
      rpdq_params.backdrop_filter_bounds.has_value()) {
    backdrop_bounds_type = rpdq_params.backdrop_filter_bounds->GetType();
  }

  // Initially the backdrop filter fills the entire rect; if we draw less than
  // that we need to clear the excess.
  bool post_backdrop_filter_clear_needed = !!params->draw_region;

  // Explicitly crop the input and the output to the backdrop bounds; this is
  // required for the backdrop-filter spec.
  sk_sp<SkImageFilter> backdrop_filter = rpdq_params.backdrop_filter;
  if (backdrop_bounds_type != gfx::RRectF::Type::kEmpty) {
    DCHECK(backdrop_filter);

    gfx::RectF crop_rect = rpdq_params.backdrop_filter_bounds->rect();

    // Only sample from pixels behind the RPDQ for backdrop filters to avoid
    // color bleeding with pixel-moving filters.
    if (rpdq_params.bypass_geometry) {
      crop_rect.Intersect(rpdq_params.bypass_geometry->rect);
    } else {
      crop_rect.Intersect(params->rect);
    }
    SkIRect sk_crop_rect = gfx::RectToSkIRect(gfx::ToEnclosingRect(crop_rect));

    SkIRect sk_src_rect = backdrop_filter->filterBounds(
        sk_crop_rect, SkMatrix::I(), SkImageFilter::kReverse_MapDirection,
        &sk_crop_rect);
    if (sk_crop_rect == sk_src_rect) {
      // The backdrop filter does not "move" pixels, i.e. a pixel's value only
      // depends on its (x,y) and prior color. Avoid cropping the input in this
      // case since composing a crop rect into the filter DAG forces Skia to
      // map the backdrop content into the local space, which can introduce
      // filtering artifacts: crbug.com/1044032. Instead just post-filter
      // clearing will achieve the same cropping of the output at higher quality
      post_backdrop_filter_clear_needed = true;
    } else {
      // Offsetting (0,0) does nothing to the actual image, but is the most
      // convenient way to embed the crop rect into the filter DAG.
      // TODO(michaelludwig) - Remove this once Skia doesn't always auto-expand
      sk_sp<SkImageFilter> crop =
          SkImageFilters::Offset(0.0f, 0.0f, nullptr, &sk_crop_rect);
      backdrop_filter = SkImageFilters::Compose(
          crop, SkImageFilters::Compose(std::move(backdrop_filter), crop));
      // Update whether or not a post-filter clear is needed (crop didn't
      // completely match bounds)
      post_backdrop_filter_clear_needed |=
          backdrop_bounds_type != gfx::RRectF::Type::kRect ||
          crop_rect != rpdq_params.backdrop_filter_bounds->rect();
    }
  }

  SkRect bounds = gfx::RectFToSkRect(
      rpdq_params.bypass_geometry ? rpdq_params.bypass_geometry->visible_rect
                                  : params->visible_rect);
  current_canvas_->saveLayer(
      SkCanvas::SaveLayerRec(&bounds, &layer_paint, backdrop_filter.get(), 0));

  // If we have backdrop filtered content (and not transparent black like with
  // regular render passes), we have to clear out the parts of the layer that
  // shouldn't show the backdrop
  if (backdrop_filter && post_backdrop_filter_clear_needed) {
    current_canvas_->save();
    if (rpdq_params.backdrop_filter_bounds.has_value()) {
      current_canvas_->clipRRect(SkRRect(*rpdq_params.backdrop_filter_bounds),
                                 SkClipOp::kDifference, aa);
    }
    if (params->draw_region) {
      SkPath clip_path = params->draw_region_in_path();
      if (rpdq_params.bypass_geometry) {
        clip_path.transform(rpdq_params.bypass_geometry->transform);
      }
      current_canvas_->clipPath(clip_path, SkClipOp::kDifference, aa);
    }
    current_canvas_->clear(SK_ColorTRANSPARENT);
    current_canvas_->restore();
  }
}

void SkiaRenderer::PreparePaintOrCanvasForRPDQ(
    const DrawRPDQParams& rpdq_params,
    DrawQuadParams* params,
    SkPaint* paint) {
  // When the draw call accepts an SkPaint, some of the rpdq effects are more
  // efficient to store on the paint instead of making an explicit layer in
  // the canvas. But there are several requirements in order for the order of
  // operations to be consistent with what RenderPasses require:
  // 1. Backdrop filtering always requires a layer.
  // 2. The content bypassing the renderpass needs to be clipped before the
  //    image filter is evaluated.
  bool needs_bypass_clip = rpdq_params.needs_bypass_clip(params->visible_rect);
  bool needs_save_layer = false;
  if (rpdq_params.backdrop_filter)
    needs_save_layer = true;
  else if (rpdq_params.has_complex_image_filter())
    needs_save_layer = needs_bypass_clip;

  if (rpdq_params.mask_shader) {
    // Apply the mask image using clipShader(), this works the same regardless
    // of if we need a saveLayer for image filtering since the clip is applied
    // at the end automatically.
    current_canvas_->clipShader(rpdq_params.mask_shader);
  }

  if (needs_save_layer) {
    PrepareCanvasForRPDQ(rpdq_params, params);
    // Sync the content's paint with the updated |params|
    paint->setAlphaf(params->opacity);
    paint->setBlendMode(params->blend_mode);
  } else {
    // At this point, the image filter and/or color filter are on the paint.
    DCHECK(!rpdq_params.backdrop_filter);
    if (rpdq_params.color_filter) {
      // Use the color filter directly, instead of the image filter.
      if (paint->getColorFilter()) {
        paint->setColorFilter(
            rpdq_params.color_filter->makeComposed(paint->refColorFilter()));
      } else {
        paint->setColorFilter(rpdq_params.color_filter);
      }
      DCHECK(paint->getColorFilter());
    } else if (rpdq_params.image_filter) {
      // Store the image filter on the paint.
      if (params->opacity != 1.f) {
        // Apply opacity as the last step of image filter so it is uniform
        // across any overlapping content produced by the image filters.
        paint->setImageFilter(SkImageFilters::ColorFilter(
            MakeOpacityFilter(params->opacity, nullptr),
            rpdq_params.image_filter));
        paint->setAlphaf(1.f);
        params->opacity = 1.f;
      } else {
        paint->setImageFilter(rpdq_params.image_filter);
      }
    }
  }

  // Whether or not we saved a layer, clip the bypassed RenderPass's content
  if (needs_bypass_clip) {
    current_canvas_->clipRect(
        gfx::RectFToSkRect(rpdq_params.bypass_geometry->visible_rect),
        params->aa_flags != SkCanvas::kNone_QuadAAFlags);
  }
}

void SkiaRenderer::PrepareColorOrCanvasForRPDQ(
    const DrawRPDQParams& rpdq_params,
    DrawQuadParams* params,
    SkColor* content_color) {
  // When the draw call only takes a color and not an SkPaint, rpdq params
  // with just a color filter can be handled directly. Otherwise, the rpdq
  // params must use a layer on the canvas.
  bool needs_save_layer =
      rpdq_params.has_complex_image_filter() || rpdq_params.backdrop_filter;
  if (rpdq_params.mask_shader) {
    current_canvas_->clipShader(rpdq_params.mask_shader);
  }

  if (needs_save_layer) {
    PrepareCanvasForRPDQ(rpdq_params, params);
  } else if (rpdq_params.color_filter) {
    // At this point, the RPDQ effect is at most a color filter, so it can
    // modify |content_color| directly.
    *content_color = rpdq_params.color_filter->filterColor(*content_color);
  }

  // Even if the color filter image filter was applied to the content color
  // directly (so no explicit save layer), the draw may need to be clipped to
  // the output rect of the renderpass it is bypassing.
  if (rpdq_params.needs_bypass_clip(params->visible_rect)) {
    current_canvas_->clipRect(
        gfx::RectFToSkRect(rpdq_params.bypass_geometry->visible_rect),
        params->aa_flags != SkCanvas::kNone_QuadAAFlags);
  }
}

SkiaRenderer::DrawQuadParams SkiaRenderer::CalculateDrawQuadParams(
    const gfx::Transform& target_to_device,
    const gfx::Rect* scissor_rect,
    const DrawQuad* quad,
    const gfx::QuadF* draw_region) const {
  DrawQuadParams params(
      target_to_device * quad->shared_quad_state->quad_to_target_transform,
      gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect),
      SkCanvas::kNone_QuadAAFlags, quad->shared_quad_state->blend_mode,
      quad->shared_quad_state->opacity, GetSampling(quad), draw_region);

  params.content_device_transform.FlattenTo2d();

  // Respect per-quad setting overrides as highest priority setting
  if (!IsAAForcedOff(quad)) {
    if (settings_->force_antialiasing) {
      // This setting makes the entire draw AA, so don't bother checking edges
      params.aa_flags = SkCanvas::kAll_QuadAAFlags;
    } else if (settings_->allow_antialiasing) {
      params.aa_flags = GetRectilinearEdgeFlags(quad);
      if (draw_region && params.aa_flags != SkCanvas::kNone_QuadAAFlags) {
        // Turn off interior edges' AA from the BSP splitting
        GetClippedEdgeFlags(quad, &params.aa_flags, &*params.draw_region);
      }
    }
  }

  if (!quad->ShouldDrawWithBlending()) {
    // The quad layer is src-over with 1.0 opacity and its needs_blending flag
    // has been set to false. However, even if the layer's opacity is 1.0, the
    // contents may not be (e.g. png or a color with alpha).
    if (quad->shared_quad_state->are_contents_opaque) {
      // Visually, this is the same as kSrc but Skia is faster with SrcOver
      params.blend_mode = SkBlendMode::kSrcOver;
    } else {
      // Replaces dst contents with the new color (e.g. no blending); this is
      // just as fast as srcover when there's no AA, but is slow when coverage
      // must be taken into account.
      params.blend_mode = SkBlendMode::kSrc;
    }
    params.opacity = 1.f;
  }

  params.ApplyScissor(this, quad, scissor_rect);

  // Determine final rounded rect clip geometry. We transform it from target
  // space to window space to make batching and canvas preparation easier
  // (otherwise we'd have to separate those two matrices in the CDT).
  if (ShouldApplyRoundedCorner(quad)) {
    // Transform by the window and projection matrix to go from target to
    // device space, which should always be a scale+translate.
    SkRRect corner_bounds = SkRRect(
        quad->shared_quad_state->mask_filter_info.rounded_corner_bounds());
    SkMatrix to_device;
    gfx::TransformToFlattenedSkMatrix(target_to_device, &to_device);

    // SkRRect::transform should always succeed here, since we know
    // corner_bounds is not empty and 'to_device' should just be scale+translate
    SkRRect device_bounds;
    if (corner_bounds.transform(to_device, &device_bounds)) {
      params.rounded_corner_bounds.emplace(device_bounds);
    } else {
      // TODO(crbug/1220004): We used to assert transform succeeded, but an
      // unreproduceable fuzzer test case could trip it. To be safe, and to
      // match the most likely scenario that the device transform has scale=0,
      // just force the clip to empty so we don't draw anything.
      params.rounded_corner_bounds.emplace(SkRRect::MakeEmpty());
    }
  }

  return params;
}

void SkiaRenderer::DrawQuadParams::ApplyScissor(
    const SkiaRenderer* renderer,
    const DrawQuad* quad,
    const gfx::Rect* scissor_to_apply) {
  // No scissor should have been set before calling ApplyScissor
  DCHECK(!scissor_rect.has_value());

  if (!scissor_to_apply) {
    // No scissor at all, which matches the DCHECK'ed state above
    return;
  }

  // Assume at start that the scissor will be applied through the canvas clip,
  // so that this can simply return when it detects the scissor cannot be
  // applied explicitly to |visible_rect|.
  scissor_rect = *scissor_to_apply;

  // PICTURE_CONTENT is not like the others, since it is executing a list of
  // draw calls into the canvas.
  if (quad->material == DrawQuad::Material::kPictureContent)
    return;
  // Intersection with scissor and a quadrilateral is not necessarily a quad,
  // so don't complicate things
  if (draw_region.has_value())
    return;

  // This is slightly different than
  // gfx::Transform::IsPositiveScaleAndTranslation in that it also allows zero
  // scales. This is because in the common orthographic case the z scale is 0.
  if (!content_device_transform.IsScaleOrTranslation() ||
      content_device_transform.matrix().get(0, 0) < 0.0f ||
      content_device_transform.matrix().get(1, 1) < 0.0f ||
      content_device_transform.matrix().get(2, 2) < 0.0f) {
    return;
  }

  // State check: should not have a CompositorRenderPassDrawQuad if we got here.
  DCHECK_NE(quad->material, DrawQuad::Material::kCompositorRenderPass);
  if (quad->material == DrawQuad::Material::kAggregatedRenderPass) {
    // If the renderpass has filters, the filters may modify the effective
    // geometry beyond the quad's visible_rect, so it's not safe to pre-clip.
    auto pass_id =
        AggregatedRenderPassDrawQuad::MaterialCast(quad)->render_pass_id;
    if (renderer->FiltersForPass(pass_id) ||
        renderer->BackdropFiltersForPass(pass_id))
      return;
  }

  // If the intersection of the scissor and the quad's visible_rect results in
  // subpixel device-space geometry, do not drop the scissor. Otherwise Skia
  // sees an unclipped anti-aliased hairline and uses different AA methods that
  // would cause the rasterized result to extend beyond the scissor.
  gfx::RectF device_bounds(visible_rect);
  content_device_transform.TransformRect(&device_bounds);
  device_bounds.Intersect(gfx::RectF(*scissor_rect));
  if (device_bounds.width() < 1.0f || device_bounds.height() < 1.0f) {
    return;
  }

  // The explicit scissor is applied in the quad's local space. If the transform
  // does not leave sufficient precision to round-trip the scissor rect to-from
  // device->local->device space, the explicitly "clipped" geometry does not
  // necessarily respect the original scissor.
  gfx::RectF local_scissor(*scissor_rect);
  content_device_transform.TransformRectReverse(&local_scissor);
  gfx::RectF remapped_scissor(local_scissor);
  content_device_transform.TransformRect(&remapped_scissor);
  if (gfx::ToRoundedRect(remapped_scissor) != *scissor_rect) {
    return;
  }

  // At this point, we've determined that we can transform the scissor rect into
  // the quad's local space and adjust |vis_rect|, such that when it's mapped to
  // device space, it will be contained in in the original scissor.
  // Applying the scissor explicitly means avoiding a clipRect() call and
  // allows more quads to be batched together in a DrawEdgeAAImageSet call
  float left_inset = local_scissor.x() - visible_rect.x();
  float top_inset = local_scissor.y() - visible_rect.y();
  float right_inset = visible_rect.right() - local_scissor.right();
  float bottom_inset = visible_rect.bottom() - local_scissor.bottom();

  // The scissor is a non-AA clip, so we unset the bit flag for clipped edges.
  if (left_inset >= kAAEpsilon) {
    aa_flags &= ~SkCanvas::kLeft_QuadAAFlag;
  } else {
    left_inset = 0;
  }
  if (top_inset >= kAAEpsilon) {
    aa_flags &= ~SkCanvas::kTop_QuadAAFlag;
  } else {
    top_inset = 0;
  }
  if (right_inset >= kAAEpsilon) {
    aa_flags &= ~SkCanvas::kRight_QuadAAFlag;
  } else {
    right_inset = 0;
  }
  if (bottom_inset >= kAAEpsilon) {
    aa_flags &= ~SkCanvas::kBottom_QuadAAFlag;
  } else {
    bottom_inset = 0;
  }

  visible_rect.Inset(left_inset, top_inset, right_inset, bottom_inset);
  vis_tex_coords = visible_rect;
  scissor_rect.reset();
}

const DrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(
    const AggregatedRenderPass* pass) {
  // If render pass bypassing is disabled for testing
  if (settings_->disable_render_pass_bypassing)
    return nullptr;

  // TODO(michaelludwig) - For now, this only supports opaque, src-over quads
  // with invertible transforms and simple content (image or color only).
  // Can only collapse a single tile quad.
  if (pass->quad_list.size() != 1)
    return nullptr;

  // If it there are supposed to be mipmaps, the renderpass must exist
  if (pass->generate_mipmap)
    return nullptr;

  const DrawQuad* quad = *pass->quad_list.BackToFrontBegin();
  // For simplicity in their draw implementations, debug borders, picture quads,
  // and nested render passes cannot bypass a render pass
  // (their draw functions do not accept DrawRPDQParams either).
  DCHECK_NE(quad->material, DrawQuad::Material::kCompositorRenderPass);
  if (quad->material == DrawQuad::Material::kAggregatedRenderPass ||
      quad->material == DrawQuad::Material::kDebugBorder ||
      quad->material == DrawQuad::Material::kPictureContent)
    return nullptr;

  // TODO(penghuang): support composite TileDrawQuad in a sub render pass for
  // raw draw directly.
  if (is_using_raw_draw_ && quad->material == DrawQuad::Material::kTiledContent)
    return nullptr;

  // If the quad specifies nearest-neighbor scaling then there could be two
  // scaling operations at different quality levels. This requires drawing to an
  // intermediate render pass. See https://crbug.com/1155338.
  if (UseNearestNeighborSampling(quad))
    return nullptr;

  if (quad->material == DrawQuad::Material::kTextureContent) {
    // Per-vertex opacities complicate bypassing the RP and alpha blending the
    // texture with image filters, so punt under that rare circumstance.
    const TextureDrawQuad* tex = TextureDrawQuad::MaterialCast(quad);
    if (tex->vertex_opacity[0] < 1.f || tex->vertex_opacity[1] < 1.f ||
        tex->vertex_opacity[2] < 1.f || tex->vertex_opacity[3] < 1.f) {
      return nullptr;
    }
  }

  // In order to concatenate the bypass'ed quads transform with RP itself, it
  // needs to be invertible.
  // TODO(michaelludwig) - See crbug.com/1175981 and crbug.com/1186657;
  // We can't use gfx::Transform.IsInvertible() since that checks the 4x4 matrix
  // and the rest of skia_renderer->Skia flattens to a 3x3 matrix, which can
  // change invertibility.
  SkMatrix flattened;
  gfx::TransformToFlattenedSkMatrix(
      quad->shared_quad_state->quad_to_target_transform,
      &flattened);
  if (!flattened.invert(nullptr))
    return nullptr;

  // A renderpass normally draws its content into a transparent destination,
  // using the quad's blend mode, then that result is later drawn into the
  // real dst with the RP's blend mode. In order to bypass the RP and draw
  // correctly, CalculateBypassParams must be able to reason about the quad's
  // blend mode.
  if (!IsPorterDuffBlendMode(quad->shared_quad_state->blend_mode))
    return nullptr;
  // All Porter-Duff blending with transparent black should fall into one of
  // these two categories:
  DCHECK(RenderPassPreservesContent(quad->shared_quad_state->blend_mode) ||
         RenderPassRemainsTransparent(quad->shared_quad_state->blend_mode));

  // The content must not have any rrect clipping, since skia_renderer applies
  // the rrect in device space, and in this case, the bypass quad's device space
  // is the RP's buffer.
  // TODO(michaelludwig) - If this becomes a bottleneck, we can track the
  // bypass rrect separately and update PrepareCanvasForRDQP to apply the
  // additional clip.
  if (ShouldApplyRoundedCorner(quad))
    return nullptr;

  // The quad type knows how to apply RPDQ filters, and the quad settings can
  // be merged into the RPDQs settings in CalculateBypassParams.
  return quad;
}

SkiaRenderer::BypassMode SkiaRenderer::CalculateBypassParams(
    const DrawQuad* bypass_quad,
    DrawRPDQParams* rpdq_params,
    DrawQuadParams* params) const {
  // Depending on bypass_quad's blend mode, its content may be irrelevant
  if (RenderPassRemainsTransparent(
          bypass_quad->shared_quad_state->blend_mode)) {
    // NOTE: this uses the pass's blend mode since this refers to the final draw
    // of the render pass itself
    if (TransparentBlackAffectsOutput(params->blend_mode)) {
      return BypassMode::kDrawTransparentQuad;
    } else {
      return BypassMode::kSkip;
    }
  }
  // If we made it here, the bypass blend mode would have just preserved the
  // bypass quad's content, so we can draw it directly using the render pass's
  // blend mode instead.
  DCHECK(
      RenderPassPreservesContent(bypass_quad->shared_quad_state->blend_mode));

  // The bypass quad will be drawn directly, so update |params| and
  // |rpdq_params| to reflect the change of coordinate system and merge settings
  // between the inner and outer quads.
  SkMatrix rpdq_to_bypass;
  SkMatrix bypass_to_rpdq;
  gfx::TransformToFlattenedSkMatrix(
      bypass_quad->shared_quad_state->quad_to_target_transform,
      &bypass_to_rpdq);
  bool inverted = bypass_to_rpdq.invert(&rpdq_to_bypass);
  // Invertibility was a requirement for being bypassable.
  DCHECK(inverted);

  if (params->draw_region) {
    // The draw region was determined by the RPDQ's geometry, so map the
    // quadrilateral to the bypass'ed quad's coordinate space so that BSP
    // splitting is still respected.
    rpdq_to_bypass.mapPoints(params->draw_region->points,
                             base::size(params->draw_region->points));
  }

  // Compute draw params for the bypass quad from scratch, but since the
  // bypass_quad would have originally been drawn into the RP, the
  // target_to_device transform is the full transform of the RPDQ. Must also
  // include the RP's output rect as part of the scissor rect, since it would
  // have been clipped to the edges of the RP's offscreen buffer normally.
  DrawQuadParams bypass_params = CalculateDrawQuadParams(
      gfx::Transform() /* identity */, nullptr, bypass_quad, nullptr);

  // |params| already holds the correct |draw_region|, but must be updated to
  // use the bypassed transform and geometry.
  rpdq_params->bypass_geometry = DrawRPDQParams::BypassGeometry{
      bypass_to_rpdq, params->rect, params->visible_rect};

  // NOTE: params |content_device_transform| remains that of the RPDQ to prepare
  // the canvas' CTM to match what any image filters require. The above
  // BypassGeometry::transform is then applied when drawing so that these
  // updated coordinates are correctly transformed to device space.
  params->visible_rect = bypass_params.visible_rect;
  params->vis_tex_coords = bypass_params.vis_tex_coords;

  // Combine anti-aliasing policy (use AND so that any draw_region clipping
  // is preserved).
  params->aa_flags &= bypass_params.aa_flags;

  // Blending will use the top-level RPDQ blend mode, but factor in the
  // content's opacity as well, since that would have normally been baked into
  // the RP's buffer.
  params->opacity *= bypass_params.opacity;

  // Take the highest quality filter, since this single draw will reflect the
  // filtering decisions made both when drawing into the RP and when drawing the
  // RP results itself. The ord() lambda simulates this notion of "highest" when
  // we used to use FilterQuality.
  auto ord = [](const SkSamplingOptions& sampling) {
    if (sampling.useCubic)
      return 3;
    if (sampling.mipmap != SkMipmapMode::kNone)
      return 2;
    return sampling.filter == SkFilterMode::kLinear ? 1 : 0;
  };

  if (ord(bypass_params.sampling) > ord(params->sampling))
    params->sampling = bypass_params.sampling;

  // Rounded corner bounds are in device space, which gets tricky when bypassing
  // the device that the RP would have represented
  DCHECK(!bypass_params.rounded_corner_bounds.has_value());
  return BypassMode::kDrawBypassQuad;
}

SkCanvas::ImageSetEntry SkiaRenderer::MakeEntry(
    const SkImage* image,
    int matrix_index,
    const DrawQuadParams& params) const {
  return SkCanvas::ImageSetEntry(
      {sk_ref_sp(image), gfx::RectFToSkRect(params.vis_tex_coords),
       gfx::RectFToSkRect(params.visible_rect), matrix_index, params.opacity,
       params.aa_flags, params.draw_region.has_value()});
}

SkCanvas::SrcRectConstraint SkiaRenderer::ResolveTextureConstraints(
    const SkImage* image,
    const gfx::RectF& valid_texel_bounds,
    DrawQuadParams* params) const {
  if (params->aa_flags == SkCanvas::kNone_QuadAAFlags &&
      params->sampling == SkSamplingOptions()) {
    // Non-AA and no bilinear filtering so rendering won't filter outside the
    // provided texture coordinates.
    return SkCanvas::kFast_SrcRectConstraint;
  }

  // Resolve texture coordinates against the valid content area of the image
  SkCanvas::SrcRectConstraint constraint =
      GetTextureConstraint(image, params->vis_tex_coords, valid_texel_bounds);

  // Skia clamps to the provided texture coordinates, not the content_area. If
  // there is a mismatch, have to update the draw params to account for the new
  // constraint
  if (constraint == SkCanvas::kFast_SrcRectConstraint ||
      valid_texel_bounds == params->vis_tex_coords) {
    return constraint;
  }

  // To get |valid_texel_bounds| as the constraint, it must be sent as the tex
  // coords. To draw the right shape, store |visible_rect| as the |draw_region|
  // and change the visible rect so that the mapping from |visible_rect| to
  // |valid_texel_bounds| causes |draw_region| to map to original
  // |vis_tex_coords|
  if (!params->draw_region) {
    params->draw_region.emplace(gfx::QuadF(params->visible_rect));
  }

  // Preserve the src-to-dst transformation for the padded texture coords
  SkMatrix src_to_dst =
      SkMatrix::RectToRect(gfx::RectFToSkRect(params->vis_tex_coords),
                           gfx::RectFToSkRect(params->visible_rect));
  params->visible_rect = gfx::SkRectToRectF(
      src_to_dst.mapRect(gfx::RectFToSkRect(valid_texel_bounds)));
  params->vis_tex_coords = valid_texel_bounds;

  return SkCanvas::kStrict_SrcRectConstraint;
}

bool SkiaRenderer::MustFlushBatchedQuads(const DrawQuad* new_quad,
                                         const DrawRPDQParams* rpdq_params,
                                         const DrawQuadParams& params) const {
  if (batched_quads_.empty())
    return false;

  // If |new_quad| is the bypass quad for a renderpass with filters, it must be
  // drawn by itself, regardless of if it could otherwise would've been batched.
  if (rpdq_params)
    return true;

  DCHECK_NE(new_quad->material, DrawQuad::Material::kCompositorRenderPass);
  if (new_quad->material != DrawQuad::Material::kAggregatedRenderPass &&
      new_quad->material != DrawQuad::Material::kStreamVideoContent &&
      new_quad->material != DrawQuad::Material::kTextureContent &&
      new_quad->material != DrawQuad::Material::kTiledContent)
    return true;

  if (batched_quad_state_.blend_mode != params.blend_mode ||
      batched_quad_state_.sampling != params.sampling)
    return true;

  if (batched_quad_state_.scissor_rect != params.scissor_rect) {
    return true;
  }

  if (batched_quad_state_.rounded_corner_bounds !=
      params.rounded_corner_bounds) {
    return true;
  }

  return false;
}

void SkiaRenderer::AddQuadToBatch(const SkImage* image,
                                  const gfx::RectF& valid_texel_bounds,
                                  DrawQuadParams* params) {
  SkCanvas::SrcRectConstraint constraint =
      ResolveTextureConstraints(image, valid_texel_bounds, params);
  // Last check for flushing the batch, since constraint can't be known until
  // the last minute.
  if (!batched_quads_.empty() && batched_quad_state_.constraint != constraint) {
    FlushBatchedQuads();
  }

  // Configure batch state if it's the first
  if (batched_quads_.empty()) {
    batched_quad_state_.scissor_rect = params->scissor_rect;
    batched_quad_state_.rounded_corner_bounds = params->rounded_corner_bounds;
    batched_quad_state_.blend_mode = params->blend_mode;
    batched_quad_state_.sampling = params->sampling;
    batched_quad_state_.constraint = constraint;
  }
  DCHECK(batched_quad_state_.constraint == constraint);

  // Add entry, with optional clip quad and shared transform
  if (params->draw_region) {
    for (const auto& point : params->draw_region->points) {
      batched_draw_regions_.push_back(point);
    }
  }

  SkMatrix m;
  gfx::TransformToFlattenedSkMatrix(params->content_device_transform, &m);
  std::vector<SkMatrix>& cdts = batched_cdt_matrices_;
  if (cdts.empty() || cdts[cdts.size() - 1] != m) {
    cdts.push_back(m);
  }
  int matrix_index = cdts.size() - 1;

  batched_quads_.push_back(MakeEntry(image, matrix_index, *params));
}

void SkiaRenderer::FlushBatchedQuads() {
  TRACE_EVENT0("viz", "SkiaRenderer::FlushBatchedQuads");

  SkAutoCanvasRestore acr(current_canvas_, true /* do_save */);
  PrepareCanvas(batched_quad_state_.scissor_rect,
                batched_quad_state_.rounded_corner_bounds, nullptr);

  SkPaint paint;
  sk_sp<SkColorFilter> color_filter = GetContentColorFilter();
  if (color_filter)
    paint.setColorFilter(color_filter);
  paint.setBlendMode(batched_quad_state_.blend_mode);

  current_canvas_->experimental_DrawEdgeAAImageSet(
      &batched_quads_.front(), batched_quads_.size(),
      batched_draw_regions_.data(), &batched_cdt_matrices_.front(),
      batched_quad_state_.sampling, &paint, batched_quad_state_.constraint);

  batched_quads_.clear();
  batched_draw_regions_.clear();
  batched_cdt_matrices_.clear();
}

void SkiaRenderer::DrawColoredQuad(SkColor color,
                                   const DrawRPDQParams* rpdq_params,
                                   DrawQuadParams* params) {
  DCHECK(batched_quads_.empty());
  TRACE_EVENT0("viz", "SkiaRenderer::DrawColoredQuad");

  SkAutoCanvasRestore acr(current_canvas_, true /* do_save */);
  PrepareCanvas(params->scissor_rect, params->rounded_corner_bounds,
                &params->content_device_transform);

  if (rpdq_params) {
    // This will modify the provided content color as needed for the RP effects,
    // or it will make an explicit save layer on the current canvas
    PrepareColorOrCanvasForRPDQ(*rpdq_params, params, &color);
    if (rpdq_params->bypass_geometry) {
      // Concatenate the bypass'ed quad's transform after all the RPDQ state
      // has been pushed to the canvas.
      current_canvas_->concat(rpdq_params->bypass_geometry->transform);
    }
  }

  sk_sp<SkColorFilter> color_filter = GetContentColorFilter();
  if (color_filter)
    color = color_filter->filterColor(color);
  // PrepareCanvasForRPDQ will have updated params->opacity and blend_mode to
  // account for the layer applying those effects.
  color = SkColorSetA(color, params->opacity * SkColorGetA(color));

  const SkPoint* draw_region =
      params->draw_region ? params->draw_region->points : nullptr;

  current_canvas_->experimental_DrawEdgeAAQuad(
      gfx::RectFToSkRect(params->visible_rect), draw_region,
      static_cast<SkCanvas::QuadAAFlags>(params->aa_flags),
      SkColor4f::FromColor(color), params->blend_mode);
}

void SkiaRenderer::DrawSingleImage(const SkImage* image,
                                   const gfx::RectF& valid_texel_bounds,
                                   const DrawRPDQParams* rpdq_params,
                                   SkPaint* paint,
                                   DrawQuadParams* params) {
  DCHECK(batched_quads_.empty());
  TRACE_EVENT0("viz", "SkiaRenderer::DrawSingleImage");

  SkAutoCanvasRestore acr(current_canvas_, true /* do_save */);
  PrepareCanvas(params->scissor_rect, params->rounded_corner_bounds,
                &params->content_device_transform);

  int matrix_index = -1;
  const SkMatrix* bypass_transform = nullptr;
  if (rpdq_params) {
    // This will modify the provided content paint as needed for the RP effects,
    // or it will make an explicit save layer on the current canvas
    PreparePaintOrCanvasForRPDQ(*rpdq_params, params, paint);
    if (rpdq_params->bypass_geometry) {
      // Incorporate the bypass transform, but unlike for solid color quads, do
      // not modify the SkCanvas's CTM. This is because the RPDQ's filters may
      // have been optimally placed on the SkPaint of the draw, which means the
      // canvas' transform must match that of the RenderPass. The pre-CTM matrix
      // of the image set entry can be used instead to modify the drawn geometry
      // without impacting the filter's coordinate space.
      bypass_transform = &rpdq_params->bypass_geometry->transform;
      matrix_index = 0;
    }
  }

  // At this point, the params' opacity should be handled by |paint| (either
  // as its alpha or in a color filter), or in an image filter from the RPDQ,
  // or in the saved layer for the RPDQ. Set opacity to 1 to ensure the image
  // set entry does not doubly-apply the opacity then.
  params->opacity = 1.f;

  SkCanvas::SrcRectConstraint constraint =
      ResolveTextureConstraints(image, valid_texel_bounds, params);

  // Use -1 for matrix index since the cdt is set on the canvas.
  SkCanvas::ImageSetEntry entry = MakeEntry(image, matrix_index, *params);
  const SkPoint* draw_region =
      params->draw_region ? params->draw_region->points : nullptr;
  current_canvas_->experimental_DrawEdgeAAImageSet(
      &entry, 1, draw_region, bypass_transform, params->sampling, paint,
      constraint);
}

void SkiaRenderer::DrawPaintOpBuffer(const cc::PaintOpBuffer* buffer,
                                     const absl::optional<SkColor>& clear_color,
                                     const TileDrawQuad* quad,
                                     const DrawQuadParams* params) {
  if (!batched_quads_.empty())
    FlushBatchedQuads();

  SkAutoCanvasRestore auto_canvas_restore(current_canvas_, true /* do_save */);
  PrepareCanvas(params->scissor_rect, params->rounded_corner_bounds,
                &params->content_device_transform);

  auto visible_rect = gfx::RectFToSkRect(params->visible_rect);
  current_canvas_->clipRect(visible_rect);

  if (params->draw_region) {
    bool aa = params->aa_flags != SkCanvas::kNone_QuadAAFlags;
    current_canvas_->clipPath(params->draw_region_in_path(), aa);
  }

  if (quad->ShouldDrawWithBlending()) {
    auto paint = params->paint(nullptr);
    // TODO(penghuang): saveLayer() is expensive, try to avoid it as much as
    // possible.
    current_canvas_->saveLayer(&visible_rect, &paint);
  }

  if (clear_color)
    current_canvas_->drawColor(*clear_color);

  float scale_x = params->rect.width() / quad->tex_coord_rect.width();
  float scale_y = params->rect.height() / quad->tex_coord_rect.height();

  float offset_x =
      params->visible_rect.x() - params->vis_tex_coords.x() * scale_x;
  float offset_y =
      params->visible_rect.y() - params->vis_tex_coords.y() * scale_y;

  current_canvas_->translate(offset_x, offset_y);
  current_canvas_->scale(scale_x, scale_y);

  cc::PlaybackParams playback_params(nullptr, SkM44());
  buffer->Playback(current_canvas_, playback_params);
}

void SkiaRenderer::DrawDebugBorderQuad(const DebugBorderDrawQuad* quad,
                                       DrawQuadParams* params) {
  DCHECK(batched_quads_.empty());

  SkAutoCanvasRestore acr(current_canvas_, true /* do_save */);
  // We need to apply the matrix manually to have pixel-sized stroke width.
  PrepareCanvas(params->scissor_rect, params->rounded_corner_bounds, nullptr);
  SkMatrix cdt;
  gfx::TransformToFlattenedSkMatrix(params->content_device_transform, &cdt);

  SkPath path = params->draw_region
                    ? params->draw_region_in_path()
                    : SkPath::Rect(gfx::RectFToSkRect(params->visible_rect));
  path.transform(cdt);

  SkPaint paint = params->paint(nullptr /* color_filter */);
  paint.setColor(quad->color);  // Must correct alpha afterwards
  paint.setAlphaf(params->opacity * paint.getAlphaf());
  paint.setStyle(SkPaint::kStroke_Style);
  paint.setStrokeJoin(SkPaint::kMiter_Join);
  paint.setStrokeWidth(quad->width);

  current_canvas_->drawPath(path, paint);
}

void SkiaRenderer::DrawPictureQuad(const PictureDrawQuad* quad,
                                   DrawQuadParams* params) {
  DCHECK(batched_quads_.empty());
  TRACE_EVENT0("viz", "SkiaRenderer::DrawPictureQuad");

  // If the layer is transparent or needs a non-SrcOver blend mode, saveLayer
  // must be used so that the display list is drawn into a transient image and
  // then blended as a single layer at the end.
  const bool needs_transparency =
      params->opacity < 1.f || params->blend_mode != SkBlendMode::kSrcOver;
  const bool disable_image_filtering = disable_picture_quad_image_filtering_ ||
                                       params->sampling == SkSamplingOptions();

  SkAutoCanvasRestore acr(current_canvas_, true /* do_save */);
  PrepareCanvas(params->scissor_rect, params->rounded_corner_bounds,
                &params->content_device_transform);

  // Unlike other quads which draw visible_rect or draw_region as their geometry
  // these represent the valid windows of content to show for the display list,
  // so they need to be used as a clip in Skia.
  SkRect visible_rect = gfx::RectFToSkRect(params->visible_rect);
  SkPaint paint = params->paint(GetContentColorFilter());

  if (params->draw_region) {
    current_canvas_->clipPath(params->draw_region_in_path(),
                              paint.isAntiAlias());
  } else {
    current_canvas_->clipRect(visible_rect, paint.isAntiAlias());
  }

  if (needs_transparency) {
    // Use the DrawQuadParams' paint for the layer, since that will affect the
    // final draw of the backing image.
    current_canvas_->saveLayer(&visible_rect, &paint);
  }

  SkCanvas* raster_canvas = current_canvas_;
  absl::optional<skia::OpacityFilterCanvas> opacity_canvas;
  if (disable_image_filtering) {
    // TODO(vmpstr): Fold this canvas into playback and have raster source
    // accept a set of settings on playback that will determine which canvas to
    // apply. (http://crbug.com/594679)
    // saveLayer applies the opacity, this filter is only used for quality
    // overriding in the display list, hence the fixed 1.f for alpha.
    opacity_canvas.emplace(raster_canvas, 1.f, disable_image_filtering);
    raster_canvas = &*opacity_canvas;
  }

  // Treat all subnormal values as zero for performance.
  cc::ScopedSubnormalFloatDisabler disabler;

  raster_canvas->concat(SkMatrix::RectToRect(
      gfx::RectFToSkRect(quad->tex_coord_rect), gfx::RectToSkRect(quad->rect)));

  raster_canvas->translate(-quad->content_rect.x(), -quad->content_rect.y());
  raster_canvas->clipRect(gfx::RectToSkRect(quad->content_rect));
  raster_canvas->scale(quad->contents_scale, quad->contents_scale);
  quad->display_item_list->Raster(raster_canvas);
}

void SkiaRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad,
                                      const DrawRPDQParams* rpdq_params,
                                      DrawQuadParams* params) {
  DrawColoredQuad(quad->color, rpdq_params, params);
}

void SkiaRenderer::DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
                                       const DrawRPDQParams* rpdq_params,
                                       DrawQuadParams* params) {
  DCHECK(!MustFlushBatchedQuads(quad, rpdq_params, *params));

  absl::optional<gfx::ColorSpace> override_color_space;

  // Force SRGB color space if we don't want real color space from media
  // decoder.
  if (!use_real_color_space_for_stream_video_) {
    override_color_space = gfx::ColorSpace::CreateSRGB();
  }

  ScopedSkImageBuilder builder(this, quad->resource_id(),
                               /*maybe_concurrent_reads=*/true,
                               kUnpremul_SkAlphaType, kTopLeft_GrSurfaceOrigin,
                               override_color_space);
  const SkImage* image = builder.sk_image();
  if (!image)
    return;

  gfx::RectF uv_rect = gfx::ScaleRect(
      gfx::BoundingRect(quad->uv_top_left, quad->uv_bottom_right),
      image->width(), image->height());
  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
      uv_rect, gfx::RectF(quad->rect), params->visible_rect);

  // Use provided resource size if not empty, otherwise use the full image size
  // as the content area
  gfx::RectF valid_texel_bounds =
      quad->resource_size_in_pixels().IsEmpty()
          ? gfx::RectF(image->width(), image->height())
          : gfx::RectF(gfx::SizeF(quad->resource_size_in_pixels()));

  if (rpdq_params) {
    SkPaint paint = params->paint(GetContentColorFilter());
    DrawSingleImage(image, valid_texel_bounds, rpdq_params, &paint, params);
  } else {
    AddQuadToBatch(image, valid_texel_bounds, params);
  }
}

void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad,
                                   const DrawRPDQParams* rpdq_params,
                                   DrawQuadParams* params) {
  const gfx::ColorSpace& src_color_space =
      resource_provider()->GetColorSpace(quad->resource_id());
  const bool needs_color_conversion_filter =
      quad->is_video_frame && src_color_space.IsHDR();

  absl::optional<gfx::ColorSpace> override_color_space;
  if (needs_color_conversion_filter)
    override_color_space = CurrentRenderPassColorSpace();

  ScopedSkImageBuilder builder(
      this, quad->resource_id(), /*maybe_concurrent_reads=*/true,
      quad->premultiplied_alpha ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
      quad->y_flipped ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin,
      override_color_space);
  const SkImage* image = builder.sk_image();
  if (!image)
    return;
  gfx::RectF uv_rect = gfx::ScaleRect(
      gfx::BoundingRect(quad->uv_top_left, quad->uv_bottom_right),
      image->width(), image->height());
  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
      uv_rect, gfx::RectF(quad->rect), params->visible_rect);

  // Use provided resource size if not empty, otherwise use the full image size
  // as the content area
  gfx::RectF valid_texel_bounds =
      quad->resource_size_in_pixels().IsEmpty()
          ? gfx::RectF(image->width(), image->height())
          : gfx::RectF(gfx::SizeF(quad->resource_size_in_pixels()));

  // There are three scenarios where a texture quad cannot be put into a batch:
  // 1. It needs to be blended with a constant background color.
  // 2. The vertex opacities are not all 1s.
  // 3. The quad contains video which might need special white level adjustment.
  const bool blend_background =
      quad->background_color != SK_ColorTRANSPARENT && !image->isOpaque();
  const bool vertex_alpha =
      quad->vertex_opacity[0] < 1.f || quad->vertex_opacity[1] < 1.f ||
      quad->vertex_opacity[2] < 1.f || quad->vertex_opacity[3] < 1.f;

  if (!blend_background && !vertex_alpha && !needs_color_conversion_filter &&
      !rpdq_params) {
    // This is a simple texture draw and can go into the batching system
    DCHECK(!MustFlushBatchedQuads(quad, rpdq_params, *params));
    AddQuadToBatch(image, valid_texel_bounds, params);
    return;
  }
  // This needs a color filter for background blending and/or a mask filter
  // to simulate the vertex opacity, which requires configuring a full SkPaint
  // and is incompatible with anything batched, but since MustFlushBatchedQuads
  // was optimistic for TextureQuad's, we're responsible for flushing now.
  if (!batched_quads_.empty())
    FlushBatchedQuads();

  SkPaint paint = params->paint(GetContentColorFilter());

  float quad_alpha;
  if (rpdq_params) {
    // The added color filters for background blending will not apply the
    // layer's opacity, but make sure there's no vertex_alpha since
    // CanPassBeDrawnDirectly() should have caught that case.
    DCHECK(!vertex_alpha);
    quad_alpha = 1.f;
  } else {
    // We will entirely handle the quad's opacity with the mask or color filter
    quad_alpha = params->opacity;
    params->opacity = 1.f;
  }

  if (vertex_alpha) {
    // If they are all the same value, combine it with the overall opacity,
    // otherwise use a mask filter to emulate vertex opacity interpolation
    if (quad->vertex_opacity[0] == quad->vertex_opacity[1] &&
        quad->vertex_opacity[0] == quad->vertex_opacity[2] &&
        quad->vertex_opacity[0] == quad->vertex_opacity[3]) {
      quad_alpha *= quad->vertex_opacity[0];
    } else {
      // The only occurrences of non-constant vertex opacities come from unit
      // tests and src/chrome/browser/android/compositor/decoration_title.cc,
      // but they always produce the effect of a linear alpha gradient.
      // All signs indicate point order is [BL, TL, TR, BR]
      SkPoint gradient_pts[2];
      if (quad->vertex_opacity[0] == quad->vertex_opacity[1] &&
          quad->vertex_opacity[2] == quad->vertex_opacity[3]) {
        // Left to right gradient
        float y =
            params->visible_rect.y() + 0.5f * params->visible_rect.height();
        gradient_pts[0] = {params->visible_rect.x(), y};
        gradient_pts[1] = {params->visible_rect.right(), y};
      } else if (quad->vertex_opacity[0] == quad->vertex_opacity[3] &&
                 quad->vertex_opacity[1] == quad->vertex_opacity[2]) {
        // Top to bottom gradient
        float x =
            params->visible_rect.x() + 0.5f * params->visible_rect.width();
        gradient_pts[0] = {x, params->visible_rect.y()};
        gradient_pts[1] = {x, params->visible_rect.bottom()};
      } else {
        // Not sure how to emulate
        NOTIMPLEMENTED();
        return;
      }

      float a1 = quad->vertex_opacity[0] * quad_alpha;
      float a2 = quad->vertex_opacity[2] * quad_alpha;
      SkColor gradient_colors[2] = {SkColor4f({a1, a1, a1, a1}).toSkColor(),
                                    SkColor4f({a2, a2, a2, a2}).toSkColor()};
      sk_sp<SkShader> gradient = SkGradientShader::MakeLinear(
          gradient_pts, gradient_colors, nullptr, 2, SkTileMode::kClamp);
      paint.setMaskFilter(SkShaderMaskFilter::Make(std::move(gradient)));
      // shared quad opacity was folded into the gradient, so this will shorten
      // any color filter chain needed for background blending
      quad_alpha = 1.f;
    }
  }

  // From gl_renderer, the final src color will be
  // vertexAlpha * (textureColor + backgroundColor * (1 - textureAlpha)), where
  // vertexAlpha is the quad's alpha * interpolated per-vertex alpha
  if (blend_background) {
    // Add a color filter that does DstOver blending between texture and the
    // background color. Then, modulate by quad's opacity *after* blending.
    sk_sp<SkColorFilter> cf =
        SkColorFilters::Blend(quad->background_color, SkBlendMode::kDstOver);
    if (quad_alpha < 1.f) {
      cf = MakeOpacityFilter(quad_alpha, std::move(cf));
      quad_alpha = 1.f;
      DCHECK(cf);
    }
    // |cf| could be null if alpha in |quad->background_color| is 0.
    if (cf)
      paint.setColorFilter(cf->makeComposed(paint.refColorFilter()));
  }

  if (needs_color_conversion_filter) {
    // Skia won't perform color conversion.
    const gfx::ColorSpace dst_color_space = CurrentRenderPassColorSpace();
    DCHECK(SkColorSpace::Equals(image->colorSpace(),
                                dst_color_space.ToSkColorSpace().get()));
    sk_sp<SkColorFilter> color_filter =
        GetColorSpaceConversionFilter(src_color_space, dst_color_space);
    paint.setColorFilter(color_filter->makeComposed(paint.refColorFilter()));
  }

  if (!rpdq_params) {
    // Reset the paint's alpha, since it started as params.opacity and that
    // is now applied outside of the paint's alpha.
    paint.setAlphaf(quad_alpha);
  }

  DrawSingleImage(image, valid_texel_bounds, rpdq_params, &paint, params);
}

void SkiaRenderer::DrawTileDrawQuad(const TileDrawQuad* quad,
                                    const DrawRPDQParams* rpdq_params,
                                    DrawQuadParams* params) {
  DCHECK(!MustFlushBatchedQuads(quad, rpdq_params, *params));
  // |resource_provider()| can be NULL in resourceless software draws, which
  // should never produce tile quads in the first place.
  DCHECK(resource_provider());

  // If quad->ShouldDrawWithBlending() is true, we need to raster tile paint ops
  // to an offscreen texture first, and then blend it with content behind the
  // tile. Since a tile could be used cross frames, so it would better to not
  // use raw draw.
  bool raw_draw_if_possible =
      is_using_raw_draw_ && !quad->ShouldDrawWithBlending();
  ScopedSkImageBuilder builder(
      this, quad->resource_id(), /*maybe_concurrent_reads=*/false,
      quad->is_premultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
      /*origin=*/kTopLeft_GrSurfaceOrigin,
      /*override_colorspace=*/absl::nullopt, raw_draw_if_possible);

  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
      quad->tex_coord_rect, gfx::RectF(quad->rect), params->visible_rect);

  bool translate_only = params->content_device_transform.matrix().isTranslate();
  UMA_HISTOGRAM_BOOLEAN(
      "Compositing.SkiaRenderer.DrawTileDrawQuad.CDT.IsTranslateOnly",
      translate_only);
  if (builder.paint_op_buffer()) {
    DCHECK(!rpdq_params);
    DrawPaintOpBuffer(builder.paint_op_buffer(), builder.clear_color(), quad,
                      params);
    return;
  }

  const SkImage* image = builder.sk_image();
  if (!image)
    return;

  // When a tile is at the right or bottom edge of the entire tiled area, its
  // images won't be fully filled so use the unclipped texture coords. On
  // interior tiles or left/top tiles, the image has been filled with
  // overlapping content so the entire image is valid for sampling.
  gfx::RectF valid_texel_bounds(gfx::SizeF(quad->texture_size));
  if (quad->IsRightEdge()) {
    // Restrict the width to match far side of texture coords
    valid_texel_bounds.set_width(quad->tex_coord_rect.right());
  }
  if (quad->IsBottomEdge()) {
    // Restrict the height to match far side of texture coords
    valid_texel_bounds.set_height(quad->tex_coord_rect.bottom());
  }

  if (rpdq_params) {
    SkPaint paint = params->paint(GetContentColorFilter());
    DrawSingleImage(image, valid_texel_bounds, rpdq_params, &paint, params);
  } else {
    AddQuadToBatch(image, valid_texel_bounds, params);
  }
}

void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad,
                                    const DrawRPDQParams* rpdq_params,
                                    DrawQuadParams* params) {
  // Since YUV quads always use a color filter, they require a complex skPaint
  // that precludes batching. If this changes, we could add YUV quads that don't
  // require a filter to the batch instead of drawing one at a time.
  DCHECK(batched_quads_.empty());

  gfx::ColorSpace src_color_space = quad->video_color_space;
  // Invalid or unspecified color spaces should be treated as REC709.
  if (!src_color_space.IsValid())
    src_color_space = gfx::ColorSpace::CreateREC709();

  // We might modify |dst_color_space| to be something other than the
  // destination color space for the frame. The generated SkColorFilter does the
  // real color space adjustment. To avoid having skia also try to adjust the
  // color space we lie and say the SkImage destination color space is always
  // the same as the rest of the frame. Otherwise the two color space
  // adjustments combined will produce the wrong result.
  const gfx::ColorSpace& frame_color_space = CurrentRenderPassColorSpace();
  gfx::ColorSpace dst_color_space = frame_color_space;

#if BUILDFLAG(IS_WIN)
  // Force sRGB output on Windows for overlay candidate video quads to match
  // DirectComposition behavior in case these switch between overlays and
  // compositing. See https://crbug.com/811118 for details.
  // Currently if HDR is supported, OverlayProcessor doesn't promote HDR video
  // frame as overlay candidate. So it's unnecessary to worry about the
  // compositing-overlay switch here. In addition drawing a HDR video using sRGB
  // can cancel the advantages of HDR.
  const bool supports_dc_layers =
      output_surface_->capabilities().supports_dc_layers;
  if (supports_dc_layers && !src_color_space.IsHDR() &&
      resource_provider()->IsOverlayCandidate(quad->y_plane_resource_id())) {
    DCHECK(
        resource_provider()->IsOverlayCandidate(quad->u_plane_resource_id()));
    dst_color_space = gfx::ColorSpace::CreateSRGB();
  }
#endif

  DCHECK(resource_provider());
  // Pass in |frame_color_space| here instead of |dst_color_space| so the color
  // space transform going from SkImage to SkSurface is identity. The
  // SkColorFilter already handles color space conversion so this avoids
  // applying the conversion twice.
  ScopedYUVSkImageBuilder builder(this, quad,
                                  frame_color_space.ToSkColorSpace());
  const SkImage* image = builder.sk_image();
  if (!image)
    return;

  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
      quad->ya_tex_coord_rect, gfx::RectF(quad->rect), params->visible_rect);

  sk_sp<SkColorFilter> color_filter = GetColorSpaceConversionFilter(
      src_color_space, dst_color_space, quad->resource_offset,
      quad->resource_multiplier);

  auto content_color_filter = GetContentColorFilter();
  if (content_color_filter)
    color_filter = content_color_filter->makeComposed(color_filter);

  // Use provided, unclipped texture coordinates as the content area, which will
  // force coord clamping unless the geometry was clipped, or they span the
  // entire YUV image.
  SkPaint paint = params->paint(color_filter);

  DrawSingleImage(image, quad->ya_tex_coord_rect, rpdq_params, &paint, params);
}

void SkiaRenderer::DrawUnsupportedQuad(const DrawQuad* quad,
                                       const DrawRPDQParams* rpdq_params,
                                       DrawQuadParams* params) {
#ifdef NDEBUG
  DrawColoredQuad(SK_ColorWHITE, rpdq_params, params);
#else
  DrawColoredQuad(SK_ColorMAGENTA, rpdq_params, params);
#endif
}

void SkiaRenderer::ScheduleOverlays() {
  DCHECK(!current_frame_resource_fence_->WasSet());

  pending_overlay_locks_.emplace_back();
  if (current_frame()->overlay_list.empty())
    return;

  std::vector<gpu::SyncToken> sync_tokens;

#if !BUILDFLAG(IS_WIN)
  DCHECK(output_surface_->capabilities().supports_surfaceless);
#endif

#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
  // CrOS and Android SurfaceControl use this code path. Android classic has
  // switched over to OverlayProcessor.
  // TODO(weiliangc): Remove this when CrOS and Android SurfaceControl switch
  // to OverlayProcessor as well.
  auto& locks = pending_overlay_locks_.back();
  for (auto& overlay : current_frame()->overlay_list) {
    // Resources will be unlocked after the next SwapBuffers() is completed.
    locks.emplace_back(resource_provider(), overlay.resource_id);
    auto& lock = locks.back();

    // Sync tokens ensure the texture to be overlaid is available before
    // scheduling it for display.
    if (lock.sync_token().HasData())
      sync_tokens.push_back(lock.sync_token());

    overlay.mailbox = lock.mailbox();
    DCHECK(!overlay.mailbox.IsZero());
  }
#elif BUILDFLAG(IS_WIN)
  auto& locks = pending_overlay_locks_.back();
  for (auto& dc_layer_overlay : current_frame()->overlay_list) {
    for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) {
      ResourceId resource_id = dc_layer_overlay.resources[i];
      if (resource_id == kInvalidResourceId)
        break;

      // Resources will be unlocked after the next SwapBuffers() is completed.
      locks.emplace_back(resource_provider(), resource_id);
      auto& lock = locks.back();

      // Sync tokens ensure the texture to be overlaid is available before
      // scheduling it for display.
      if (lock.sync_token().HasData())
        sync_tokens.push_back(lock.sync_token());

      dc_layer_overlay.mailbox[i] = lock.mailbox();
    }
    DCHECK(!dc_layer_overlay.mailbox[0].IsZero());
  }
#elif BUILDFLAG(IS_APPLE)
  auto& locks = pending_overlay_locks_.back();
  for (CALayerOverlay& ca_layer_overlay : current_frame()->overlay_list) {
    if (ca_layer_overlay.rpdq) {
      PrepareRenderPassOverlay(&ca_layer_overlay);
      continue;
    }
    // Some overlays are for solid-color layers.
    if (!ca_layer_overlay.contents_resource_id)
      continue;

    // TODO(https://crbug.com/894929): Track IOSurface in-use instead of just
    // unlocking after the next SwapBuffers is completed.
    locks.emplace_back(resource_provider(),
                       ca_layer_overlay.contents_resource_id);
    auto& lock = locks.back();

    // Sync tokens ensure the texture to be overlaid is available before
    // scheduling it for display.
    if (lock.sync_token().HasData())
      sync_tokens.push_back(lock.sync_token());

    // Populate the |mailbox| of the CALayerOverlay which will be used to look
    // up the corresponding GLImageIOSurface when building the CALayer tree.
    ca_layer_overlay.mailbox = lock.mailbox();
    DCHECK(!ca_layer_overlay.mailbox.IsZero());
  }
#elif defined(USE_OZONE)
  // Only Wayland uses this code path.
  auto& locks = pending_overlay_locks_.back();
  for (auto& overlay : current_frame()->overlay_list) {
    if (overlay.rpdq) {
      PrepareRenderPassOverlay(&overlay);
      // The output will be attached via mailbox when overlays are scheduled.
      continue;
    }
    // Solid Color quads do not have associated resource buffers.
    if (overlay.solid_color.has_value())
      continue;

    // Resources will be unlocked after the next SwapBuffers() is completed.
    locks.emplace_back(resource_provider(), overlay.resource_id);
    auto& lock = locks.back();

    // Sync tokens ensure the texture to be overlaid is available before
    // scheduling it for display.
    if (lock.sync_token().HasData())
      sync_tokens.push_back(lock.sync_token());

    overlay.mailbox = lock.mailbox();
    DCHECK(!overlay.mailbox.IsZero());
  }
#else   // BUILDFLAG(IS_ANDROID)
  // For platforms that don't support overlays, the
  // current_frame()->overlay_list should be empty, and this code should not be
  // reached.
  NOTREACHED();
#endif  // BUILDFLAG(IS_ANDROID)

  base::OnceClosure on_finished_callback;
  if (current_frame_resource_fence_->WasSet()) {
    on_finished_callback = base::BindOnce(
        &FrameResourceFence::Signal, std::move(current_frame_resource_fence_));
    current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>();
    resource_provider()->SetReadLockFence(current_frame_resource_fence_.get());
  }

  skia_output_surface_->ScheduleOverlays(
      std::move(current_frame()->overlay_list), std::move(sync_tokens),
      std::move(on_finished_callback));
}

sk_sp<SkColorFilter> SkiaRenderer::GetColorSpaceConversionFilter(
    const gfx::ColorSpace& src,
    const gfx::ColorSpace& dst,
    float resource_offset,
    float resource_multiplier) {
  // If the input color space is HDR, and it did not specify a white level,
  // override it with the frame's white level.
  gfx::ColorSpace adjusted_src = src.GetWithSDRWhiteLevel(
      current_frame()->display_color_spaces.GetSDRMaxLuminanceNits());

  ColorFilterCacheKey key;
  key.src = src;
  key.dst = dst;
  key.resource_offset = resource_offset;
  key.resource_multiplier = resource_multiplier;
  key.sdr_max_luminance_nits =
      current_frame()->display_color_spaces.GetSDRMaxLuminanceNits();
  key.dst_max_luminance_relative =
      current_frame()->display_color_spaces.GetHDRMaxLuminanceRelative();
  sk_sp<SkRuntimeEffect>& effect = color_filter_cache_[key];
  if (!effect) {
    gfx::ColorTransform::Options options;
    options.sdr_max_luminance_nits = key.sdr_max_luminance_nits;
    options.dst_max_luminance_relative = key.dst_max_luminance_relative;
    std::unique_ptr<gfx::ColorTransform> transform =
        gfx::ColorTransform::NewColorTransform(adjusted_src, dst, options);

    const char* hdr = R"(
uniform half offset;
uniform half multiplier;

half4 main(half4 color) {
  // un-premultiply alpha
  if (color.a > 0)
    color.rgb /= color.a;

  color.rgb -= offset;
  color.rgb *= multiplier;
)";
    const char* ftr = R"(
  // premultiply alpha
  color.rgb *= color.a;
  return color;
}
)";

    std::string shader = hdr + transform->GetSkShaderSource() + ftr;

    auto result = SkRuntimeEffect::MakeForColorFilter(
        SkString(shader.c_str(), shader.size()),
        /*options=*/{});
    DCHECK(result.effect) << std::endl
                          << result.errorText.c_str() << "\n\nShader Source:\n"
                          << shader;
    effect = result.effect;
  }

  YUVInput input;
  input.offset = resource_offset;
  input.multiplier = resource_multiplier;
  sk_sp<SkData> data = SkData::MakeWithCopy(&input, sizeof(input));

  return effect->makeColorFilter(std::move(data));
}

namespace {
SkColorMatrix ToColorMatrix(const skia::Matrix44& mat) {
  std::array<float, 20> values;
  values.fill(0.0f);
  for (uint32_t r = 0; r < 4; r++) {
    for (uint32_t c = 0; c < 4; c++) {
      values[r * 5 + c] = mat.getFloat(r, c);
    }
  }
  SkColorMatrix mat_out;
  mat_out.setRowMajor(values.data());
  return mat_out;
}
}  // namespace

sk_sp<SkColorFilter> SkiaRenderer::GetContentColorFilter() {
  sk_sp<SkColorFilter> color_transform = nullptr;
  if (current_canvas_ == root_canvas_ &&
      !output_surface_->color_matrix().isIdentity()) {
    color_transform =
        SkColorFilters::Matrix(ToColorMatrix(output_surface_->color_matrix()));
  }

  sk_sp<SkColorFilter> tint_transform = nullptr;
  if (current_canvas_ == root_canvas_ &&
      debug_settings_->tint_composited_content) {
    if (debug_settings_->tint_composited_content_modulate) {
      // Integer counter causes modulation through rgb dimming variations.
      std::array<float, 3> rgb;
      uint32_t ci = debug_tint_modulate_count_ % 7u;
      for (int rc = 0; rc < 3; rc++) {
        rgb[rc] = (ci & (1u << rc)) ? 0.7f : 1.0f;
      }
      SkColorMatrix color_mat;
      color_mat.setScale(rgb[0], rgb[1], rgb[2]);
      tint_transform = SkColorFilters::Matrix(color_mat);
    } else {
      skia::Matrix44 mat44;
      mat44.setColMajorf(
          cc::DebugColors::TintCompositedContentColorTransformMatrix().data());
      tint_transform = SkColorFilters::Matrix(ToColorMatrix(mat44));
    }
  }

  if (color_transform) {
    return tint_transform ? color_transform->makeComposed(tint_transform)
                          : color_transform;
  } else {
    return tint_transform;
  }
}

SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
    const AggregatedRenderPassDrawQuad* quad,
    DrawQuadParams* params) {
  DrawRPDQParams rpdq_params(params->visible_rect);

  // Prepare mask.
  ResourceId mask_resource_id = quad->mask_resource_id();
  ScopedSkImageBuilder mask_image_builder(this, mask_resource_id,
                                          /*maybe_concurrent_reads=*/false);
  const SkImage* mask_image = mask_image_builder.sk_image();
  DCHECK_EQ(!!mask_resource_id, !!mask_image);
  if (mask_image) {
    // Scale normalized uv rect into absolute texel coordinates.
    SkRect mask_rect = gfx::RectFToSkRect(
        gfx::ScaleRect(quad->mask_uv_rect, quad->mask_texture_size.width(),
                       quad->mask_texture_size.height()));
    // Map to full quad rect so that mask coordinates don't change with clipping
    SkMatrix mask_to_quad_matrix =
        SkMatrix::RectToRect(mask_rect, gfx::RectToSkRect(quad->rect));

    rpdq_params.mask_shader = mask_image->makeShader(
        SkTileMode::kClamp, SkTileMode::kClamp,
        SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
        &mask_to_quad_matrix);
  }

  const cc::FilterOperations* filters = FiltersForPass(quad->render_pass_id);
  const cc::FilterOperations* backdrop_filters =
      BackdropFiltersForPass(quad->render_pass_id);
  // Early out if there are no filters to convert to SkImageFilters
  if (!filters && !backdrop_filters) {
    return rpdq_params;
  }

  // Calculate local matrix that's shared by filters and backdrop_filters
  SkMatrix local_matrix;
  local_matrix.setTranslate(quad->filters_origin.x(), quad->filters_origin.y());
  local_matrix.postScale(quad->filters_scale.x(), quad->filters_scale.y());

  gfx::SizeF filter_size(quad->rect.width(), quad->rect.height());

  // Convert CC image filters into a SkImageFilter root node
  if (filters) {
    DCHECK(!filters->IsEmpty());
    auto paint_filter =
        cc::RenderSurfaceFilters::BuildImageFilter(*filters, filter_size);
    auto sk_filter = paint_filter ? paint_filter->cached_sk_filter_ : nullptr;

    if (sk_filter) {
      // Update the filter bounds based to account for how the image filters
      // grow or expand the area touched by drawing.
      rpdq_params.filter_bounds =
          filters->MapRect(rpdq_params.filter_bounds, local_matrix);

      // If after applying the filter we would be clipped out, skip the draw.
      gfx::Rect clip_rect =
          quad->shared_quad_state->clip_rect.value_or(current_draw_rect_);
      gfx::Transform transform =
          quad->shared_quad_state->quad_to_target_transform;
      transform.FlattenTo2d();
      if (!transform.IsInvertible()) {
        return rpdq_params;
      }

      // If the transform has perspective, there might be visible content
      // outside of the bounds of the quad.
      if (!transform.HasPerspective()) {
        gfx::QuadF clip_quad = gfx::QuadF(gfx::RectF(clip_rect));
        gfx::QuadF local_clip =
            cc::MathUtil::InverseMapQuadToLocalSpace(transform, clip_quad);

        rpdq_params.filter_bounds.Intersect(
            gfx::ToEnclosingRect(local_clip.BoundingBox()));
      }

      // If we've been fully clipped out (by crop rect or clipping), there's
      // nothing to draw.
      if (rpdq_params.filter_bounds.IsEmpty()) {
        return rpdq_params;
      }

      rpdq_params.image_filter = sk_filter->makeWithLocalMatrix(local_matrix);

      // Attempt to simplify the image filter to a color filter, which enables
      // the RPDQ effects to be applied more efficiently.
      SkColorFilter* color_filter_ptr = nullptr;
      if (rpdq_params.image_filter) {
        if (rpdq_params.image_filter->asAColorFilter(&color_filter_ptr)) {
          // asAColorFilter already ref'ed the filter when true is returned,
          // reset() does not add a ref itself, so everything is okay.
          rpdq_params.color_filter.reset(color_filter_ptr);
        }
      }
    }
  }

  // Convert CC image filters for the backdrop into a SkImageFilter root node
  // TODO(weiliangc): ChromeOS would need backdrop_filter_quality implemented
  if (backdrop_filters) {
    DCHECK(!backdrop_filters->IsEmpty());

    // Must account for clipping that occurs for backdrop filters, since their
    // input content has already been clipped to the output rect.
    gfx::Rect device_rect = gfx::ToEnclosingRect(cc::MathUtil::MapClippedRect(
        params->content_device_transform, gfx::RectF(quad->rect)));
    gfx::Rect out_rect = MoveFromDrawToWindowSpace(
        current_frame()->current_render_pass->output_rect);
    out_rect.Intersect(device_rect);
    gfx::Vector2dF offset =
        (device_rect.top_right() - out_rect.top_right()) +
        (device_rect.bottom_left() - out_rect.bottom_left());

    auto bg_paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
        *backdrop_filters, gfx::SizeF(out_rect.size()), offset);
    auto sk_bg_filter =
        bg_paint_filter ? bg_paint_filter->cached_sk_filter_ : nullptr;

    if (sk_bg_filter) {
      rpdq_params.backdrop_filter =
          sk_bg_filter->makeWithLocalMatrix(local_matrix);
    }
  }

  // Determine if the backdrop filter has its own clip (which only needs to be
  // checked when we have a backdrop filter to apply)
  if (rpdq_params.backdrop_filter) {
    const absl::optional<gfx::RRectF> backdrop_filter_bounds =
        BackdropFilterBoundsForPass(quad->render_pass_id);
    if (backdrop_filter_bounds) {
      // The backdrop filters effect will be cropped by these bounds. If the
      // bounds are empty, discard the backdrop filter now since none of it
      // would have been visible anyways.
      if (backdrop_filter_bounds->IsEmpty()) {
        rpdq_params.backdrop_filter = nullptr;
      } else {
        rpdq_params.backdrop_filter_bounds = *backdrop_filter_bounds;
        // Scale by the filter's scale, but don't apply filter origin
        rpdq_params.backdrop_filter_bounds->Scale(quad->filters_scale.x(),
                                                  quad->filters_scale.y());

        // If there are also regular image filters, they apply to the area of
        // the backdrop_filter_bounds too, so expand the backdrop bounds and
        // join it with the main filter bounds.
        if (rpdq_params.image_filter) {
          gfx::Rect backdrop_rect =
              gfx::ToEnclosingRect(rpdq_params.backdrop_filter_bounds->rect());
          rpdq_params.filter_bounds.Union(
              filters->MapRect(backdrop_rect, local_matrix));
        }
      }
    }
  }

  return rpdq_params;
}

void SkiaRenderer::DrawRenderPassQuad(const AggregatedRenderPassDrawQuad* quad,
                                      DrawQuadParams* params) {
  DrawRPDQParams rpdq_params = CalculateRPDQParams(quad, params);

  // |filter_bounds| is the content space bounds that includes any filtered
  // extents. If empty, the draw can be skipped.
  if (rpdq_params.filter_bounds.IsEmpty())
    return;

  auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id);
  // When Render Pass has a single quad inside we would draw that directly.
  if (bypass != render_pass_bypass_quads_.end()) {
    BypassMode mode =
        CalculateBypassParams(bypass->second, &rpdq_params, params);
    if (mode == BypassMode::kDrawTransparentQuad) {
      // The RPDQ is masquerading as a solid color quad, which do not support
      // batching.
      if (!batched_quads_.empty())
        FlushBatchedQuads();
      DrawColoredQuad(SK_ColorTRANSPARENT, &rpdq_params, params);
    } else if (mode == BypassMode::kDrawBypassQuad) {
      DrawQuadInternal(bypass->second, &rpdq_params, params);
    }  // else mode == kSkip
    return;
  }

  // A real render pass that was turned into an image
  auto iter = render_pass_backings_.find(quad->render_pass_id);
  DCHECK(render_pass_backings_.end() != iter);
  // This function is called after AllocateRenderPassResourceIfNeeded, so
  // there should be backing ready.
  RenderPassBacking& backing = iter->second;

  sk_sp<SkImage> content_image =
      skia_output_surface_->MakePromiseSkImageFromRenderPass(
          quad->render_pass_id, backing.size, backing.format,
          backing.generate_mipmap, backing.color_space.ToSkColorSpace(),
          backing.mailbox);
  DLOG_IF(ERROR, !content_image)
      << "MakePromiseSkImageFromRenderPass() failed for render pass";

  if (!content_image)
    return;

  if (backing.generate_mipmap)
    params->sampling =
        SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);

  params->vis_tex_coords = cc::MathUtil::ScaleRectProportional(
      quad->tex_coord_rect, gfx::RectF(quad->rect), params->visible_rect);
  gfx::RectF valid_texel_bounds(content_image->width(),
                                content_image->height());

  // When the RPDQ was needed because of a copy request, it may not require any
  // advanced filtering/effects at which point it's basically a tiled quad.
  if (!rpdq_params.image_filter && !rpdq_params.backdrop_filter &&
      !rpdq_params.mask_shader) {
    DCHECK(!MustFlushBatchedQuads(quad, nullptr, *params));
    AddQuadToBatch(content_image.get(), valid_texel_bounds, params);
    return;
  }

  // The paint is complex enough that it has to be drawn on its own, and since
  // MustFlushBatchedQuads() was optimistic, we manage the flush here.
  if (!batched_quads_.empty())
    FlushBatchedQuads();

  SkPaint paint = params->paint(GetContentColorFilter());

  DrawSingleImage(content_image.get(), valid_texel_bounds, &rpdq_params, &paint,
                  params);
}

void SkiaRenderer::CopyDrawnRenderPass(
    const copy_output::RenderPassGeometry& geometry,
    std::unique_ptr<CopyOutputRequest> request) {
  // TODO(weiliangc): Make copy request work. (crbug.com/644851)
  TRACE_EVENT0("viz", "SkiaRenderer::CopyDrawnRenderPass");

  // Root framebuffer uses id 0 in SkiaOutputSurface.
  AggregatedRenderPassId render_pass_id;
  gpu::Mailbox mailbox;
  const auto* const render_pass = current_frame()->current_render_pass;
  if (render_pass != current_frame()->root_render_pass) {
    render_pass_id = render_pass->id;
    auto it = render_pass_backings_.find(render_pass_id);
    DCHECK(it != render_pass_backings_.end());
    mailbox = it->second.mailbox;
  }

  skia_output_surface_->CopyOutput(render_pass_id, geometry,
                                   CurrentRenderPassColorSpace(),
                                   std::move(request), mailbox);
}

void SkiaRenderer::DidChangeVisibility() {
  if (visible_)
    output_surface_->EnsureBackbuffer();
  else
    output_surface_->DiscardBackbuffer();
}

void SkiaRenderer::FinishDrawingQuadList() {
  if (!current_canvas_)
    return;

  if (!batched_quads_.empty())
    FlushBatchedQuads();

  bool is_root_render_pass =
      current_frame()->current_render_pass == current_frame()->root_render_pass;

  // Drawing the delegated ink trail must happen after the final
  // FlushBatchedQuads() call so that the trail can always be on top of
  // everything else that has already been drawn on the page. For the same
  // reason, it should only happen on the root render pass.
  if (is_root_render_pass && UsingSkiaForDelegatedInk())
    DrawDelegatedInkTrail();

  base::OnceClosure on_finished_callback;
  // Signal |current_frame_resource_fence_| when the root render pass is
  // finished.
  if (current_frame_resource_fence_->WasSet()) {
    on_finished_callback = base::BindOnce(
        &FrameResourceFence::Signal, std::move(current_frame_resource_fence_));
    current_frame_resource_fence_ = base::MakeRefCounted<FrameResourceFence>();
    resource_provider()->SetReadLockFence(current_frame_resource_fence_.get());
  }
  skia_output_surface_->EndPaint(std::move(on_finished_callback));

  // Defer flushing drawing task for root render pass, to avoid extra
  // MakeCurrent() call. It is expensive on GL.
  // TODO(https://crbug.com/1141008): Consider deferring drawing tasks for
  // all render passes.
  if (is_root_render_pass)
    return;

  FlushOutputSurface();
}

void SkiaRenderer::GenerateMipmap() {
  // This is a no-op since setting FilterQuality to high during drawing of
  // CompositorRenderPassDrawQuad is what actually generates generate_mipmap.
}

void SkiaRenderer::UpdateRenderPassTextures(
    const AggregatedRenderPassList& render_passes_in_draw_order,
    const base::flat_map<AggregatedRenderPassId, RenderPassRequirements>&
        render_passes_in_frame) {
  std::vector<AggregatedRenderPassId> passes_to_delete;
  for (const auto& pair : render_pass_backings_) {
    auto render_pass_it = render_passes_in_frame.find(pair.first);
    if (render_pass_it == render_passes_in_frame.end()) {
      passes_to_delete.push_back(pair.first);
      continue;
    }

    const RenderPassRequirements& requirements = render_pass_it->second;
    const RenderPassBacking& backing = pair.second;
    bool size_appropriate = backing.size.width() >= requirements.size.width() &&
                            backing.size.height() >= requirements.size.height();
    bool mipmap_appropriate =
        !requirements.generate_mipmap || backing.generate_mipmap;
    if (!size_appropriate || !mipmap_appropriate)
      passes_to_delete.push_back(pair.first);
  }

  // Delete RenderPass backings from the previous frame that will not be used
  // again.
  for (size_t i = 0; i < passes_to_delete.size(); ++i) {
    auto it = render_pass_backings_.find(passes_to_delete[i]);
    skia_output_surface_->GetSharedImageInterface()->DestroySharedImage(
        gpu::SyncToken(), it->second.mailbox);
    render_pass_backings_.erase(it);
  }

  if (!passes_to_delete.empty()) {
    skia_output_surface_->RemoveRenderPassResource(std::move(passes_to_delete));
  }
}

void SkiaRenderer::AllocateRenderPassResourceIfNeeded(
    const AggregatedRenderPassId& render_pass_id,
    const RenderPassRequirements& requirements) {
  auto it = render_pass_backings_.find(render_pass_id);
  if (it != render_pass_backings_.end()) {
    DCHECK(gfx::Rect(it->second.size).Contains(gfx::Rect(requirements.size)));
    return;
  }

  auto color_space = CurrentRenderPassColorSpace();
  // TODO(penghuang): check supported format correctly.
  gpu::Capabilities caps;
  caps.texture_format_bgra8888 = true;
  auto format = color_space.IsHDR()
                    ? RGBA_F16
                    : PlatformColor::BestSupportedTextureFormat(caps);
  uint32_t usage = gpu::SHARED_IMAGE_USAGE_DISPLAY;
  if (requirements.generate_mipmap)
    usage |= gpu::SHARED_IMAGE_USAGE_MIPMAP;
  auto mailbox =
      skia_output_surface_->GetSharedImageInterface()->CreateSharedImage(
          format, requirements.size, color_space,
          GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
          SkAlphaType::kPremul_SkAlphaType, usage, gpu::kNullSurfaceHandle);
  render_pass_backings_.emplace(
      render_pass_id,
      RenderPassBacking({requirements.size, requirements.generate_mipmap,
                         color_space, format, mailbox}));
}

void SkiaRenderer::FlushOutputSurface() {
  auto sync_token = skia_output_surface_->Flush();
  lock_set_for_external_use_->UnlockResources(sync_token);
}

#if BUILDFLAG(IS_APPLE) || defined(USE_OZONE)
void SkiaRenderer::PrepareRenderPassOverlay(
    OverlayProcessorInterface::PlatformOverlayCandidate* overlay) {
  DCHECK(!current_canvas_);
  DCHECK(batched_quads_.empty());
  DCHECK(overlay->rpdq);

  auto* const quad = overlay->rpdq;

  // The overlay will be sent to GPU the thread, so set rpdq to nullptr to avoid
  // being accessed on the GPU thread.
  overlay->rpdq = nullptr;

  // The |current_render_pass| could be used for calculating destination
  // color space or clipping rect for backdrop filters. However
  // the |current_render_pass| is nullptr during ScheduleOverlays(), since all
  // overlay quads should be in the |root_render_pass|, before they are promoted
  // to overlays, so set the |root_render_pass| to the |current_render_pass|.
  base::AutoReset<const AggregatedRenderPass*> auto_reset_current_render_pass(
      &current_frame()->current_render_pass, current_frame()->root_render_pass);

  auto* shared_quad_state =
      const_cast<SharedQuadState*>(quad->shared_quad_state);

  absl::optional<gfx::Transform> quad_to_target_transform_inverse;
  if (shared_quad_state->clip_rect ||
      !shared_quad_state->mask_filter_info.IsEmpty()) {
    // We cannot handle rotation with clip rect or mask filter.
    DCHECK(
        shared_quad_state->quad_to_target_transform.Preserves2dAxisAlignment());
    quad_to_target_transform_inverse.emplace(
        gfx::Transform::kSkipInitialization);
    // Flatten before inverting, since we're interested in how points
    // with z=0 in local space map to the clip rect, not in how the clip
    // rect at z=0 in device space maps to some other z in local space.
    gfx::Transform flat_quad_to_target_transform(
        shared_quad_state->quad_to_target_transform);
    flat_quad_to_target_transform.FlattenTo2d();
    bool result = flat_quad_to_target_transform.GetInverse(
        &*quad_to_target_transform_inverse);
    DCHECK(result) << "flat_quad_to_target_transform.GetInverse() failed";
  }

  // The |clip_rect| is in the device coordinate and with all transforms
  // (translation, scaling, rotation, etc), so remove them.
  absl::optional<base::AutoReset<gfx::Rect>> auto_reset_clip_rect;
  if (shared_quad_state->clip_rect) {
    // TODO(dbaron): This operation is likely not to be valid if
    // quad_to_target_transform_inverse.HasPerspective().
    gfx::RectF clip_rect(*shared_quad_state->clip_rect);
    quad_to_target_transform_inverse->TransformRect(&clip_rect);
    auto_reset_clip_rect.emplace(&shared_quad_state->clip_rect.value(),
                                 gfx::ToEnclosedRect(clip_rect));
  }

  // The |mask_filter_info| is in the device coordinate and with all transforms
  // (translation, scaling, rotation, etc), so remove them.
  if (!shared_quad_state->mask_filter_info.IsEmpty()) {
    auto result = shared_quad_state->mask_filter_info.Transform(
        *quad_to_target_transform_inverse);
    if (!result) {
      // Skia cannot transform a SkRRect with a matrix which contains epsilons,
      // workaround the problem by removing epsilons in the matrix.
      auto matrix = quad_to_target_transform_inverse->matrix();
      matrix.set(0, 0, remove_epsilon(matrix.get(0, 0)));
      matrix.set(0, 1, remove_epsilon(matrix.get(0, 1)));
      matrix.set(1, 0, remove_epsilon(matrix.get(1, 0)));
      matrix.set(1, 1, remove_epsilon(matrix.get(1, 1)));
      result =
          shared_quad_state->mask_filter_info.Transform(gfx::Transform(matrix));
    }
    DCHECK(result) << "shared_quad_state->mask_filter_info.Transform() failed.";
  }

  // Reset |quad_to_target_transform|, so the quad will be rendered at the
  // origin (0,0) without all transforms (translation, scaling, rotation, etc)
  // and then we will use OS compositor to do those transforms.
  base::AutoReset<gfx::Transform> auto_reset_transform(
      &shared_quad_state->quad_to_target_transform, gfx::Transform());

  const auto& viewport_size = current_frame()->device_viewport_size;
  auto projection_matrix = gfx::OrthoProjectionMatrix(
      /*left=*/0, /*right=*/viewport_size.width(), /*bottom=*/0,
      /*top=*/viewport_size.height());
  auto window_matrix =
      gfx::WindowMatrix(/*x=*/0, /*y=*/0, /*width=*/viewport_size.width(),
                        /*height=*/viewport_size.height());

  gfx::Transform target_to_device = window_matrix * projection_matrix;

  // Use nullptr scissor, so we can always render the whole render pass in an
  // overlay backing.
  // TODO(penghuang): reusing overlay backing from previous frame to avoid
  // reproducing the overlay backing if the render pass content quad properties
  // and content are not changed.
  DrawQuadParams params = CalculateDrawQuadParams(
      target_to_device, /*scissor=*/nullptr, quad, /*draw_region=*/nullptr);
  DrawRPDQParams rpdq_params = CalculateRPDQParams(quad, &params);

  const auto& filter_bounds = rpdq_params.filter_bounds;

  // |filter_bounds| is the content space bounds that includes any filtered
  // extents. If empty, the draw can be skipped.
  if (filter_bounds.IsEmpty())
    return;

  ResourceFormat buffer_format{};
  gfx::ColorSpace color_space;

  RenderPassBacking* backing = nullptr;
  auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id);
  BypassMode bypass_mode = BypassMode::kSkip;
  // When Render Pass has a single quad inside we would draw that directly.
  if (bypass != render_pass_bypass_quads_.end()) {
    bypass_mode = CalculateBypassParams(bypass->second, &rpdq_params, &params);
    if (bypass_mode == BypassMode::kSkip)
      return;

    // For bypassed render pass, we use the same format and color space for the
    // framebuffer.
    buffer_format = GetResourceFormat(reshape_buffer_format());
    color_space = reshape_color_space();
  } else {
    // A real render pass that was turned into an image
    auto it = render_pass_backings_.find(quad->render_pass_id);
    DCHECK(render_pass_backings_.end() != it);
    // This function is called after AllocateRenderPassResourceIfNeeded, so
    // there should be backing ready.
    backing = &it->second;
    buffer_format = backing->format;
    color_space = backing->color_space;
  }

  // Adjust the overlay |buffer_size| to reduce memory fragmentation. It also
  // increases buffer reusing possibilities.
#if BUILDFLAG(IS_APPLE)
  constexpr int kBufferMultiple = 64;
#else  // defined(USE_OZONE)
  // TODO(petermcneeley) : Support buffer rounding by dynamically changing
  // texture uvs.
  constexpr int kBufferMultiple = 1;
#endif
  gfx::Size buffer_size(
      cc::MathUtil::CheckedRoundUp(filter_bounds.width(), kBufferMultiple),
      cc::MathUtil::CheckedRoundUp(filter_bounds.height(), kBufferMultiple));

  current_canvas_ = skia_output_surface_->BeginPaintRenderPassOverlay(
      buffer_size, buffer_format, /*mipmap=*/false,
      color_space.ToSkColorSpace());
  if (!current_canvas_) {
    DLOG(ERROR) << "BeginPaintRenderPassOverlay() failed.";
    return;
  }

  // Clear the backing to ARGB(0,0,0,0).
  current_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));

  // Adjust the |content_device_transform| to make sure filter extends are drawn
  // inside of the buffer.
  params.content_device_transform.Translate(-filter_bounds.x(),
                                            -filter_bounds.y());

  // Also adjust the |rounded_corner_bounds| to the new location.
  if (params.rounded_corner_bounds) {
    params.rounded_corner_bounds->Offset(-filter_bounds.x(),
                                         -filter_bounds.y());
  }

  // When Render Pass has a single quad inside we would draw that directly.
  if (bypass != render_pass_bypass_quads_.end()) {
    if (bypass_mode == BypassMode::kDrawTransparentQuad) {
      DrawColoredQuad(SK_ColorTRANSPARENT, &rpdq_params, &params);
    } else if (bypass_mode == BypassMode::kDrawBypassQuad) {
      DrawQuadInternal(bypass->second, &rpdq_params, &params);
    } else {
      NOTREACHED();
    }
  } else {
    DCHECK(backing);
    auto content_image = skia_output_surface_->MakePromiseSkImageFromRenderPass(
        quad->render_pass_id, backing->size, backing->format,
        backing->generate_mipmap, backing->color_space.ToSkColorSpace(),
        backing->mailbox);
    if (!content_image) {
      DLOG(ERROR)
          << "MakePromiseSkImageFromRenderPass() failed for render pass";
      skia_output_surface_->EndPaintRenderPassOverlay();
      return;
    }

    if (backing->generate_mipmap)
      params.sampling =
          SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear);

    params.vis_tex_coords = cc::MathUtil::ScaleRectProportional(
        quad->tex_coord_rect, gfx::RectF(quad->rect), params.visible_rect);
    gfx::RectF valid_texel_bounds(content_image->width(),
                                  content_image->height());

    SkPaint paint = params.paint(GetContentColorFilter());
    DrawSingleImage(content_image.get(), valid_texel_bounds, &rpdq_params,
                    &paint, &params);
  }

  current_canvas_ = nullptr;
  auto ddl = skia_output_surface_->EndPaintRenderPassOverlay();
  DCHECK(ddl);

  // Put overlay related information in CALayerOverlay,
  // so SkiaOutputSurfaceImplOnGpu can use the DDL to create overlay buffer and
  // play the DDL back to it accordingly.
  overlay->ddl = std::move(ddl);

  // Adjust |bounds_rect| to contain the whole buffer and at the right location.
  overlay->bounds_rect.set_origin(gfx::PointF(filter_bounds.origin()));
  overlay->bounds_rect.set_size(gfx::SizeF(buffer_size));
}
#endif

bool SkiaRenderer::IsRenderPassResourceAllocated(
    const AggregatedRenderPassId& render_pass_id) const {
  auto it = render_pass_backings_.find(render_pass_id);
  return it != render_pass_backings_.end();
}

gfx::Size SkiaRenderer::GetRenderPassBackingPixelSize(
    const AggregatedRenderPassId& render_pass_id) {
  auto it = render_pass_backings_.find(render_pass_id);
  DCHECK(it != render_pass_backings_.end());
  return it->second.size;
}

void SkiaRenderer::SetDelegatedInkPointRendererSkiaForTest(
    std::unique_ptr<DelegatedInkPointRendererSkia> renderer) {
  DCHECK(!delegated_ink_handler_);
  delegated_ink_handler_ = std::make_unique<DelegatedInkHandler>(
      output_surface_->capabilities().supports_delegated_ink);
  delegated_ink_handler_->SetDelegatedInkPointRendererForTest(
      std::move(renderer));
}

void SkiaRenderer::DrawDelegatedInkTrail() {
  if (!delegated_ink_handler_ || !delegated_ink_handler_->GetInkRenderer())
    return;

  delegated_ink_handler_->GetInkRenderer()->DrawDelegatedInkTrail(
      current_canvas_);
}

DelegatedInkPointRendererBase* SkiaRenderer::GetDelegatedInkPointRenderer(
    bool create_if_necessary) {
  if (!delegated_ink_handler_ && !create_if_necessary)
    return nullptr;

  if (!delegated_ink_handler_) {
    delegated_ink_handler_ = std::make_unique<DelegatedInkHandler>(
        output_surface_->capabilities().supports_delegated_ink);
  }

  return delegated_ink_handler_->GetInkRenderer();
}

void SkiaRenderer::SetDelegatedInkMetadata(
    std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
  if (!delegated_ink_handler_) {
    delegated_ink_handler_ = std::make_unique<DelegatedInkHandler>(
        output_surface_->capabilities().supports_delegated_ink);
  }
  delegated_ink_handler_->SetDelegatedInkMetadata(std::move(metadata));
}

bool SkiaRenderer::UsingSkiaForDelegatedInk() const {
  return delegated_ink_handler_ && delegated_ink_handler_->GetInkRenderer();
}

#if BUILDFLAG(IS_APPLE) || defined(USE_OZONE)
bool SkiaRenderer::ScopedReadLockComparator::operator()(
    const DisplayResourceProviderSkia::ScopedReadLockSharedImage& lhs,
    const DisplayResourceProviderSkia::ScopedReadLockSharedImage& rhs) const {
  return lhs.mailbox() < rhs.mailbox();
}

bool SkiaRenderer::ScopedReadLockComparator::operator()(
    const DisplayResourceProviderSkia::ScopedReadLockSharedImage& lhs,
    const gpu::Mailbox& rhs) const {
  return lhs.mailbox() < rhs;
}

bool SkiaRenderer::ScopedReadLockComparator::operator()(
    const gpu::Mailbox& lhs,
    const DisplayResourceProviderSkia::ScopedReadLockSharedImage& rhs) const {
  return lhs < rhs.mailbox();
}
#endif  // BUILDFLAG(IS_APPLE) || defined(USE_OZONE)

bool SkiaRenderer::ColorFilterCacheKey::operator==(
    const ColorFilterCacheKey& other) const {
  return src == other.src && dst == other.dst &&
         resource_offset == other.resource_offset &&
         resource_multiplier == other.resource_multiplier &&
         sdr_max_luminance_nits == other.sdr_max_luminance_nits &&
         dst_max_luminance_relative == other.dst_max_luminance_relative;
}

bool SkiaRenderer::ColorFilterCacheKey::operator!=(
    const ColorFilterCacheKey& other) const {
  return !(*this == other);
}

bool SkiaRenderer::ColorFilterCacheKey::operator<(
    const ColorFilterCacheKey& other) const {
  return std::tie(src, dst, resource_offset, resource_multiplier,
                  sdr_max_luminance_nits, dst_max_luminance_relative) <
         std::tie(other.src, other.dst, other.resource_offset,
                  other.resource_multiplier, other.sdr_max_luminance_nits,
                  other.dst_max_luminance_relative);
}

}  // namespace viz
