[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:
Jonah Williams 2024-10-04 23:32:08 -05:00 committed by GitHub
parent 248c2a7062
commit fd33d17487
14 changed files with 388 additions and 1070 deletions

View File

@ -9,8 +9,10 @@
#include <utility> #include <utility>
#include "display_list/effects/dl_color_source.h" #include "display_list/effects/dl_color_source.h"
#include "display_list/effects/dl_image_filter.h"
#include "flutter/fml/logging.h" #include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.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/image_filter.h"
#include "impeller/display_list/skia_conversions.h" #include "impeller/display_list/skia_conversions.h"
#include "impeller/entity/contents/atlas_contents.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. // Attempt to apply the color filter on the CPU first.
// Note: This is not just an optimization; some color sources rely on // Note: This is not just an optimization; some color sources rely on
// CPU-applied color filters to behave properly. // CPU-applied color filters to behave properly.
bool needs_color_filter = paint.HasColorFilter(); bool needs_color_filter = paint.color_filter || paint.invert_colors;
if (needs_color_filter) { if (needs_color_filter &&
auto color_filter = paint.GetColorFilter(); contents->ApplyColorFilter([&](Color color) -> Color {
if (contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) { if (paint.color_filter) {
needs_color_filter = false; 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(); 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 // we need to be careful to only apply the color filter to the source
// colors. CreateMaskBlur is able to handle this case. // colors. CreateMaskBlur is able to handle this case.
return paint.mask_blur_descriptor->CreateMaskBlur( 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); std::shared_ptr<Contents> contents_copy = std::move(contents);
// Image input types will directly set their color filter, // Image input types will directly set their color filter,
// if any. See `TiledTextureContents.SetColorFilter`. // if any. See `TiledTextureContents.SetColorFilter`.
if (needs_color_filter && if (needs_color_filter &&
(!paint.color_source || (!paint.color_source ||
paint.color_source->type() != flutter::DlColorSourceType::kImage)) { paint.color_source->type() != flutter::DlColorSourceType::kImage)) {
std::shared_ptr<ColorFilter> color_filter = paint.GetColorFilter(); if (paint.color_filter) {
contents_copy = color_filter->WrapWithGPUColorFilter( contents_copy = WrapWithGPUColorFilter(
FilterInput::Make(std::move(contents_copy)), paint.color_filter, FilterInput::Make(std::move(contents_copy)),
ColorFilterContents::AbsorbOpacity::kYes); ColorFilterContents::AbsorbOpacity::kYes);
} }
if (paint.invert_colors) {
contents_copy =
WrapWithInvertColors(FilterInput::Make(contents_copy),
ColorFilterContents::AbsorbOpacity::kYes);
}
}
if (paint.image_filter) { if (paint.image_filter) {
std::shared_ptr<FilterContents> filter = paint.image_filter->WrapInput( std::shared_ptr<FilterContents> filter = WrapInput(
FilterInput::Make(std::move(contents_copy))); paint.image_filter, FilterInput::Make(std::move(contents_copy)));
filter->SetRenderingMode(Entity::RenderingMode::kDirect); filter->SetRenderingMode(Entity::RenderingMode::kDirect);
return filter; return filter;
} }
@ -471,12 +487,13 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect,
// For symmetrically mask blurred solid RRects, absorb the mask blur and use // For symmetrically mask blurred solid RRects, absorb the mask blur and use
// a faster SDF approximation. // a faster SDF approximation.
Color rrect_color = paint.color;
Color rrect_color = if (paint.invert_colors) {
paint.HasColorFilter() rrect_color = rrect_color.ApplyColorMatrix(kColorInversion);
// Absorb the color filter, if any. }
? paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color) if (paint.color_filter) {
: paint.color; rrect_color = GetCPUColorFilterProc(paint.color_filter)(rrect_color);
}
Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor}; 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); render_bounds.Expand(paint.mask_blur_descriptor->sigma.sigma * 4.0);
} }
// Defer the alpha, blend mode, and image filter to a separate layer. // 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, .blend_mode = paint.blend_mode,
.image_filter = paint.image_filter}, },
render_bounds, nullptr, ContentBoundsPromise::kContainsContents, render_bounds, nullptr, ContentBoundsPromise::kContainsContents, 1u);
1u);
rrect_paint.color = rrect_color.WithAlpha(1); rrect_paint.color = rrect_color.WithAlpha(1);
} else { } else {
rrect_paint.color = rrect_color; rrect_paint.color = rrect_color;
@ -892,8 +911,9 @@ void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
auto src_paint = paint; auto src_paint = paint;
src_paint.color = paint.color.WithAlpha(1.0); src_paint.color = paint.color.WithAlpha(1.0);
std::shared_ptr<Contents> src_contents = std::shared_ptr<ColorSourceContents> src_contents =
src_paint.CreateContentsForGeometry(vertices); src_paint.CreateContents();
src_contents->SetGeometry(vertices);
// If the color source has an intrinsic size, then we use that to // If the color source has an intrinsic size, then we use that to
// create the src contents as a simplification. Otherwise we use // 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) // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
vertices->GetTextureCoordinateCoverge().value_or(cvg.value()); vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
} }
src_contents = src_paint.CreateContentsForGeometry( src_contents = src_paint.CreateContents();
Geometry::MakeRect(Rect::Round(src_coverage))); src_contents->SetGeometry(Geometry::MakeRect(Rect::Round(src_coverage)));
auto contents = std::make_shared<VerticesSimpleBlendContents>(); auto contents = std::make_shared<VerticesSimpleBlendContents>();
contents->SetBlendMode(blend_mode); contents->SetBlendMode(blend_mode);
@ -1049,7 +1069,7 @@ std::optional<Rect> Canvas::GetLocalCoverageLimit() const {
void Canvas::SaveLayer(const Paint& paint, void Canvas::SaveLayer(const Paint& paint,
std::optional<Rect> bounds, std::optional<Rect> bounds,
const std::shared_ptr<ImageFilter>& backdrop_filter, const flutter::DlImageFilter* backdrop_filter,
ContentBoundsPromise bounds_promise, ContentBoundsPromise bounds_promise,
uint32_t total_content_depth, uint32_t total_content_depth,
bool can_distribute_opacity) { bool can_distribute_opacity) {
@ -1125,10 +1145,10 @@ void Canvas::SaveLayer(const Paint& paint,
if (backdrop_filter) { if (backdrop_filter) {
local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition(); local_position = subpass_coverage.GetOrigin() - GetGlobalPassPosition();
Canvas::BackdropFilterProc backdrop_filter_proc = Canvas::BackdropFilterProc backdrop_filter_proc =
[backdrop_filter = backdrop_filter->Clone()]( [backdrop_filter = backdrop_filter](
const FilterInput::Ref& input, const Matrix& effect_transform, const FilterInput::Ref& input, const Matrix& effect_transform,
Entity::RenderingMode rendering_mode) { Entity::RenderingMode rendering_mode) {
auto filter = backdrop_filter->WrapInput(input); auto filter = WrapInput(backdrop_filter, input);
filter->SetEffectTransform(effect_transform); filter->SetEffectTransform(effect_transform);
filter->SetRenderingMode(rendering_mode); filter->SetRenderingMode(rendering_mode);
return filter; return filter;

View File

@ -11,8 +11,8 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
#include "display_list/effects/dl_image_filter.h"
#include "impeller/core/sampler_descriptor.h" #include "impeller/core/sampler_descriptor.h"
#include "impeller/display_list/image_filter.h"
#include "impeller/display_list/paint.h" #include "impeller/display_list/paint.h"
#include "impeller/entity/contents/atlas_contents.h" #include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/entity.h" #include "impeller/entity/entity.h"
@ -132,7 +132,7 @@ class Canvas {
void SaveLayer( void SaveLayer(
const Paint& paint, const Paint& paint,
std::optional<Rect> bounds = std::nullopt, 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, ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown,
uint32_t total_content_depth = kMaxDepth, uint32_t total_content_depth = kMaxDepth,
bool can_distribute_opacity = false); bool can_distribute_opacity = false);

View File

@ -3,14 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "flutter/testing/testing.h" #include "flutter/testing/testing.h"
#include "impeller/display_list/aiks_context.h"
#include "impeller/display_list/aiks_unittests.h" #include "impeller/display_list/aiks_unittests.h"
#include "impeller/display_list/canvas.h" #include "impeller/display_list/canvas.h"
#include "impeller/geometry/geometry_asserts.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 impeller {
namespace testing { namespace testing {
@ -98,34 +93,5 @@ TEST_P(AiksTest, CanvasCTMCanBeUpdated) {
Matrix::MakeTranslation({100.0, 100.0, 0.0})); 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 testing
} // namespace impeller } // namespace impeller
// NOLINTEND(bugprone-unchecked-optional-access)

View File

@ -4,187 +4,99 @@
#include "impeller/display_list/color_filter.h" #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/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/geometry/color.h" #include "impeller/geometry/color.h"
namespace impeller { namespace impeller {
/******************************************************************************* std::shared_ptr<ColorFilterContents> WrapWithInvertColors(
******* ColorFilter const std::shared_ptr<FilterInput>& input,
******************************************************************************/ ColorFilterContents::AbsorbOpacity absorb_opacity) {
auto filter = ColorFilterContents::MakeColorMatrix({input}, kColorInversion);
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_);
filter->SetAbsorbOpacity(absorb_opacity); filter->SetAbsorbOpacity(absorb_opacity);
return filter; return filter;
} }
ColorFilter::ColorFilterProc BlendColorFilter::GetCPUColorFilterProc() const { std::shared_ptr<ColorFilterContents> WrapWithGPUColorFilter(
return [filter_blend_mode = blend_mode_, filter_color = color_](Color color) { 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); 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 { impeller::ColorMatrix color_matrix;
return std::make_shared<BlendColorFilter>(*this); matrix_filter->get_matrix(color_matrix.array);
} return [color_matrix = color_matrix](Color color) {
/*******************************************************************************
******* 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) {
return color.ApplyColorMatrix(color_matrix); return color.ApplyColorMatrix(color_matrix);
}; };
} }
case flutter::DlColorFilterType::kSrgbToLinearGamma: {
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 {
return [](Color color) { return color.SRGBToLinear(); }; return [](Color color) { return color.SRGBToLinear(); };
} }
std::shared_ptr<ColorFilter> SrgbToLinearColorFilter::Clone() const { case flutter::DlColorFilterType::kLinearToSrgbGamma: {
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 {
return [](Color color) { return color.LinearToSRGB(); }; return [](Color color) { return color.LinearToSRGB(); };
} }
std::shared_ptr<ColorFilter> LinearToSrgbColorFilter::Clone() const {
return std::make_shared<LinearToSrgbColorFilter>(*this);
} }
/******************************************************************************* FML_UNREACHABLE();
******* 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_);
} }
} // namespace impeller } // namespace impeller

View File

@ -5,176 +5,37 @@
#ifndef FLUTTER_IMPELLER_DISPLAY_LIST_COLOR_FILTER_H_ #ifndef FLUTTER_IMPELLER_DISPLAY_LIST_COLOR_FILTER_H_
#define 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/entity/contents/filters/color_filter_contents.h"
#include "impeller/geometry/color.h" #include "impeller/geometry/color.h"
namespace impeller { 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 //
}
};
/******************************************************************************* std::shared_ptr<ColorFilterContents> WrapWithInvertColors(
******* ColorFilter 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 /// A procedure that filters a given unpremultiplied color to produce a new
/// unpremultiplied color. /// unpremultiplied color.
using ColorFilterProc = std::function<Color(Color)>; using ColorFilterProc = std::function<Color(Color)>;
ColorFilter(); ColorFilterProc GetCPUColorFilterProc(const flutter::DlColorFilter* filter);
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_;
};
} // namespace impeller } // namespace impeller

View File

@ -114,70 +114,6 @@ struct DepthWatcher {
#define UNIMPLEMENTED \ #define UNIMPLEMENTED \
FML_DLOG(ERROR) << "Unimplemented detail in " << __FUNCTION__; 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( static impeller::SamplerDescriptor ToSamplerDescriptor(
const flutter::DlFilterMode options) { const flutter::DlFilterMode options) {
impeller::SamplerDescriptor desc; 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| // |flutter::DlOpReceiver|
void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) { void DlDispatcherBase::setColorFilter(const flutter::DlColorFilter* filter) {
AUTO_DEPTH_WATCHER(0u); AUTO_DEPTH_WATCHER(0u);
paint_.color_filter = ToColorFilter(filter); paint_.color_filter = filter;
} }
// |flutter::DlOpReceiver| // |flutter::DlOpReceiver|
@ -333,7 +243,7 @@ void DlDispatcherBase::setInvertColors(bool invert) {
void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) { void DlDispatcherBase::setBlendMode(flutter::DlBlendMode dl_mode) {
AUTO_DEPTH_WATCHER(0u); 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) { 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| // |flutter::DlOpReceiver|
void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) { void DlDispatcherBase::setImageFilter(const flutter::DlImageFilter* filter) {
AUTO_DEPTH_WATCHER(0u); AUTO_DEPTH_WATCHER(0u);
paint_.image_filter = ToImageFilter(filter); paint_.image_filter = filter;
} }
// |flutter::DlOpReceiver| // |flutter::DlOpReceiver|
@ -497,8 +316,7 @@ void DlDispatcherBase::saveLayer(const DlRect& bounds,
} }
GetCanvas().SaveLayer( GetCanvas().SaveLayer(
paint, impeller_bounds, ToImageFilter(backdrop), promise, paint, impeller_bounds, backdrop, promise, total_content_depth,
total_content_depth,
// Unbounded content can still have user specified bounds that require a // Unbounded content can still have user specified bounds that require a
// saveLayer to be created to perform the clip. // saveLayer to be created to perform the clip.
options.can_distribute_opacity() && !options.content_is_unbounded()); options.can_distribute_opacity() && !options.content_is_unbounded());
@ -674,7 +492,7 @@ void DlDispatcherBase::drawColor(flutter::DlColor color,
Paint paint; Paint paint;
paint.color = skia_conversions::ToColor(color); paint.color = skia_conversions::ToColor(color);
paint.blend_mode = ToBlendMode(dl_mode); paint.blend_mode = skia_conversions::ToBlendMode(dl_mode);
GetCanvas().DrawPaint(paint); GetCanvas().DrawPaint(paint);
} }
@ -950,7 +768,7 @@ void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
tex, // tex, //
colors, // colors, //
static_cast<size_t>(count), // static_cast<size_t>(count), //
ToBlendMode(mode), // skia_conversions::ToBlendMode(mode), //
skia_conversions::ToSamplerDescriptor(sampling), // skia_conversions::ToSamplerDescriptor(sampling), //
skia_conversions::ToRect(cull_rect) // skia_conversions::ToRect(cull_rect) //
); );
@ -1117,7 +935,8 @@ static bool RequiresReadbackForBlends(
const ContentContext& renderer, const ContentContext& renderer,
flutter::DlBlendMode max_root_blend_mode) { flutter::DlBlendMode max_root_blend_mode) {
return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() && return !renderer.GetDeviceCapabilities().SupportsFramebufferFetch() &&
ToBlendMode(max_root_blend_mode) > Entity::kLastPipelineBlendMode; skia_conversions::ToBlendMode(max_root_blend_mode) >
Entity::kLastPipelineBlendMode;
} }
CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer, CanvasDlDispatcher::CanvasDlDispatcher(ContentContext& renderer,
@ -1143,7 +962,7 @@ void CanvasDlDispatcher::drawVertices(
GetCanvas().DrawVertices( GetCanvas().DrawVertices(
std::make_shared<DlVerticesGeometry>(vertices, renderer_), std::make_shared<DlVerticesGeometry>(vertices, renderer_),
ToBlendMode(dl_mode), paint_); skia_conversions::ToBlendMode(dl_mode), paint_);
} }
//// Text Frame Dispatcher //// Text Frame Dispatcher

View File

@ -3,206 +3,107 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "impeller/display_list/image_filter.h" #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/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/contents/filters/inputs/filter_input.h"
namespace impeller { namespace impeller {
/******************************************************************************* std::shared_ptr<FilterContents> WrapInput(const flutter::DlImageFilter* filter,
******* ImageFilter 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; return FilterContents::MakeGaussianBlur(
input, //
std::shared_ptr<ImageFilter> ImageFilter::MakeBlur( Sigma(blur_filter->sigma_x()), //
Sigma sigma_x, Sigma(blur_filter->sigma_y()), //
Sigma sigma_y, static_cast<Entity::TileMode>(blur_filter->tile_mode()), //
FilterContents::BlurStyle blur_style, FilterContents::BlurStyle::kNormal //
Entity::TileMode tile_mode) { );
return std::make_shared<BlurImageFilter>(sigma_x, sigma_y, blur_style,
tile_mode);
} }
case flutter::DlImageFilterType::kDilate: {
auto dilate_filter = filter->asDilate();
FML_DCHECK(dilate_filter);
std::shared_ptr<ImageFilter> ImageFilter::MakeDilate(Radius radius_x, return FilterContents::MakeMorphology(
Radius radius_y) { input, //
return std::make_shared<DilateImageFilter>(radius_x, radius_y); 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, return FilterContents::MakeMorphology(
Radius radius_y) { input, //
return std::make_shared<ErodeImageFilter>(radius_x, radius_y); 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( auto matrix = skia_conversions::ToMatrix(matrix_filter->matrix());
const Matrix& matrix, auto desc =
SamplerDescriptor sampler_descriptor) { skia_conversions::ToSamplerDescriptor(matrix_filter->sampling());
return std::make_shared<MatrixImageFilter>(matrix, return FilterContents::MakeMatrixFilter(input, matrix, desc);
std::move(sampler_descriptor));
} }
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( auto matrix = skia_conversions::ToMatrix(matrix_filter->matrix());
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 {
return FilterContents::MakeLocalMatrixFilter( 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 { // When color filters are used as image filters, set the color filter's
return std::make_shared<LocalMatrixImageFilter>(*this); // "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 } // namespace impeller

View File

@ -5,233 +5,15 @@
#ifndef FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_ #ifndef FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_
#define FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_ #define FLUTTER_IMPELLER_DISPLAY_LIST_IMAGE_FILTER_H_
#include "impeller/core/sampler_descriptor.h" #include "display_list/effects/dl_image_filter.h"
#include "impeller/display_list/color_filter.h"
#include "impeller/entity/contents/filters/filter_contents.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 { 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. /// @brief Generate a new FilterContents using this filter's configuration.
/// ///
/// This is the same as WrapInput, except no input is set. The input std::shared_ptr<FilterContents> WrapInput(const flutter::DlImageFilter* filter,
/// for the filter chain can be set later using. const FilterInput::Ref& input);
/// 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_;
};
} // namespace impeller } // namespace impeller

View File

@ -6,9 +6,11 @@
#include <memory> #include <memory>
#include "display_list/effects/dl_color_filter.h"
#include "display_list/effects/dl_color_source.h" #include "display_list/effects/dl_color_source.h"
#include "display_list/geometry/dl_path.h" #include "display_list/geometry/dl_path.h"
#include "fml/logging.h" #include "fml/logging.h"
#include "impeller/display_list/color_filter.h"
#include "impeller/display_list/skia_conversions.h" #include "impeller/display_list/skia_conversions.h"
#include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/color_source_contents.h"
#include "impeller/entity/contents/conical_gradient_contents.h" #include "impeller/entity/contents/conical_gradient_contents.h"
@ -31,18 +33,6 @@ using DlRect = flutter::DlRect;
using DlIRect = flutter::DlIRect; using DlIRect = flutter::DlIRect;
using DlPath = flutter::DlPath; 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 { std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
if (color_source == nullptr) { if (color_source == nullptr) {
auto contents = std::make_shared<SolidColorContents>(); 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->SetTileModes(x_tile_mode, y_tile_mode);
contents->SetSamplerDescriptor(sampler_descriptor); contents->SetSamplerDescriptor(sampler_descriptor);
contents->SetEffectTransform(effect_transform); contents->SetEffectTransform(effect_transform);
if (color_filter) { if (color_filter || invert_colors) {
TiledTextureContents::ColorFilterProc filter_proc = TiledTextureContents::ColorFilterProc filter_proc =
[color_filter = color_filter](FilterInput::Ref input) { [color_filter = color_filter,
return color_filter->WrapWithGPUColorFilter( invert_colors = invert_colors](const FilterInput::Ref& input) {
std::move(input), ColorFilterContents::AbsorbOpacity::kNo); 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); contents->SetColorFilter(filter_proc);
} }
@ -247,32 +252,6 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
FML_UNREACHABLE(); 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> Paint::WithFilters(
std::shared_ptr<Contents> input) const { std::shared_ptr<Contents> input) const {
input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes); input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
@ -314,7 +293,7 @@ std::shared_ptr<FilterContents> Paint::WithImageFilter(
if (!image_filter) { if (!image_filter) {
return nullptr; return nullptr;
} }
auto filter = image_filter->WrapInput(FilterInput::Make(input)); auto filter = WrapInput(image_filter, FilterInput::Make(input));
filter->SetRenderingMode(rendering_mode); filter->SetRenderingMode(rendering_mode);
filter->SetEffectTransform(effect_transform); filter->SetEffectTransform(effect_transform);
return filter; return filter;
@ -330,20 +309,35 @@ std::shared_ptr<Contents> Paint::WithColorFilter(
return input; return input;
} }
auto color_filter = GetColorFilter(); if (!color_filter && !invert_colors) {
if (!color_filter) {
return input; return input;
} }
// Attempt to apply the color filter on the CPU first. // Attempt to apply the color filter on the CPU first.
// Note: This is not just an optimization; some color sources rely on // Note: This is not just an optimization; some color sources rely on
// CPU-applied color filters to behave properly. // 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 input;
} }
return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input),
if (color_filter) {
input = WrapWithGPUColorFilter(color_filter, FilterInput::Make(input),
absorb_opacity); absorb_opacity);
} }
if (invert_colors) {
input = WrapWithInvertColors(FilterInput::Make(input), absorb_opacity);
}
return input;
}
std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur( std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
std::shared_ptr<TextureContents> texture_contents) const { 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<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
std::shared_ptr<ColorSourceContents> color_source_contents, std::shared_ptr<ColorSourceContents> color_source_contents,
const std::shared_ptr<ColorFilter>& color_filter) const { const flutter::DlColorFilter* color_filter,
// If it's a solid color and there is no color filter, then we can just get bool invert_colors) const {
// away with doing one Gaussian blur. // If it's a solid color then we can just get away with doing one Gaussian
if (color_source_contents->IsSolidColor() && !color_filter) { // blur. The color filter will always be applied on the CPU.
if (color_source_contents->IsSolidColor()) {
return FilterContents::MakeGaussianBlur( return FilterContents::MakeGaussianBlur(
FilterInput::Make(color_source_contents), sigma, sigma, FilterInput::Make(color_source_contents), sigma, sigma,
Entity::TileMode::kDecal, style, color_source_contents->GetGeometry()); 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; std::shared_ptr<Contents> color_contents = color_source_contents;
/// 4. Apply the user set color filter on the GPU, if applicable. /// 4. Apply the user set color filter on the GPU, if applicable.
if (color_filter) { if (color_filter) {
color_contents = color_filter->WrapWithGPUColorFilter( color_contents =
FilterInput::Make(color_source_contents), WrapWithGPUColorFilter(color_filter, FilterInput::Make(color_contents),
ColorFilterContents::AbsorbOpacity::kYes);
}
if (invert_colors) {
color_contents =
WrapWithInvertColors(FilterInput::Make(color_contents),
ColorFilterContents::AbsorbOpacity::kYes); ColorFilterContents::AbsorbOpacity::kYes);
} }
@ -441,22 +440,8 @@ std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
Sigma(blur_sigma.y), style); 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 { bool Paint::HasColorFilter() const {
return !!color_filter || invert_colors; return color_filter || invert_colors;
} }
} // namespace impeller } // namespace impeller

View File

@ -7,7 +7,9 @@
#include <memory> #include <memory>
#include "display_list/effects/dl_color_filter.h"
#include "display_list/effects/dl_color_source.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/color_filter.h"
#include "impeller/display_list/image_filter.h" #include "impeller/display_list/image_filter.h"
#include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/color_source_contents.h"
@ -55,7 +57,8 @@ struct Paint {
std::shared_ptr<FilterContents> CreateMaskBlur( std::shared_ptr<FilterContents> CreateMaskBlur(
std::shared_ptr<ColorSourceContents> color_source_contents, 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<FilterContents> CreateMaskBlur(
std::shared_ptr<TextureContents> texture_contents) const; std::shared_ptr<TextureContents> texture_contents) const;
@ -68,6 +71,8 @@ struct Paint {
Color color = Color::Black(); Color color = Color::Black();
const flutter::DlColorSource* color_source = nullptr; const flutter::DlColorSource* color_source = nullptr;
const flutter::DlColorFilter* color_filter = nullptr;
const flutter::DlImageFilter* image_filter = nullptr;
Scalar stroke_width = 0.0; Scalar stroke_width = 0.0;
Cap stroke_cap = Cap::kButt; Cap stroke_cap = Cap::kButt;
@ -77,12 +82,8 @@ struct Paint {
BlendMode blend_mode = BlendMode::kSourceOver; BlendMode blend_mode = BlendMode::kSourceOver;
bool invert_colors = false; bool invert_colors = false;
std::shared_ptr<ImageFilter> image_filter;
std::shared_ptr<ColorFilter> color_filter;
std::optional<MaskBlurDescriptor> mask_blur_descriptor; std::optional<MaskBlurDescriptor> mask_blur_descriptor;
std::shared_ptr<ColorFilter> GetColorFilter() const;
/// @brief Wrap this paint's configured filters to the given contents. /// @brief Wrap this paint's configured filters to the given contents.
/// @param[in] input The contents to wrap with paint's filters. /// @param[in] input The contents to wrap with paint's filters.
/// @return The filter-wrapped contents. If there are no filters that need /// @return The filter-wrapped contents. If there are no filters that need
@ -102,9 +103,6 @@ struct Paint {
std::shared_ptr<Contents> input, std::shared_ptr<Contents> input,
const Matrix& effect_transform = Matrix()) const; 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 /// @brief Whether this paint has a color filter that can apply opacity
bool HasColorFilter() const; bool HasColorFilter() const;

View File

@ -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 skia_conversions
} // namespace impeller } // namespace impeller

View File

@ -61,6 +61,8 @@ impeller::SamplerDescriptor ToSamplerDescriptor(
Matrix ToMatrix(const SkMatrix& m); Matrix ToMatrix(const SkMatrix& m);
BlendMode ToBlendMode(flutter::DlBlendMode mode);
/// @brief Convert display list colors + stops into impeller colors and stops, /// @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. /// taking care to ensure that the stops monotonically increase from 0.0 to 1.0.
/// ///

View File

@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "display_list/dl_blend_mode.h"
#include "display_list/dl_color.h" #include "display_list/dl_color.h"
#include "display_list/dl_tile_mode.h" #include "display_list/dl_tile_mode.h"
#include "flutter/testing/testing.h" #include "flutter/testing/testing.h"
#include "impeller/core/formats.h" #include "impeller/core/formats.h"
#include "impeller/display_list/skia_conversions.h" #include "impeller/display_list/skia_conversions.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/scalar.h" #include "impeller/geometry/scalar.h"
#include "include/core/SkMatrix.h" #include "include/core/SkMatrix.h"
#include "include/core/SkRRect.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 testing
} // namespace impeller } // namespace impeller

View File

@ -7,13 +7,11 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <vector>
#include "impeller/core/sampler_descriptor.h" #include "impeller/core/sampler_descriptor.h"
#include "impeller/entity/contents/color_source_contents.h" #include "impeller/entity/contents/color_source_contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/entity.h" #include "impeller/entity/entity.h"
#include "impeller/geometry/path.h"
#include "impeller/renderer/capabilities.h" #include "impeller/renderer/capabilities.h"
namespace impeller { namespace impeller {