[Impeller] remove aiks color_filter and image_filter types. (flutter/engine#55654)
Like the color_source, these classes are just copies of the DL types. Use the DLTypes instead. Part of https://github.com/flutter/flutter/issues/142054
This commit is contained in:
parent
248c2a7062
commit
fd33d17487
@ -9,8 +9,10 @@
|
||||
#include <utility>
|
||||
|
||||
#include "display_list/effects/dl_color_source.h"
|
||||
#include "display_list/effects/dl_image_filter.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
#include "impeller/display_list/skia_conversions.h"
|
||||
#include "impeller/entity/contents/atlas_contents.h"
|
||||
@ -41,12 +43,18 @@ static std::shared_ptr<Contents> CreateContentsForGeometryWithFilters(
|
||||
// Attempt to apply the color filter on the CPU first.
|
||||
// Note: This is not just an optimization; some color sources rely on
|
||||
// CPU-applied color filters to behave properly.
|
||||
bool needs_color_filter = paint.HasColorFilter();
|
||||
if (needs_color_filter) {
|
||||
auto color_filter = paint.GetColorFilter();
|
||||
if (contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
|
||||
needs_color_filter = false;
|
||||
bool needs_color_filter = paint.color_filter || paint.invert_colors;
|
||||
if (needs_color_filter &&
|
||||
contents->ApplyColorFilter([&](Color color) -> Color {
|
||||
if (paint.color_filter) {
|
||||
color = GetCPUColorFilterProc(paint.color_filter)(color);
|
||||
}
|
||||
if (paint.invert_colors) {
|
||||
color = color.ApplyColorMatrix(kColorInversion);
|
||||
}
|
||||
return color;
|
||||
})) {
|
||||
needs_color_filter = false;
|
||||
}
|
||||
|
||||
bool can_apply_mask_filter = geometry->CanApplyMaskFilter();
|
||||
@ -57,24 +65,32 @@ static std::shared_ptr<Contents> CreateContentsForGeometryWithFilters(
|
||||
// we need to be careful to only apply the color filter to the source
|
||||
// colors. CreateMaskBlur is able to handle this case.
|
||||
return paint.mask_blur_descriptor->CreateMaskBlur(
|
||||
contents, needs_color_filter ? paint.GetColorFilter() : nullptr);
|
||||
contents, needs_color_filter ? paint.color_filter : nullptr,
|
||||
needs_color_filter ? paint.invert_colors : false);
|
||||
}
|
||||
|
||||
std::shared_ptr<Contents> contents_copy = std::move(contents);
|
||||
|
||||
// Image input types will directly set their color filter,
|
||||
// if any. See `TiledTextureContents.SetColorFilter`.
|
||||
if (needs_color_filter &&
|
||||
(!paint.color_source ||
|
||||
paint.color_source->type() != flutter::DlColorSourceType::kImage)) {
|
||||
std::shared_ptr<ColorFilter> color_filter = paint.GetColorFilter();
|
||||
contents_copy = color_filter->WrapWithGPUColorFilter(
|
||||
FilterInput::Make(std::move(contents_copy)),
|
||||
if (paint.color_filter) {
|
||||
contents_copy = WrapWithGPUColorFilter(
|
||||
paint.color_filter, FilterInput::Make(std::move(contents_copy)),
|
||||
ColorFilterContents::AbsorbOpacity::kYes);
|
||||
}
|
||||
if (paint.invert_colors) {
|
||||
contents_copy =
|
||||
WrapWithInvertColors(FilterInput::Make(contents_copy),
|
||||
ColorFilterContents::AbsorbOpacity::kYes);
|
||||
}
|
||||
}
|
||||
|
||||
if (paint.image_filter) {
|
||||
std::shared_ptr<FilterContents> filter = paint.image_filter->WrapInput(
|
||||
FilterInput::Make(std::move(contents_copy)));
|
||||
std::shared_ptr<FilterContents> filter = WrapInput(
|
||||
paint.image_filter, FilterInput::Make(std::move(contents_copy)));
|
||||
filter->SetRenderingMode(Entity::RenderingMode::kDirect);
|
||||
return filter;
|
||||
}
|
||||
@ -471,12 +487,13 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect,
|
||||
|
||||
// For symmetrically mask blurred solid RRects, absorb the mask blur and use
|
||||
// a faster SDF approximation.
|
||||
|
||||
Color rrect_color =
|
||||
paint.HasColorFilter()
|
||||
// Absorb the color filter, if any.
|
||||
? paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color)
|
||||
: paint.color;
|
||||
Color rrect_color = paint.color;
|
||||
if (paint.invert_colors) {
|
||||
rrect_color = rrect_color.ApplyColorMatrix(kColorInversion);
|
||||
}
|
||||
if (paint.color_filter) {
|
||||
rrect_color = GetCPUColorFilterProc(paint.color_filter)(rrect_color);
|
||||
}
|
||||
|
||||
Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor};
|
||||
|
||||
@ -512,11 +529,13 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect,
|
||||
render_bounds.Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
|
||||
}
|
||||
// Defer the alpha, blend mode, and image filter to a separate layer.
|
||||
SaveLayer({.color = Color::White().WithAlpha(rrect_color.alpha),
|
||||
SaveLayer(
|
||||
Paint{
|
||||
.color = Color::White().WithAlpha(rrect_color.alpha),
|
||||
.image_filter = paint.image_filter,
|
||||
.blend_mode = paint.blend_mode,
|
||||
.image_filter = paint.image_filter},
|
||||
render_bounds, nullptr, ContentBoundsPromise::kContainsContents,
|
||||
1u);
|
||||
},
|
||||
render_bounds, nullptr, ContentBoundsPromise::kContainsContents, 1u);
|
||||
rrect_paint.color = rrect_color.WithAlpha(1);
|
||||
} else {
|
||||
rrect_paint.color = rrect_color;
|
||||
@ -892,8 +911,9 @@ void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
|
||||
auto src_paint = paint;
|
||||
src_paint.color = paint.color.WithAlpha(1.0);
|
||||
|
||||
std::shared_ptr<Contents> src_contents =
|
||||
src_paint.CreateContentsForGeometry(vertices);
|
||||
std::shared_ptr<ColorSourceContents> src_contents =
|
||||
src_paint.CreateContents();
|
||||
src_contents->SetGeometry(vertices);
|
||||
|
||||
// If the color source has an intrinsic size, then we use that to
|
||||
// create the src contents as a simplification. Otherwise we use
|
||||
@ -912,8 +932,8 @@ void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
|
||||
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
||||
vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
|
||||
}
|
||||
src_contents = src_paint.CreateContentsForGeometry(
|
||||
Geometry::MakeRect(Rect::Round(src_coverage)));
|
||||
src_contents = src_paint.CreateContents();
|
||||
src_contents->SetGeometry(Geometry::MakeRect(Rect::Round(src_coverage)));
|
||||
|
||||
auto contents = std::make_shared<VerticesSimpleBlendContents>();
|
||||
contents->SetBlendMode(blend_mode);
|
||||
@ -1049,7 +1069,7 @@ std::optional<Rect> Canvas::GetLocalCoverageLimit() const {
|
||||
|
||||
void Canvas::SaveLayer(const Paint& paint,
|
||||
std::optional<Rect> bounds,
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter,
|
||||
const flutter::DlImageFilter* backdrop_filter,
|
||||
ContentBoundsPromise bounds_promise,
|
||||
uint32_t total_content_depth,
|
||||
bool can_distribute_opacity) {
|
||||
@ -1125,10 +1145,10 @@ void Canvas::SaveLayer(const Paint& paint,
|
||||
if (backdrop_filter) {
|
||||
local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
|
||||
Canvas::BackdropFilterProc backdrop_filter_proc =
|
||||
[backdrop_filter = backdrop_filter->Clone()](
|
||||
[backdrop_filter = backdrop_filter](
|
||||
const FilterInput::Ref& input, const Matrix& effect_transform,
|
||||
Entity::RenderingMode rendering_mode) {
|
||||
auto filter = backdrop_filter->WrapInput(input);
|
||||
auto filter = WrapInput(backdrop_filter, input);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
filter->SetRenderingMode(rendering_mode);
|
||||
return filter;
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "display_list/effects/dl_image_filter.h"
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
#include "impeller/display_list/paint.h"
|
||||
#include "impeller/entity/contents/atlas_contents.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
@ -132,7 +132,7 @@ class Canvas {
|
||||
void SaveLayer(
|
||||
const Paint& paint,
|
||||
std::optional<Rect> bounds = std::nullopt,
|
||||
const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr,
|
||||
const flutter::DlImageFilter* backdrop_filter = nullptr,
|
||||
ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown,
|
||||
uint32_t total_content_depth = kMaxDepth,
|
||||
bool can_distribute_opacity = false);
|
||||
|
@ -3,14 +3,9 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "impeller/display_list/aiks_context.h"
|
||||
#include "impeller/display_list/aiks_unittests.h"
|
||||
#include "impeller/display_list/canvas.h"
|
||||
#include "impeller/geometry/geometry_asserts.h"
|
||||
#include "impeller/geometry/path_builder.h"
|
||||
|
||||
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
|
||||
// NOLINTBEGIN(bugprone-unchecked-optional-access)
|
||||
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
@ -98,34 +93,5 @@ TEST_P(AiksTest, CanvasCTMCanBeUpdated) {
|
||||
Matrix::MakeTranslation({100.0, 100.0, 0.0}));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, PaintWithFilters) {
|
||||
// validate that a paint with a color filter "HasFilters", no other filters
|
||||
// impact this setting.
|
||||
Paint paint;
|
||||
|
||||
ASSERT_FALSE(paint.HasColorFilter());
|
||||
|
||||
paint.color_filter =
|
||||
ColorFilter::MakeBlend(BlendMode::kSourceOver, Color::Blue());
|
||||
|
||||
ASSERT_TRUE(paint.HasColorFilter());
|
||||
|
||||
paint.image_filter = ImageFilter::MakeBlur(Sigma(1.0), Sigma(1.0),
|
||||
FilterContents::BlurStyle::kNormal,
|
||||
Entity::TileMode::kClamp);
|
||||
|
||||
ASSERT_TRUE(paint.HasColorFilter());
|
||||
|
||||
paint.mask_blur_descriptor = {};
|
||||
|
||||
ASSERT_TRUE(paint.HasColorFilter());
|
||||
|
||||
paint.color_filter = nullptr;
|
||||
|
||||
ASSERT_FALSE(paint.HasColorFilter());
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
// NOLINTEND(bugprone-unchecked-optional-access)
|
||||
|
@ -4,187 +4,99 @@
|
||||
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
|
||||
#include <utility>
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "fml/logging.h"
|
||||
#include "impeller/display_list/skia_conversions.h"
|
||||
#include "impeller/entity/contents/filters/color_filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/inputs/filter_input.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
/*******************************************************************************
|
||||
******* ColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
ColorFilter::ColorFilter() = default;
|
||||
|
||||
ColorFilter::~ColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilter> ColorFilter::MakeBlend(BlendMode blend_mode,
|
||||
Color color) {
|
||||
return std::make_shared<BlendColorFilter>(blend_mode, color);
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> ColorFilter::MakeMatrix(ColorMatrix color_matrix) {
|
||||
return std::make_shared<MatrixColorFilter>(color_matrix);
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> ColorFilter::MakeSrgbToLinear() {
|
||||
return std::make_shared<SrgbToLinearColorFilter>();
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> ColorFilter::MakeLinearToSrgb() {
|
||||
return std::make_shared<LinearToSrgbColorFilter>();
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> ColorFilter::MakeComposed(
|
||||
const std::shared_ptr<ColorFilter>& outer,
|
||||
const std::shared_ptr<ColorFilter>& inner) {
|
||||
return std::make_shared<ComposedColorFilter>(outer, inner);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* BlendColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
BlendColorFilter::BlendColorFilter(BlendMode blend_mode, Color color)
|
||||
: blend_mode_(blend_mode), color_(color) {}
|
||||
|
||||
BlendColorFilter::~BlendColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilterContents> BlendColorFilter::WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
|
||||
auto filter =
|
||||
ColorFilterContents::MakeBlend(blend_mode_, {std::move(input)}, color_);
|
||||
std::shared_ptr<ColorFilterContents> WrapWithInvertColors(
|
||||
const std::shared_ptr<FilterInput>& input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) {
|
||||
auto filter = ColorFilterContents::MakeColorMatrix({input}, kColorInversion);
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
|
||||
ColorFilter::ColorFilterProc BlendColorFilter::GetCPUColorFilterProc() const {
|
||||
return [filter_blend_mode = blend_mode_, filter_color = color_](Color color) {
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
const flutter::DlColorFilter* filter,
|
||||
const std::shared_ptr<FilterInput>& input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) {
|
||||
FML_DCHECK(filter);
|
||||
|
||||
switch (filter->type()) {
|
||||
case flutter::DlColorFilterType::kBlend: {
|
||||
const flutter::DlBlendColorFilter* blend_filter = filter->asBlend();
|
||||
FML_DCHECK(blend_filter);
|
||||
|
||||
auto filter = ColorFilterContents::MakeBlend(
|
||||
static_cast<BlendMode>(blend_filter->mode()), {input},
|
||||
skia_conversions::ToColor(blend_filter->color()));
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
case flutter::DlColorFilterType::kMatrix: {
|
||||
const flutter::DlMatrixColorFilter* matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
|
||||
impeller::ColorMatrix color_matrix;
|
||||
matrix_filter->get_matrix(color_matrix.array);
|
||||
auto filter = ColorFilterContents::MakeColorMatrix({input}, color_matrix);
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
case flutter::DlColorFilterType::kSrgbToLinearGamma: {
|
||||
auto filter = ColorFilterContents::MakeSrgbToLinearFilter({input});
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
case flutter::DlColorFilterType::kLinearToSrgbGamma: {
|
||||
auto filter = ColorFilterContents::MakeLinearToSrgbFilter({input});
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter* filter) {
|
||||
FML_DCHECK(filter);
|
||||
|
||||
switch (filter->type()) {
|
||||
case flutter::DlColorFilterType::kBlend: {
|
||||
const flutter::DlBlendColorFilter* blend_filter = filter->asBlend();
|
||||
FML_DCHECK(blend_filter);
|
||||
|
||||
return [filter_blend_mode = static_cast<BlendMode>(blend_filter->mode()),
|
||||
filter_color = skia_conversions::ToColor(blend_filter->color())](
|
||||
Color color) {
|
||||
return color.Blend(filter_color, filter_blend_mode);
|
||||
};
|
||||
}
|
||||
case flutter::DlColorFilterType::kMatrix: {
|
||||
const flutter::DlMatrixColorFilter* matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
|
||||
std::shared_ptr<ColorFilter> BlendColorFilter::Clone() const {
|
||||
return std::make_shared<BlendColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* MatrixColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
MatrixColorFilter::MatrixColorFilter(ColorMatrix color_matrix)
|
||||
: color_matrix_(color_matrix) {}
|
||||
|
||||
MatrixColorFilter::~MatrixColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilterContents> MatrixColorFilter::WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
|
||||
auto filter =
|
||||
ColorFilterContents::MakeColorMatrix({std::move(input)}, color_matrix_);
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
|
||||
ColorFilter::ColorFilterProc MatrixColorFilter::GetCPUColorFilterProc() const {
|
||||
return [color_matrix = color_matrix_](Color color) {
|
||||
impeller::ColorMatrix color_matrix;
|
||||
matrix_filter->get_matrix(color_matrix.array);
|
||||
return [color_matrix = color_matrix](Color color) {
|
||||
return color.ApplyColorMatrix(color_matrix);
|
||||
};
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> MatrixColorFilter::Clone() const {
|
||||
return std::make_shared<MatrixColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* SrgbToLinearColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
SrgbToLinearColorFilter::SrgbToLinearColorFilter() = default;
|
||||
|
||||
SrgbToLinearColorFilter::~SrgbToLinearColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilterContents>
|
||||
SrgbToLinearColorFilter::WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
|
||||
auto filter = ColorFilterContents::MakeSrgbToLinearFilter({std::move(input)});
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
|
||||
ColorFilter::ColorFilterProc SrgbToLinearColorFilter::GetCPUColorFilterProc()
|
||||
const {
|
||||
case flutter::DlColorFilterType::kSrgbToLinearGamma: {
|
||||
return [](Color color) { return color.SRGBToLinear(); };
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> SrgbToLinearColorFilter::Clone() const {
|
||||
return std::make_shared<SrgbToLinearColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* LinearToSrgbColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
LinearToSrgbColorFilter::LinearToSrgbColorFilter() = default;
|
||||
|
||||
LinearToSrgbColorFilter::~LinearToSrgbColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilterContents>
|
||||
LinearToSrgbColorFilter::WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
|
||||
auto filter = ColorFilterContents::MakeSrgbToLinearFilter({std::move(input)});
|
||||
filter->SetAbsorbOpacity(absorb_opacity);
|
||||
return filter;
|
||||
}
|
||||
|
||||
ColorFilter::ColorFilterProc LinearToSrgbColorFilter::GetCPUColorFilterProc()
|
||||
const {
|
||||
case flutter::DlColorFilterType::kLinearToSrgbGamma: {
|
||||
return [](Color color) { return color.LinearToSRGB(); };
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> LinearToSrgbColorFilter::Clone() const {
|
||||
return std::make_shared<LinearToSrgbColorFilter>(*this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
******* ComposedColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
ComposedColorFilter::ComposedColorFilter(
|
||||
const std::shared_ptr<ColorFilter>& outer,
|
||||
const std::shared_ptr<ColorFilter>& inner)
|
||||
: outer_(outer), inner_(inner) {}
|
||||
|
||||
ComposedColorFilter::~ComposedColorFilter() = default;
|
||||
|
||||
std::shared_ptr<ColorFilterContents>
|
||||
ComposedColorFilter::WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const {
|
||||
std::shared_ptr<FilterContents> inner = inner_->WrapWithGPUColorFilter(
|
||||
input, ColorFilterContents::AbsorbOpacity::kNo);
|
||||
return outer_->WrapWithGPUColorFilter(FilterInput::Make(inner),
|
||||
absorb_opacity);
|
||||
}
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilter::ColorFilterProc ComposedColorFilter::GetCPUColorFilterProc()
|
||||
const {
|
||||
return [inner = inner_, outer = outer_](Color color) {
|
||||
auto inner_proc = inner->GetCPUColorFilterProc();
|
||||
auto outer_proc = outer->GetCPUColorFilterProc();
|
||||
return outer_proc(inner_proc(color));
|
||||
};
|
||||
}
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> ComposedColorFilter::Clone() const {
|
||||
return std::make_shared<ComposedColorFilter>(outer_, inner_);
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -5,176 +5,37 @@
|
||||
#ifndef FLUTTER_IMPELLER_DISPLAY_LIST_COLOR_FILTER_H_
|
||||
#define FLUTTER_IMPELLER_DISPLAY_LIST_COLOR_FILTER_H_
|
||||
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "impeller/entity/contents/filters/color_filter_contents.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
struct Paint;
|
||||
/// A color matrix which inverts colors.
|
||||
// clang-format off
|
||||
static const constexpr ColorMatrix kColorInversion = {
|
||||
.array = {
|
||||
-1.0, 0, 0, 1.0, 0, //
|
||||
0, -1.0, 0, 1.0, 0, //
|
||||
0, 0, -1.0, 1.0, 0, //
|
||||
1.0, 1.0, 1.0, 1.0, 0 //
|
||||
}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* ColorFilter
|
||||
******************************************************************************/
|
||||
std::shared_ptr<ColorFilterContents> WrapWithInvertColors(
|
||||
const std::shared_ptr<FilterInput>& input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity);
|
||||
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
const flutter::DlColorFilter* filter,
|
||||
const std::shared_ptr<FilterInput>& input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity);
|
||||
|
||||
class ColorFilter {
|
||||
public:
|
||||
/// A procedure that filters a given unpremultiplied color to produce a new
|
||||
/// unpremultiplied color.
|
||||
using ColorFilterProc = std::function<Color(Color)>;
|
||||
|
||||
ColorFilter();
|
||||
|
||||
virtual ~ColorFilter();
|
||||
|
||||
static std::shared_ptr<ColorFilter> MakeBlend(BlendMode blend_mode,
|
||||
Color color);
|
||||
|
||||
static std::shared_ptr<ColorFilter> MakeMatrix(ColorMatrix color_matrix);
|
||||
|
||||
static std::shared_ptr<ColorFilter> MakeSrgbToLinear();
|
||||
|
||||
static std::shared_ptr<ColorFilter> MakeLinearToSrgb();
|
||||
|
||||
static std::shared_ptr<ColorFilter> MakeComposed(
|
||||
const std::shared_ptr<ColorFilter>& outer,
|
||||
const std::shared_ptr<ColorFilter>& inner);
|
||||
|
||||
/// @brief Wraps the given filter input with a GPU-based filter that will
|
||||
/// perform the color operation. The given input will first be
|
||||
/// rendered to a texture and then filtered.
|
||||
///
|
||||
/// Note that this operation has no consideration for the original
|
||||
/// geometry mask of the filter input. And the entire input texture is
|
||||
/// treated as color information.
|
||||
virtual std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const = 0;
|
||||
|
||||
/// @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;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* BlendColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
class BlendColorFilter final : public ColorFilter {
|
||||
public:
|
||||
BlendColorFilter(BlendMode blend_mode, Color color);
|
||||
|
||||
~BlendColorFilter() override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
BlendMode blend_mode_;
|
||||
Color color_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* MatrixColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
class MatrixColorFilter final : public ColorFilter {
|
||||
public:
|
||||
explicit MatrixColorFilter(ColorMatrix color_matrix);
|
||||
|
||||
~MatrixColorFilter() override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
ColorMatrix color_matrix_;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* SrgbToLinearColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
class SrgbToLinearColorFilter final : public ColorFilter {
|
||||
public:
|
||||
explicit SrgbToLinearColorFilter();
|
||||
|
||||
~SrgbToLinearColorFilter() override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* LinearToSrgbColorFilter
|
||||
******************************************************************************/
|
||||
|
||||
class LinearToSrgbColorFilter final : public ColorFilter {
|
||||
public:
|
||||
explicit LinearToSrgbColorFilter();
|
||||
|
||||
~LinearToSrgbColorFilter() override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
};
|
||||
|
||||
/// @brief Applies color filters as f(g(x)), where x is the input color.
|
||||
class ComposedColorFilter final : public ColorFilter {
|
||||
public:
|
||||
ComposedColorFilter(const std::shared_ptr<ColorFilter>& outer,
|
||||
const std::shared_ptr<ColorFilter>& inner);
|
||||
|
||||
~ComposedColorFilter() override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
|
||||
std::shared_ptr<FilterInput> input,
|
||||
ColorFilterContents::AbsorbOpacity absorb_opacity) const override;
|
||||
|
||||
// |ColorFilter|
|
||||
ColorFilterProc GetCPUColorFilterProc() const override;
|
||||
|
||||
// |ColorFilter|
|
||||
std::shared_ptr<ColorFilter> Clone() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ColorFilter> outer_;
|
||||
std::shared_ptr<ColorFilter> inner_;
|
||||
};
|
||||
ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter* filter);
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
|
@ -114,70 +114,6 @@ struct DepthWatcher {
|
||||
#define UNIMPLEMENTED \
|
||||
FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__;
|
||||
|
||||
static BlendMode ToBlendMode(flutter::DlBlendMode mode) {
|
||||
switch (mode) {
|
||||
case flutter::DlBlendMode::kClear:
|
||||
return BlendMode::kClear;
|
||||
case flutter::DlBlendMode::kSrc:
|
||||
return BlendMode::kSource;
|
||||
case flutter::DlBlendMode::kDst:
|
||||
return BlendMode::kDestination;
|
||||
case flutter::DlBlendMode::kSrcOver:
|
||||
return BlendMode::kSourceOver;
|
||||
case flutter::DlBlendMode::kDstOver:
|
||||
return BlendMode::kDestinationOver;
|
||||
case flutter::DlBlendMode::kSrcIn:
|
||||
return BlendMode::kSourceIn;
|
||||
case flutter::DlBlendMode::kDstIn:
|
||||
return BlendMode::kDestinationIn;
|
||||
case flutter::DlBlendMode::kSrcOut:
|
||||
return BlendMode::kSourceOut;
|
||||
case flutter::DlBlendMode::kDstOut:
|
||||
return BlendMode::kDestinationOut;
|
||||
case flutter::DlBlendMode::kSrcATop:
|
||||
return BlendMode::kSourceATop;
|
||||
case flutter::DlBlendMode::kDstATop:
|
||||
return BlendMode::kDestinationATop;
|
||||
case flutter::DlBlendMode::kXor:
|
||||
return BlendMode::kXor;
|
||||
case flutter::DlBlendMode::kPlus:
|
||||
return BlendMode::kPlus;
|
||||
case flutter::DlBlendMode::kModulate:
|
||||
return BlendMode::kModulate;
|
||||
case flutter::DlBlendMode::kScreen:
|
||||
return BlendMode::kScreen;
|
||||
case flutter::DlBlendMode::kOverlay:
|
||||
return BlendMode::kOverlay;
|
||||
case flutter::DlBlendMode::kDarken:
|
||||
return BlendMode::kDarken;
|
||||
case flutter::DlBlendMode::kLighten:
|
||||
return BlendMode::kLighten;
|
||||
case flutter::DlBlendMode::kColorDodge:
|
||||
return BlendMode::kColorDodge;
|
||||
case flutter::DlBlendMode::kColorBurn:
|
||||
return BlendMode::kColorBurn;
|
||||
case flutter::DlBlendMode::kHardLight:
|
||||
return BlendMode::kHardLight;
|
||||
case flutter::DlBlendMode::kSoftLight:
|
||||
return BlendMode::kSoftLight;
|
||||
case flutter::DlBlendMode::kDifference:
|
||||
return BlendMode::kDifference;
|
||||
case flutter::DlBlendMode::kExclusion:
|
||||
return BlendMode::kExclusion;
|
||||
case flutter::DlBlendMode::kMultiply:
|
||||
return BlendMode::kMultiply;
|
||||
case flutter::DlBlendMode::kHue:
|
||||
return BlendMode::kHue;
|
||||
case flutter::DlBlendMode::kSaturation:
|
||||
return BlendMode::kSaturation;
|
||||
case flutter::DlBlendMode::kColor:
|
||||
return BlendMode::kColor;
|
||||
case flutter::DlBlendMode::kLuminosity:
|
||||
return BlendMode::kLuminosity;
|
||||
}
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
static impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
const flutter::DlFilterMode options) {
|
||||
impeller::SamplerDescriptor desc;
|
||||
@ -289,37 +225,11 @@ void DlDispatcherBase::setColorSource(const flutter::DlColorSource* source) {
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<ColorFilter> ToColorFilter(
|
||||
const flutter::DlColorFilter* filter) {
|
||||
if (filter == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
switch (filter->type()) {
|
||||
case flutter::DlColorFilterType::kBlend: {
|
||||
auto dl_blend = filter->asBlend();
|
||||
auto blend_mode = ToBlendMode(dl_blend->mode());
|
||||
auto color = skia_conversions::ToColor(dl_blend->color());
|
||||
return ColorFilter::MakeBlend(blend_mode, color);
|
||||
}
|
||||
case flutter::DlColorFilterType::kMatrix: {
|
||||
const flutter::DlMatrixColorFilter* dl_matrix = filter->asMatrix();
|
||||
impeller::ColorMatrix color_matrix;
|
||||
dl_matrix->get_matrix(color_matrix.array);
|
||||
return ColorFilter::MakeMatrix(color_matrix);
|
||||
}
|
||||
case flutter::DlColorFilterType::kSrgbToLinearGamma:
|
||||
return ColorFilter::MakeSrgbToLinear();
|
||||
case flutter::DlColorFilterType::kLinearToSrgbGamma:
|
||||
return ColorFilter::MakeLinearToSrgb();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) {
|
||||
AUTO_DEPTH_WATCHER(0u);
|
||||
|
||||
paint_.color_filter = ToColorFilter(filter);
|
||||
paint_.color_filter = filter;
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
@ -333,7 +243,7 @@ void DlDispatcherBase::setInvertColors(bool invert) {
|
||||
void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) {
|
||||
AUTO_DEPTH_WATCHER(0u);
|
||||
|
||||
paint_.blend_mode = ToBlendMode(dl_mode);
|
||||
paint_.blend_mode = skia_conversions::ToBlendMode(dl_mode);
|
||||
}
|
||||
|
||||
static FilterContents::BlurStyle ToBlurStyle(flutter::DlBlurStyle blur_style) {
|
||||
@ -372,102 +282,11 @@ void DlDispatcherBase::setMaskFilter(const flutter::DlMaskFilter* filter) {
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<ImageFilter> ToImageFilter(
|
||||
const flutter::DlImageFilter* filter) {
|
||||
if (filter == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (filter->type()) {
|
||||
case flutter::DlImageFilterType::kBlur: {
|
||||
auto blur = filter->asBlur();
|
||||
auto sigma_x = Sigma(blur->sigma_x());
|
||||
auto sigma_y = Sigma(blur->sigma_y());
|
||||
auto tile_mode = static_cast<Entity::TileMode>(blur->tile_mode());
|
||||
return ImageFilter::MakeBlur(
|
||||
sigma_x, sigma_y, FilterContents::BlurStyle::kNormal, tile_mode);
|
||||
}
|
||||
case flutter::DlImageFilterType::kDilate: {
|
||||
auto dilate = filter->asDilate();
|
||||
FML_DCHECK(dilate);
|
||||
if (dilate->radius_x() < 0 || dilate->radius_y() < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
auto radius_x = Radius(dilate->radius_x());
|
||||
auto radius_y = Radius(dilate->radius_y());
|
||||
return ImageFilter::MakeDilate(radius_x, radius_y);
|
||||
}
|
||||
case flutter::DlImageFilterType::kErode: {
|
||||
auto erode = filter->asErode();
|
||||
FML_DCHECK(erode);
|
||||
if (erode->radius_x() < 0 || erode->radius_y() < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
auto radius_x = Radius(erode->radius_x());
|
||||
auto radius_y = Radius(erode->radius_y());
|
||||
return ImageFilter::MakeErode(radius_x, radius_y);
|
||||
}
|
||||
case flutter::DlImageFilterType::kMatrix: {
|
||||
auto matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
auto matrix = skia_conversions::ToMatrix(matrix_filter->matrix());
|
||||
auto desc =
|
||||
skia_conversions::ToSamplerDescriptor(matrix_filter->sampling());
|
||||
return ImageFilter::MakeMatrix(matrix, desc);
|
||||
}
|
||||
case flutter::DlImageFilterType::kCompose: {
|
||||
auto compose = filter->asCompose();
|
||||
FML_DCHECK(compose);
|
||||
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_filter) {
|
||||
return outer_filter;
|
||||
}
|
||||
FML_DCHECK(outer_filter && inner_filter);
|
||||
|
||||
return ImageFilter::MakeCompose(*inner_filter, *outer_filter);
|
||||
}
|
||||
case flutter::DlImageFilterType::kColorFilter: {
|
||||
auto color_filter_image_filter = filter->asColorFilter();
|
||||
FML_DCHECK(color_filter_image_filter);
|
||||
auto color_filter =
|
||||
ToColorFilter(color_filter_image_filter->color_filter().get());
|
||||
if (!color_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
// 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();
|
||||
FML_DCHECK(local_matrix_filter);
|
||||
auto internal_filter = local_matrix_filter->image_filter();
|
||||
FML_DCHECK(internal_filter);
|
||||
|
||||
auto image_filter = ToImageFilter(internal_filter.get());
|
||||
if (!image_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto matrix = skia_conversions::ToMatrix(local_matrix_filter->matrix());
|
||||
return ImageFilter::MakeLocalMatrix(matrix, *image_filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) {
|
||||
AUTO_DEPTH_WATCHER(0u);
|
||||
|
||||
paint_.image_filter = ToImageFilter(filter);
|
||||
paint_.image_filter = filter;
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
@ -497,8 +316,7 @@ void DlDispatcherBase::saveLayer(const DlRect& bounds,
|
||||
}
|
||||
|
||||
GetCanvas().SaveLayer(
|
||||
paint, impeller_bounds, ToImageFilter(backdrop), promise,
|
||||
total_content_depth,
|
||||
paint, impeller_bounds, backdrop, promise, total_content_depth,
|
||||
// Unbounded content can still have user specified bounds that require a
|
||||
// saveLayer to be created to perform the clip.
|
||||
options.can_distribute_opacity() && !options.content_is_unbounded());
|
||||
@ -674,7 +492,7 @@ void DlDispatcherBase::drawColor(flutter::DlColor color,
|
||||
|
||||
Paint paint;
|
||||
paint.color = skia_conversions::ToColor(color);
|
||||
paint.blend_mode = ToBlendMode(dl_mode);
|
||||
paint.blend_mode = skia_conversions::ToBlendMode(dl_mode);
|
||||
GetCanvas().DrawPaint(paint);
|
||||
}
|
||||
|
||||
@ -950,7 +768,7 @@ void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
tex, //
|
||||
colors, //
|
||||
static_cast<size_t>(count), //
|
||||
ToBlendMode(mode), //
|
||||
skia_conversions::ToBlendMode(mode), //
|
||||
skia_conversions::ToSamplerDescriptor(sampling), //
|
||||
skia_conversions::ToRect(cull_rect) //
|
||||
);
|
||||
@ -1117,7 +935,8 @@ static bool RequiresReadbackForBlends(
|
||||
const ContentContext& renderer,
|
||||
flutter::DlBlendMode max_root_blend_mode) {
|
||||
return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
|
||||
ToBlendMode(max_root_blend_mode) > Entity::kLastPipelineBlendMode;
|
||||
skia_conversions::ToBlendMode(max_root_blend_mode) >
|
||||
Entity::kLastPipelineBlendMode;
|
||||
}
|
||||
|
||||
CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
|
||||
@ -1143,7 +962,7 @@ void CanvasDlDispatcher::drawVertices(
|
||||
|
||||
GetCanvas().DrawVertices(
|
||||
std::make_shared<DlVerticesGeometry>(vertices, renderer_),
|
||||
ToBlendMode(dl_mode), paint_);
|
||||
skia_conversions::ToBlendMode(dl_mode), paint_);
|
||||
}
|
||||
|
||||
//// Text Frame Dispatcher
|
||||
|
@ -3,206 +3,107 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
#include "fml/logging.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "impeller/display_list/skia_conversions.h"
|
||||
#include "impeller/entity/contents/filters/color_filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/filter_contents.h"
|
||||
#include "impeller/entity/contents/filters/inputs/filter_input.h"
|
||||
|
||||
namespace impeller {
|
||||
|
||||
/*******************************************************************************
|
||||
******* ImageFilter
|
||||
******************************************************************************/
|
||||
std::shared_ptr<FilterContents> WrapInput(const flutter::DlImageFilter* filter,
|
||||
const FilterInput::Ref& input) {
|
||||
FML_DCHECK(filter);
|
||||
|
||||
ImageFilter::ImageFilter() = default;
|
||||
switch (filter->type()) {
|
||||
case flutter::DlImageFilterType::kBlur: {
|
||||
auto blur_filter = filter->asBlur();
|
||||
FML_DCHECK(blur_filter);
|
||||
|
||||
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);
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
input, //
|
||||
Sigma(blur_filter->sigma_x()), //
|
||||
Sigma(blur_filter->sigma_y()), //
|
||||
static_cast<Entity::TileMode>(blur_filter->tile_mode()), //
|
||||
FilterContents::BlurStyle::kNormal //
|
||||
);
|
||||
}
|
||||
case flutter::DlImageFilterType::kDilate: {
|
||||
auto dilate_filter = filter->asDilate();
|
||||
FML_DCHECK(dilate_filter);
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeDilate(Radius radius_x,
|
||||
Radius radius_y) {
|
||||
return std::make_shared<DilateImageFilter>(radius_x, radius_y);
|
||||
return FilterContents::MakeMorphology(
|
||||
input, //
|
||||
Radius(dilate_filter->radius_x()), //
|
||||
Radius(dilate_filter->radius_y()), //
|
||||
FilterContents::MorphType::kDilate //
|
||||
);
|
||||
}
|
||||
case flutter::DlImageFilterType::kErode: {
|
||||
auto erode_filter = filter->asErode();
|
||||
FML_DCHECK(erode_filter);
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeErode(Radius radius_x,
|
||||
Radius radius_y) {
|
||||
return std::make_shared<ErodeImageFilter>(radius_x, radius_y);
|
||||
return FilterContents::MakeMorphology(
|
||||
input, //
|
||||
Radius(erode_filter->radius_x()), //
|
||||
Radius(erode_filter->radius_y()), //
|
||||
FilterContents::MorphType::kErode //
|
||||
);
|
||||
}
|
||||
case flutter::DlImageFilterType::kMatrix: {
|
||||
auto matrix_filter = filter->asMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
|
||||
std::shared_ptr<ImageFilter> ImageFilter::MakeMatrix(
|
||||
const Matrix& matrix,
|
||||
SamplerDescriptor sampler_descriptor) {
|
||||
return std::make_shared<MatrixImageFilter>(matrix,
|
||||
std::move(sampler_descriptor));
|
||||
auto matrix = skia_conversions::ToMatrix(matrix_filter->matrix());
|
||||
auto desc =
|
||||
skia_conversions::ToSamplerDescriptor(matrix_filter->sampling());
|
||||
return FilterContents::MakeMatrixFilter(input, matrix, desc);
|
||||
}
|
||||
case flutter::DlImageFilterType::kLocalMatrix: {
|
||||
auto matrix_filter = filter->asLocalMatrix();
|
||||
FML_DCHECK(matrix_filter);
|
||||
FML_DCHECK(matrix_filter->image_filter());
|
||||
|
||||
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_, tile_mode_,
|
||||
blur_style_);
|
||||
}
|
||||
|
||||
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, ColorFilterContents::AbsorbOpacity::kNo);
|
||||
}
|
||||
|
||||
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 {
|
||||
auto matrix = skia_conversions::ToMatrix(matrix_filter->matrix());
|
||||
return FilterContents::MakeLocalMatrixFilter(
|
||||
FilterInput::Make(internal_filter_->WrapInput(input)), matrix_);
|
||||
FilterInput::Make(
|
||||
WrapInput(matrix_filter->image_filter().get(), input)),
|
||||
matrix);
|
||||
}
|
||||
case flutter::DlImageFilterType::kColorFilter: {
|
||||
auto image_color_filter = filter->asColorFilter();
|
||||
FML_DCHECK(image_color_filter);
|
||||
auto color_filter = image_color_filter->color_filter();
|
||||
FML_DCHECK(color_filter);
|
||||
|
||||
std::shared_ptr<ImageFilter> LocalMatrixImageFilter::Clone() const {
|
||||
return std::make_shared<LocalMatrixImageFilter>(*this);
|
||||
// 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 WrapWithGPUColorFilter(color_filter.get(), input,
|
||||
ColorFilterContents::AbsorbOpacity::kNo);
|
||||
}
|
||||
case flutter::DlImageFilterType::kCompose: {
|
||||
auto compose = filter->asCompose();
|
||||
FML_DCHECK(compose);
|
||||
|
||||
auto outer_dl_filter = compose->outer();
|
||||
auto inner_dl_filter = compose->inner();
|
||||
if (!outer_dl_filter) {
|
||||
return WrapInput(inner_dl_filter.get(), input);
|
||||
}
|
||||
if (!inner_dl_filter) {
|
||||
return WrapInput(outer_dl_filter.get(), input);
|
||||
}
|
||||
FML_DCHECK(outer_dl_filter && inner_dl_filter);
|
||||
|
||||
return WrapInput(
|
||||
outer_dl_filter.get(),
|
||||
FilterInput::Make(WrapInput(inner_dl_filter.get(), input)));
|
||||
}
|
||||
}
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -5,233 +5,15 @@
|
||||
#ifndef FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_
|
||||
#define FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_
|
||||
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "display_list/effects/dl_image_filter.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;
|
||||
|
||||
virtual int GetRequiredMipCount() const { return 1; }
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******* 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;
|
||||
|
||||
int GetRequiredMipCount() const override { return 4; }
|
||||
|
||||
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;
|
||||
|
||||
const Matrix& GetMatrix() const { return matrix_; }
|
||||
|
||||
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_;
|
||||
};
|
||||
std::shared_ptr<FilterContents> WrapInput(const flutter::DlImageFilter* filter,
|
||||
const FilterInput::Ref& input);
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
|
@ -6,9 +6,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "display_list/effects/dl_color_source.h"
|
||||
#include "display_list/geometry/dl_path.h"
|
||||
#include "fml/logging.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "impeller/display_list/skia_conversions.h"
|
||||
#include "impeller/entity/contents/color_source_contents.h"
|
||||
#include "impeller/entity/contents/conical_gradient_contents.h"
|
||||
@ -31,18 +33,6 @@ using DlRect = flutter::DlRect;
|
||||
using DlIRect = flutter::DlIRect;
|
||||
using DlPath = flutter::DlPath;
|
||||
|
||||
/// A color matrix which inverts colors.
|
||||
// clang-format off
|
||||
constexpr ColorMatrix kColorInversion = {
|
||||
.array = {
|
||||
-1.0, 0, 0, 1.0, 0, //
|
||||
0, -1.0, 0, 1.0, 0, //
|
||||
0, 0, -1.0, 1.0, 0, //
|
||||
1.0, 1.0, 1.0, 1.0, 0 //
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
if (color_source == nullptr) {
|
||||
auto contents = std::make_shared<SolidColorContents>();
|
||||
@ -194,11 +184,26 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
contents->SetTileModes(x_tile_mode, y_tile_mode);
|
||||
contents->SetSamplerDescriptor(sampler_descriptor);
|
||||
contents->SetEffectTransform(effect_transform);
|
||||
if (color_filter) {
|
||||
if (color_filter || invert_colors) {
|
||||
TiledTextureContents::ColorFilterProc filter_proc =
|
||||
[color_filter = color_filter](FilterInput::Ref input) {
|
||||
return color_filter->WrapWithGPUColorFilter(
|
||||
std::move(input), ColorFilterContents::AbsorbOpacity::kNo);
|
||||
[color_filter = color_filter,
|
||||
invert_colors = invert_colors](const FilterInput::Ref& input) {
|
||||
if (invert_colors && color_filter) {
|
||||
std::shared_ptr<FilterContents> color_filter_output =
|
||||
WrapWithGPUColorFilter(
|
||||
color_filter, input,
|
||||
ColorFilterContents::AbsorbOpacity::kNo);
|
||||
return WrapWithInvertColors(
|
||||
FilterInput::Make(color_filter_output),
|
||||
ColorFilterContents::AbsorbOpacity::kNo);
|
||||
}
|
||||
if (color_filter) {
|
||||
return WrapWithGPUColorFilter(
|
||||
color_filter, input,
|
||||
ColorFilterContents::AbsorbOpacity::kNo);
|
||||
}
|
||||
return WrapWithInvertColors(
|
||||
input, ColorFilterContents::AbsorbOpacity::kNo);
|
||||
};
|
||||
contents->SetColorFilter(filter_proc);
|
||||
}
|
||||
@ -247,32 +252,6 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
|
||||
const std::shared_ptr<Geometry>& geometry) const {
|
||||
auto contents = CreateContents();
|
||||
|
||||
// Attempt to apply the color filter on the CPU first.
|
||||
// Note: This is not just an optimization; some color sources rely on
|
||||
// CPU-applied color filters to behave properly.
|
||||
auto color_filter = GetColorFilter();
|
||||
bool needs_color_filter = !!color_filter;
|
||||
if (color_filter &&
|
||||
contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
|
||||
needs_color_filter = false;
|
||||
}
|
||||
|
||||
contents->SetGeometry(geometry);
|
||||
if (mask_blur_descriptor.has_value()) {
|
||||
// If there's a mask blur and we need to apply the color filter on the GPU,
|
||||
// we need to be careful to only apply the color filter to the source
|
||||
// colors. CreateMaskBlur is able to handle this case.
|
||||
return mask_blur_descriptor->CreateMaskBlur(
|
||||
contents, needs_color_filter ? color_filter : nullptr);
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::shared_ptr<Contents> Paint::WithFilters(
|
||||
std::shared_ptr<Contents> input) const {
|
||||
input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
|
||||
@ -314,7 +293,7 @@ std::shared_ptr<FilterContents> Paint::WithImageFilter(
|
||||
if (!image_filter) {
|
||||
return nullptr;
|
||||
}
|
||||
auto filter = image_filter->WrapInput(FilterInput::Make(input));
|
||||
auto filter = WrapInput(image_filter, FilterInput::Make(input));
|
||||
filter->SetRenderingMode(rendering_mode);
|
||||
filter->SetEffectTransform(effect_transform);
|
||||
return filter;
|
||||
@ -330,20 +309,35 @@ std::shared_ptr<Contents> Paint::WithColorFilter(
|
||||
return input;
|
||||
}
|
||||
|
||||
auto color_filter = GetColorFilter();
|
||||
if (!color_filter) {
|
||||
if (!color_filter && !invert_colors) {
|
||||
return input;
|
||||
}
|
||||
|
||||
// Attempt to apply the color filter on the CPU first.
|
||||
// Note: This is not just an optimization; some color sources rely on
|
||||
// CPU-applied color filters to behave properly.
|
||||
if (input->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
|
||||
if (input->ApplyColorFilter([&](Color color) -> Color {
|
||||
if (color_filter) {
|
||||
color = GetCPUColorFilterProc(color_filter)(color);
|
||||
}
|
||||
if (invert_colors) {
|
||||
color = color.ApplyColorMatrix(kColorInversion);
|
||||
}
|
||||
return color;
|
||||
})) {
|
||||
return input;
|
||||
}
|
||||
return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input),
|
||||
|
||||
if (color_filter) {
|
||||
input = WrapWithGPUColorFilter(color_filter, FilterInput::Make(input),
|
||||
absorb_opacity);
|
||||
}
|
||||
if (invert_colors) {
|
||||
input = WrapWithInvertColors(FilterInput::Make(input), absorb_opacity);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
std::shared_ptr<TextureContents> texture_contents) const {
|
||||
@ -375,10 +369,11 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
|
||||
std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
std::shared_ptr<ColorSourceContents> color_source_contents,
|
||||
const std::shared_ptr<ColorFilter>& color_filter) const {
|
||||
// If it's a solid color and there is no color filter, then we can just get
|
||||
// away with doing one Gaussian blur.
|
||||
if (color_source_contents->IsSolidColor() && !color_filter) {
|
||||
const flutter::DlColorFilter* color_filter,
|
||||
bool invert_colors) const {
|
||||
// If it's a solid color then we can just get away with doing one Gaussian
|
||||
// blur. The color filter will always be applied on the CPU.
|
||||
if (color_source_contents->IsSolidColor()) {
|
||||
return FilterContents::MakeGaussianBlur(
|
||||
FilterInput::Make(color_source_contents), sigma, sigma,
|
||||
Entity::TileMode::kDecal, style, color_source_contents->GetGeometry());
|
||||
@ -409,10 +404,14 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
std::shared_ptr<Contents> color_contents = color_source_contents;
|
||||
|
||||
/// 4. Apply the user set color filter on the GPU, if applicable.
|
||||
|
||||
if (color_filter) {
|
||||
color_contents = color_filter->WrapWithGPUColorFilter(
|
||||
FilterInput::Make(color_source_contents),
|
||||
color_contents =
|
||||
WrapWithGPUColorFilter(color_filter, FilterInput::Make(color_contents),
|
||||
ColorFilterContents::AbsorbOpacity::kYes);
|
||||
}
|
||||
if (invert_colors) {
|
||||
color_contents =
|
||||
WrapWithInvertColors(FilterInput::Make(color_contents),
|
||||
ColorFilterContents::AbsorbOpacity::kYes);
|
||||
}
|
||||
|
||||
@ -441,22 +440,8 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
|
||||
Sigma(blur_sigma.y), style);
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorFilter> Paint::GetColorFilter() const {
|
||||
if (invert_colors && color_filter) {
|
||||
auto filter = ColorFilter::MakeMatrix(kColorInversion);
|
||||
return ColorFilter::MakeComposed(filter, color_filter);
|
||||
}
|
||||
if (invert_colors) {
|
||||
return ColorFilter::MakeMatrix(kColorInversion);
|
||||
}
|
||||
if (color_filter) {
|
||||
return color_filter;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Paint::HasColorFilter() const {
|
||||
return !!color_filter || invert_colors;
|
||||
return color_filter || invert_colors;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
@ -7,7 +7,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "display_list/effects/dl_color_source.h"
|
||||
#include "display_list/effects/dl_image_filter.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
#include "impeller/entity/contents/color_source_contents.h"
|
||||
@ -55,7 +57,8 @@ struct Paint {
|
||||
|
||||
std::shared_ptr<FilterContents> CreateMaskBlur(
|
||||
std::shared_ptr<ColorSourceContents> color_source_contents,
|
||||
const std::shared_ptr<ColorFilter>& color_filter) const;
|
||||
const flutter::DlColorFilter* color_filter,
|
||||
bool invert_colors) const;
|
||||
|
||||
std::shared_ptr<FilterContents> CreateMaskBlur(
|
||||
std::shared_ptr<TextureContents> texture_contents) const;
|
||||
@ -68,6 +71,8 @@ struct Paint {
|
||||
|
||||
Color color = Color::Black();
|
||||
const flutter::DlColorSource* color_source = nullptr;
|
||||
const flutter::DlColorFilter* color_filter = nullptr;
|
||||
const flutter::DlImageFilter* image_filter = nullptr;
|
||||
|
||||
Scalar stroke_width = 0.0;
|
||||
Cap stroke_cap = Cap::kButt;
|
||||
@ -77,12 +82,8 @@ struct Paint {
|
||||
BlendMode blend_mode = BlendMode::kSourceOver;
|
||||
bool invert_colors = false;
|
||||
|
||||
std::shared_ptr<ImageFilter> image_filter;
|
||||
std::shared_ptr<ColorFilter> color_filter;
|
||||
std::optional<MaskBlurDescriptor> mask_blur_descriptor;
|
||||
|
||||
std::shared_ptr<ColorFilter> GetColorFilter() const;
|
||||
|
||||
/// @brief Wrap this paint's configured filters to the given contents.
|
||||
/// @param[in] input The contents to wrap with paint's filters.
|
||||
/// @return The filter-wrapped contents. If there are no filters that need
|
||||
@ -102,9 +103,6 @@ struct Paint {
|
||||
std::shared_ptr<Contents> input,
|
||||
const Matrix& effect_transform = Matrix()) const;
|
||||
|
||||
std::shared_ptr<Contents> CreateContentsForGeometry(
|
||||
const std::shared_ptr<Geometry>& geometry) const;
|
||||
|
||||
/// @brief Whether this paint has a color filter that can apply opacity
|
||||
bool HasColorFilter() const;
|
||||
|
||||
|
@ -201,5 +201,69 @@ Matrix ToMatrix(const SkMatrix& m) {
|
||||
};
|
||||
}
|
||||
|
||||
BlendMode ToBlendMode(flutter::DlBlendMode mode) {
|
||||
switch (mode) {
|
||||
case flutter::DlBlendMode::kClear:
|
||||
return BlendMode::kClear;
|
||||
case flutter::DlBlendMode::kSrc:
|
||||
return BlendMode::kSource;
|
||||
case flutter::DlBlendMode::kDst:
|
||||
return BlendMode::kDestination;
|
||||
case flutter::DlBlendMode::kSrcOver:
|
||||
return BlendMode::kSourceOver;
|
||||
case flutter::DlBlendMode::kDstOver:
|
||||
return BlendMode::kDestinationOver;
|
||||
case flutter::DlBlendMode::kSrcIn:
|
||||
return BlendMode::kSourceIn;
|
||||
case flutter::DlBlendMode::kDstIn:
|
||||
return BlendMode::kDestinationIn;
|
||||
case flutter::DlBlendMode::kSrcOut:
|
||||
return BlendMode::kSourceOut;
|
||||
case flutter::DlBlendMode::kDstOut:
|
||||
return BlendMode::kDestinationOut;
|
||||
case flutter::DlBlendMode::kSrcATop:
|
||||
return BlendMode::kSourceATop;
|
||||
case flutter::DlBlendMode::kDstATop:
|
||||
return BlendMode::kDestinationATop;
|
||||
case flutter::DlBlendMode::kXor:
|
||||
return BlendMode::kXor;
|
||||
case flutter::DlBlendMode::kPlus:
|
||||
return BlendMode::kPlus;
|
||||
case flutter::DlBlendMode::kModulate:
|
||||
return BlendMode::kModulate;
|
||||
case flutter::DlBlendMode::kScreen:
|
||||
return BlendMode::kScreen;
|
||||
case flutter::DlBlendMode::kOverlay:
|
||||
return BlendMode::kOverlay;
|
||||
case flutter::DlBlendMode::kDarken:
|
||||
return BlendMode::kDarken;
|
||||
case flutter::DlBlendMode::kLighten:
|
||||
return BlendMode::kLighten;
|
||||
case flutter::DlBlendMode::kColorDodge:
|
||||
return BlendMode::kColorDodge;
|
||||
case flutter::DlBlendMode::kColorBurn:
|
||||
return BlendMode::kColorBurn;
|
||||
case flutter::DlBlendMode::kHardLight:
|
||||
return BlendMode::kHardLight;
|
||||
case flutter::DlBlendMode::kSoftLight:
|
||||
return BlendMode::kSoftLight;
|
||||
case flutter::DlBlendMode::kDifference:
|
||||
return BlendMode::kDifference;
|
||||
case flutter::DlBlendMode::kExclusion:
|
||||
return BlendMode::kExclusion;
|
||||
case flutter::DlBlendMode::kMultiply:
|
||||
return BlendMode::kMultiply;
|
||||
case flutter::DlBlendMode::kHue:
|
||||
return BlendMode::kHue;
|
||||
case flutter::DlBlendMode::kSaturation:
|
||||
return BlendMode::kSaturation;
|
||||
case flutter::DlBlendMode::kColor:
|
||||
return BlendMode::kColor;
|
||||
case flutter::DlBlendMode::kLuminosity:
|
||||
return BlendMode::kLuminosity;
|
||||
}
|
||||
FML_UNREACHABLE();
|
||||
}
|
||||
|
||||
} // namespace skia_conversions
|
||||
} // namespace impeller
|
||||
|
@ -61,6 +61,8 @@ impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
|
||||
Matrix ToMatrix(const SkMatrix& m);
|
||||
|
||||
BlendMode ToBlendMode(flutter::DlBlendMode mode);
|
||||
|
||||
/// @brief Convert display list colors + stops into impeller colors and stops,
|
||||
/// taking care to ensure that the stops monotonically increase from 0.0 to 1.0.
|
||||
///
|
||||
|
@ -2,11 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "display_list/dl_blend_mode.h"
|
||||
#include "display_list/dl_color.h"
|
||||
#include "display_list/dl_tile_mode.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
#include "impeller/core/formats.h"
|
||||
#include "impeller/display_list/skia_conversions.h"
|
||||
#include "impeller/geometry/color.h"
|
||||
#include "impeller/geometry/scalar.h"
|
||||
#include "include/core/SkMatrix.h"
|
||||
#include "include/core/SkRRect.h"
|
||||
@ -292,5 +294,13 @@ TEST(SkiaConversionsTest, IsNearlySimpleRRect) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, BlendMode) {
|
||||
for (auto i = 0; i < static_cast<int>(flutter::DlBlendMode::kLastMode); i++) {
|
||||
EXPECT_EQ(
|
||||
skia_conversions::ToBlendMode(static_cast<flutter::DlBlendMode>(i)),
|
||||
static_cast<BlendMode>(i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
@ -7,13 +7,11 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "impeller/core/sampler_descriptor.h"
|
||||
#include "impeller/entity/contents/color_source_contents.h"
|
||||
#include "impeller/entity/contents/filters/color_filter_contents.h"
|
||||
#include "impeller/entity/entity.h"
|
||||
#include "impeller/geometry/path.h"
|
||||
#include "impeller/renderer/capabilities.h"
|
||||
|
||||
namespace impeller {
|
||||
|
Loading…
x
Reference in New Issue
Block a user