Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit d2997de

Browse files
[skwasm] Always do backdrop filter operation even if empty. (#54844)
This is a partial fix for flutter/flutter#152026 We are still blocked on https://g-issues.skia.org/issues/362552959 for things to be completely working.
1 parent 135864f commit d2997de

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

lib/web_ui/lib/src/engine/layers.dart

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class BackdropFilterOperation implements LayerOperation {
3535

3636
@override
3737
PlatformViewStyling createPlatformViewStyling() => const PlatformViewStyling();
38+
39+
// The backdrop filter actually has an effect on the scene even if it contains
40+
// no pictures, so we return true here.
41+
@override
42+
bool get shouldDrawIfEmpty => true;
3843
}
3944

4045
class ClipPathLayer
@@ -70,6 +75,9 @@ class ClipPathOperation implements LayerOperation {
7075
PlatformViewStyling createPlatformViewStyling() {
7176
return PlatformViewStyling(clip: PlatformViewPathClip(path));
7277
}
78+
79+
@override
80+
bool get shouldDrawIfEmpty => false;
7381
}
7482

7583
class ClipRectLayer
@@ -105,6 +113,9 @@ class ClipRectOperation implements LayerOperation {
105113
PlatformViewStyling createPlatformViewStyling() {
106114
return PlatformViewStyling(clip: PlatformViewRectClip(rect));
107115
}
116+
117+
@override
118+
bool get shouldDrawIfEmpty => false;
108119
}
109120

110121
class ClipRRectLayer
@@ -140,6 +151,9 @@ class ClipRRectOperation implements LayerOperation {
140151
PlatformViewStyling createPlatformViewStyling() {
141152
return PlatformViewStyling(clip: PlatformViewRRectClip(rrect));
142153
}
154+
155+
@override
156+
bool get shouldDrawIfEmpty => false;
143157
}
144158

145159
class ColorFilterLayer
@@ -165,6 +179,9 @@ class ColorFilterOperation implements LayerOperation {
165179

166180
@override
167181
PlatformViewStyling createPlatformViewStyling() => const PlatformViewStyling();
182+
183+
@override
184+
bool get shouldDrawIfEmpty => false;
168185
}
169186

170187
class ImageFilterLayer
@@ -207,6 +224,9 @@ class ImageFilterOperation implements LayerOperation {
207224
return const PlatformViewStyling();
208225
}
209226
}
227+
228+
@override
229+
bool get shouldDrawIfEmpty => false;
210230
}
211231

212232
class OffsetLayer
@@ -236,6 +256,9 @@ class OffsetOperation implements LayerOperation {
236256
PlatformViewStyling createPlatformViewStyling() => PlatformViewStyling(
237257
position: PlatformViewPosition.offset(ui.Offset(dx, dy))
238258
);
259+
260+
@override
261+
bool get shouldDrawIfEmpty => false;
239262
}
240263

241264
class OpacityLayer
@@ -276,6 +299,9 @@ class OpacityOperation implements LayerOperation {
276299
position: offset != ui.Offset.zero ? PlatformViewPosition.offset(offset) : const PlatformViewPosition.zero(),
277300
opacity: alpha.toDouble() / 255.0,
278301
);
302+
303+
@override
304+
bool get shouldDrawIfEmpty => false;
279305
}
280306

281307
class TransformLayer
@@ -307,6 +333,9 @@ class TransformOperation implements LayerOperation {
307333
PlatformViewStyling createPlatformViewStyling() => PlatformViewStyling(
308334
position: PlatformViewPosition.transform(matrix),
309335
);
336+
337+
@override
338+
bool get shouldDrawIfEmpty => false;
310339
}
311340

312341
class ShaderMaskLayer
@@ -346,6 +375,9 @@ class ShaderMaskOperation implements LayerOperation {
346375

347376
@override
348377
PlatformViewStyling createPlatformViewStyling() => const PlatformViewStyling();
378+
379+
@override
380+
bool get shouldDrawIfEmpty => false;
349381
}
350382

351383
class PlatformView {
@@ -414,6 +446,11 @@ abstract class LayerOperation {
414446
void post(SceneCanvas canvas, ui.Rect contentRect);
415447

416448
PlatformViewStyling createPlatformViewStyling();
449+
450+
/// Indicates whether this operation's `pre` and `post` methods should be
451+
/// invoked even if it contains no pictures. (Most operations don't need to
452+
/// actually be performed at all if they don't contain any pictures.)
453+
bool get shouldDrawIfEmpty;
417454
}
418455

419456
class PictureDrawCommand {
@@ -771,7 +808,7 @@ class LayerBuilder {
771808
}
772809

773810
void flushSlices() {
774-
if (pendingPictures.isNotEmpty) {
811+
if (pendingPictures.isNotEmpty || (operation?.shouldDrawIfEmpty ?? false)) {
775812
// Merge the existing draw commands into a single picture and add a slice
776813
// with that picture to the slice list.
777814
final ui.Rect drawnRect = picturesRect ?? ui.Rect.zero;

lib/web_ui/test/ui/scene_builder_test.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,34 @@ Future<void> testMain() async {
215215
await matchGoldenFile('scene_builder_backdrop_filter.png', region: region);
216216
});
217217

218+
test('empty backdrop filter layer with clip', () async {
219+
// Note that this test does not actually render properly in skwasm due to
220+
// a Skia bug. See https://g-issues.skia.org/issues/362552959 and
221+
// https://github.com/flutter/flutter/issues/152026
222+
final ui.SceneBuilder sceneBuilder = ui.SceneBuilder();
223+
224+
sceneBuilder.addPicture(ui.Offset.zero, drawPicture((ui.Canvas canvas) {
225+
// Create a red and blue checkerboard pattern
226+
final ui.Paint redPaint = ui.Paint()..color = const ui.Color(0xFFFF0000);
227+
final ui.Paint bluePaint = ui.Paint()..color = const ui.Color(0xFF0000FF);
228+
for (double y = 0; y < 300; y += 10) {
229+
for (double x = 0; x < 300; x += 10) {
230+
final ui.Paint paint = ((x + y) % 20 == 0) ? redPaint : bluePaint;
231+
canvas.drawRect(ui.Rect.fromLTWH(x, y, 10, 10), paint);
232+
}
233+
}
234+
}));
235+
236+
sceneBuilder.pushClipRect(const ui.Rect.fromLTRB(100, 100, 200, 200));
237+
238+
sceneBuilder.pushBackdropFilter(ui.ImageFilter.blur(
239+
sigmaX: 3.0,
240+
sigmaY: 3.0,
241+
));
242+
await renderScene(sceneBuilder.build());
243+
await matchGoldenFile('scene_builder_empty_backdrop_filter_with_clip.png', region: region);
244+
});
245+
218246
test('image filter layer', () async {
219247
final ui.SceneBuilder sceneBuilder = ui.SceneBuilder();
220248
sceneBuilder.pushImageFilter(ui.ImageFilter.blur(

0 commit comments

Comments
 (0)