Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 51 additions & 31 deletions impeller/display_list/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();
Expand All @@ -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)),
ColorFilterContents::AbsorbOpacity::kYes);
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;
}
Expand Down Expand Up @@ -466,12 +482,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};

Expand Down Expand Up @@ -507,11 +524,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),
.blend_mode = paint.blend_mode,
.image_filter = paint.image_filter},
render_bounds, nullptr, ContentBoundsPromise::kContainsContents,
1u);
SaveLayer(
Paint{
.color = Color::White().WithAlpha(rrect_color.alpha),
.image_filter = paint.image_filter,
.blend_mode = paint.blend_mode,
},
render_bounds, nullptr, ContentBoundsPromise::kContainsContents, 1u);
rrect_paint.color = rrect_color.WithAlpha(1);
} else {
rrect_paint.color = rrect_color;
Expand Down Expand Up @@ -887,8 +906,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
Expand All @@ -907,8 +927,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);
Expand Down Expand Up @@ -1044,7 +1064,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) {
Expand Down Expand Up @@ -1120,10 +1140,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;
Expand Down
4 changes: 2 additions & 2 deletions impeller/display_list/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
34 changes: 0 additions & 34 deletions impeller/display_list/canvas_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Loading