// 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.

#ifndef FLUTTER_FLOW_LAYERS_LAYER_STATE_STACK_H_
#define FLUTTER_FLOW_LAYERS_LAYER_STATE_STACK_H_

#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_canvas_recorder.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/paint_utils.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace flutter {

/// The LayerStateStack manages the inherited state passed down between
/// |Layer| objects in a |LayerTree| during |Preroll| and |Paint|.
///
/// More specifically, it manages the clip and transform state during
/// recursive rendering and will hold and lazily apply opacity, ImageFilter
/// and ColorFilter attributes to recursive content. This is not a truly
/// general state management mechnanism as it makes assumptions that code
/// will be applying the attributes to rendered content that happens in
/// recursive calls. The automatic save/restore mechanisms only work in
/// a context where C++ auto-destruct calls will engage the restore at
/// the end of a code block and that any applied attributes will only
/// be applied to the content rendered inside that block. These restrictions
/// match the organization of the |LayerTree| methods precisely.
///
/// The stack can manage a single state delegate. The delegate will provide
/// tracking of the current transform and clip and will also execute
/// saveLayer calls at the appropriate time if it is a rendering delegate.
/// The delegate can be swapped out on the fly (as is typically done by
/// PlatformViewLayer when recording the state for multiple "overlay"
/// layers that occur between embedded view subtrees. The old delegate
/// will be restored to its original state before it became a delegate
/// and the new delegate will have all of the state recorded by the stack
/// replayed into it to bring it up to speed with the current rendering
/// context.
///
/// The delegate can be any one of:
///   - Preroll delegate: used during Preroll to remember the outstanding
///                       state for embedded platform layers
///   - SkCanvas: used during Paint for the default output to a Skia
///               surface
///   - DisplayListBuilder: used during Paint to construct a DisplayList
///                         for Impeller output
/// The stack will know which state needs to be conveyed to any of these
/// delegates and when is the best time to convey that state (i.e. lazy
/// saveLayer calls for example).
///
/// The rendering state attributes will be automatically applied to the
/// nested content using a |saveLayer| call at the point at which we
/// encounter rendered content (i.e. various nested layers that exist only
/// to apply new state will not trigger the |saveLayer| and the attributes
/// can accumulate until we reach actual content that is rendered.) Some
/// rendered content can avoid the |saveLayer| if it reports to the object
/// that it is able to apply all of the attributes that happen to be
/// outstanding (accumulated from parent state-modifiers). A |ContainerLayer|
/// can also monitor the attribute rendering capabilities of a list of
/// children and can ask the object to apply a protective |saveLayer| or
/// not based on the negotiated capabilities of the entire group.
///
/// Any code that is planning to modify the clip, transform, or rendering
/// attributes for its child content must start by calling the |save| method
/// which returns a MutatorContext object. The methods that modify such
/// state only exist on the MutatorContext object so it is difficult to get
/// that wrong, but the caller must make sure that the call happens within
/// a C++ code block that will define the "rendering scope" of those
/// state changes as they will be automatically restored on exit from that
/// block. Note that the layer might make similar state calls directly on
/// the canvas or builder during the Paint cycle (via saveLayer, transform,
/// or clip calls), but should avoid doing so if there is any nested content
/// that needs to track or react to those state calls.
///
/// Code that needs to render content can simply inform the parent of their
/// abilities by setting the |PrerollContext::renderable_state_flags| during
/// |Preroll| and then render with those attributes during |Paint| by
/// requesting the outstanding values of those attributes from the state_stack
/// object. Individual leaf layers can ignore this feature as the default
/// behavior during |Preroll| will have their parent |ContainerLayer| assume
/// that they cannot render any outstanding state attributes and will apply
/// the protective saveLayer on their behalf if needed. As such, this object
/// only provides "opt-in" features for leaf layers and no responsibilities
/// otherwise.
/// See |LayerStateStack::fill|
/// See |LayerStateStack::outstanding_opacity|
/// See |LayerStateStack::outstanding_color_filter|
/// See |LayerStateStack::outstanding_image_filter|
///
/// State-modifying layers should contain code similar to this pattern in both
/// their |Preroll| and |Paint| methods.
///
/// void [LayerType]::[Preroll/Paint](context) {
///   auto mutator = context.state_stack.save();
///   mutator.translate(origin.x, origin.y);
///   mutator.applyOpacity(content_bounds, opacity_value);
///   mutator.applyColorFilter(content_bounds, color_filter);
///   // or any of the mutator transform, clip or attribute methods
///
///   // Children will react to the state applied above during their
///   // Preroll/Paint methods or ContainerLayer will protect them
///   // conservatively by default.
///   [Preroll/Paint]Children(context);
///
///   // here the mutator will be auto-destructed and the state accumulated
///   // by it will be restored out of the state_stack and its associated
///   // delegates.
/// }
class LayerStateStack {
 public:
  LayerStateStack();

