// Copyright 2013 The Flutter 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 "flutter/display_list/dl_builder.h"

#include "flutter/display_list/display_list.h"
#include "flutter/display_list/dl_blend_mode.h"
#include "flutter/display_list/dl_op_flags.h"
#include "flutter/display_list/dl_op_records.h"
#include "flutter/display_list/effects/dl_color_source.h"
#include "flutter/display_list/utils/dl_accumulation_rect.h"
#include "fml/logging.h"
#include "third_party/skia/include/core/SkScalar.h"

namespace flutter {

#define DL_BUILDER_PAGE 4096

// CopyV(dst, src,n, src,n, ...) copies any number of typed srcs into dst.
static void CopyV(void* dst) {}

template <typename S, typename... Rest>
static void CopyV(void* dst, const S* src, int n, Rest&&... rest) {
  FML_DCHECK(((uintptr_t)dst & (alignof(S) - 1)) == 0)
      << "Expected " << dst << " to be aligned for at least " << alignof(S)
      << " bytes.";
  // If n is 0, there is nothing to copy into dst from src.
  if (n > 0) {
    memcpy(dst, src, n * sizeof(S));
    dst = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(dst) +
                                  n * sizeof(S));
  }
  // Repeat for the next items, if any
  CopyV(dst, std::forward<Rest>(rest)...);
}

static constexpr inline bool is_power_of_two(int value) {
  return (value & (value - 1)) == 0;
}

template <typename T, typename... Args>
void* DisplayListBuilder::Push(size_t pod, Args&&... args) {
  size_t size = SkAlignPtr(sizeof(T) + pod);
  FML_CHECK(size < (1 << 24));
  if (used_ + size > allocated_) {
    static_assert(is_power_of_two(DL_BUILDER_PAGE),
                  "This math needs updating for non-pow2.");
    // Next greater multiple of DL_BUILDER_PAGE.
    allocated_ = (used_ + size + DL_BUILDER_PAGE) & ~(DL_BUILDER_PAGE - 1);
    storage_.realloc(allocated_);
    FML_CHECK(storage_.get());
    memset(storage_.get() + used_, 0, allocated_ - used_);
  }
  FML_CHECK(used_ + size <= allocated_);
  auto op = reinterpret_cast<T*>(storage_.get() + used_);
  used_ += size;
  new (op) T{std::forward<Args>(args)...};
  op->type = T::kType;
  op->size = size;
  render_op_count_ += T::kRenderOpInc;
  depth_ += T::kDepthInc * render_op_depth_cost_;
  op_index_++;
  return op + 1;
}

sk_sp<DisplayList> DisplayListBuilder::Build() {
  while (save_stack_.size() > 1) {
    restore();
  }

  size_t bytes = used_;
  int count = render_op_count_;
  size_t nested_bytes = nested_bytes_;
  int nested_count = nested_op_count_;
  uint32_t total_depth = depth_;
  bool opacity_compatible = current_layer().is_group_opacity_compatible();
  bool is_safe = is_ui_thread_safe_;
  bool affects_transparency = current_layer().affects_transparent_layer;
  bool root_has_backdrop_filter = current_layer().contains_backdrop_filter;
  DlBlendMode max_root_blend_mode = current_layer().max_blend_mode;

  sk_sp<DlRTree> rtree;
  SkRect bounds;
  if (rtree_data_.has_value()) {
    auto& rects = rtree_data_->rects;
    auto& indices = rtree_data_->indices;
    rtree = sk_make_sp<DlRTree>(rects.data(), rects.size(), indices.data(),
                                [](int id) { return id >= 0; });
    // RTree bounds may be tighter due to applying filter bounds
    // adjustments to each op as we restore layers rather than to
    // the entire layer bounds.
    bounds = rtree->bounds();
    rtree_data_.reset();
  } else {
    bounds = current_layer().global_space_accumulator.bounds();
  }

  used_ = allocated_ = render_op_count_ = op_index_ = 0;
  nested_bytes_ = nested_op_count_ = 0;
  depth_ = 0;
  is_ui_thread_safe_ = true;
  current_opacity_compatibility_ = true;
  render_op_depth_cost_ = 1u;
  current_ = DlPaint();

  save_stack_.pop_back();
  Init(rtree != nullptr);

  storage_.realloc(bytes);
  return sk_sp<DisplayList>(new DisplayList(
      std::move(storage_), bytes, count, nested_bytes, nested_count,
      total_depth, bounds, opacity_compatible, is_safe, affects_transparency,
      max_root_blend_mode, root_has_backdrop_filter, std::move(rtree)));
}

static constexpr DlRect kEmpty = DlRect();

static const DlRect& ProtectEmpty(const SkRect& rect) {
  // isEmpty protects us against NaN while we normalize any empty cull rects
  return rect.isEmpty() ? kEmpty : ToDlRect(rect);
}

DisplayListBuilder::DisplayListBuilder(const SkRect& cull_rect,
                                       bool prepare_rtree)
    : original_cull_rect_(ProtectEmpty(cull_rect)) {
  Init(prepare_rtree);
}

void DisplayListBuilder::Init(bool prepare_rtree) {
  FML_DCHECK(save_stack_.empty());
  FML_DCHECK(!rtree_data_.has_value());

  save_stack_.emplace_back(original_cull_rect_);
  current_info().is_nop = original_cull_rect_.IsEmpty();
  if (prepare_rtree) {
    rtree_data_.emplace();
  }
}

DisplayListBuilder::~DisplayListBuilder() {
  uint8_t* ptr = storage_.get();
  if (ptr) {
    DisplayList::DisposeOps(ptr, ptr + used_);
  }
}

SkISize DisplayListBuilder::GetBaseLayerSize() const {
  return ToSkISize(DlIRect::RoundOut(original_cull_rect_).GetSize());
}

SkImageInfo DisplayListBuilder::GetImageInfo() const {
  SkISize size = GetBaseLayerSize();
  return SkImageInfo::MakeUnknown(size.width(), size.height());
}

void DisplayListBuilder::onSetAntiAlias(bool aa) {
  current_.setAntiAlias(aa);
  Push<SetAntiAliasOp>(0, aa);
}
void DisplayListBuilder::onSetInvertColors(bool invert) {
  current_.setInvertColors(invert);
  Push<SetInvertColorsOp>(0, invert);
  UpdateCurrentOpacityCompatibility();
}
void DisplayListBuilder::onSetStrokeCap(DlStrokeCap cap) {
  current_.setStrokeCap(cap);
  Push<SetStrokeCapOp>(0, cap);
}
void DisplayListBuilder::onSetStrokeJoin(DlStrokeJoin join) {
  current_.setStrokeJoin(join);
  Push<SetStrokeJoinOp>(0, join);
}
void DisplayListBuilder::onSetDrawStyle(DlDrawStyle style) {
  current_.setDrawStyle(style);
  Push<SetStyleOp>(0, style);
}
void DisplayListBuilder::onSetStrokeWidth(float width) {
  current_.setStrokeWidth(width);
  Push<SetStrokeWidthOp>(0, width);
}
void DisplayListBuilder::onSetStrokeMiter(float limit) {
  current_.setStrokeMiter(limit);
  Push<SetStrokeMiterOp>(0, limit);
}
void DisplayListBuilder::onSetColor(DlColor color) {
  current_.setColor(color);
  Push<SetColorOp>(0, color);
}
void DisplayListBuilder::onSetBlendMode(DlBlendMode mode) {
  current_.setBlendMode(mode);
  Push<SetBlendModeOp>(0, mode);
  UpdateCurrentOpacityCompatibility();
}

