blob: 6c420a269738593abb51ca9f2c0ef0a382a382a4 [file] [log] [blame]
// 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_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_
#define FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_
#include <memory>
#include <optional>
#include <variant>
#include <vector>
#include "impeller/core/formats.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/sigma.h"
namespace impeller {
class FilterContents : public Contents {
public:
static const int32_t kBlurFilterRequiredMipCount;
enum class BlurStyle {
/// Blurred inside and outside.
kNormal,
/// Solid inside, blurred outside.
kSolid,
/// Nothing inside, blurred outside.
kOuter,
/// Blurred inside, nothing outside.
kInner,
};
enum class MorphType { kDilate, kErode };
/// Creates a gaussian blur that operates in one direction.
/// See also: `MakeGaussianBlur`
static std::shared_ptr<FilterContents> MakeDirectionalGaussianBlur(
FilterInput::Ref input,
Sigma sigma,
Vector2 direction,
BlurStyle blur_style = BlurStyle::kNormal,
Entity::TileMode tile_mode = Entity::TileMode::kDecal,
bool is_second_pass = false,
Sigma secondary_sigma = {});
/// Creates a gaussian blur that operates in 2 dimensions.
/// See also: `MakeDirectionalGaussianBlur`
static std::shared_ptr<FilterContents> MakeGaussianBlur(
const FilterInput::Ref& input,
Sigma sigma_x,
Sigma sigma_y,
BlurStyle blur_style = BlurStyle::kNormal,
Entity::TileMode tile_mode = Entity::TileMode::kDecal);
static std::shared_ptr<FilterContents> MakeBorderMaskBlur(
FilterInput::Ref input,
Sigma sigma_x,
Sigma sigma_y,
BlurStyle blur_style = BlurStyle::kNormal);
static std::shared_ptr<FilterContents> MakeDirectionalMorphology(
FilterInput::Ref input,
Radius radius,
Vector2 direction,
MorphType morph_type);
static std::shared_ptr<FilterContents> MakeMorphology(FilterInput::Ref input,
Radius radius_x,
Radius radius_y,
MorphType morph_type);
static std::shared_ptr<FilterContents> MakeMatrixFilter(
FilterInput::Ref input,
const Matrix& matrix,
const SamplerDescriptor& desc);
static std::shared_ptr<FilterContents> MakeLocalMatrixFilter(
FilterInput::Ref input,
const Matrix& matrix);
static std::shared_ptr<FilterContents> MakeYUVToRGBFilter(
std::shared_ptr<Texture> y_texture,
std::shared_ptr<Texture> uv_texture,
YUVColorSpace yuv_color_space);
FilterContents();
~FilterContents() override;
/// @brief The input texture sources for this filter. Each input's emitted
/// texture is expected to have premultiplied alpha colors.
///
/// The number of required or optional textures depends on the
/// particular filter's implementation.
void SetInputs(FilterInput::Vector inputs);
/// @brief Sets the transform which gets appended to the effect of this
/// filter. Note that this is in addition to the entity's transform.
///
/// This is useful for subpass rendering scenarios where it's
/// difficult to encode the current transform of the layer into the
/// Entity being rendered.
void SetEffectTransform(const Matrix& effect_transform);
/// @brief Create an Entity that renders this filter's output.
std::optional<Entity> GetEntity(
const ContentContext& renderer,
const Entity& entity,
const std::optional<Rect>& coverage_hint) const;
// |Contents|
bool Render(const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) const override;
// |Contents|
std::optional<Rect> GetCoverage(const Entity& entity) const override;
// |Contents|
void PopulateGlyphAtlas(
const std::shared_ptr<LazyGlyphAtlas>& lazy_glyph_atlas,
Scalar scale) override;
// |Contents|
std::optional<Snapshot> RenderToSnapshot(
const ContentContext& renderer,
const Entity& entity,
std::optional<Rect> coverage_limit = std::nullopt,
const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
bool msaa_enabled = true,
int32_t mip_count = 1,
const std::string& label = "Filter Snapshot") const override;
// |Contents|
const FilterContents* AsFilter() const override;
/// @brief Determines the coverage of source pixels that will be needed
/// to produce results for the specified |output_limit| under the
/// specified |effect_transform|. This is essentially a reverse of
/// the |GetCoverage| method computing a source coverage from
/// an intended |output_limit| coverage.
///
/// Both the |output_limit| and the return value are in the
/// transformed coordinate space, and so do not need to be
/// transformed or inverse transformed by the |effect_transform|
/// but individual parameters on the filter might be in the
/// untransformed space and should be transformed by the
/// |effect_transform| before applying them to the coverages.
///
/// The method computes a result such that if the filter is applied
/// to a set of pixels filling the computed source coverage, it
/// should produce an output that covers the entire specified
/// |output_limit|.
///
/// This is useful for subpass rendering scenarios where a filter
/// will be applied to the output of the subpass and we need to
/// determine how large of a render target to allocate in order
/// to collect all pixels that might affect the supplied output
/// coverage limit. While we might end up clipping the rendering
/// of the subpass to its destination, we want to avoid clipping
/// out any pixels that contribute to the output limit via the
/// filtering operation.
///
/// @return The coverage bounds in the transformed space of any source pixel
/// that may be needed to produce output for the indicated filter
/// that covers the indicated |output_limit|.
std::optional<Rect> GetSourceCoverage(const Matrix& effect_transform,
const Rect& output_limit) const;
virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;
Matrix GetTransform(const Matrix& parent_transform) const;
/// @brief Returns true if this filter graph doesn't perform any basis
/// transforms to the filtered content. For example: Rotating,
/// scaling, and skewing are all basis transforms, but
/// translating is not.
///
/// This is useful for determining whether a filtered object's space
/// is compatible enough with the parent pass space to perform certain
/// subpass clipping optimizations.
virtual bool IsTranslationOnly() const;
/// @brief Returns `true` if this filter does not have any `FilterInput`
/// children.
bool IsLeaf() const;
/// @brief Replaces the set of all leaf `FilterContents` with a new set
/// of `FilterInput`s.
/// @see `FilterContents::IsLeaf`
void SetLeafInputs(const FilterInput::Vector& inputs);
/// @brief Marks this filter chain as applying in a subpass scenario.
///
/// Subpasses render in screenspace, and this setting informs filters
/// that the current transform matrix of the entity is not stored
/// in the Entity transform matrix. Instead, the effect transform
/// is used in this case.
virtual void SetRenderingMode(Entity::RenderingMode rendering_mode);
private:
/// @brief Internal utility method for |GetLocalCoverage| that computes
/// the output coverage of this filter across the specified inputs,
/// ignoring the coverage hint.
virtual std::optional<Rect> GetFilterCoverage(
const FilterInput::Vector& inputs,
const Entity& entity,
const Matrix& effect_transform) const;
/// @brief Internal utility method for |GetSourceCoverage| that computes
/// the inverse effect of this transform on the specified output
/// coverage, ignoring the inputs which will be accommodated by
/// the caller.
virtual std::optional<Rect> GetFilterSourceCoverage(
const Matrix& effect_transform,
const Rect& output_limit) const = 0;
/// @brief Converts zero or more filter inputs into a render instruction.
virtual std::optional<Entity> RenderFilter(
const FilterInput::Vector& inputs,
const ContentContext& renderer,
const Entity& entity,
const Matrix& effect_transform,
const Rect& coverage,
const std::optional<Rect>& coverage_hint) const = 0;
/// @brief Internal utility method to compute the coverage of this
/// filter across its internally specified inputs and subject
/// to the coverage hint.
///
/// Uses |GetFilterCoverage|.
std::optional<Rect> GetLocalCoverage(const Entity& local_entity) const;
FilterInput::Vector inputs_;
Matrix effect_transform_ = Matrix();
FilterContents(const FilterContents&) = delete;
FilterContents& operator=(const FilterContents&) = delete;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_