  // Clears out any old delegate to make room for a new one.
  void clear_delegate();

  // Return the SkCanvas delegate if the state stack has such a delegate.
  // The state stack will only have one delegate at a time holding either
  // an SkCanvas, DisplayListBuilder, or a preroll accumulator.
  // See also |builder_delegate|.
  SkCanvas* canvas_delegate() { return delegate_->canvas(); }

  // Return the DisplayListBuilder delegate if the state stack has such a
  // delegate.
  // The state stack will only have one delegate at a time holding either
  // an SkCanvas, DisplayListBuilder, or a preroll accumulator.
  // See also |builder_delegate|.
  DisplayListBuilder* builder_delegate() { return delegate_->builder(); }

  // Clears the old delegate and sets the canvas delegate to the indicated
  // canvas (if not nullptr). This ensures that only one delegate - either a
  // canvas, a builder, or a preroll accumulator - is present at any one time.
  void set_delegate(SkCanvas* canvas);

  // Clears the old delegate and sets the builder delegate to the indicated
  // buider (if not nullptr). This ensures that only one delegate - either a
  // canvas, a builder, or a preroll accumulator - is present at any one time.
  void set_delegate(DisplayListBuilder* builder);
  void set_delegate(sk_sp<DisplayListBuilder> builder) {
    set_delegate(builder.get());
  }
  void set_delegate(DisplayListCanvasRecorder& recorder) {
    set_delegate(recorder.builder().get());
  }

  // Clears the old delegate and sets the state stack up to accumulate
  // clip and transform information for a Preroll phase. This ensures
  // that only one delegate - either a canvas, a builder, or a preroll
  // accumulator - is present at any one time.
  void set_preroll_delegate(const SkRect& cull_rect, const SkMatrix& matrix);
  void set_preroll_delegate(const SkRect& cull_rect);
  void set_preroll_delegate(const SkMatrix& matrix);

  // Fills the supplied MatatorsStack object with the mutations recorded
  // by this LayerStateStack in the order encountered.
  void fill(MutatorsStack* mutators);

  // Sets up a checkerboard function that will be used to checkerboard the
  // contents of any saveLayer executed by the state stack.
  CheckerboardFunc checkerboard_func() const { return checkerboard_func_; }
  void set_checkerboard_func(CheckerboardFunc checkerboard_func) {
    checkerboard_func_ = checkerboard_func;
  }

  class AutoRestore {
   public:
    ~AutoRestore() {
      layer_state_stack_->restore_to_count(stack_restore_count_);
    }

   private:
    AutoRestore(LayerStateStack* stack, const SkRect& bounds, int flags)
        : layer_state_stack_(stack),
          stack_restore_count_(stack->stack_count()) {
      if (stack->needs_save_layer(flags)) {
        stack->save_layer(bounds);
      }
    }
    friend class LayerStateStack;

    LayerStateStack* layer_state_stack_;
    const size_t stack_restore_count_;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(AutoRestore);
  };

  class MutatorContext {
   public:
    ~MutatorContext() {
      layer_state_stack_->restore_to_count(stack_restore_count_);
    }

    // Immediately executes a saveLayer with all accumulated state
    // onto the canvas or builder to be applied at the next matching
    // restore. A saveLayer is always executed by this method even if
    // there are no outstanding attributes.
    void saveLayer(const SkRect& bounds);

    // Records the opacity for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the opacity cannot be batched with other
    // outstanding attributes.
    void applyOpacity(const SkRect& bounds, SkScalar opacity);

