Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] Add backdrop filter support; refactor EntityPass #33887

Merged
merged 13 commits into from
Jun 15, 2022
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ FILE: ../../../flutter/impeller/entity/entity_pass_delegate.h
FILE: ../../../flutter/impeller/entity/entity_playground.cc
FILE: ../../../flutter/impeller/entity/entity_playground.h
FILE: ../../../flutter/impeller/entity/entity_unittests.cc
FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag
Expand Down
7 changes: 5 additions & 2 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,17 @@ size_t Canvas::GetStencilDepth() const {
return xformation_stack_.back().stencil_depth;
}

void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
void Canvas::SaveLayer(Paint paint,
std::optional<Rect> bounds,
std::optional<Paint::ImageFilterProc> backdrop_filter) {
Save(true, paint.blend_mode);

auto& new_layer_pass = GetCurrentPass();
new_layer_pass.SetDelegate(
std::make_unique<PaintPassDelegate>(paint, bounds));
new_layer_pass.SetBackdropFilter(backdrop_filter);

if (bounds.has_value()) {
if (bounds.has_value() && !backdrop_filter.has_value()) {
// Render target switches due to a save layer can be elided. In such cases
// where passes are collapsed into their parent, the clipping effect to
// the size of the render target that would have been allocated will be
Expand Down
5 changes: 4 additions & 1 deletion impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class Canvas {

void Save();

void SaveLayer(Paint paint, std::optional<Rect> bounds = std::nullopt);
void SaveLayer(
Paint paint,
std::optional<Rect> bounds = std::nullopt,
std::optional<Paint::ImageFilterProc> backdrop_filter = std::nullopt);

bool Restore();

Expand Down
25 changes: 15 additions & 10 deletions impeller/display_list/display_list_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,12 @@ void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
}
}

// |flutter::Dispatcher|
void DisplayListDispatcher::setImageFilter(
static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
const flutter::DlImageFilter* filter) {
if (filter == nullptr) {
return std::nullopt;
}

switch (filter->type()) {
case flutter::DlImageFilterType::kBlur: {
auto blur = filter->asBlur();
Expand All @@ -338,7 +341,7 @@ void DisplayListDispatcher::setImageFilter(
UNIMPLEMENTED;
}

paint_.image_filter = [sigma_x, sigma_y](FilterInput::Ref input) {
return [sigma_x, sigma_y](FilterInput::Ref input) {
return FilterContents::MakeGaussianBlur(input, sigma_x, sigma_y);
};

Expand All @@ -350,11 +353,16 @@ void DisplayListDispatcher::setImageFilter(
case flutter::DlImageFilterType::kComposeFilter:
case flutter::DlImageFilterType::kColorFilter:
case flutter::DlImageFilterType::kUnknown:
UNIMPLEMENTED;
break;
return std::nullopt;
}
}

// |flutter::Dispatcher|
void DisplayListDispatcher::setImageFilter(
const flutter::DlImageFilter* filter) {
paint_.image_filter = ToImageFilterProc(filter);
}

// |flutter::Dispatcher|
void DisplayListDispatcher::save() {
canvas_.Save();
Expand All @@ -371,11 +379,8 @@ static std::optional<Rect> ToRect(const SkRect* rect) {
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) {
if (backdrop) {
UNIMPLEMENTED;
}
canvas_.SaveLayer(options.renders_with_attributes() ? paint_ : Paint{},
ToRect(bounds));
auto paint = options.renders_with_attributes() ? paint_ : Paint{};
canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop));
}

// |flutter::Dispatcher|
Expand Down
61 changes: 61 additions & 0 deletions impeller/display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
// found in the LICENSE file.

#include "display_list/display_list_blend_mode.h"
#include "display_list/display_list_color.h"
#include "display_list/display_list_color_filter.h"
#include "display_list/display_list_image_filter.h"
#include "display_list/display_list_paint.h"
#include "display_list/display_list_tile_mode.h"
#include "gtest/gtest.h"
#include "third_party/imgui/imgui.h"
Expand Down Expand Up @@ -285,5 +287,64 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(DisplayListTest, CanDrawBackdropFilter) {
auto texture = CreateTextureForFixture("embarcadero.jpg");

bool first_frame = true;
auto callback = [&]() {
if (first_frame) {
first_frame = false;
ImGui::SetNextWindowSize({400, 100});
ImGui::SetNextWindowPos({300, 650});
}

static float sigma[] = {10, 10};
static bool use_bounds = true;
static bool draw_circle = true;

ImGui::Begin("Controls");
ImGui::SliderFloat2("Sigma", sigma, 0, 100);
ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
ImGui::Checkbox("Draw child element", &draw_circle);
ImGui::End();

flutter::DisplayListBuilder builder;

Vector2 scale = GetContentScale();
builder.scale(scale.x, scale.y);

auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
flutter::DlTileMode::kClamp);

std::optional<SkRect> bounds;
if (use_bounds) {
auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
Point(250, 150), Point(800, 600), 20, Color::White(), Color::White());
bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
}

builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
SkSamplingOptions{}, true);
builder.saveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
&filter);

if (draw_circle) {
auto circle_center =
IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());

builder.setStyle(flutter::DlDrawStyle::kStroke);
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
builder.setStrokeWidth(10);
builder.setColor(flutter::DlColor::kRed().withAlpha(100));
builder.drawCircle({circle_center.x, circle_center.y}, 100);
}

return builder.Build();
};

ASSERT_TRUE(OpenPlaygroundHere(callback));
}

} // namespace testing
} // namespace impeller
2 changes: 2 additions & 0 deletions impeller/entity/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ impeller_component("entity") {
"entity_pass.h",
"entity_pass_delegate.cc",
"entity_pass_delegate.h",
"inline_pass_context.cc",
"inline_pass_context.h",
]

public_deps = [
Expand Down
Loading