void DisplayListBuilder::onSetColorSource(const DlColorSource* source) {
  if (source == nullptr) {
    current_.setColorSource(nullptr);
    Push<ClearColorSourceOp>(0);
  } else {
    current_.setColorSource(source->shared());
    is_ui_thread_safe_ = is_ui_thread_safe_ && source->isUIThreadSafe();
    switch (source->type()) {
      case DlColorSourceType::kColor: {
        const DlColorColorSource* color_source = source->asColor();
        current_.setColorSource(nullptr);
        setColor(color_source->color());
        break;
      }
      case DlColorSourceType::kImage: {
        const DlImageColorSource* image_source = source->asImage();
        FML_DCHECK(image_source);
        Push<SetImageColorSourceOp>(0, image_source);
        break;
      }
      case DlColorSourceType::kLinearGradient: {
        const DlLinearGradientColorSource* linear = source->asLinearGradient();
        FML_DCHECK(linear);
        void* pod = Push<SetPodColorSourceOp>(linear->size());
        new (pod) DlLinearGradientColorSource(linear);
        break;
      }
      case DlColorSourceType::kRadialGradient: {
        const DlRadialGradientColorSource* radial = source->asRadialGradient();
        FML_DCHECK(radial);
        void* pod = Push<SetPodColorSourceOp>(radial->size());
        new (pod) DlRadialGradientColorSource(radial);
        break;
      }
      case DlColorSourceType::kConicalGradient: {
        const DlConicalGradientColorSource* conical =
            source->asConicalGradient();
        FML_DCHECK(conical);
        void* pod = Push<SetPodColorSourceOp>(conical->size());
        new (pod) DlConicalGradientColorSource(conical);
        break;
      }
      case DlColorSourceType::kSweepGradient: {
        const DlSweepGradientColorSource* sweep = source->asSweepGradient();
        FML_DCHECK(sweep);
        void* pod = Push<SetPodColorSourceOp>(sweep->size());
        new (pod) DlSweepGradientColorSource(sweep);
        break;
      }
      case DlColorSourceType::kRuntimeEffect: {
        const DlRuntimeEffectColorSource* effect = source->asRuntimeEffect();
        FML_DCHECK(effect);
        Push<SetRuntimeEffectColorSourceOp>(0, effect);
        break;
      }
#ifdef IMPELLER_ENABLE_3D
      case DlColorSourceType::kScene: {
        const DlSceneColorSource* scene = source->asScene();
        FML_DCHECK(scene);
        Push<SetSceneColorSourceOp>(0, scene);
        break;
      }
#endif  // IMPELLER_ENABLE_3D
    }
  }
}
void DisplayListBuilder::onSetImageFilter(const DlImageFilter* filter) {
  if (filter == nullptr) {
    current_.setImageFilter(nullptr);
    Push<ClearImageFilterOp>(0);
  } else {
    current_.setImageFilter(filter->shared());
    switch (filter->type()) {
      case DlImageFilterType::kBlur: {
        const DlBlurImageFilter* blur_filter = filter->asBlur();
        FML_DCHECK(blur_filter);
        void* pod = Push<SetPodImageFilterOp>(blur_filter->size());
        new (pod) DlBlurImageFilter(blur_filter);
        break;
      }
      case DlImageFilterType::kDilate: {
        const DlDilateImageFilter* dilate_filter = filter->asDilate();
        FML_DCHECK(dilate_filter);
        void* pod = Push<SetPodImageFilterOp>(dilate_filter->size());
        new (pod) DlDilateImageFilter(dilate_filter);
        break;
      }
      case DlImageFilterType::kErode: {
        const DlErodeImageFilter* erode_filter = filter->asErode();
        FML_DCHECK(erode_filter);
        void* pod = Push<SetPodImageFilterOp>(erode_filter->size());
        new (pod) DlErodeImageFilter(erode_filter);
        break;
      }
      case DlImageFilterType::kMatrix: {
        const DlMatrixImageFilter* matrix_filter = filter->asMatrix();
        FML_DCHECK(matrix_filter);
        void* pod = Push<SetPodImageFilterOp>(matrix_filter->size());
        new (pod) DlMatrixImageFilter(matrix_filter);
        break;
      }
      case DlImageFilterType::kCompose:
      case DlImageFilterType::kLocalMatrix:
      case DlImageFilterType::kColorFilter: {
        Push<SetSharedImageFilterOp>(0, filter);
        break;
      }
    }
  }
}
void DisplayListBuilder::onSetColorFilter(const DlColorFilter* filter) {
  if (filter == nullptr) {
    current_.setColorFilter(nullptr);
    Push<ClearColorFilterOp>(0);
  } else {
    current_.setColorFilter(filter->shared());
    switch (filter->type()) {
      case DlColorFilterType::kBlend: {
        const DlBlendColorFilter* blend_filter = filter->asBlend();
        FML_DCHECK(blend_filter);
        void* pod = Push<SetPodColorFilterOp>(blend_filter->size());
        new (pod) DlBlendColorFilter(blend_filter);
        break;
      }
      case DlColorFilterType::kMatrix: {
        const DlMatrixColorFilter* matrix_filter = filter->asMatrix();
        FML_DCHECK(matrix_filter);
        void* pod = Push<SetPodColorFilterOp>(matrix_filter->size());
        new (pod) DlMatrixColorFilter(matrix_filter);
        break;
      }
      case DlColorFilterType::kSrgbToLinearGamma: {
        void* pod = Push<SetPodColorFilterOp>(filter->size());
        new (pod) DlSrgbToLinearGammaColorFilter();
        break;
      }
      case DlColorFilterType::kLinearToSrgbGamma: {
        void* pod = Push<SetPodColorFilterOp>(filter->size());
        new (pod) DlLinearToSrgbGammaColorFilter();
        break;
      }
    }
  }
  UpdateCurrentOpacityCompatibility();
}
void DisplayListBuilder::onSetMaskFilter(const DlMaskFilter* filter) {
  if (filter == nullptr) {
    current_.setMaskFilter(nullptr);
    render_op_depth_cost_ = 1u;
    Push<ClearMaskFilterOp>(0);
  } else {
    current_.setMaskFilter(filter->shared());
    render_op_depth_cost_ = 2u;
    switch (filter->type()) {
      case DlMaskFilterType::kBlur: {
        const DlBlurMaskFilter* blur_filter = filter->asBlur();
        FML_DCHECK(blur_filter);
        void* pod = Push<SetPodMaskFilterOp>(blur_filter->size());
        new (pod) DlBlurMaskFilter(blur_filter);
        break;
      }
    }
  }
}

void DisplayListBuilder::SetAttributesFromPaint(
    const DlPaint& paint,
    const DisplayListAttributeFlags flags) {
  if (flags.applies_anti_alias()) {
    setAntiAlias(paint.isAntiAlias());
  }
  if (flags.applies_alpha_or_color()) {
    setColor(paint.getColor());
  }
  if (flags.applies_blend()) {
    setBlendMode(paint.getBlendMode());
  }
  if (flags.applies_style()) {
    setDrawStyle(paint.getDrawStyle());
  }
  if (flags.is_stroked(paint.getDrawStyle())) {
    setStrokeWidth(paint.getStrokeWidth());
    setStrokeMiter(paint.getStrokeMiter());
    setStrokeCap(paint.getStrokeCap());
    setStrokeJoin(paint.getStrokeJoin());
  }
  if (flags.applies_shader()) {
    setColorSource(paint.getColorSource().get());
  }
  if (flags.applies_color_filter()) {
    setInvertColors(paint.isInvertColors());
    setColorFilter(paint.getColorFilter().get());
  }
  if (flags.applies_image_filter()) {
    setImageFilter(paint.getImageFilter().get());
  }
  if (flags.applies_mask_filter()) {
    setMaskFilter(paint.getMaskFilter().get());
  }
}

void DisplayListBuilder::checkForDeferredSave() {
  if (current_info().has_deferred_save_op) {
    size_t save_offset = used_;
    Push<SaveOp>(0);
    current_info().save_offset = save_offset;
    current_info().save_depth = depth_;
    current_info().has_deferred_save_op = false;
  }
}

void DisplayListBuilder::Save() {
  bool was_nop = current_info().is_nop;
  save_stack_.emplace_back(&current_info());
  current_info().is_nop = was_nop;

  FML_DCHECK(save_stack_.size() >= 2u);
  FML_DCHECK(current_info().has_deferred_save_op);
}

void DisplayListBuilder::saveLayer(const SkRect& bounds,
                                   const SaveLayerOptions in_options,
                                   const DlImageFilter* backdrop) {
  SaveLayerOptions options = in_options.without_optimizations();
  DisplayListAttributeFlags flags = options.renders_with_attributes()
                                        ? kSaveLayerWithPaintFlags
                                        : kSaveLayerFlags;
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    // If we can't render, whether because we were already in a no-render
    // state from the parent or because our own attributes make us a nop,
    // we can just simplify this whole layer to a regular save that has
    // nop state. We need to have a SaveInfo for the eventual restore(),
    // but no rendering ops should be accepted between now and then so
    // it doesn't need any of the data associated with a layer SaveInfo.
    Save();
    current_info().is_nop = true;
    return;
  }

  if (backdrop != nullptr) {
    current_layer().contains_backdrop_filter = true;
  }

  // Snapshot these values before we do any work as we need the values
  // from before the method was called, but some of the operations below
  // might update them.
  size_t save_offset = used_;
  uint32_t save_depth = depth_;

  // A backdrop will affect up to the entire surface, bounded by the clip
  bool will_be_unbounded = (backdrop != nullptr);
  std::shared_ptr<const DlImageFilter> filter;

  if (options.renders_with_attributes()) {
    if (!paint_nops_on_transparency()) {
      // We will fill the clip of the outer layer when we restore.
      will_be_unbounded = true;
    }
    filter = current_.getImageFilter();
    CheckLayerOpacityCompatibility(true);
    UpdateLayerResult(result, true);
  } else {
    CheckLayerOpacityCompatibility(false);
    UpdateLayerResult(result, false);
  }

  // The actual flood of the outer layer clip will occur after the
  // (eventual) corresponding restore is called, but rather than
  // remember this information in the LayerInfo until the restore
  // method is processed, we just mark the unbounded state up front.
  // Another reason to accumulate the clip here rather than in
  // restore is so that this savelayer will be tagged in the rtree
  // with its full bounds and the right op_index so that it doesn't
  // get culled during rendering.
  if (will_be_unbounded) {
    // Accumulate should always return true here because if the
    // clip was empty then that would have been caught up above
    // when we tested the PaintResult.
    [[maybe_unused]] bool unclipped = AccumulateUnbounded();
    FML_DCHECK(unclipped);
  }

  // Accumulate information for the SaveInfo we are about to push onto the
  // stack.
  {
    size_t rtree_index =
        rtree_data_.has_value() ? rtree_data_->rects.size() : 0u;

    save_stack_.emplace_back(&current_info(), filter, rtree_index);
    FML_DCHECK(current_info().is_save_layer);
    FML_DCHECK(!current_info().is_nop);
    FML_DCHECK(!current_info().has_deferred_save_op);
    current_info().save_offset = save_offset;
    current_info().save_depth = save_depth;

    // If we inherit some culling bounds and we have a filter then we need
    // to adjust them so that we cull for the correct input space for the
    // output of the filter.
    if (filter) {
      SkRect outer_cull_rect = current_info().global_state.device_cull_rect();
      SkMatrix matrix = current_info().global_state.matrix_3x3();

      SkIRect output_bounds = outer_cull_rect.roundOut();
      SkIRect input_bounds;
      if (filter->get_input_device_bounds(output_bounds, matrix,
                                          input_bounds)) {
        current_info().global_state.resetDeviceCullRect(
            SkRect::Make(input_bounds));
      } else {
        // Filter could not make any promises about the bounds it needs to
        // fill the output space, so we use a maximal rect to accumulate
        // the layer bounds.
        current_info().global_state.resetDeviceCullRect(kMaxCullRect);
      }
    }

    // We always want to cull based on user provided bounds, though, as
    // that is legacy behavior even if it doesn't always work precisely
    // in a rotated or skewed coordinate system (but it will work
    // conservatively).
    if (in_options.bounds_from_caller()) {
      current_info().global_state.clipRect(bounds, ClipOp::kIntersect, false);
    }
  }

  // Accumulate options to store in the SaveLayer op record.
  {
    SkRect record_bounds;
    if (in_options.bounds_from_caller()) {
      options = options.with_bounds_from_caller();
      record_bounds = bounds;
    } else {
      FML_DCHECK(record_bounds.isEmpty());
    }

    if (backdrop) {
      Push<SaveLayerBackdropOp>(0, options, record_bounds, backdrop);
    } else {
      Push<SaveLayerOp>(0, options, record_bounds);
    }
  }

  if (options.renders_with_attributes()) {
    // |current_opacity_compatibility_| does not take an ImageFilter into
    // account because an individual primitive with an ImageFilter can apply
    // opacity on top of it. But, if the layer is applying the ImageFilter
    // then it cannot pass the opacity on.
    if (!current_opacity_compatibility_ || filter) {
      UpdateLayerOpacityCompatibility(false);
    }
  }
}
void DisplayListBuilder::SaveLayer(const SkRect* bounds,
                                   const DlPaint* paint,
                                   const DlImageFilter* backdrop) {
  SaveLayerOptions options;
  SkRect temp_bounds;
  if (bounds) {
    options = options.with_bounds_from_caller();
    temp_bounds = *bounds;
  } else {
    temp_bounds.setEmpty();
  }
  if (paint != nullptr) {
    options = options.with_renders_with_attributes();
    SetAttributesFromPaint(*paint,
                           DisplayListOpFlags::kSaveLayerWithPaintFlags);
  }
  saveLayer(temp_bounds, options, backdrop);
}