    // Records the image filter for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the image filter cannot be batched with other
    // outstanding attributes.
    // (Currently only opacity is recorded for batching)
    void applyImageFilter(const SkRect& bounds,
                          const std::shared_ptr<const DlImageFilter>& filter);

    // Records the color filter for application at the next call to
    // saveLayer or applyState. A saveLayer may be executed at
    // this time if the color filter cannot be batched with other
    // outstanding attributes.
    // (Currently only opacity is recorded for batching)
    void applyColorFilter(const SkRect& bounds,
                          const std::shared_ptr<const DlColorFilter>& filter);

    // Saves the state stack and immediately executes a saveLayer
    // with the indicated backdrop filter and any outstanding
    // state attributes. Since the backdrop filter only applies
    // to the pixels alrady on the screen when this call is made,
    // the backdrop filter will only be applied to the canvas or
    // builder installed at the time that this call is made, and
    // subsequent canvas or builder objects that are made delegates
    // will only see a saveLayer with the indicated blend_mode.
    void applyBackdropFilter(const SkRect& bounds,
                             const std::shared_ptr<const DlImageFilter>& filter,
                             DlBlendMode blend_mode);

    void translate(SkScalar tx, SkScalar ty);
    void translate(SkPoint tp) { translate(tp.fX, tp.fY); }
    void transform(const SkM44& m44);
    void transform(const SkMatrix& matrix);
    void integralTransform();

    void clipRect(const SkRect& rect, bool is_aa);
    void clipRRect(const SkRRect& rrect, bool is_aa);
    void clipPath(const SkPath& path, bool is_aa);

   private:
    MutatorContext(LayerStateStack* stack)
        : layer_state_stack_(stack),
          stack_restore_count_(stack->stack_count()),
          save_needed_(true) {}
    friend class LayerStateStack;

    LayerStateStack* layer_state_stack_;
    const size_t stack_restore_count_;
    bool save_needed_;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(MutatorContext);
  };

  static constexpr int kCallerCanApplyOpacity = 0x1;
  static constexpr int kCallerCanApplyColorFilter = 0x2;
  static constexpr int kCallerCanApplyImageFilter = 0x4;
  static constexpr int kCallerCanApplyAnything =
      (kCallerCanApplyOpacity | kCallerCanApplyColorFilter |
       kCallerCanApplyImageFilter);

  // Apply the outstanding state via saveLayer if necessary,
  // respecting the flags representing which potentially
  // outstanding attributes the calling layer can apply
  // themselves.
  //
  // A saveLayer may or may not be sent to the delegates depending
  // on how the outstanding state intersects with the flags supplied
  // by the caller.
  //
  // An AutoRestore instance will always be returned even if there
  // was no saveLayer applied.
  [[nodiscard]] inline AutoRestore applyState(const SkRect& bounds,
                                              int can_apply_flags) {
    return AutoRestore(this, bounds, can_apply_flags);
  }

  SkScalar outstanding_opacity() const { return outstanding_.opacity; }

  std::shared_ptr<const DlColorFilter> outstanding_color_filter() const {
    return outstanding_.color_filter;
  }

  std::shared_ptr<const DlImageFilter> outstanding_image_filter() const {
    return outstanding_.image_filter;
  }

  // The outstanding bounds are the bounds recorded during the last
  // attribute applied to this state stack. The assumption is that
  // the nested calls to the state stack will each supply bounds relative
  // to the content of that single attribute and the bounds of the content
  // of any outstanding attributes will include the output bounds of
  // applying any nested attributes. Thus, only the innermost content
  // bounds received will be sufficient to apply all outstanding attributes.
  SkRect outstanding_bounds() const { return outstanding_.save_layer_bounds; }

  // Fill the provided paint object with any oustanding attributes and
  // return a pointer to it, or return a nullptr if there were no
  // outstanding attributes to paint with.
  SkPaint* fill(SkPaint& paint) const { return outstanding_.fill(paint); }

  // Fill the provided paint object with any oustanding attributes and
  // return a pointer to it, or return a nullptr if there were no
  // outstanding attributes to paint with.
  DlPaint* fill(DlPaint& paint) const { return outstanding_.fill(paint); }

  // The cull_rect (not the exact clip) relative to the device pixels.
  // This rectangle may be a conservative estimate of the true clip region.
  SkRect device_cull_rect() const { return delegate_->device_cull_rect(); }

