Skip to content

Commit e46c24e

Browse files
authored
[Impeller] Add backdrop filter support; refactor EntityPass (flutter#33887)
1 parent 35bc1d7 commit e46c24e

File tree

10 files changed

+498
-204
lines changed

10 files changed

+498
-204
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ FILE: ../../../flutter/impeller/entity/entity_pass_delegate.h
568568
FILE: ../../../flutter/impeller/entity/entity_playground.cc
569569
FILE: ../../../flutter/impeller/entity/entity_playground.h
570570
FILE: ../../../flutter/impeller/entity/entity_unittests.cc
571+
FILE: ../../../flutter/impeller/entity/inline_pass_context.cc
572+
FILE: ../../../flutter/impeller/entity/inline_pass_context.h
571573
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.glsl
572574
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend.vert
573575
FILE: ../../../flutter/impeller/entity/shaders/blending/advanced_blend_color.frag

impeller/aiks/canvas.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,17 @@ size_t Canvas::GetStencilDepth() const {
265265
return xformation_stack_.back().stencil_depth;
266266
}
267267

268-
void Canvas::SaveLayer(Paint paint, std::optional<Rect> bounds) {
268+
void Canvas::SaveLayer(Paint paint,
269+
std::optional<Rect> bounds,
270+
std::optional<Paint::ImageFilterProc> backdrop_filter) {
269271
Save(true, paint.blend_mode);
270272

271273
auto& new_layer_pass = GetCurrentPass();
272274
new_layer_pass.SetDelegate(
273275
std::make_unique<PaintPassDelegate>(paint, bounds));
276+
new_layer_pass.SetBackdropFilter(backdrop_filter);
274277

275-
if (bounds.has_value()) {
278+
if (bounds.has_value() && !backdrop_filter.has_value()) {
276279
// Render target switches due to a save layer can be elided. In such cases
277280
// where passes are collapsed into their parent, the clipping effect to
278281
// the size of the render target that would have been allocated will be

impeller/aiks/canvas.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ class Canvas {
3535

3636
void Save();
3737

38-
void SaveLayer(Paint paint, std::optional<Rect> bounds = std::nullopt);
38+
void SaveLayer(
39+
Paint paint,
40+
std::optional<Rect> bounds = std::nullopt,
41+
std::optional<Paint::ImageFilterProc> backdrop_filter = std::nullopt);
3942

4043
bool Restore();
4144

impeller/display_list/display_list_dispatcher.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,12 @@ void DisplayListDispatcher::setMaskFilter(const flutter::DlMaskFilter* filter) {
324324
}
325325
}
326326

327-
// |flutter::Dispatcher|
328-
void DisplayListDispatcher::setImageFilter(
327+
static std::optional<Paint::ImageFilterProc> ToImageFilterProc(
329328
const flutter::DlImageFilter* filter) {
329+
if (filter == nullptr) {
330+
return std::nullopt;
331+
}
332+
330333
switch (filter->type()) {
331334
case flutter::DlImageFilterType::kBlur: {
332335
auto blur = filter->asBlur();
@@ -338,7 +341,7 @@ void DisplayListDispatcher::setImageFilter(
338341
UNIMPLEMENTED;
339342
}
340343

341-
paint_.image_filter = [sigma_x, sigma_y](FilterInput::Ref input) {
344+
return [sigma_x, sigma_y](FilterInput::Ref input) {
342345
return FilterContents::MakeGaussianBlur(input, sigma_x, sigma_y);
343346
};
344347

@@ -350,11 +353,16 @@ void DisplayListDispatcher::setImageFilter(
350353
case flutter::DlImageFilterType::kComposeFilter:
351354
case flutter::DlImageFilterType::kColorFilter:
352355
case flutter::DlImageFilterType::kUnknown:
353-
UNIMPLEMENTED;
354-
break;
356+
return std::nullopt;
355357
}
356358
}
357359

360+
// |flutter::Dispatcher|
361+
void DisplayListDispatcher::setImageFilter(
362+
const flutter::DlImageFilter* filter) {
363+
paint_.image_filter = ToImageFilterProc(filter);
364+
}
365+
358366
// |flutter::Dispatcher|
359367
void DisplayListDispatcher::save() {
360368
canvas_.Save();
@@ -371,11 +379,8 @@ static std::optional<Rect> ToRect(const SkRect* rect) {
371379
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
372380
const flutter::SaveLayerOptions options,
373381
const flutter::DlImageFilter* backdrop) {
374-
if (backdrop) {
375-
UNIMPLEMENTED;
376-
}
377-
canvas_.SaveLayer(options.renders_with_attributes() ? paint_ : Paint{},
378-
ToRect(bounds));
382+
auto paint = options.renders_with_attributes() ? paint_ : Paint{};
383+
canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop));
379384
}
380385

381386
// |flutter::Dispatcher|

impeller/display_list/display_list_unittests.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
// found in the LICENSE file.
44

55
#include "display_list/display_list_blend_mode.h"
6+
#include "display_list/display_list_color.h"
67
#include "display_list/display_list_color_filter.h"
78
#include "display_list/display_list_image_filter.h"
9+
#include "display_list/display_list_paint.h"
810
#include "display_list/display_list_tile_mode.h"
911
#include "gtest/gtest.h"
1012
#include "third_party/imgui/imgui.h"
@@ -285,5 +287,64 @@ TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
285287
ASSERT_TRUE(OpenPlaygroundHere(callback));
286288
}
287289

290+
TEST_P(DisplayListTest, CanDrawBackdropFilter) {
291+
auto texture = CreateTextureForFixture("embarcadero.jpg");
292+
293+
bool first_frame = true;
294+
auto callback = [&]() {
295+
if (first_frame) {
296+
first_frame = false;
297+
ImGui::SetNextWindowSize({400, 100});
298+
ImGui::SetNextWindowPos({300, 650});
299+
}
300+
301+
static float sigma[] = {10, 10};
302+
static bool use_bounds = true;
303+
static bool draw_circle = true;
304+
305+
ImGui::Begin("Controls");
306+
ImGui::SliderFloat2("Sigma", sigma, 0, 100);
307+
ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
308+
ImGui::Checkbox("Draw child element", &draw_circle);
309+
ImGui::End();
310+
311+
flutter::DisplayListBuilder builder;
312+
313+
Vector2 scale = GetContentScale();
314+
builder.scale(scale.x, scale.y);
315+
316+
auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
317+
flutter::DlTileMode::kClamp);
318+
319+
std::optional<SkRect> bounds;
320+
if (use_bounds) {
321+
auto [p1, p2] = IMPELLER_PLAYGROUND_LINE(
322+
Point(250, 150), Point(800, 600), 20, Color::White(), Color::White());
323+
bounds = SkRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
324+
}
325+
326+
builder.drawImage(DlImageImpeller::Make(texture), SkPoint::Make(200, 200),
327+
SkSamplingOptions{}, true);
328+
builder.saveLayer(bounds.has_value() ? &bounds.value() : nullptr, nullptr,
329+
&filter);
330+
331+
if (draw_circle) {
332+
auto circle_center =
333+
IMPELLER_PLAYGROUND_POINT(Point(500, 400), 20, Color::Red());
334+
335+
builder.setStyle(flutter::DlDrawStyle::kStroke);
336+
builder.setStrokeCap(flutter::DlStrokeCap::kButt);
337+
builder.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
338+
builder.setStrokeWidth(10);
339+
builder.setColor(flutter::DlColor::kRed().withAlpha(100));
340+
builder.drawCircle({circle_center.x, circle_center.y}, 100);
341+
}
342+
343+
return builder.Build();
344+
};
345+
346+
ASSERT_TRUE(OpenPlaygroundHere(callback));
347+
}
348+
288349
} // namespace testing
289350
} // namespace impeller

impeller/entity/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ impeller_component("entity") {
8787
"entity_pass.h",
8888
"entity_pass_delegate.cc",
8989
"entity_pass_delegate.h",
90+
"inline_pass_context.cc",
91+
"inline_pass_context.h",
9092
]
9193

9294
public_deps = [

0 commit comments

Comments
 (0)