void DisplayListBuilder::Restore() {
  if (save_stack_.size() <= 1) {
    return;
  }

  if (!current_info().has_deferred_save_op) {
    SaveOpBase* op = reinterpret_cast<SaveOpBase*>(storage_.get() +
                                                   current_info().save_offset);
    FML_CHECK(op->type == DisplayListOpType::kSave ||
              op->type == DisplayListOpType::kSaveLayer ||
              op->type == DisplayListOpType::kSaveLayerBackdrop);

    op->restore_index = op_index_;
    op->total_content_depth = depth_ - current_info().save_depth;

    if (current_info().is_save_layer) {
      RestoreLayer();
    }

    // Wait until all outgoing bounds information for the saveLayer is
    // recorded before pushing the record to the buffer so that any rtree
    // bounds will be attributed to the op_index of the restore op.
    Push<RestoreOp>(0);
  } else {
    FML_DCHECK(!current_info().is_save_layer);
  }

  save_stack_.pop_back();
}

void DisplayListBuilder::RestoreLayer() {
  FML_DCHECK(save_stack_.size() > 1);
  FML_DCHECK(current_info().is_save_layer);
  FML_DCHECK(!current_info().has_deferred_save_op);

  // A saveLayer will usually do a final copy to the main buffer in
  // addition to its content, but that is accounted for outside of
  // the total content depth computed above in Restore.
  depth_ += render_op_depth_cost_;

  SkRect content_bounds = current_layer().layer_local_accumulator.bounds();

  SaveLayerOpBase* layer_op = reinterpret_cast<SaveLayerOpBase*>(
      storage_.get() + current_info().save_offset);
  FML_CHECK(layer_op->type == DisplayListOpType::kSaveLayer ||
            layer_op->type == DisplayListOpType::kSaveLayerBackdrop);

  if (layer_op->options.bounds_from_caller()) {
    if (!content_bounds.isEmpty() && !layer_op->rect.contains(content_bounds)) {
      layer_op->options = layer_op->options.with_content_is_clipped();
      content_bounds.intersect(layer_op->rect);
    }
  }
  layer_op->rect = content_bounds;
  layer_op->max_blend_mode = current_layer().max_blend_mode;

  if (current_layer().contains_backdrop_filter) {
    layer_op->options = layer_op->options.with_contains_backdrop_filter();
  }

  if (current_layer().is_group_opacity_compatible()) {
    layer_op->options = layer_op->options.with_can_distribute_opacity();
  }

  // Ensure that the bounds transferred in the following call will be
  // attributed to the index of the restore op.
  FML_DCHECK(layer_op->restore_index == op_index_);
  TransferLayerBounds(content_bounds);
}

// There are a few different conditions and corresponding operations to
// consider when transferring bounds from one layer to another. The current
// layer will have accumulated its bounds into 2 potential places:
//
// - Its own private layer local bounds, which were potentially clipped by
//   the supplied bounds and passed here as the content_bounds.
//
// - Either the rtree rect list, or the global space accumulator, one or
//   the other.
//
// If there is no filter then the private layer bounds are complete and
// they simply need to be passed along to the parent into its layer local
// accumulator. Also, if there was no filter then the existing bounds
// recorded in either the rtree rects or the layer's global space accumulator
// (shared with its parent) need no updating so no global space transfer
// has to occur.
//
// If there is a filter then the global content bounds will need to be
// adjusted in one of two ways (rtree vs non-rtree):
//
// - If we are accumulating rtree rects then each of the rects accumulated
//   during this current layer will need to be updated by the filter in the
//   global coordinate space in which they were accumulated. In this mode
//   we should never have a global space accumulator on the layer.
//
// - Otherwise we were accumulating global bounds into our own private
//   global space accumulator which need to be adjusted in the global space
//   coordinate system by the filter.
//
// Finally, we will have to adjust the layer's content bounds by the filter
// and accumulate those into the parent layer's local bounds.
void DisplayListBuilder::TransferLayerBounds(const SkRect& content_bounds) {
  auto& filter = current_layer().filter;

  if (!filter) {
    // We either accumulate global bounds into the rtree_data if there
    // is one, or into the global_space_accumulator, but not both.
    FML_DCHECK(!rtree_data_.has_value() ||
               current_layer().global_space_accumulator.is_empty());

    parent_info().AccumulateBoundsLocal(content_bounds);
    parent_layer().global_space_accumulator.accumulate(
        current_layer().global_space_accumulator);
    return;
  }

  bool parent_is_flooded = false;
  SkRect bounds_for_parent = content_bounds;

  // First, let's adjust or transfer the global/rtree bounds by the filter.

  // Matrix and Clip for the filter adjustment are the global values from
  // just before our saveLayer and should still be the current values
  // present in the parent layer.
  const SkRect clip = parent_info().global_state.device_cull_rect();
  const SkMatrix matrix = parent_info().global_state.matrix_3x3();

  if (rtree_data_.has_value()) {
    // Neither current or parent layer should have any global bounds in
    // their accumulator
    FML_DCHECK(current_layer().global_space_accumulator.is_empty());
    FML_DCHECK(parent_layer().global_space_accumulator.is_empty());

    // The rtree rects were accumulated without the bounds modification of
    // the filter applied to the layer so they may fail to trigger on a
    // culled dispatch if their filter "fringes" are in the dispatch scope
    // but their base rendering bounds are not. (Also, they will not
    // contribute fully when we compute the overall bounds of this DL.)
    //
    // To make sure they are rendered in the culled dispatch situation, we
    // revisit all of the RTree rects accumulated during the current layer
    // (indicated by rtree_rects_start_index) and expand them by the filter.

    if (AdjustRTreeRects(rtree_data_.value(), *filter, matrix, clip,
                         current_layer().rtree_rects_start_index)) {
      parent_is_flooded = true;
    }
  } else {
    SkRect global_bounds = current_layer().global_space_accumulator.bounds();
    if (!global_bounds.isEmpty()) {
      SkIRect global_ibounds = global_bounds.roundOut();
      if (!filter->map_device_bounds(global_ibounds, matrix, global_ibounds)) {
        parent_is_flooded = true;
      } else {
        global_bounds.set(global_ibounds);
        if (global_bounds.intersect(clip)) {
          parent_layer().global_space_accumulator.accumulate(global_bounds);
        }
      }
    }
  }

  // Now we visit the layer bounds which are in the layer's local coordinate
  // system must be accumulated into the parent layer's bounds while
  // adjusting them by the layer's local coordinate system (handled by the
  // Accumulate() methods).

  // A filter will happily adjust empty bounds to be non-empty, so we
  // specifically avoid that case here. Also, if we are already planning
  // to flood the parent due to any of the cases above, we don't need to
  // run the filter on the content bounds only to discover the same
  // condition.
  if (!parent_is_flooded && !bounds_for_parent.isEmpty()) {
    if (!filter->map_local_bounds(bounds_for_parent, bounds_for_parent)) {
      parent_is_flooded = true;
    }
  }

  if (parent_is_flooded) {
    // All of the above computations deferred the flooded parent status
    // to here. We need to mark the parent as flooded in both its layer
    // and global accumulators. Note that even though the rtree rects
    // were expanded to the size of the clip above, this method will still
    // add one more rect to the rtree with the op index of the restore
    // command to prevent the saveLayer itself from being elided in the
    // rare case that there are no rendering ops in it, or somehow none
    // of them were chosen by the rtree search (unlikely). The saveLayer
    // must be processed for the parent flood to happen.
    AccumulateUnbounded(parent_info());
  } else {
    parent_info().AccumulateBoundsLocal(bounds_for_parent);
  }
}