  // The cull_rect (not the exact clip) relative to the local coordinates.
  // This rectangle may be a conservative estimate of the true clip region.
  SkRect local_cull_rect() const { return delegate_->local_cull_rect(); }

  // The transform from the local coordinates to the device coordinates
  // in the most capable 4x4 matrix representation. This matrix may be
  // more information than is needed to compute bounds for a 2D rendering
  // primitive, but it will accurately concatenate with other 4x4 matrices
  // without losing information.
  SkM44 transform_4x4() const { return delegate_->matrix_4x4(); }

  // The transform from the local coordinates to the device coordinates
  // in a more compact 3x3 matrix represenation that provides enough
  // information to accurately transform 2D primitives into their
  // resulting 2D bounds. This matrix also has enough information to
  // concat with other 2D affine transforms, but does not carry enough
  // information to accurately concat with fully perspective matrics.
  SkMatrix transform_3x3() const { return delegate_->matrix_3x3(); }

  // Tests if painting content with the current outstanding attributes
  // will produce any content. This method does not check the current
  // transform or clip for being singular or empty.
  // See |content_culled|
  bool painting_is_nop() const { return outstanding_.opacity <= 0; }

  // Tests if painting content with the given bounds will produce any output.
  // This method does not check the outstanding attributes to verify that
  // they produce visible results.
  // See |painting_is_nop|
  bool content_culled(const SkRect& content_bounds) const {
    return delegate_->content_culled(content_bounds);
  }

  // Saves the current state of the state stack and returns a
  // MutatorContext which can be used to manipulate the state.
  // The state stack will be restored to its current state
  // when the MutatorContext object goes out of scope.
  [[nodiscard]] inline MutatorContext save() { return MutatorContext(this); }

  // Returns true if the state stack is in, or has returned to,
  // its initial state.
  bool is_empty() const { return state_stack_.empty(); }

 private:
  size_t stack_count() const { return state_stack_.size(); }
  void restore_to_count(size_t restore_count);
  void reapply_all();

  void apply_last_entry() { state_stack_.back()->apply(this); }

  // The push methods simply push an associated StateEntry on the stack
  // and then apply it to the current canvas and builder.
  // ---------------------
  // void push_attributes();
  void push_opacity(const SkRect& rect, SkScalar opacity);
  void push_color_filter(const SkRect& bounds,
                         const std::shared_ptr<const DlColorFilter>& filter);
  void push_image_filter(const SkRect& bounds,
                         const std::shared_ptr<const DlImageFilter>& filter);
  void push_backdrop(const SkRect& bounds,
                     const std::shared_ptr<const DlImageFilter>& filter,
                     DlBlendMode blend_mode);

  void push_translate(SkScalar tx, SkScalar ty);
  void push_transform(const SkM44& matrix);
  void push_transform(const SkMatrix& matrix);
  void push_integral_transform();

  void push_clip_rect(const SkRect& rect, bool is_aa);
  void push_clip_rrect(const SkRRect& rrect, bool is_aa);
  void push_clip_path(const SkPath& path, bool is_aa);
  // ---------------------

  // The maybe/needs_save_layer methods will determine if the indicated
  // attribute can be incorporated into the outstanding attributes as is,
  // or if the apply_flags are compatible with the outstanding attributes.
  // If the oustanding attributes are incompatible with the new attribute
  // or the apply flags, then a protective saveLayer will be executed.
  // ---------------------
  bool needs_save_layer(int flags) const;
  void do_save();
  void save_layer(const SkRect& bounds);
  void maybe_save_layer_for_transform(bool needs_save);
  void maybe_save_layer_for_clip(bool needs_save);
  void maybe_save_layer(int apply_flags);
  void maybe_save_layer(SkScalar opacity);
  void maybe_save_layer(const std::shared_ptr<const DlColorFilter>& filter);
  void maybe_save_layer(const std::shared_ptr<const DlImageFilter>& filter);
  // ---------------------

