[Impeller] Aiks image filters; allow setting effect transforms after FilterContents instantiation. (flutter/engine#45530)
These are API improvements on the way to solving https://github.com/flutter/flutter/issues/131182. * Remove `effect_transform` and `is_subpass` from the static `FilterContents` factories. These are for internal use only. * Replace `impeller::Paint` filter procs with Aiks `ImageFilter` factories similar to `ColorFilter`. This gives Aiks a simple interface for constructing filters and prevents possible state cloning bugs when copying filters into `EntityPass`. * Allow for setting filter inputs, setting the effect transform, and enabling subpass mode on a filter chain after it has been instantiated. This will allow us to sample coverage in `EntityPass` without rendering any snapshots using rect filter inputs.
This commit is contained in:
@@ -1029,6 +1029,8 @@ ORIGIN: ../../../flutter/impeller/aiks/color_source.cc + ../../../flutter/LICENS
|
||||
ORIGIN: ../../../flutter/impeller/aiks/color_source.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/image.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/image.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/image_filter.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/image_filter.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/paint.cc + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/paint.h + ../../../flutter/LICENSE
|
||||
ORIGIN: ../../../flutter/impeller/aiks/paint_pass_delegate.cc + ../../../flutter/LICENSE
|
||||
@@ -3773,6 +3775,8 @@ FILE: ../../../flutter/impeller/aiks/color_source.cc
|
||||
FILE: ../../../flutter/impeller/aiks/color_source.h
|
||||
FILE: ../../../flutter/impeller/aiks/image.cc
|
||||
FILE: ../../../flutter/impeller/aiks/image.h
|
||||
FILE: ../../../flutter/impeller/aiks/image_filter.cc
|
||||
FILE: ../../../flutter/impeller/aiks/image_filter.h
|
||||
FILE: ../../../flutter/impeller/aiks/paint.cc
|
||||
FILE: ../../../flutter/impeller/aiks/paint.h
|
||||
FILE: ../../../flutter/impeller/aiks/paint_pass_delegate.cc
|
||||
|
||||
@@ -16,6 +16,8 @@ impeller_component("aiks") {
|
||||
"color_source.h",
|
||||
"image.cc",
|
||||
"image.h",
|
||||
"image_filter.cc",
|
||||
"image_filter.h",
|
||||
"paint.cc",
|
||||
"paint.h",
|
||||
"paint_pass_delegate.cc",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "impeller/aiks/aiks_playground.h"
|
||||
#include "impeller/aiks/canvas.h"
|
||||
#include "impeller/aiks/image.h"
|
||||
#include "impeller/aiks/image_filter.h"
|
||||
#include "impeller/aiks/paint_pass_delegate.h"
|
||||
#include "impeller/aiks/testing/context_spy.h"
|
||||
#include "impeller/core/capture.h"
|
||||
@@ -2110,12 +2111,9 @@ TEST_P(AiksTest, PaintWithFilters) {
|
||||
|
||||
ASSERT_TRUE(paint.HasColorFilter());
|
||||
|
||||
paint.image_filter = [](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(1.0), Sigma(1.0), FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
};
|
||||
paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp);
|
||||
|
||||
ASSERT_TRUE(paint.HasColorFilter());
|
||||
|
||||
@@ -2141,12 +2139,9 @@ TEST_P(AiksTest, OpacityPeepHoleApplicationTest) {
|
||||
ASSERT_FALSE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
|
||||
|
||||
paint.color_filter = nullptr;
|
||||
paint.image_filter = [](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(1.0), Sigma(1.0), FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
};
|
||||
paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp);
|
||||
|
||||
// Paint has image filter, can't elide.
|
||||
delegate = std::make_shared<OpacityPeepholePassDelegate>(paint);
|
||||
@@ -2313,11 +2308,9 @@ TEST_P(AiksTest, CollapsedDrawPaintInSubpassBackdropFilter) {
|
||||
canvas.DrawPaint(
|
||||
{.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
|
||||
canvas.SaveLayer({}, {},
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(input, Sigma(20.0),
|
||||
Sigma(20.0));
|
||||
});
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kDecal));
|
||||
canvas.DrawPaint(
|
||||
{.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
|
||||
|
||||
@@ -2515,12 +2508,8 @@ TEST_P(AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly) {
|
||||
|
||||
canvas.SaveLayer({
|
||||
.color = Color::Black().WithAlpha(0.5),
|
||||
.image_filter =
|
||||
[](FilterInput::Ref input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return ColorFilterContents::MakeBlend(
|
||||
BlendMode::kDestinationOver, {std::move(input)}, Color::Red());
|
||||
},
|
||||
.image_filter = ImageFilter::MakeFromColorFilter(
|
||||
*ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
|
||||
});
|
||||
|
||||
canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
|
||||
@@ -2589,17 +2578,14 @@ TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly) {
|
||||
|
||||
canvas.SaveLayer({
|
||||
.color = Color::Black().WithAlpha(0.5),
|
||||
.image_filter =
|
||||
[](FilterInput::Ref input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return ColorFilterContents::MakeColorMatrix({std::move(input)},
|
||||
{.array = {
|
||||
1, 0, 0, 0, 0, //
|
||||
0, 1, 0, 0, 0, //
|
||||
0, 0, 1, 0, 0, //
|
||||
0, 0, 0, 2, 0 //
|
||||
}});
|
||||
},
|
||||
.image_filter = ImageFilter::MakeFromColorFilter(
|
||||
*ColorFilter::MakeMatrix({.array =
|
||||
{
|
||||
1, 0, 0, 0, 0, //
|
||||
0, 1, 0, 0, 0, //
|
||||
0, 0, 1, 0, 0, //
|
||||
0, 0, 0, 2, 0 //
|
||||
}})),
|
||||
});
|
||||
canvas.DrawImage(image, {100, 500}, {});
|
||||
canvas.Restore();
|
||||
@@ -2616,17 +2602,14 @@ TEST_P(AiksTest,
|
||||
|
||||
canvas.SaveLayer({
|
||||
.color = Color::Black().WithAlpha(0.5),
|
||||
.image_filter =
|
||||
[](FilterInput::Ref input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return ColorFilterContents::MakeColorMatrix(
|
||||
{std::move(input)}, {.array = {
|
||||
1, 0, 0, 0, 0, //
|
||||
0, 1, 0, 0, 0, //
|
||||
0, 0.2, 1, 0, 0, //
|
||||
0, 0, 0, 0.5, 0 //
|
||||
}});
|
||||
},
|
||||
.image_filter = ImageFilter::MakeFromColorFilter(
|
||||
*ColorFilter::MakeMatrix({.array =
|
||||
{
|
||||
1, 0, 0, 0, 0, //
|
||||
0, 1, 0, 0, 0, //
|
||||
0, 0.2, 1, 0, 0, //
|
||||
0, 0, 0, 0.5, 0 //
|
||||
}})),
|
||||
.color_filter =
|
||||
ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
|
||||
});
|
||||
@@ -2758,13 +2741,9 @@ TEST_P(AiksTest, CanRenderBackdropBlurInteractive) {
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(a.x, a.y, b.x, b.y), 20);
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
});
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
return canvas.EndRecordingAsPicture();
|
||||
@@ -2781,13 +2760,9 @@ TEST_P(AiksTest, CanRenderBackdropBlur) {
|
||||
canvas.DrawCircle({180, 120}, 100, {.color = Color::OrangeRed()});
|
||||
canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), 20);
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(30.0), Sigma(30.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
});
|
||||
ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
@@ -2797,13 +2772,9 @@ TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) {
|
||||
Canvas canvas;
|
||||
canvas.DrawCircle({400, 400}, 300, {.color = Color::Green()});
|
||||
canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt,
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(999999), Sigma(999999),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
});
|
||||
ImageFilter::MakeBlur(Sigma(999999), Sigma(999999),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp));
|
||||
canvas.Restore();
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
|
||||
@@ -2816,14 +2787,9 @@ TEST_P(AiksTest, CanRenderClippedBlur) {
|
||||
{400, 400}, 200,
|
||||
{
|
||||
.color = Color::Green(),
|
||||
.image_filter =
|
||||
[](const FilterInput::Ref& input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(20), Sigma(20),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp, effect_transform);
|
||||
},
|
||||
.image_filter = ImageFilter::MakeBlur(
|
||||
Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp),
|
||||
});
|
||||
canvas.Restore();
|
||||
|
||||
@@ -3127,11 +3093,9 @@ TEST_P(AiksTest, CanCanvasDrawPictureWithAdvancedBlend) {
|
||||
TEST_P(AiksTest, CanCanvasDrawPictureWithBackdropFilter) {
|
||||
Canvas subcanvas;
|
||||
subcanvas.SaveLayer({}, {},
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, Sigma(20.0), Sigma(20.0));
|
||||
});
|
||||
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kDecal));
|
||||
auto image = std::make_shared<Image>(CreateTextureForFixture("kalimba.jpg"));
|
||||
Paint paint;
|
||||
paint.color = Color::Red().WithAlpha(0.5);
|
||||
@@ -3206,17 +3170,12 @@ TEST_P(AiksTest, MatrixSaveLayerFilter) {
|
||||
.blend_mode = BlendMode::kPlus});
|
||||
// Should render a second circle, centered on the bottom-right-most edge of
|
||||
// the circle.
|
||||
canvas.SaveLayer({.image_filter =
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
Matrix matrix =
|
||||
Matrix::MakeTranslation(
|
||||
Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
|
||||
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
|
||||
Matrix::MakeTranslation(Vector2(-100, -100));
|
||||
return FilterContents::MakeMatrixFilter(
|
||||
input, matrix, {}, Matrix(), true);
|
||||
}},
|
||||
canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
|
||||
Matrix::MakeTranslation(Vector2(1, 1) *
|
||||
(200 + 100 * k1OverSqrt2)) *
|
||||
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
|
||||
Matrix::MakeTranslation(Vector2(-200, -200)),
|
||||
SamplerDescriptor{})},
|
||||
std::nullopt);
|
||||
canvas.DrawCircle(Point(200, 200), 100,
|
||||
{.color = Color::Green().WithAlpha(0.5),
|
||||
@@ -3238,17 +3197,13 @@ TEST_P(AiksTest, MatrixBackdropFilter) {
|
||||
.blend_mode = BlendMode::kPlus});
|
||||
// Should render a second circle, centered on the bottom-right-most edge of
|
||||
// the circle.
|
||||
canvas.SaveLayer({}, std::nullopt,
|
||||
[](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
Matrix matrix =
|
||||
Matrix::MakeTranslation(Vector2(1, 1) *
|
||||
(100 + 100 * k1OverSqrt2)) *
|
||||
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
|
||||
Matrix::MakeTranslation(Vector2(-100, -100));
|
||||
return FilterContents::MakeMatrixFilter(
|
||||
input, matrix, {}, Matrix(), true);
|
||||
});
|
||||
canvas.SaveLayer(
|
||||
{}, std::nullopt,
|
||||
ImageFilter::MakeMatrix(
|
||||
Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
|
||||
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
|
||||
Matrix::MakeTranslation(Vector2(-100, -100)),
|
||||
SamplerDescriptor{}));
|
||||
canvas.Restore();
|
||||
}
|
||||
canvas.Restore();
|
||||
@@ -3329,14 +3284,14 @@ TEST_P(AiksTest, PipelineBlendSingleParameter) {
|
||||
canvas.Translate(Point(100, 100));
|
||||
canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
|
||||
canvas.ClipRect(Rect(100, 100, 200, 200));
|
||||
canvas.DrawCircle(
|
||||
Point(200, 200), 200,
|
||||
{.color = Color::Green(),
|
||||
.blend_mode = BlendMode::kSourceOver,
|
||||
.image_filter = [](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return ColorFilterContents::MakeBlend(BlendMode::kSource, {input});
|
||||
}});
|
||||
canvas.DrawCircle(Point(200, 200), 200,
|
||||
{
|
||||
.color = Color::Green(),
|
||||
.blend_mode = BlendMode::kSourceOver,
|
||||
.image_filter = ImageFilter::MakeFromColorFilter(
|
||||
*ColorFilter::MakeBlend(BlendMode::kDestination,
|
||||
Color::White())),
|
||||
});
|
||||
canvas.Restore();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "impeller/aiks/image_filter.h"
|
||||
#include "impeller/aiks/paint_pass_delegate.h"
|
||||
#include "impeller/entity/contents/atlas_contents.h"
|
||||
#include "impeller/entity/contents/clip_contents.h"
|
||||
@@ -57,7 +58,7 @@ void Canvas::Save() {
|
||||
|
||||
void Canvas::Save(bool create_subpass,
|
||||
BlendMode blend_mode,
|
||||
EntityPass::BackdropFilterProc backdrop_filter) {
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter) {
|
||||
auto entry = CanvasStackEntry{};
|
||||
entry.xformation = xformation_stack_.back().xformation;
|
||||
entry.cull_rect = xformation_stack_.back().cull_rect;
|
||||
@@ -67,7 +68,18 @@ void Canvas::Save(bool create_subpass,
|
||||
auto subpass = std::make_unique<EntityPass>();
|
||||
subpass->SetEnableOffscreenCheckerboard(
|
||||
debug_options.offscreen_texture_checkerboard);
|
||||
subpass->SetBackdropFilter(std::move(backdrop_filter));
|
||||
if (backdrop_filter) {
|
||||
EntityPass::BackdropFilterProc backdrop_filter_proc =
|
||||
[backdrop_filter = backdrop_filter->Clone()](
|
||||
const FilterInput::Ref& input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
auto filter = backdrop_filter->WrapInput(input);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
filter->SetIsForSubpass(is_subpass);
|
||||
return filter;
|
||||
};
|
||||
subpass->SetBackdropFilter(backdrop_filter_proc);
|
||||
}
|
||||
subpass->SetBlendMode(blend_mode);
|
||||
current_pass_ = GetCurrentPass().AddSubpass(std::move(subpass));
|
||||
current_pass_->SetTransformation(xformation_stack_.back().xformation);
|
||||
@@ -518,7 +530,7 @@ size_t Canvas::GetStencilDepth() const {
|
||||
|
||||
void Canvas::SaveLayer(const Paint& paint,
|
||||
std::optional<Rect> bounds,
|
||||
const Paint::ImageFilterProc& backdrop_filter) {
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter) {
|
||||
Save(true, paint.blend_mode, backdrop_filter);
|
||||
|
||||
auto& new_layer_pass = GetCurrentPass();
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/aiks/image.h"
|
||||
#include "impeller/aiks/image_filter.h"
|
||||
#include "impeller/aiks/paint.h"
|
||||
#include "impeller/aiks/picture.h"
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
@@ -68,7 +69,7 @@ class Canvas {
|
||||
|
||||
void SaveLayer(const Paint& paint,
|
||||
std::optional<Rect> bounds = std::nullopt,
|
||||
const Paint::ImageFilterProc& backdrop_filter = nullptr);
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr);
|
||||
|
||||
bool Restore();
|
||||
|
||||
@@ -180,7 +181,7 @@ class Canvas {
|
||||
|
||||
void Save(bool create_subpass,
|
||||
BlendMode = BlendMode::kSourceOver,
|
||||
EntityPass::BackdropFilterProc backdrop_filter = nullptr);
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr);
|
||||
|
||||
void RestoreClip();
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ ColorFilter::ColorFilterProc BlendColorFilter::GetCPUColorFilterProc() const {
|
||||
};
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> BlendColorFilter::Clone() const {
|
||||
return std::make_shared<BlendColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* MatrixColorFilter
|
||||
******************************************************************************/
|
||||
@@ -82,6 +86,10 @@ ColorFilter::ColorFilterProc MatrixColorFilter::GetCPUColorFilterProc() const {
|
||||
};
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> MatrixColorFilter::Clone() const {
|
||||
return std::make_shared<MatrixColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* SrgbToLinearColorFilter
|
||||
******************************************************************************/
|
||||
@@ -104,6 +112,10 @@ ColorFilter::ColorFilterProc SrgbToLinearColorFilter::GetCPUColorFilterProc()
|
||||
return [](Color color) { return color.SRGBToLinear(); };
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> SrgbToLinearColorFilter::Clone() const {
|
||||
return std::make_shared<SrgbToLinearColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* LinearToSrgbColorFilter
|
||||
******************************************************************************/
|
||||
@@ -126,4 +138,8 @@ ColorFilter::ColorFilterProc LinearToSrgbColorFilter::GetCPUColorFilterProc()
|
||||
return [](Color color) { return color.LinearToSRGB(); };
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> LinearToSrgbColorFilter::Clone() const {
|
||||
return std::make_shared<LinearToSrgbColorFilter>(*this);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -48,6 +48,8 @@ class ColorFilter {
|
||||
/// @brief Returns a function that can be used to filter unpremultiplied
|
||||
/// Impeller Colors on the CPU.
|
||||
virtual ColorFilterProc GetCPUColorFilterProc() const = 0;
|
||||
|
||||
virtual std::shared_ptr<ColorFilter> Clone() const = 0;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -68,6 +70,9 @@ class BlendColorFilter final : public ColorFilter {
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
BlendMode blend_mode_;
|
||||
Color color_;
|
||||
@@ -91,6 +96,9 @@ class MatrixColorFilter final : public ColorFilter {
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
ColorMatrix color_matrix_;
|
||||
};
|
||||
@@ -112,6 +120,9 @@ class SrgbToLinearColorFilter final : public ColorFilter {
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -131,6 +142,9 @@ class LinearToSrgbColorFilter final : public ColorFilter {
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
206
engine/src/flutter/impeller/aiks/image_filter.cc
Normal file
206
engine/src/flutter/impeller/aiks/image_filter.cc
Normal file
@@ -0,0 +1,206 @@
|
||||
// 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 "impeller/aiks/image_filter.h"
|
||||
#include "impeller/entity/contents/filters/filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/inputs/filter_input.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
/*******************************************************************************
|
||||
******* ImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
ImageFilter::ImageFilter() = default;
|
||||
|
||||
ImageFilter::~ImageFilter() = default;
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeBlur(
|
||||
Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
FilterContents::BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode) {
|
||||
return std::make_shared<BlurImageFilter>(sigma_x, sigma_y, blur_style,
|
||||
tile_mode);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeDilate(Radius radius_x,
|
||||
Radius radius_y) {
|
||||
return std::make_shared<DilateImageFilter>(radius_x, radius_y);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeErode(Radius radius_x,
|
||||
Radius radius_y) {
|
||||
return std::make_shared<ErodeImageFilter>(radius_x, radius_y);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeMatrix(
|
||||
const Matrix& matrix,
|
||||
SamplerDescriptor sampler_descriptor) {
|
||||
return std::make_shared<MatrixImageFilter>(matrix,
|
||||
std::move(sampler_descriptor));
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeCompose(
|
||||
const ImageFilter& inner,
|
||||
const ImageFilter& outer) {
|
||||
return std::make_shared<ComposeImageFilter>(inner, outer);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeFromColorFilter(
|
||||
const ColorFilter& color_filter) {
|
||||
return std::make_shared<ColorImageFilter>(color_filter);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeLocalMatrix(
|
||||
const Matrix& matrix,
|
||||
const ImageFilter& internal_filter) {
|
||||
return std::make_shared<LocalMatrixImageFilter>(matrix, internal_filter);
|
||||
}
|
||||
|
||||
std::shared_ptr<FilterContents> ImageFilter::GetFilterContents() const {
|
||||
return WrapInput(FilterInput::Make(Rect()));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* BlurImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
BlurImageFilter::BlurImageFilter(Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
FilterContents::BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode)
|
||||
: sigma_x_(sigma_x),
|
||||
sigma_y_(sigma_y),
|
||||
blur_style_(blur_style),
|
||||
tile_mode_(tile_mode) {}
|
||||
|
||||
BlurImageFilter::~BlurImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> BlurImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return FilterContents::MakeGaussianBlur(input, sigma_x_, sigma_y_,
|
||||
blur_style_, tile_mode_);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> BlurImageFilter::Clone() const {
|
||||
return std::make_shared<BlurImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* DilateImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
DilateImageFilter::DilateImageFilter(Radius radius_x, Radius radius_y)
|
||||
: radius_x_(radius_x), radius_y_(radius_y) {}
|
||||
|
||||
DilateImageFilter::~DilateImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> DilateImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return FilterContents::MakeMorphology(input, radius_x_, radius_y_,
|
||||
FilterContents::MorphType::kDilate);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> DilateImageFilter::Clone() const {
|
||||
return std::make_shared<DilateImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* ErodeImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
ErodeImageFilter::ErodeImageFilter(Radius radius_x, Radius radius_y)
|
||||
: radius_x_(radius_x), radius_y_(radius_y) {}
|
||||
|
||||
ErodeImageFilter::~ErodeImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> ErodeImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return FilterContents::MakeMorphology(input, radius_x_, radius_y_,
|
||||
FilterContents::MorphType::kErode);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ErodeImageFilter::Clone() const {
|
||||
return std::make_shared<ErodeImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* MatrixImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
MatrixImageFilter::MatrixImageFilter(const Matrix& matrix,
|
||||
SamplerDescriptor sampler_descriptor)
|
||||
: matrix_(matrix), sampler_descriptor_(std::move(sampler_descriptor)) {}
|
||||
|
||||
MatrixImageFilter::~MatrixImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> MatrixImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return FilterContents::MakeMatrixFilter(input, matrix_, sampler_descriptor_);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> MatrixImageFilter::Clone() const {
|
||||
return std::make_shared<MatrixImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* ComposeImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
ComposeImageFilter::ComposeImageFilter(const ImageFilter& inner,
|
||||
const ImageFilter& outer)
|
||||
: inner_(inner.Clone()), outer_(outer.Clone()) {}
|
||||
|
||||
ComposeImageFilter::~ComposeImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> ComposeImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return outer_->WrapInput(FilterInput::Make(inner_->WrapInput(input)));
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ComposeImageFilter::Clone() const {
|
||||
return std::make_shared<ComposeImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* ColorImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
ColorImageFilter::ColorImageFilter(const ColorFilter& color_filter)
|
||||
: color_filter_(color_filter.Clone()) {}
|
||||
|
||||
ColorImageFilter::~ColorImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> ColorImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return color_filter_->WrapWithGPUColorFilter(input, false);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> ColorImageFilter::Clone() const {
|
||||
return std::make_shared<ColorImageFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* LocalMatrixImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
LocalMatrixImageFilter::LocalMatrixImageFilter(
|
||||
const Matrix& matrix,
|
||||
const ImageFilter& internal_filter)
|
||||
: matrix_(matrix), internal_filter_(internal_filter.Clone()) {}
|
||||
|
||||
LocalMatrixImageFilter::~LocalMatrixImageFilter() = default;
|
||||
|
||||
std::shared_ptr<FilterContents> LocalMatrixImageFilter::WrapInput(
|
||||
const FilterInput::Ref& input) const {
|
||||
return FilterContents::MakeLocalMatrixFilter(
|
||||
FilterInput::Make(internal_filter_->WrapInput(input)), matrix_);
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageFilter> LocalMatrixImageFilter::Clone() const {
|
||||
return std::make_shared<LocalMatrixImageFilter>(*this);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
229
engine/src/flutter/impeller/aiks/image_filter.h
Normal file
229
engine/src/flutter/impeller/aiks/image_filter.h
Normal file
@@ -0,0 +1,229 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "impeller/aiks/color_filter.h"
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/entity/contents/filters/filter_contents.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/geometry/matrix.h"
|
||||
#include "impeller/geometry/sigma.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
struct Paint;
|
||||
|
||||
/*******************************************************************************
|
||||
******* ImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class ImageFilter {
|
||||
public:
|
||||
ImageFilter();
|
||||
|
||||
virtual ~ImageFilter();
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeBlur(
|
||||
Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
FilterContents::BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeDilate(Radius radius_x,
|
||||
Radius radius_y);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeErode(Radius radius_x,
|
||||
Radius radius_y);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeMatrix(
|
||||
const Matrix& matrix,
|
||||
SamplerDescriptor sampler_descriptor);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeCompose(const ImageFilter& inner,
|
||||
const ImageFilter& outer);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeFromColorFilter(
|
||||
const ColorFilter& color_filter);
|
||||
|
||||
static std::shared_ptr<ImageFilter> MakeLocalMatrix(
|
||||
const Matrix& matrix,
|
||||
const ImageFilter& internal_filter);
|
||||
|
||||
/// @brief Generate a new FilterContents using this filter's configuration.
|
||||
///
|
||||
/// This is the same as WrapInput, except no input is set. The input
|
||||
/// for the filter chain can be set later using.
|
||||
/// FilterContents::SetLeafInputs().
|
||||
///
|
||||
/// @see `FilterContents::SetLeafInputs`
|
||||
std::shared_ptr<FilterContents> GetFilterContents() const;
|
||||
|
||||
/// @brief Wraps the given filter input with a GPU-based image filter.
|
||||
virtual std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const = 0;
|
||||
|
||||
virtual std::shared_ptr<ImageFilter> Clone() const = 0;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* BlurImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class BlurImageFilter : public ImageFilter {
|
||||
public:
|
||||
BlurImageFilter(Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
FilterContents::BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode);
|
||||
|
||||
~BlurImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
Sigma sigma_x_;
|
||||
Sigma sigma_y_;
|
||||
FilterContents::BlurStyle blur_style_;
|
||||
Entity::TileMode tile_mode_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* DilateImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class DilateImageFilter : public ImageFilter {
|
||||
public:
|
||||
DilateImageFilter(Radius radius_x, Radius radius_y);
|
||||
|
||||
~DilateImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
Radius radius_x_;
|
||||
Radius radius_y_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* ErodeImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class ErodeImageFilter : public ImageFilter {
|
||||
public:
|
||||
ErodeImageFilter(Radius radius_x, Radius radius_y);
|
||||
|
||||
~ErodeImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
Radius radius_x_;
|
||||
Radius radius_y_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* MatrixImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class MatrixImageFilter : public ImageFilter {
|
||||
public:
|
||||
MatrixImageFilter(const Matrix& matrix, SamplerDescriptor sampler_descriptor);
|
||||
|
||||
~MatrixImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
Matrix matrix_;
|
||||
SamplerDescriptor sampler_descriptor_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* ComposeImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class ComposeImageFilter : public ImageFilter {
|
||||
public:
|
||||
ComposeImageFilter(const ImageFilter& inner, const ImageFilter& outer);
|
||||
|
||||
~ComposeImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ImageFilter> inner_;
|
||||
std::shared_ptr<ImageFilter> outer_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* ColorImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class ColorImageFilter : public ImageFilter {
|
||||
public:
|
||||
explicit ColorImageFilter(const ColorFilter& color_filter);
|
||||
|
||||
~ColorImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ColorFilter> color_filter_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* LocalMatrixImageFilter
|
||||
******************************************************************************/
|
||||
|
||||
class LocalMatrixImageFilter : public ImageFilter {
|
||||
public:
|
||||
LocalMatrixImageFilter(const Matrix& matrix,
|
||||
const ImageFilter& internal_filter);
|
||||
|
||||
~LocalMatrixImageFilter() override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<FilterContents> WrapInput(
|
||||
const FilterInput::Ref& input) const override;
|
||||
|
||||
// |ImageFilter|
|
||||
std::shared_ptr<ImageFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
Matrix matrix_;
|
||||
std::shared_ptr<ImageFilter> internal_filter_;
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
@@ -85,11 +85,13 @@ std::shared_ptr<Contents> Paint::WithImageFilter(
|
||||
std::shared_ptr<Contents> input,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) const {
|
||||
if (image_filter) {
|
||||
input =
|
||||
image_filter(FilterInput::Make(input), effect_transform, is_subpass);
|
||||
if (!image_filter) {
|
||||
return input;
|
||||
}
|
||||
return input;
|
||||
auto filter = image_filter->WrapInput(FilterInput::Make(input));
|
||||
filter->SetIsForSubpass(is_subpass);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
return filter;
|
||||
}
|
||||
|
||||
std::shared_ptr<Contents> Paint::WithColorFilter(
|
||||
@@ -146,7 +148,7 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
if (color_source_contents->IsSolidColor() && !color_filter) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
FilterInput::Make(color_source_contents), sigma, sigma, style,
|
||||
Entity::TileMode::kDecal, Matrix());
|
||||
Entity::TileMode::kDecal);
|
||||
}
|
||||
|
||||
/// 1. Create an opaque white mask of the original geometry.
|
||||
@@ -158,8 +160,7 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
/// 2. Blur the mask.
|
||||
|
||||
auto blurred_mask = FilterContents::MakeGaussianBlur(
|
||||
FilterInput::Make(mask), sigma, sigma, style, Entity::TileMode::kDecal,
|
||||
Matrix());
|
||||
FilterInput::Make(mask), sigma, sigma, style, Entity::TileMode::kDecal);
|
||||
|
||||
/// 3. Replace the geometry of the original color source with a rectangle that
|
||||
/// covers the full region of the blurred mask. Note that geometry is in
|
||||
@@ -193,10 +194,9 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
bool is_solid_color) const {
|
||||
if (is_solid_color) {
|
||||
return FilterContents::MakeGaussianBlur(input, sigma, sigma, style,
|
||||
Entity::TileMode::kDecal, Matrix());
|
||||
Entity::TileMode::kDecal);
|
||||
}
|
||||
return FilterContents::MakeBorderMaskBlur(input, sigma, sigma, style,
|
||||
Matrix());
|
||||
return FilterContents::MakeBorderMaskBlur(input, sigma, sigma, style);
|
||||
}
|
||||
|
||||
bool Paint::HasColorFilter() const {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "impeller/aiks/color_filter.h"
|
||||
#include "impeller/aiks/color_source.h"
|
||||
#include "impeller/aiks/image_filter.h"
|
||||
#include "impeller/entity/contents/contents.h"
|
||||
#include "impeller/entity/contents/filters/color_filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/filter_contents.h"
|
||||
@@ -62,7 +63,7 @@ struct Paint {
|
||||
BlendMode blend_mode = BlendMode::kSourceOver;
|
||||
bool invert_colors = false;
|
||||
|
||||
ImageFilterProc image_filter = nullptr;
|
||||
std::shared_ptr<ImageFilter> image_filter;
|
||||
std::shared_ptr<ColorFilter> color_filter;
|
||||
std::optional<MaskBlurDescriptor> mask_blur_descriptor;
|
||||
|
||||
|
||||
@@ -560,7 +560,7 @@ void DlDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
|
||||
}
|
||||
}
|
||||
|
||||
static Paint::ImageFilterProc ToImageFilterProc(
|
||||
static std::shared_ptr<ImageFilter> ToImageFilter(
|
||||
const flutter::DlImageFilter* filter) {
|
||||
if (filter == nullptr) {
|
||||
return nullptr;
|
||||
@@ -572,16 +572,8 @@ static Paint::ImageFilterProc ToImageFilterProc(
|
||||
auto sigma_x = Sigma(blur->sigma_x());
|
||||
auto sigma_y = Sigma(blur->sigma_y());
|
||||
auto tile_mode = ToTileMode(blur->tile_mode());
|
||||
|
||||
return [sigma_x, sigma_y, tile_mode](const FilterInput::Ref& input,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, sigma_x, sigma_y, FilterContents::BlurStyle::kNormal,
|
||||
tile_mode, effect_transform);
|
||||
};
|
||||
|
||||
break;
|
||||
return ImageFilter::MakeBlur(
|
||||
sigma_x, sigma_y, FilterContents::BlurStyle::kNormal, tile_mode);
|
||||
}
|
||||
case flutter::DlImageFilterType::kDilate: {
|
||||
auto dilate = filter->asDilate();
|
||||
@@ -591,14 +583,7 @@ static Paint::ImageFilterProc ToImageFilterProc(
|
||||
}
|
||||
auto radius_x = Radius(dilate->radius_x());
|
||||
auto radius_y = Radius(dilate->radius_y());
|
||||
return [radius_x, radius_y](FilterInput::Ref input,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return FilterContents::MakeMorphology(
|
||||
std::move(input), radius_x, radius_y,
|
||||
FilterContents::MorphType::kDilate, effect_transform);
|
||||
};
|
||||
break;
|
||||
return ImageFilter::MakeDilate(radius_x, radius_y);
|
||||
}
|
||||
case flutter::DlImageFilterType::kErode: {
|
||||
auto erode = filter->asErode();
|
||||
@@ -608,51 +593,31 @@ static Paint::ImageFilterProc ToImageFilterProc(
|
||||
}
|
||||
auto radius_x = Radius(erode->radius_x());
|
||||
auto radius_y = Radius(erode->radius_y());
|
||||
return [radius_x, radius_y](FilterInput::Ref input,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
return FilterContents::MakeMorphology(
|
||||
std::move(input), radius_x, radius_y,
|
||||
FilterContents::MorphType::kErode, effect_transform);
|
||||
};
|
||||
break;
|
||||
return ImageFilter::MakeErode(radius_x, radius_y);
|
||||
}
|
||||
case flutter::DlImageFilterType::kMatrix: {
|
||||
auto matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
auto matrix = ToMatrix(matrix_filter->matrix());
|
||||
auto desc = ToSamplerDescriptor(matrix_filter->sampling());
|
||||
return [matrix, desc](FilterInput::Ref input,
|
||||
const Matrix& effect_transform, bool is_subpass) {
|
||||
return FilterContents::MakeMatrixFilter(std::move(input), matrix, desc,
|
||||
effect_transform, is_subpass);
|
||||
};
|
||||
break;
|
||||
return ImageFilter::MakeMatrix(matrix, desc);
|
||||
}
|
||||
case flutter::DlImageFilterType::kCompose: {
|
||||
auto compose = filter->asCompose();
|
||||
FML_DCHECK(compose);
|
||||
auto outer = compose->outer();
|
||||
auto inner = compose->inner();
|
||||
auto outer_proc = ToImageFilterProc(outer.get());
|
||||
auto inner_proc = ToImageFilterProc(inner.get());
|
||||
if (!outer_proc) {
|
||||
return inner_proc;
|
||||
auto outer_dl_filter = compose->outer();
|
||||
auto inner_dl_filter = compose->inner();
|
||||
auto outer_filter = ToImageFilter(outer_dl_filter.get());
|
||||
auto inner_filter = ToImageFilter(inner_dl_filter.get());
|
||||
if (!outer_filter) {
|
||||
return inner_filter;
|
||||
}
|
||||
if (!inner_proc) {
|
||||
return outer_proc;
|
||||
if (!inner_filter) {
|
||||
return outer_filter;
|
||||
}
|
||||
FML_DCHECK(outer_proc && inner_proc);
|
||||
return [outer_filter = outer_proc, inner_filter = inner_proc](
|
||||
FilterInput::Ref input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
auto contents =
|
||||
inner_filter(std::move(input), effect_transform, is_subpass);
|
||||
contents = outer_filter(FilterInput::Make(contents), effect_transform,
|
||||
is_subpass);
|
||||
return contents;
|
||||
};
|
||||
break;
|
||||
FML_DCHECK(outer_filter && inner_filter);
|
||||
|
||||
return ImageFilter::MakeCompose(*inner_filter, *outer_filter);
|
||||
}
|
||||
case flutter::DlImageFilterType::kColorFilter: {
|
||||
auto color_filter_image_filter = filter->asColorFilter();
|
||||
@@ -662,16 +627,11 @@ static Paint::ImageFilterProc ToImageFilterProc(
|
||||
if (!color_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
return [filter = color_filter](FilterInput::Ref input,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
// When color filters are used as image filters, set the color filter's
|
||||
// "absorb opacity" flag to false. For image filters, the snapshot
|
||||
// opacity needs to be deferred until the result of the filter chain is
|
||||
// being blended with the layer.
|
||||
return filter->WrapWithGPUColorFilter(std::move(input), false);
|
||||
};
|
||||
break;
|
||||
// When color filters are used as image filters, set the color filter's
|
||||
// "absorb opacity" flag to false. For image filters, the snapshot
|
||||
// opacity needs to be deferred until the result of the filter chain is
|
||||
// being blended with the layer.
|
||||
return ImageFilter::MakeFromColorFilter(*color_filter);
|
||||
}
|
||||
case flutter::DlImageFilterType::kLocalMatrix: {
|
||||
auto local_matrix_filter = filter->asLocalMatrix();
|
||||
@@ -679,29 +639,20 @@ static Paint::ImageFilterProc ToImageFilterProc(
|
||||
auto internal_filter = local_matrix_filter->image_filter();
|
||||
FML_DCHECK(internal_filter);
|
||||
|
||||
auto image_filter_proc = ToImageFilterProc(internal_filter.get());
|
||||
if (!image_filter_proc) {
|
||||
auto image_filter = ToImageFilter(internal_filter.get());
|
||||
if (!image_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto matrix = ToMatrix(local_matrix_filter->matrix());
|
||||
|
||||
return [matrix, filter_proc = image_filter_proc](
|
||||
FilterInput::Ref input, const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
std::shared_ptr<FilterContents> filter =
|
||||
filter_proc(std::move(input), effect_transform, is_subpass);
|
||||
return FilterContents::MakeLocalMatrixFilter(FilterInput::Make(filter),
|
||||
matrix);
|
||||
};
|
||||
break;
|
||||
return ImageFilter::MakeLocalMatrix(matrix, *image_filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcher::setImageFilter(const flutter::DlImageFilter* filter) {
|
||||
paint_.image_filter = ToImageFilterProc(filter);
|
||||
paint_.image_filter = ToImageFilter(filter);
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
@@ -715,7 +666,7 @@ void DlDispatcher::saveLayer(const SkRect* bounds,
|
||||
const flutter::DlImageFilter* backdrop) {
|
||||
auto paint = options.renders_with_attributes() ? paint_ : Paint{};
|
||||
canvas_.SaveLayer(paint, skia_conversions::ToRect(bounds),
|
||||
ToImageFilterProc(backdrop));
|
||||
ToImageFilter(backdrop));
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
|
||||
@@ -37,8 +37,7 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
|
||||
BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode,
|
||||
bool is_second_pass,
|
||||
Sigma secondary_sigma,
|
||||
const Matrix& effect_transform) {
|
||||
Sigma secondary_sigma) {
|
||||
auto blur = std::make_shared<DirectionalGaussianBlurFilterContents>();
|
||||
blur->SetInputs({std::move(input)});
|
||||
blur->SetSigma(sigma);
|
||||
@@ -47,7 +46,6 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
|
||||
blur->SetTileMode(tile_mode);
|
||||
blur->SetIsSecondPass(is_second_pass);
|
||||
blur->SetSecondarySigma(secondary_sigma);
|
||||
blur->SetEffectTransform(effect_transform);
|
||||
return blur;
|
||||
}
|
||||
|
||||
@@ -56,14 +54,12 @@ std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
|
||||
Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
BlurStyle blur_style,
|
||||
Entity::TileMode tile_mode,
|
||||
const Matrix& effect_transform) {
|
||||
auto x_blur = MakeDirectionalGaussianBlur(input, sigma_x, Point(1, 0),
|
||||
BlurStyle::kNormal, tile_mode,
|
||||
false, {}, effect_transform);
|
||||
Entity::TileMode tile_mode) {
|
||||
auto x_blur = MakeDirectionalGaussianBlur(
|
||||
input, sigma_x, Point(1, 0), BlurStyle::kNormal, tile_mode, false, {});
|
||||
auto y_blur = MakeDirectionalGaussianBlur(FilterInput::Make(x_blur), sigma_y,
|
||||
Point(0, 1), blur_style, tile_mode,
|
||||
true, sigma_x, effect_transform);
|
||||
true, sigma_x);
|
||||
return y_blur;
|
||||
}
|
||||
|
||||
@@ -71,13 +67,11 @@ std::shared_ptr<FilterContents> FilterContents::MakeBorderMaskBlur(
|
||||
FilterInput::Ref input,
|
||||
Sigma sigma_x,
|
||||
Sigma sigma_y,
|
||||
BlurStyle blur_style,
|
||||
const Matrix& effect_transform) {
|
||||
BlurStyle blur_style) {
|
||||
auto filter = std::make_shared<BorderMaskBlurFilterContents>();
|
||||
filter->SetInputs({std::move(input)});
|
||||
filter->SetSigma(sigma_x, sigma_y);
|
||||
filter->SetBlurStyle(blur_style);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -85,14 +79,12 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalMorphology(
|
||||
FilterInput::Ref input,
|
||||
Radius radius,
|
||||
Vector2 direction,
|
||||
MorphType morph_type,
|
||||
const Matrix& effect_transform) {
|
||||
MorphType morph_type) {
|
||||
auto filter = std::make_shared<DirectionalMorphologyFilterContents>();
|
||||
filter->SetInputs({std::move(input)});
|
||||
filter->SetRadius(radius);
|
||||
filter->SetDirection(direction);
|
||||
filter->SetMorphType(morph_type);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -100,28 +92,22 @@ std::shared_ptr<FilterContents> FilterContents::MakeMorphology(
|
||||
FilterInput::Ref input,
|
||||
Radius radius_x,
|
||||
Radius radius_y,
|
||||
MorphType morph_type,
|
||||
const Matrix& effect_transform) {
|
||||
auto x_morphology = MakeDirectionalMorphology(
|
||||
std::move(input), radius_x, Point(1, 0), morph_type, effect_transform);
|
||||
auto y_morphology =
|
||||
MakeDirectionalMorphology(FilterInput::Make(x_morphology), radius_y,
|
||||
Point(0, 1), morph_type, effect_transform);
|
||||
MorphType morph_type) {
|
||||
auto x_morphology = MakeDirectionalMorphology(std::move(input), radius_x,
|
||||
Point(1, 0), morph_type);
|
||||
auto y_morphology = MakeDirectionalMorphology(
|
||||
FilterInput::Make(x_morphology), radius_y, Point(0, 1), morph_type);
|
||||
return y_morphology;
|
||||
}
|
||||
|
||||
std::shared_ptr<FilterContents> FilterContents::MakeMatrixFilter(
|
||||
FilterInput::Ref input,
|
||||
const Matrix& matrix,
|
||||
const SamplerDescriptor& desc,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass) {
|
||||
const SamplerDescriptor& desc) {
|
||||
auto filter = std::make_shared<MatrixFilterContents>();
|
||||
filter->SetInputs({std::move(input)});
|
||||
filter->SetMatrix(matrix);
|
||||
filter->SetSamplerDescriptor(desc);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
filter->SetIsSubpass(is_subpass);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -153,8 +139,12 @@ void FilterContents::SetInputs(FilterInput::Vector inputs) {
|
||||
inputs_ = std::move(inputs);
|
||||
}
|
||||
|
||||
void FilterContents::SetEffectTransform(Matrix effect_transform) {
|
||||
void FilterContents::SetEffectTransform(const Matrix& effect_transform) {
|
||||
effect_transform_ = effect_transform;
|
||||
|
||||
for (auto& input : inputs_) {
|
||||
input->SetEffectTransform(effect_transform);
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterContents::Render(const ContentContext& renderer,
|
||||
@@ -296,4 +286,10 @@ void FilterContents::SetLeafInputs(const FilterInput::Vector& inputs) {
|
||||
}
|
||||
}
|
||||
|
||||
void FilterContents::SetIsForSubpass(bool is_subpass) {
|
||||
for (auto& input : inputs_) {
|
||||
input->SetIsForSubpass(is_subpass);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -38,44 +38,36 @@ class FilterContents : public Contents {
|
||||
BlurStyle blur_style = BlurStyle::kNormal,
|
||||
Entity::TileMode tile_mode = Entity::TileMode::kDecal,
|
||||
bool is_second_pass = false,
|
||||
Sigma secondary_sigma = {},
|
||||
const Matrix& effect_transform = Matrix());
|
||||
Sigma secondary_sigma = {});
|
||||
|
||||
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,
|
||||
const Matrix& effect_transform = Matrix());
|
||||
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,
|
||||
const Matrix& effect_transform = Matrix());
|
||||
BlurStyle blur_style = BlurStyle::kNormal);
|
||||
|
||||
static std::shared_ptr<FilterContents> MakeDirectionalMorphology(
|
||||
FilterInput::Ref input,
|
||||
Radius radius,
|
||||
Vector2 direction,
|
||||
MorphType morph_type,
|
||||
const Matrix& effect_transform = Matrix());
|
||||
MorphType morph_type);
|
||||
|
||||
static std::shared_ptr<FilterContents> MakeMorphology(
|
||||
FilterInput::Ref input,
|
||||
Radius radius_x,
|
||||
Radius radius_y,
|
||||
MorphType morph_type,
|
||||
const Matrix& effect_transform = Matrix());
|
||||
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,
|
||||
const Matrix& effect_transform,
|
||||
bool is_subpass);
|
||||
const SamplerDescriptor& desc);
|
||||
|
||||
static std::shared_ptr<FilterContents> MakeLocalMatrixFilter(
|
||||
FilterInput::Ref input,
|
||||
@@ -99,7 +91,11 @@ class FilterContents : public Contents {
|
||||
|
||||
/// @brief Sets the transform which gets appended to the effect of this
|
||||
/// filter. Note that this is in addition to the entity's transform.
|
||||
void SetEffectTransform(Matrix effect_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(
|
||||
@@ -137,11 +133,19 @@ class FilterContents : public Contents {
|
||||
/// children.
|
||||
bool IsLeaf() const;
|
||||
|
||||
/// @brief Replaces the leaf of all leaf `FilterContents` with a new set
|
||||
/// of `inputs`.
|
||||
/// @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 transformation matrix of the entity is not stored
|
||||
/// in the Entity transformation matrix. Instead, the effect transform
|
||||
/// is used in this case.
|
||||
virtual void SetIsForSubpass(bool is_subpass);
|
||||
|
||||
private:
|
||||
virtual std::optional<Rect> GetFilterCoverage(
|
||||
const FilterInput::Vector& inputs,
|
||||
|
||||
@@ -67,4 +67,12 @@ void FilterContentsFilterInput::SetLeafInputs(
|
||||
filter_->SetLeafInputs(inputs);
|
||||
}
|
||||
|
||||
void FilterContentsFilterInput::SetEffectTransform(const Matrix& matrix) {
|
||||
filter_->SetEffectTransform(matrix);
|
||||
}
|
||||
|
||||
void FilterContentsFilterInput::SetIsForSubpass(bool is_for_subpass) {
|
||||
filter_->SetIsForSubpass(is_for_subpass);
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -42,6 +42,12 @@ class FilterContentsFilterInput final : public FilterInput {
|
||||
// |FilterInput|
|
||||
void SetLeafInputs(const FilterInput::Vector& inputs) override;
|
||||
|
||||
// |FilterInput|
|
||||
virtual void SetEffectTransform(const Matrix& matrix) override;
|
||||
|
||||
// |FilterInput|
|
||||
virtual void SetIsForSubpass(bool is_for_subpass) override;
|
||||
|
||||
private:
|
||||
explicit FilterContentsFilterInput(std::shared_ptr<FilterContents> filter);
|
||||
|
||||
|
||||
@@ -82,4 +82,8 @@ bool FilterInput::IsLeaf() const {
|
||||
|
||||
void FilterInput::SetLeafInputs(const FilterInput::Vector& inputs) {}
|
||||
|
||||
void FilterInput::SetEffectTransform(const Matrix& matrix) {}
|
||||
|
||||
void FilterInput::SetIsForSubpass(bool is_for_subpass) {}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -77,6 +77,12 @@ class FilterInput {
|
||||
/// of `inputs`.
|
||||
/// @see `FilterInput::IsLeaf`
|
||||
virtual void SetLeafInputs(const FilterInput::Vector& inputs);
|
||||
|
||||
/// @brief Sets the effect transform of filter inputs.
|
||||
virtual void SetEffectTransform(const Matrix& matrix);
|
||||
|
||||
/// @brief Turns on subpass mode for filter inputs.
|
||||
virtual void SetIsForSubpass(bool is_for_subpass);
|
||||
};
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@@ -32,8 +32,8 @@ TEST(FilterInputTest, IsLeaf) {
|
||||
ColorFilterContents::MakeBlend(BlendMode::kSource, {});
|
||||
ASSERT_TRUE(leaf->IsLeaf());
|
||||
|
||||
auto base = ColorFilterContents::MakeMatrixFilter(
|
||||
FilterInput::Make(leaf), Matrix(), {}, Matrix(), false);
|
||||
auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
|
||||
Matrix(), {});
|
||||
|
||||
ASSERT_TRUE(leaf->IsLeaf());
|
||||
ASSERT_FALSE(base->IsLeaf());
|
||||
@@ -44,8 +44,8 @@ TEST(FilterInputTest, SetCoverageInputs) {
|
||||
ColorFilterContents::MakeBlend(BlendMode::kSource, {});
|
||||
ASSERT_TRUE(leaf->IsLeaf());
|
||||
|
||||
auto base = ColorFilterContents::MakeMatrixFilter(
|
||||
FilterInput::Make(leaf), Matrix(), {}, Matrix(), false);
|
||||
auto base = ColorFilterContents::MakeMatrixFilter(FilterInput::Make(leaf),
|
||||
Matrix(), {});
|
||||
|
||||
{
|
||||
auto result = base->GetCoverage({});
|
||||
|
||||
@@ -14,8 +14,9 @@ void MatrixFilterContents::SetMatrix(Matrix matrix) {
|
||||
matrix_ = matrix;
|
||||
}
|
||||
|
||||
void MatrixFilterContents::SetIsSubpass(bool is_subpass) {
|
||||
is_subpass_ = is_subpass;
|
||||
void MatrixFilterContents::SetIsForSubpass(bool is_subpass) {
|
||||
is_for_subpass_ = is_subpass;
|
||||
FilterContents::SetIsForSubpass(is_subpass);
|
||||
}
|
||||
|
||||
void MatrixFilterContents::SetSamplerDescriptor(SamplerDescriptor desc) {
|
||||
@@ -49,7 +50,8 @@ std::optional<Entity> MatrixFilterContents::RenderFilter(
|
||||
// mentioned above). And so we sneak the subpass's captured CTM in through the
|
||||
// effect transform.
|
||||
|
||||
auto transform = is_subpass_ ? effect_transform : entity.GetTransformation();
|
||||
auto transform =
|
||||
is_for_subpass_ ? effect_transform : entity.GetTransformation();
|
||||
snapshot->transform = transform * //
|
||||
matrix_ * //
|
||||
transform.Invert() * //
|
||||
@@ -72,7 +74,8 @@ std::optional<Rect> MatrixFilterContents::GetFilterCoverage(
|
||||
if (!coverage.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto& m = is_subpass_ ? effect_transform : inputs[0]->GetTransform(entity);
|
||||
auto& m =
|
||||
is_for_subpass_ ? effect_transform : inputs[0]->GetTransform(entity);
|
||||
auto transform = m * //
|
||||
matrix_ * //
|
||||
m.Invert(); //
|
||||
|
||||
@@ -17,7 +17,8 @@ class MatrixFilterContents final : public FilterContents {
|
||||
|
||||
void SetMatrix(Matrix matrix);
|
||||
|
||||
void SetIsSubpass(bool is_subpass);
|
||||
// |FilterContents|
|
||||
void SetIsForSubpass(bool is_for_subpass) override;
|
||||
|
||||
void SetSamplerDescriptor(SamplerDescriptor desc);
|
||||
|
||||
@@ -39,7 +40,7 @@ class MatrixFilterContents final : public FilterContents {
|
||||
|
||||
Matrix matrix_;
|
||||
SamplerDescriptor sampler_descriptor_ = {};
|
||||
bool is_subpass_ = false;
|
||||
bool is_for_subpass_ = false;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MatrixFilterContents);
|
||||
};
|
||||
|
||||
@@ -604,13 +604,15 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
|
||||
// right thing.
|
||||
return EntityPass::EntityResult::Failure();
|
||||
}
|
||||
|
||||
element_entity.SetCapture(capture.CreateChild("Entity (Subpass texture)"));
|
||||
Capture subpass_texture_capture =
|
||||
capture.CreateChild("Entity (Subpass texture)");
|
||||
element_entity.SetCapture(subpass_texture_capture);
|
||||
element_entity.SetContents(std::move(offscreen_texture_contents));
|
||||
element_entity.SetStencilDepth(subpass->stencil_depth_);
|
||||
element_entity.SetBlendMode(subpass->blend_mode_);
|
||||
element_entity.SetTransformation(Matrix::MakeTranslation(
|
||||
Vector3(subpass_coverage->origin - global_pass_position)));
|
||||
element_entity.SetTransformation(subpass_texture_capture.AddMatrix(
|
||||
"Transform", Matrix::MakeTranslation(Vector3(subpass_coverage->origin -
|
||||
global_pass_position))));
|
||||
} else {
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
@@ -1191,12 +1191,11 @@ TEST_P(EntityTest, MorphologyFilter) {
|
||||
input = texture;
|
||||
input_size = input_rect.size;
|
||||
|
||||
auto effect_transform = Matrix::MakeScale(
|
||||
Vector2{effect_transform_scale, effect_transform_scale});
|
||||
|
||||
auto contents = FilterContents::MakeMorphology(
|
||||
FilterInput::Make(input), Radius{radius[0]}, Radius{radius[1]},
|
||||
morphology_types[selected_morphology_type], effect_transform);
|
||||
morphology_types[selected_morphology_type]);
|
||||
contents->SetEffectTransform(Matrix::MakeScale(
|
||||
Vector2{effect_transform_scale, effect_transform_scale}));
|
||||
|
||||
auto ctm = Matrix::MakeScale(GetContentScale()) *
|
||||
Matrix::MakeTranslation(Vector3(offset[0], offset[1])) *
|
||||
|
||||
Reference in New Issue
Block a user