bool DisplayListBuilder::AdjustRTreeRects(RTreeData& data,
                                          const DlImageFilter& filter,
                                          const SkMatrix& matrix,
                                          const SkRect& clip,
                                          size_t rect_start_index) {
  auto& rects = data.rects;
  auto& indices = data.indices;
  FML_DCHECK(rects.size() == indices.size());
  int ret = false;
  auto rect_keep = rect_start_index;
  for (size_t i = rect_start_index; i < rects.size(); i++) {
    SkRect bounds = rects[i];
    SkIRect ibounds;
    if (filter.map_device_bounds(bounds.roundOut(), matrix, ibounds)) {
      bounds.set(ibounds);
    } else {
      bounds = clip;
      ret = true;
    }
    if (bounds.intersect(clip)) {
      indices[rect_keep] = indices[i];
      rects[rect_keep] = bounds;
      rect_keep++;
    }
  }
  indices.resize(rect_keep);
  rects.resize(rect_keep);
  return ret;
}

void DisplayListBuilder::RestoreToCount(int restore_count) {
  FML_DCHECK(restore_count <= GetSaveCount());
  while (restore_count < GetSaveCount() && GetSaveCount() > 1) {
    restore();
  }
}

void DisplayListBuilder::Translate(SkScalar tx, SkScalar ty) {
  if (std::isfinite(tx) && std::isfinite(ty) && (tx != 0.0 || ty != 0.0)) {
    checkForDeferredSave();
    Push<TranslateOp>(0, tx, ty);
    global_state().translate(tx, ty);
    layer_local_state().translate(tx, ty);
  }
}
void DisplayListBuilder::Scale(SkScalar sx, SkScalar sy) {
  if (std::isfinite(sx) && std::isfinite(sy) && (sx != 1.0 || sy != 1.0)) {
    checkForDeferredSave();
    Push<ScaleOp>(0, sx, sy);
    global_state().scale(sx, sy);
    layer_local_state().scale(sx, sy);
  }
}
void DisplayListBuilder::Rotate(SkScalar degrees) {
  if (SkScalarMod(degrees, 360.0) != 0.0) {
    checkForDeferredSave();
    Push<RotateOp>(0, degrees);
    global_state().rotate(degrees);
    layer_local_state().rotate(degrees);
  }
}
void DisplayListBuilder::Skew(SkScalar sx, SkScalar sy) {
  if (std::isfinite(sx) && std::isfinite(sy) && (sx != 0.0 || sy != 0.0)) {
    checkForDeferredSave();
    Push<SkewOp>(0, sx, sy);
    global_state().skew(sx, sy);
    layer_local_state().skew(sx, sy);
  }
}

// clang-format off

// 2x3 2D affine subset of a 4x4 transform in row major order
void DisplayListBuilder::Transform2DAffine(
    SkScalar mxx, SkScalar mxy, SkScalar mxt,
    SkScalar myx, SkScalar myy, SkScalar myt) {
  if (std::isfinite(mxx) && std::isfinite(myx) &&
      std::isfinite(mxy) && std::isfinite(myy) &&
      std::isfinite(mxt) && std::isfinite(myt)) {
    if (mxx == 1 && mxy == 0 &&
        myx == 0 && myy == 1) {
      Translate(mxt, myt);
    } else {
      checkForDeferredSave();
      Push<Transform2DAffineOp>(0,
                                mxx, mxy, mxt,
                                myx, myy, myt);
      global_state().transform2DAffine(mxx, mxy, mxt,
                                       myx, myy, myt);
      layer_local_state().transform2DAffine(mxx, mxy, mxt,
                                            myx, myy, myt);
    }
  }
}
// full 4x4 transform in row major order
void DisplayListBuilder::TransformFullPerspective(
    SkScalar mxx, SkScalar mxy, SkScalar mxz, SkScalar mxt,
    SkScalar myx, SkScalar myy, SkScalar myz, SkScalar myt,
    SkScalar mzx, SkScalar mzy, SkScalar mzz, SkScalar mzt,
    SkScalar mwx, SkScalar mwy, SkScalar mwz, SkScalar mwt) {
  if (                        mxz == 0 &&
                              myz == 0 &&
      mzx == 0 && mzy == 0 && mzz == 1 && mzt == 0 &&
      mwx == 0 && mwy == 0 && mwz == 0 && mwt == 1) {
    Transform2DAffine(mxx, mxy, mxt,
                      myx, myy, myt);
  } else if (std::isfinite(mxx) && std::isfinite(mxy) &&
             std::isfinite(mxz) && std::isfinite(mxt) &&
             std::isfinite(myx) && std::isfinite(myy) &&
             std::isfinite(myz) && std::isfinite(myt) &&
             std::isfinite(mzx) && std::isfinite(mzy) &&
             std::isfinite(mzz) && std::isfinite(mzt) &&
             std::isfinite(mwx) && std::isfinite(mwy) &&
             std::isfinite(mwz) && std::isfinite(mwt)) {
    checkForDeferredSave();
    Push<TransformFullPerspectiveOp>(0,
                                     mxx, mxy, mxz, mxt,
                                     myx, myy, myz, myt,
                                     mzx, mzy, mzz, mzt,
                                     mwx, mwy, mwz, mwt);
    global_state().transformFullPerspective(mxx, mxy, mxz, mxt,
                                            myx, myy, myz, myt,
                                            mzx, mzy, mzz, mzt,
                                            mwx, mwy, mwz, mwt);
    layer_local_state().transformFullPerspective(mxx, mxy, mxz, mxt,
                                                 myx, myy, myz, myt,
                                                 mzx, mzy, mzz, mzt,
                                                 mwx, mwy, mwz, mwt);
  }
}
// clang-format on
void DisplayListBuilder::TransformReset() {
  checkForDeferredSave();
  Push<TransformResetOp>(0);

  // The matrices in layer_tracker_ and tracker_ are similar, but
  // start at a different base transform. The tracker_ potentially
  // has some number of transform operations on it that prefix the
  // operations accumulated in layer_tracker_. So we can't set them both
  // to identity in parallel as they would no longer maintain their
  // relationship to each other.
  // Instead we reinterpret this operation as transforming by the
  // inverse of the current transform. Doing so to tracker_ sets it
  // to identity so we can avoid the math there, but we must do the
  // math the long way for layer_tracker_. This becomes:
  //   layer_tracker_.transform(tracker_.inverse());
  if (!layer_local_state().inverseTransform(global_state())) {
    // If the inverse operation failed then that means that either
    // the matrix above the current layer was singular, or the matrix
    // became singular while we were accumulating the current layer.
    // In either case, we should no longer be accumulating any
    // contents so we set the layer tracking transform to a singular one.
    layer_local_state().setTransform(SkMatrix::Scale(0.0f, 0.0f));
  }

  global_state().setIdentity();
}
void DisplayListBuilder::Transform(const SkMatrix* matrix) {
  if (matrix != nullptr) {
    Transform(SkM44(*matrix));
  }
}
void DisplayListBuilder::Transform(const SkM44* m44) {
  if (m44 != nullptr) {
    transformFullPerspective(
        m44->rc(0, 0), m44->rc(0, 1), m44->rc(0, 2), m44->rc(0, 3),
        m44->rc(1, 0), m44->rc(1, 1), m44->rc(1, 2), m44->rc(1, 3),
        m44->rc(2, 0), m44->rc(2, 1), m44->rc(2, 2), m44->rc(2, 3),
        m44->rc(3, 0), m44->rc(3, 1), m44->rc(3, 2), m44->rc(3, 3));
  }
}

void DisplayListBuilder::ClipRect(const SkRect& rect,
                                  ClipOp clip_op,
                                  bool is_aa) {
  if (!rect.isFinite()) {
    return;
  }
  if (current_info().is_nop) {
    return;
  }
  if (current_info().has_valid_clip &&
      clip_op == DlCanvas::ClipOp::kIntersect &&
      layer_local_state().rect_covers_cull(rect)) {
    return;
  }
  global_state().clipRect(rect, clip_op, is_aa);
  layer_local_state().clipRect(rect, clip_op, is_aa);
  if (global_state().is_cull_rect_empty() ||
      layer_local_state().is_cull_rect_empty()) {
    current_info().is_nop = true;
    return;
  }
  current_info().has_valid_clip = true;
  checkForDeferredSave();
  switch (clip_op) {
    case ClipOp::kIntersect:
      Push<ClipIntersectRectOp>(0, rect, is_aa);
      break;
    case ClipOp::kDifference:
      Push<ClipDifferenceRectOp>(0, rect, is_aa);
      break;
  }
}
void DisplayListBuilder::ClipRRect(const SkRRect& rrect,
                                   ClipOp clip_op,
                                   bool is_aa) {
  if (rrect.isRect()) {
    clipRect(rrect.rect(), clip_op, is_aa);
    return;
  }
  if (current_info().is_nop) {
    return;
  }
  if (current_info().has_valid_clip &&
      clip_op == DlCanvas::ClipOp::kIntersect &&
      layer_local_state().rrect_covers_cull(rrect)) {
    return;
  }
  global_state().clipRRect(rrect, clip_op, is_aa);
  layer_local_state().clipRRect(rrect, clip_op, is_aa);
  if (global_state().is_cull_rect_empty() ||
      layer_local_state().is_cull_rect_empty()) {
    current_info().is_nop = true;
    return;
  }
  current_info().has_valid_clip = true;
  checkForDeferredSave();
  switch (clip_op) {
    case ClipOp::kIntersect:
      Push<ClipIntersectRRectOp>(0, rrect, is_aa);
      break;
    case ClipOp::kDifference:
      Push<ClipDifferenceRRectOp>(0, rrect, is_aa);
      break;
  }
}
void DisplayListBuilder::ClipPath(const SkPath& path,
                                  ClipOp clip_op,
                                  bool is_aa) {
  if (current_info().is_nop) {
    return;
  }
  if (!path.isInverseFillType()) {
    SkRect rect;
    if (path.isRect(&rect)) {
      this->clipRect(rect, clip_op, is_aa);
      return;
    }
    SkRRect rrect;
    if (path.isOval(&rect)) {
      rrect.setOval(rect);
      this->clipRRect(rrect, clip_op, is_aa);
      return;
    }
    if (path.isRRect(&rrect)) {
      this->clipRRect(rrect, clip_op, is_aa);
      return;
    }
  }
  global_state().clipPath(path, clip_op, is_aa);
  layer_local_state().clipPath(path, clip_op, is_aa);
  if (global_state().is_cull_rect_empty() ||
      layer_local_state().is_cull_rect_empty()) {
    current_info().is_nop = true;
    return;
  }
  current_info().has_valid_clip = true;
  checkForDeferredSave();
  switch (clip_op) {
    case ClipOp::kIntersect:
      Push<ClipIntersectPathOp>(0, path, is_aa);
      break;
    case ClipOp::kDifference:
      Push<ClipDifferencePathOp>(0, path, is_aa);
      break;
  }
}