  struct RenderingAttributes {
    // We need to record the last bounds we received for the last
    // attribute that we recorded so that we can perform a saveLayer
    // on the proper area. When an attribute is applied that cannot
    // be merged with the existing attributes, it will be submitted
    // with a bounds for its own source content, not the bounds for
    // the content that will be included in the saveLayer that applies
    // the existing outstanding attributes - thus we need to record
    // the bounds that were supplied with the most recent previous
    // attribute to be applied.
    SkRect save_layer_bounds{0, 0, 0, 0};

    SkScalar opacity = SK_Scalar1;
    std::shared_ptr<const DlColorFilter> color_filter;
    std::shared_ptr<const DlImageFilter> image_filter;

    SkPaint* fill(SkPaint& paint,
                  DlBlendMode mode = DlBlendMode::kSrcOver) const;
    DlPaint* fill(DlPaint& paint,
                  DlBlendMode mode = DlBlendMode::kSrcOver) const;

    bool operator==(const RenderingAttributes& other) const {
      return save_layer_bounds == other.save_layer_bounds &&
             opacity == other.opacity &&
             Equals(color_filter, other.color_filter) &&
             Equals(image_filter, other.image_filter);
    }
  };

  class StateEntry {
   public:
    virtual ~StateEntry() = default;

    virtual void apply(LayerStateStack* stack) const = 0;
    virtual void reapply(LayerStateStack* stack) const { apply(stack); }
    virtual void restore(LayerStateStack* stack) const {}
    virtual void update_mutators(MutatorsStack* mutators_stack) const {}

   protected:
    StateEntry() = default;

    FML_DISALLOW_COPY_ASSIGN_AND_MOVE(StateEntry);
  };
  friend class SaveEntry;
  friend class SaveLayerEntry;
  friend class BackdropFilterEntry;
  friend class OpacityEntry;
  friend class ImageFilterEntry;
  friend class ColorFilterEntry;
  friend class TranslateEntry;
  friend class TransformMatrixEntry;
  friend class TransformM44Entry;
  friend class IntegralTransformEntry;
  friend class ClipEntry;
  friend class ClipRectEntry;
  friend class ClipRRectEntry;
  friend class ClipPathEntry;

  class Delegate {
   public:
    virtual ~Delegate() = default;

    // Mormally when a |Paint| or |Preroll| cycle is completed, the
    // delegate will have been rewound to its initial state by the
    // trailing recursive actions of the paint and preroll methods.
    // When a delegate is swapped out, there may be unresolved state
    // that the delegate received. This method is called when the
    // delegate is cleared or swapped out to inform it to rewind its
    // state and finalize all outstanding save or saveLayer operations.
    virtual void decommission() = 0;

    virtual SkCanvas* canvas() const { return nullptr; }
    virtual DisplayListBuilder* builder() const { return nullptr; }

    virtual SkRect local_cull_rect() const = 0;
    virtual SkRect device_cull_rect() const = 0;
    virtual SkM44 matrix_4x4() const = 0;
    virtual SkMatrix matrix_3x3() const = 0;
    virtual bool content_culled(const SkRect& content_bounds) const = 0;

    virtual void save() = 0;
    virtual void saveLayer(const SkRect& bounds,
                           RenderingAttributes& attributes,
                           DlBlendMode blend,
                           const DlImageFilter* backdrop) = 0;
    virtual void restore() = 0;

    virtual void translate(SkScalar tx, SkScalar ty) = 0;
    virtual void transform(const SkM44& m44) = 0;
    virtual void transform(const SkMatrix& matrix) = 0;
    virtual void integralTransform() = 0;

    virtual void clipRect(const SkRect& rect, SkClipOp op, bool is_aa) = 0;
    virtual void clipRRect(const SkRRect& rrect, SkClipOp op, bool is_aa) = 0;
    virtual void clipPath(const SkPath& path, SkClipOp op, bool is_aa) = 0;
  };
  friend class DummyDelegate;
  friend class SkCanvasDelegate;
  friend class DlBuilderDelegate;
  friend class PrerollDelegate;

  std::vector<std::unique_ptr<StateEntry>> state_stack_;
  friend class MutatorContext;

  std::shared_ptr<Delegate> delegate_;
  RenderingAttributes outstanding_;
  CheckerboardFunc checkerboard_func_ = nullptr;

  friend class SaveLayerEntry;
};

}  // namespace flutter

#endif  // FLUTTER_FLOW_LAYERS_LAYER_STATE_STACK_H_
