// 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/flow/layers/backdrop_filter_layer.h"

namespace flutter {

BackdropFilterLayer::BackdropFilterLayer(
    std::shared_ptr<const DlImageFilter> filter,
    DlBlendMode blend_mode)
    : filter_(std::move(filter)), blend_mode_(blend_mode) {}

void BackdropFilterLayer::Diff(DiffContext* context, const Layer* old_layer) {
  DiffContext::AutoSubtreeRestore subtree(context);
  auto* prev = static_cast<const BackdropFilterLayer*>(old_layer);
  if (!context->IsSubtreeDirty()) {
    FML_DCHECK(prev);
    if (NotEquals(filter_, prev->filter_)) {
      context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
    }
  }

  // Backdrop filter paints everywhere in cull rect
  auto paint_bounds = context->GetCullRect();
  context->AddLayerBounds(paint_bounds);

  if (filter_) {
    context->GetTransform().mapRect(&paint_bounds);
    auto filter_target_bounds = paint_bounds.roundOut();
    SkIRect filter_input_bounds;  // in screen coordinates
    filter_->get_input_device_bounds(
        filter_target_bounds, context->GetTransform(), filter_input_bounds);
    context->AddReadbackRegion(filter_input_bounds);
  }

  DiffChildren(context, prev);

  context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
}

void BackdropFilterLayer::Preroll(PrerollContext* context,
                                  const SkMatrix& matrix) {
  Layer::AutoPrerollSaveLayerState save =
      Layer::AutoPrerollSaveLayerState::Create(context, true, bool(filter_));
  if (context->view_embedder != nullptr) {
    context->view_embedder->PushFilterToVisitedPlatformViews(filter_);
  }
  SkRect child_paint_bounds = SkRect::MakeEmpty();
  PrerollChildren(context, matrix, &child_paint_bounds);
  child_paint_bounds.join(context->cull_rect);
  set_paint_bounds(child_paint_bounds);
  context->subtree_can_inherit_opacity = true;
}

void BackdropFilterLayer::Paint(PaintContext& context) const {
  TRACE_EVENT0("flutter", "BackdropFilterLayer::Paint");
  FML_DCHECK(needs_painting(context));

  AutoCachePaint save_paint(context);
  save_paint.setBlendMode(blend_mode_);
  if (context.leaf_nodes_builder) {
    // Note that we perform a saveLayer directly on the
    // leaf_nodes_builder here similar to how the SkCanvas
    // path specifies the kLeafNodesCanvas below.
    // See https:://flutter.dev/go/backdrop-filter-with-overlay-canvas
    context.leaf_nodes_builder->saveLayer(&paint_bounds(),
                                          save_paint.dl_paint(), filter_.get());

    PaintChildren(context);

    context.leaf_nodes_builder->restore();
  } else {
    auto sk_filter = filter_ ? filter_->skia_object() : nullptr;
    Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(
        context,
        SkCanvas::SaveLayerRec{&paint_bounds(), save_paint.sk_paint(),
                               sk_filter.get(), 0},
        // BackdropFilter should only happen on the leaf nodes canvas.
        // See https:://flutter.dev/go/backdrop-filter-with-overlay-canvas
        AutoSaveLayer::SaveMode::kLeafNodesCanvas);

    PaintChildren(context);
  }
}

}  // namespace flutter