bool DisplayListBuilder::QuickReject(const SkRect& bounds) const {
  return global_state().content_culled(bounds);
}

void DisplayListBuilder::drawPaint() {
  OpResult result = PaintResult(current_, kDrawPaintFlags);
  if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
    Push<DrawPaintOp>(0);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawPaint(const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPaintFlags);
  drawPaint();
}
void DisplayListBuilder::DrawColor(DlColor color, DlBlendMode mode) {
  OpResult result = PaintResult(DlPaint(color).setBlendMode(mode));
  if (result != OpResult::kNoEffect && AccumulateUnbounded()) {
    Push<DrawColorOp>(0, color, mode);
    CheckLayerOpacityCompatibility(mode);
    UpdateLayerResult(result, mode);
  }
}
void DisplayListBuilder::drawLine(const SkPoint& p0, const SkPoint& p1) {
  SkRect bounds = SkRect::MakeLTRB(p0.fX, p0.fY, p1.fX, p1.fY).makeSorted();
  DisplayListAttributeFlags flags =
      (bounds.width() > 0.0f && bounds.height() > 0.0f) ? kDrawLineFlags
                                                        : kDrawHVLineFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
    Push<DrawLineOp>(0, p0, p1);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawLine(const SkPoint& p0,
                                  const SkPoint& p1,
                                  const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawLineFlags);
  drawLine(p0, p1);
}
void DisplayListBuilder::drawDashedLine(const DlPoint& p0,
                                        const DlPoint& p1,
                                        DlScalar on_length,
                                        DlScalar off_length) {
  SkRect bounds = SkRect::MakeLTRB(p0.x, p0.y, p1.x, p1.y).makeSorted();
  DisplayListAttributeFlags flags =
      (bounds.width() > 0.0f && bounds.height() > 0.0f) ? kDrawLineFlags
                                                        : kDrawHVLineFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
    Push<DrawDashedLineOp>(0, p0, p1, on_length, off_length);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawDashedLine(const DlPoint& p0,
                                        const DlPoint& p1,
                                        DlScalar on_length,
                                        DlScalar off_length,
                                        const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawLineFlags);
  drawDashedLine(p0, p1, on_length, off_length);
}
void DisplayListBuilder::drawRect(const SkRect& rect) {
  DisplayListAttributeFlags flags = kDrawRectFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect &&
      AccumulateOpBounds(rect.makeSorted(), flags)) {
    Push<DrawRectOp>(0, rect);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawRect(const SkRect& rect, const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRectFlags);
  drawRect(rect);
}
void DisplayListBuilder::drawOval(const SkRect& bounds) {
  DisplayListAttributeFlags flags = kDrawOvalFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect &&
      AccumulateOpBounds(bounds.makeSorted(), flags)) {
    Push<DrawOvalOp>(0, bounds);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawOval(const SkRect& bounds, const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawOvalFlags);
  drawOval(bounds);
}
void DisplayListBuilder::drawCircle(const SkPoint& center, SkScalar radius) {
  DisplayListAttributeFlags flags = kDrawCircleFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect) {
    SkRect bounds = SkRect::MakeLTRB(center.fX - radius, center.fY - radius,
                                     center.fX + radius, center.fY + radius);
    if (AccumulateOpBounds(bounds, flags)) {
      Push<DrawCircleOp>(0, center, radius);
      CheckLayerOpacityCompatibility();
      UpdateLayerResult(result);
    }
  }
}
void DisplayListBuilder::DrawCircle(const SkPoint& center,
                                    SkScalar radius,
                                    const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawCircleFlags);
  drawCircle(center, radius);
}
void DisplayListBuilder::drawRRect(const SkRRect& rrect) {
  if (rrect.isRect()) {
    drawRect(rrect.rect());
  } else if (rrect.isOval()) {
    drawOval(rrect.rect());
  } else {
    DisplayListAttributeFlags flags = kDrawRRectFlags;
    OpResult result = PaintResult(current_, flags);
    if (result != OpResult::kNoEffect &&
        AccumulateOpBounds(rrect.getBounds(), flags)) {
      Push<DrawRRectOp>(0, rrect);
      CheckLayerOpacityCompatibility();
      UpdateLayerResult(result);
    }
  }
}
void DisplayListBuilder::DrawRRect(const SkRRect& rrect, const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRRectFlags);
  drawRRect(rrect);
}
void DisplayListBuilder::drawDRRect(const SkRRect& outer,
                                    const SkRRect& inner) {
  DisplayListAttributeFlags flags = kDrawDRRectFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect &&
      AccumulateOpBounds(outer.getBounds(), flags)) {
    Push<DrawDRRectOp>(0, outer, inner);
    CheckLayerOpacityCompatibility();
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawDRRect(const SkRRect& outer,
                                    const SkRRect& inner,
                                    const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawDRRectFlags);
  drawDRRect(outer, inner);
}
void DisplayListBuilder::drawPath(const SkPath& path) {
  DisplayListAttributeFlags flags = kDrawPathFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect) {
    bool is_visible = path.isInverseFillType()
                          ? AccumulateUnbounded()
                          : AccumulateOpBounds(path.getBounds(), flags);
    if (is_visible) {
      Push<DrawPathOp>(0, path);
      CheckLayerOpacityHairlineCompatibility();
      UpdateLayerResult(result);
    }
  }
}
void DisplayListBuilder::DrawPath(const SkPath& path, const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPathFlags);
  drawPath(path);
}

void DisplayListBuilder::drawArc(const SkRect& bounds,
                                 SkScalar start,
                                 SkScalar sweep,
                                 bool useCenter) {
  DisplayListAttributeFlags flags =  //
      useCenter                      //
          ? kDrawArcWithCenterFlags
          : kDrawArcNoCenterFlags;
  OpResult result = PaintResult(current_, flags);
  // This could be tighter if we compute where the start and end
  // angles are and then also consider the quadrants swept and
  // the center if specified.
  if (result != OpResult::kNoEffect && AccumulateOpBounds(bounds, flags)) {
    Push<DrawArcOp>(0, bounds, start, sweep, useCenter);
    if (useCenter) {
      CheckLayerOpacityHairlineCompatibility();
    } else {
      CheckLayerOpacityCompatibility();
    }
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawArc(const SkRect& bounds,
                                 SkScalar start,
                                 SkScalar sweep,
                                 bool useCenter,
                                 const DlPaint& paint) {
  SetAttributesFromPaint(
      paint, useCenter ? kDrawArcWithCenterFlags : kDrawArcNoCenterFlags);
  drawArc(bounds, start, sweep, useCenter);
}

DisplayListAttributeFlags DisplayListBuilder::FlagsForPointMode(
    PointMode mode) {
  switch (mode) {
    case DlCanvas::PointMode::kPoints:
      return kDrawPointsAsPointsFlags;
    case PointMode::kLines:
      return kDrawPointsAsLinesFlags;
    case PointMode::kPolygon:
      return kDrawPointsAsPolygonFlags;
  }
  FML_UNREACHABLE();
}
void DisplayListBuilder::drawPoints(PointMode mode,
                                    uint32_t count,
                                    const SkPoint pts[]) {
  if (count == 0) {
    return;
  }
  DisplayListAttributeFlags flags = FlagsForPointMode(mode);
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    return;
  }

  FML_DCHECK(count < DlOpReceiver::kMaxDrawPointsCount);
  int bytes = count * sizeof(SkPoint);
  AccumulationRect accumulator;
  for (size_t i = 0; i < count; i++) {
    accumulator.accumulate(pts[i]);
  }
  SkRect point_bounds = accumulator.bounds();
  if (!AccumulateOpBounds(point_bounds, flags)) {
    return;
  }

  void* data_ptr;
  switch (mode) {
    case PointMode::kPoints:
      data_ptr = Push<DrawPointsOp>(bytes, count);
      break;
    case PointMode::kLines:
      data_ptr = Push<DrawLinesOp>(bytes, count);
      break;
    case PointMode::kPolygon:
      data_ptr = Push<DrawPolygonOp>(bytes, count);
      break;
    default:
      FML_UNREACHABLE();
      return;
  }
  CopyV(data_ptr, pts, count);
  // drawPoints treats every point or line (or segment of a polygon)
  // as a completely separate operation meaning we cannot ensure
  // distribution of group opacity without analyzing the mode and the
  // bounds of every sub-primitive.
  // See: https://fiddle.skia.org/c/228459001d2de8db117ce25ef5cedb0c
  current_layer().layer_local_accumulator.record_overlapping_bounds();
  // Even though we've eliminated the possibility of opacity peephole
  // optimizations above, we still set the appropriate flags based on
  // the rendering attributes in case we solve the overlapping points
  // problem above.
  CheckLayerOpacityCompatibility();
  UpdateLayerResult(result);
}
void DisplayListBuilder::DrawPoints(PointMode mode,
                                    uint32_t count,
                                    const SkPoint pts[],
                                    const DlPaint& paint) {
  SetAttributesFromPaint(paint, FlagsForPointMode(mode));
  drawPoints(mode, count, pts);
}
void DisplayListBuilder::drawVertices(
    const std::shared_ptr<DlVertices>& vertices,
    DlBlendMode mode) {
  DisplayListAttributeFlags flags = kDrawVerticesFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect &&
      AccumulateOpBounds(vertices->bounds(), flags)) {
    Push<DrawVerticesOp>(0, vertices, mode);
    // DrawVertices applies its colors to the paint so we have no way
    // of controlling opacity using the current paint attributes.
    // Although, examination of the |mode| might find some predictable
    // cases.
    UpdateLayerOpacityCompatibility(false);
    UpdateLayerResult(result);
    // Even though we already eliminated opacity peephole optimization
    // due to the color issues identified above, drawVertices also fails
    // based on the fact that the vertices are rendered independently
    // so we cannot guarantee the non-overlapping condition. We record
    // both conditions in case a solution is found to applying the
    // colors above - both conditions must be analyzed sufficiently
    // and implemented accordingly before drawVertices is compatible with
    // opacity peephole optimizations.
    current_layer().layer_local_accumulator.record_overlapping_bounds();
  }
}
void DisplayListBuilder::DrawVertices(
    const std::shared_ptr<DlVertices>& vertices,
    DlBlendMode mode,
    const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawVerticesFlags);
  drawVertices(vertices, mode);
}

void DisplayListBuilder::drawImage(const sk_sp<DlImage> image,
                                   const SkPoint point,
                                   DlImageSampling sampling,
                                   bool render_with_attributes) {
  DisplayListAttributeFlags flags = render_with_attributes  //
                                        ? kDrawImageWithPaintFlags
                                        : kDrawImageFlags;
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    return;
  }
  SkRect bounds = SkRect::MakeXYWH(point.fX, point.fY,  //
                                   image->width(), image->height());
  if (AccumulateOpBounds(bounds, flags)) {
    render_with_attributes
        ? Push<DrawImageWithAttrOp>(0, image, point, sampling)
        : Push<DrawImageOp>(0, image, point, sampling);
    CheckLayerOpacityCompatibility(render_with_attributes);
    UpdateLayerResult(result, render_with_attributes);
    is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe();
  }
}
void DisplayListBuilder::DrawImage(const sk_sp<DlImage>& image,
                                   const SkPoint point,
                                   DlImageSampling sampling,
                                   const DlPaint* paint) {
  if (paint != nullptr) {
    SetAttributesFromPaint(*paint,
                           DisplayListOpFlags::kDrawImageWithPaintFlags);
    drawImage(image, point, sampling, true);
  } else {
    drawImage(image, point, sampling, false);
  }
}
void DisplayListBuilder::drawImageRect(const sk_sp<DlImage> image,
                                       const SkRect& src,
                                       const SkRect& dst,
                                       DlImageSampling sampling,
                                       bool render_with_attributes,
                                       SrcRectConstraint constraint) {
  DisplayListAttributeFlags flags = render_with_attributes
                                        ? kDrawImageRectWithPaintFlags
                                        : kDrawImageRectFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
    Push<DrawImageRectOp>(0, image, src, dst, sampling, render_with_attributes,
                          constraint);
    CheckLayerOpacityCompatibility(render_with_attributes);
    UpdateLayerResult(result, render_with_attributes);
    is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe();
  }
}
void DisplayListBuilder::DrawImageRect(const sk_sp<DlImage>& image,
                                       const SkRect& src,
                                       const SkRect& dst,
                                       DlImageSampling sampling,
                                       const DlPaint* paint,
                                       SrcRectConstraint constraint) {
  if (paint != nullptr) {
    SetAttributesFromPaint(*paint,
                           DisplayListOpFlags::kDrawImageRectWithPaintFlags);
    drawImageRect(image, src, dst, sampling, true, constraint);
  } else {
    drawImageRect(image, src, dst, sampling, false, constraint);
  }
}
void DisplayListBuilder::drawImageNine(const sk_sp<DlImage> image,
                                       const SkIRect& center,
                                       const SkRect& dst,
                                       DlFilterMode filter,
                                       bool render_with_attributes) {
  DisplayListAttributeFlags flags = render_with_attributes
                                        ? kDrawImageNineWithPaintFlags
                                        : kDrawImageNineFlags;
  OpResult result = PaintResult(current_, flags);
  if (result != OpResult::kNoEffect && AccumulateOpBounds(dst, flags)) {
    render_with_attributes
        ? Push<DrawImageNineWithAttrOp>(0, image, center, dst, filter)
        : Push<DrawImageNineOp>(0, image, center, dst, filter);
    CheckLayerOpacityCompatibility(render_with_attributes);
    UpdateLayerResult(result, render_with_attributes);
    is_ui_thread_safe_ = is_ui_thread_safe_ && image->isUIThreadSafe();
  }
}
void DisplayListBuilder::DrawImageNine(const sk_sp<DlImage>& image,
                                       const SkIRect& center,
                                       const SkRect& dst,
                                       DlFilterMode filter,
                                       const DlPaint* paint) {
  if (paint != nullptr) {
    SetAttributesFromPaint(*paint,
                           DisplayListOpFlags::kDrawImageNineWithPaintFlags);
    drawImageNine(image, center, dst, filter, true);
  } else {
    drawImageNine(image, center, dst, filter, false);
  }
}
void DisplayListBuilder::drawAtlas(const sk_sp<DlImage> atlas,
                                   const SkRSXform xform[],
                                   const SkRect tex[],
                                   const DlColor colors[],
                                   int count,
                                   DlBlendMode mode,
                                   DlImageSampling sampling,
                                   const SkRect* cull_rect,
                                   bool render_with_attributes) {
  DisplayListAttributeFlags flags = render_with_attributes  //
                                        ? kDrawAtlasWithPaintFlags
                                        : kDrawAtlasFlags;
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    return;
  }
  SkPoint quad[4];
  AccumulationRect accumulator;
  for (int i = 0; i < count; i++) {
    const SkRect& src = tex[i];
    xform[i].toQuad(src.width(), src.height(), quad);
    for (int j = 0; j < 4; j++) {
      accumulator.accumulate(quad[j]);
    }
  }
  if (accumulator.is_empty() ||
      !AccumulateOpBounds(accumulator.bounds(), flags)) {
    return;
  }
  // Accumulating the bounds might not trip the overlap condition if the
  // whole atlas operation is separated from other rendering calls, but
  // since each atlas op is treated as an independent operation, we have
  // to pass along our locally computed overlap condition for the individual
  // atlas operations to the layer accumulator.
  // Note that the above accumulation may falsely trigger the overlapping
  // state as it is done quad corner by quad corner and an entire quad may
  // be non-overlapping with the layer bounds, but as we add each point
  // independently it might expand the bounds on one corner and then flag
  // the condition when the next corner is added.
  if (accumulator.overlap_detected()) {
    current_layer().layer_local_accumulator.record_overlapping_bounds();
  }

  int bytes = count * (sizeof(SkRSXform) + sizeof(SkRect));
  void* data_ptr;
  if (colors != nullptr) {
    bytes += count * sizeof(DlColor);
    if (cull_rect != nullptr) {
      data_ptr =
          Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling, true,
                                  *cull_rect, render_with_attributes);
    } else {
      data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling, true,
                                   render_with_attributes);
    }
    CopyV(data_ptr, xform, count, tex, count, colors, count);
  } else {
    if (cull_rect != nullptr) {
      data_ptr =
          Push<DrawAtlasCulledOp>(bytes, atlas, count, mode, sampling, false,
                                  *cull_rect, render_with_attributes);
    } else {
      data_ptr = Push<DrawAtlasOp>(bytes, atlas, count, mode, sampling, false,
                                   render_with_attributes);
    }
    CopyV(data_ptr, xform, count, tex, count);
  }
  // drawAtlas treats each image as a separate operation so we cannot rely
  // on it to distribute the opacity without overlap without checking all
  // of the transforms and texture rectangles.
  UpdateLayerOpacityCompatibility(false);
  UpdateLayerResult(result, render_with_attributes);
  is_ui_thread_safe_ = is_ui_thread_safe_ && atlas->isUIThreadSafe();
}
void DisplayListBuilder::DrawAtlas(const sk_sp<DlImage>& atlas,
                                   const SkRSXform xform[],
                                   const SkRect tex[],
                                   const DlColor colors[],
                                   int count,
                                   DlBlendMode mode,
                                   DlImageSampling sampling,
                                   const SkRect* cull_rect,
                                   const DlPaint* paint) {
  if (paint != nullptr) {
    SetAttributesFromPaint(*paint,
                           DisplayListOpFlags::kDrawAtlasWithPaintFlags);
    drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull_rect,
              true);
  } else {
    drawAtlas(atlas, xform, tex, colors, count, mode, sampling, cull_rect,
              false);
  }
}

void DisplayListBuilder::DrawDisplayList(const sk_sp<DisplayList> display_list,
                                         SkScalar opacity) {
  if (!std::isfinite(opacity) || opacity <= SK_ScalarNearlyZero ||
      display_list->op_count() == 0 || display_list->bounds().isEmpty() ||
      current_info().is_nop) {
    return;
  }
  const SkRect bounds = display_list->bounds();
  bool accumulated;
  sk_sp<const DlRTree> rtree;
  if (!rtree_data_.has_value() || !(rtree = display_list->rtree())) {
    accumulated = AccumulateOpBounds(bounds, kDrawDisplayListFlags);
  } else {
    std::list<SkRect> rects =
        rtree->searchAndConsolidateRects(GetLocalClipBounds(), false);
    accumulated = false;
    for (const SkRect& rect : rects) {
      // TODO (https://github.com/flutter/flutter/issues/114919): Attributes
      // are not necessarily `kDrawDisplayListFlags`.
      if (AccumulateOpBounds(rect, kDrawDisplayListFlags)) {
        accumulated = true;
      }
    }
  }
  if (!accumulated) {
    return;
  }

  DlPaint current_paint = current_;
  Push<DrawDisplayListOp>(0, display_list,
                          opacity < SK_Scalar1 ? opacity : SK_Scalar1);

  // This depth increment accounts for every draw call in the child
  // DisplayList and is in addition to the implicit depth increment
  // that was performed when we pushed the DrawDisplayListOp. The
  // eventual dispatcher can use or ignore the implicit depth increment
  // as it sees fit depending on whether it needs to do rendering
  // before or after the drawDisplayList op, but it must be accounted
  // for if the depth value accounting is to remain consistent between
  // the recording and dispatching process.
  depth_ += display_list->total_depth();

  is_ui_thread_safe_ = is_ui_thread_safe_ && display_list->isUIThreadSafe();
  // Not really necessary if the developer is interacting with us via
  // our attribute-state-less DlCanvas methods, but this avoids surprises
  // for those who may have been using the stateful Dispatcher methods.
  SetAttributesFromPaint(current_paint,
                         DisplayListOpFlags::kSaveLayerWithPaintFlags);

  // The non-nested op count accumulated in the |Push| method will include
  // this call to |drawDisplayList| for non-nested op count metrics.
  // But, for nested op count metrics we want the |drawDisplayList| call itself
  // to be transparent. So we subtract 1 from our accumulated nested count to
  // balance out against the 1 that was accumulated into the regular count.
  // This behavior is identical to the way SkPicture computed nested op counts.
  nested_op_count_ += display_list->op_count(true) - 1;
  nested_bytes_ += display_list->bytes(true);
  UpdateLayerOpacityCompatibility(display_list->can_apply_group_opacity());
  // Nop DisplayLists are eliminated above so we either affect transparent
  // pixels or we do not. We should not have [kNoEffect].
  UpdateLayerResult(display_list->modifies_transparent_black()
                        ? OpResult::kAffectsAll
                        : OpResult::kPreservesTransparency,
                    display_list->max_root_blend_mode());
  if (display_list->root_has_backdrop_filter()) {
    current_layer().contains_backdrop_filter = true;
  }
}
void DisplayListBuilder::drawTextBlob(const sk_sp<SkTextBlob> blob,
                                      SkScalar x,
                                      SkScalar y) {
  DisplayListAttributeFlags flags = kDrawTextBlobFlags;
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    return;
  }
  bool unclipped = AccumulateOpBounds(blob->bounds().makeOffset(x, y), flags);
  // TODO(https://github.com/flutter/flutter/issues/82202): Remove once the
  // unit tests can use Fuchsia's font manager instead of the empty default.
  // Until then we might encounter empty bounds for otherwise valid text and
  // thus we ignore the results from AccumulateOpBounds.
#if defined(OS_FUCHSIA)
  unclipped = true;
#endif  // OS_FUCHSIA
  if (unclipped) {
    Push<DrawTextBlobOp>(0, blob, x, y);
    // There is no way to query if the glyphs of a text blob overlap and
    // there are no current guarantees from either Skia or Impeller that
    // they will protect overlapping glyphs from the effects of overdraw
    // so we must make the conservative assessment that this DL layer is
    // not compatible with group opacity inheritance.
    UpdateLayerOpacityCompatibility(false);
    UpdateLayerResult(result);
  }
}
void DisplayListBuilder::DrawTextBlob(const sk_sp<SkTextBlob>& blob,
                                      SkScalar x,
                                      SkScalar y,
                                      const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags);
  drawTextBlob(blob, x, y);
}

void DisplayListBuilder::drawTextFrame(
    const std::shared_ptr<impeller::TextFrame>& text_frame,
    SkScalar x,
    SkScalar y) {
  DisplayListAttributeFlags flags = kDrawTextBlobFlags;
  OpResult result = PaintResult(current_, flags);
  if (result == OpResult::kNoEffect) {
    return;
  }
  impeller::Rect bounds = text_frame->GetBounds();
  SkRect sk_bounds = SkRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
                                      bounds.GetRight(), bounds.GetBottom());
  bool unclipped = AccumulateOpBounds(sk_bounds.makeOffset(x, y), flags);
  // TODO(https://github.com/flutter/flutter/issues/82202): Remove once the
  // unit tests can use Fuchsia's font manager instead of the empty default.
  // Until then we might encounter empty bounds for otherwise valid text and
  // thus we ignore the results from AccumulateOpBounds.
#if defined(OS_FUCHSIA)
  unclipped = true;
#endif  // OS_FUCHSIA
  if (unclipped) {
    Push<DrawTextFrameOp>(0, text_frame, x, y);
    // There is no way to query if the glyphs of a text blob overlap and
    // there are no current guarantees from either Skia or Impeller that
    // they will protect overlapping glyphs from the effects of overdraw
    // so we must make the conservative assessment that this DL layer is
    // not compatible with group opacity inheritance.
    UpdateLayerOpacityCompatibility(false);
    UpdateLayerResult(result);
  }
}

void DisplayListBuilder::DrawTextFrame(
    const std::shared_ptr<impeller::TextFrame>& text_frame,
    SkScalar x,
    SkScalar y,
    const DlPaint& paint) {
  SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawTextBlobFlags);
  drawTextFrame(text_frame, x, y);
}

void DisplayListBuilder::DrawShadow(const SkPath& path,
                                    const DlColor color,
                                    const SkScalar elevation,
                                    bool transparent_occluder,
                                    SkScalar dpr) {
  OpResult result = PaintResult(DlPaint(color));
  if (result != OpResult::kNoEffect) {
    SkRect shadow_bounds =
        DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform());
    if (AccumulateOpBounds(shadow_bounds, kDrawShadowFlags)) {
      transparent_occluder  //
          ? Push<DrawShadowTransparentOccluderOp>(0, path, color, elevation,
                                                  dpr)
          : Push<DrawShadowOp>(0, path, color, elevation, dpr);
      UpdateLayerOpacityCompatibility(false);
      UpdateLayerResult(result, DlBlendMode::kSrcOver);
    }
  }
}

bool DisplayListBuilder::AdjustBoundsForPaint(SkRect& bounds,
                                              DisplayListAttributeFlags flags) {
  if (flags.ignores_paint()) {
    return true;
  }

  if (flags.is_geometric()) {
    bool is_stroked = flags.is_stroked(current_.getDrawStyle());

    // Path effect occurs before stroking...
    DisplayListSpecialGeometryFlags special_flags =
        flags.GeometryFlags(is_stroked);

    if (is_stroked) {
      // Determine the max multiplier to the stroke width first.
      SkScalar pad = 1.0f;
      if (current_.getStrokeJoin() == DlStrokeJoin::kMiter &&
          special_flags.may_have_acute_joins()) {
        pad = std::max(pad, current_.getStrokeMiter());
      }
      if (current_.getStrokeCap() == DlStrokeCap::kSquare &&
          special_flags.may_have_diagonal_caps()) {
        pad = std::max(pad, SK_ScalarSqrt2);
      }
      SkScalar min_stroke_width = 0.01;
      pad *= std::max(current_.getStrokeWidth() * 0.5f, min_stroke_width);
      bounds.outset(pad, pad);
    }
  }

  if (flags.applies_mask_filter()) {
    auto filter = current_.getMaskFilter();
    if (filter) {
      switch (filter->type()) {
        case DlMaskFilterType::kBlur: {
          FML_DCHECK(filter->asBlur());
          SkScalar mask_sigma_pad = filter->asBlur()->sigma() * 3.0;
          bounds.outset(mask_sigma_pad, mask_sigma_pad);
        }
      }
    }
  }

  // Color filter does not modify bounds even if it affects transparent
  // black because it is clipped by the "mask" of the primitive. That
  // property only comes into play when it is applied to something like
  // a layer.

  if (flags.applies_image_filter()) {
    auto filter = current_.getImageFilterPtr();
    if (filter && !filter->map_local_bounds(bounds, bounds)) {
      return false;
    }
  }

  return true;
}

bool DisplayListBuilder::AccumulateUnbounded(const SaveInfo& save) {
  SkRect global_clip = save.global_state.device_cull_rect();
  SkRect layer_clip = save.global_state.local_cull_rect();
  if (global_clip.isEmpty() || !save.layer_state.mapAndClipRect(&layer_clip)) {
    return false;
  }
  if (rtree_data_.has_value()) {
    FML_DCHECK(save.layer_info->global_space_accumulator.is_empty());
    rtree_data_->rects.push_back(global_clip);
    rtree_data_->indices.push_back(op_index_);
  } else {
    save.layer_info->global_space_accumulator.accumulate(global_clip);
  }
  save.layer_info->layer_local_accumulator.accumulate(layer_clip);
  return true;
}

bool DisplayListBuilder::AccumulateOpBounds(SkRect& bounds,
                                            DisplayListAttributeFlags flags) {
  if (AdjustBoundsForPaint(bounds, flags)) {
    return AccumulateBounds(bounds);
  } else {
    return AccumulateUnbounded();
  }
}

bool DisplayListBuilder::AccumulateBounds(const SkRect& bounds,
                                          SaveInfo& layer,
                                          int id) {
  if (bounds.isEmpty()) {
    return false;
  }
  SkRect global_bounds;
  SkRect layer_bounds;
  if (!layer.global_state.mapAndClipRect(bounds, &global_bounds) ||
      !layer.layer_state.mapAndClipRect(bounds, &layer_bounds)) {
    return false;
  }
  if (rtree_data_.has_value()) {
    FML_DCHECK(layer.layer_info->global_space_accumulator.is_empty());
    if (id >= 0) {
      rtree_data_->rects.push_back(global_bounds);
      rtree_data_->indices.push_back(id);
    }
  } else {
    layer.layer_info->global_space_accumulator.accumulate(global_bounds);
  }
  layer.layer_info->layer_local_accumulator.accumulate(layer_bounds);
  return true;
}

bool DisplayListBuilder::SaveInfo::AccumulateBoundsLocal(const SkRect& bounds) {
  if (bounds.isEmpty()) {
    return false;
  }
  SkRect local_bounds;
  if (!layer_state.mapAndClipRect(bounds, &local_bounds)) {
    return false;
  }
  layer_info->layer_local_accumulator.accumulate(local_bounds);
  return true;
}

bool DisplayListBuilder::paint_nops_on_transparency() {
  // SkImageFilter::canComputeFastBounds tests for transparency behavior
  // This test assumes that the blend mode checked down below will
  // NOP on transparent black.
  if (current_.getImageFilterPtr() &&
      current_.getImageFilterPtr()->modifies_transparent_black()) {
    return false;
  }

  // We filter the transparent black that is used for the background of a
  // saveLayer and make sure it returns transparent black. If it does, then
  // the color filter will leave all area surrounding the contents of the
  // save layer untouched out to the edge of the output surface.
  // This test assumes that the blend mode checked down below will
  // NOP on transparent black.
  if (current_.getColorFilterPtr() &&
      current_.getColorFilterPtr()->modifies_transparent_black()) {
    return false;
  }

  // Unusual blendmodes require us to process a saved layer
  // even with operations outside the clip.
  // For example, DstIn is used by masking layers.
  // https://code.google.com/p/skia/issues/detail?id=1291
  // https://crbug.com/401593
  switch (current_.getBlendMode()) {
    // For each of the following transfer modes, if the source
    // alpha is zero (our transparent black), the resulting
    // blended pixel is not necessarily equal to the original
    // destination pixel.
    // Mathematically, any time in the following equations where
    // the result is not d assuming source is 0
    case DlBlendMode::kClear:     // r = 0
    case DlBlendMode::kSrc:       // r = s
    case DlBlendMode::kSrcIn:     // r = s * da
    case DlBlendMode::kDstIn:     // r = d * sa
    case DlBlendMode::kSrcOut:    // r = s * (1-da)
    case DlBlendMode::kDstATop:   // r = d*sa + s*(1-da)
    case DlBlendMode::kModulate:  // r = s*d
      return false;
      break;

    // And in these equations, the result must be d if the
    // source is 0
    case DlBlendMode::kDst:         // r = d
    case DlBlendMode::kSrcOver:     // r = s + (1-sa)*d
    case DlBlendMode::kDstOver:     // r = d + (1-da)*s
    case DlBlendMode::kDstOut:      // r = d * (1-sa)
    case DlBlendMode::kSrcATop:     // r = s*da + d*(1-sa)
    case DlBlendMode::kXor:         // r = s*(1-da) + d*(1-sa)
    case DlBlendMode::kPlus:        // r = min(s + d, 1)
    case DlBlendMode::kScreen:      // r = s + d - s*d
    case DlBlendMode::kOverlay:     // multiply or screen, depending on dest
    case DlBlendMode::kDarken:      // rc = s + d - max(s*da, d*sa),
                                    // ra = kSrcOver
    case DlBlendMode::kLighten:     // rc = s + d - min(s*da, d*sa),
                                    // ra = kSrcOver
    case DlBlendMode::kColorDodge:  // brighten destination to reflect source
    case DlBlendMode::kColorBurn:   // darken destination to reflect source
    case DlBlendMode::kHardLight:   // multiply or screen, depending on source
    case DlBlendMode::kSoftLight:   // lighten or darken, depending on source
    case DlBlendMode::kDifference:  // rc = s + d - 2*(min(s*da, d*sa)),
                                    // ra = kSrcOver
    case DlBlendMode::kExclusion:   // rc = s + d - two(s*d), ra = kSrcOver
    case DlBlendMode::kMultiply:    // r = s*(1-da) + d*(1-sa) + s*d
    case DlBlendMode::kHue:         // ra = kSrcOver
    case DlBlendMode::kSaturation:  // ra = kSrcOver
    case DlBlendMode::kColor:       // ra = kSrcOver
    case DlBlendMode::kLuminosity:  // ra = kSrcOver
      return true;
      break;
  }
}

DlColor DisplayListBuilder::GetEffectiveColor(const DlPaint& paint,
                                              DisplayListAttributeFlags flags) {
  DlColor color;
  if (flags.applies_color()) {
    const DlColorSource* source = paint.getColorSourcePtr();
    if (source) {
      if (source->asColor()) {
        color = source->asColor()->color();
      } else {
        color = source->is_opaque() ? DlColor::kBlack() : kAnyColor;
      }
    } else {
      color = paint.getColor();
    }
  } else if (flags.applies_alpha()) {
    // If the operation applies alpha, but not color, then the only impact
    // of the alpha is to modulate the output towards transparency.
    // We can not guarantee an opaque source even if the alpha is opaque
    // since that would require knowing something about the colors that
    // the alpha is modulating, but we can guarantee a transparent source
    // if the alpha is 0.
    color = (paint.getAlpha() == 0) ? DlColor::kTransparent() : kAnyColor;
  } else {
    color = kAnyColor;
  }
  if (flags.applies_image_filter()) {
    auto filter = paint.getImageFilterPtr();
    if (filter) {
      if (!color.isTransparent() || filter->modifies_transparent_black()) {
        color = kAnyColor;
      }
    }
  }
  if (flags.applies_color_filter()) {
    auto filter = paint.getColorFilterPtr();
    if (filter) {
      if (!color.isTransparent() || filter->modifies_transparent_black()) {
        color = kAnyColor;
      }
    }
  }
  return color;
}

DisplayListBuilder::OpResult DisplayListBuilder::PaintResult(
    const DlPaint& paint,
    DisplayListAttributeFlags flags) {
  if (current_info().is_nop) {
    return OpResult::kNoEffect;
  }
  if (flags.applies_blend()) {
    switch (paint.getBlendMode()) {
      // Nop blend mode (singular, there is only one)
      case DlBlendMode::kDst:
        return OpResult::kNoEffect;

      // Always clears pixels blend mode (singular, there is only one)
      case DlBlendMode::kClear:
        return OpResult::kPreservesTransparency;

      case DlBlendMode::kHue:
      case DlBlendMode::kSaturation:
      case DlBlendMode::kColor:
      case DlBlendMode::kLuminosity:
      case DlBlendMode::kColorBurn:
        return GetEffectiveColor(paint, flags).isTransparent()
                   ? OpResult::kNoEffect
                   : OpResult::kAffectsAll;

      // kSrcIn modifies pixels towards transparency
      case DlBlendMode::kSrcIn:
        return OpResult::kPreservesTransparency;

      // These blend modes preserve destination alpha
      case DlBlendMode::kSrcATop:
      case DlBlendMode::kDstOut:
        return GetEffectiveColor(paint, flags).isTransparent()
                   ? OpResult::kNoEffect
                   : OpResult::kPreservesTransparency;

      // Always destructive blend modes, potentially not affecting transparency
      case DlBlendMode::kSrc:
      case DlBlendMode::kSrcOut:
      case DlBlendMode::kDstATop:
        return GetEffectiveColor(paint, flags).isTransparent()
                   ? OpResult::kPreservesTransparency
                   : OpResult::kAffectsAll;

      // The kDstIn blend mode modifies the destination unless the
      // source color is opaque.
      case DlBlendMode::kDstIn:
        return GetEffectiveColor(paint, flags).isOpaque()
                   ? OpResult::kNoEffect
                   : OpResult::kPreservesTransparency;

      // The next group of blend modes modifies the destination unless the
      // source color is transparent.
      case DlBlendMode::kSrcOver:
      case DlBlendMode::kDstOver:
      case DlBlendMode::kXor:
      case DlBlendMode::kPlus:
      case DlBlendMode::kScreen:
      case DlBlendMode::kMultiply:
      case DlBlendMode::kOverlay:
      case DlBlendMode::kDarken:
      case DlBlendMode::kLighten:
      case DlBlendMode::kColorDodge:
      case DlBlendMode::kHardLight:
      case DlBlendMode::kSoftLight:
      case DlBlendMode::kDifference:
      case DlBlendMode::kExclusion:
        return GetEffectiveColor(paint, flags).isTransparent()
                   ? OpResult::kNoEffect
                   : OpResult::kAffectsAll;

      // Modulate only leaves the pixel alone when the source is white.
      case DlBlendMode::kModulate:
        return GetEffectiveColor(paint, flags) == DlColor::kWhite()
                   ? OpResult::kNoEffect
                   : OpResult::kPreservesTransparency;
    }
  }
  return OpResult::kAffectsAll;
}

}  // namespace flutter
