Skip to content

Commit f6a95de

Browse files
author
Harry Terkelsen
authored
Cache CanvasKit objects and delete if not used. (flutter#19341)
1 parent fae8141 commit f6a95de

17 files changed

+706
-310
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/initialization.dart
431431
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/layer.dart
432432
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart
433433
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/layer_tree.dart
434+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/mask_filter.dart
434435
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/n_way_canvas.dart
435436
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/painting.dart
436437
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/path.dart
@@ -440,6 +441,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/picture_recorder.dar
440441
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/platform_message.dart
441442
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/raster_cache.dart
442443
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/rasterizer.dart
444+
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/skia_object_cache.dart
443445
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/surface.dart
444446
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/text.dart
445447
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/util.dart

lib/web_ui/lib/src/engine.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
library engine;
66

77
import 'dart:async';
8-
import 'dart:collection' show ListBase, IterableBase;
8+
import 'dart:collection'
9+
show ListBase, IterableBase, DoubleLinkedQueue, DoubleLinkedQueueEntry;
910
import 'dart:convert' hide Codec;
1011
import 'dart:developer' as developer;
1112
import 'dart:html' as html;
@@ -37,6 +38,7 @@ part 'engine/compositor/initialization.dart';
3738
part 'engine/compositor/layer.dart';
3839
part 'engine/compositor/layer_scene_builder.dart';
3940
part 'engine/compositor/layer_tree.dart';
41+
part 'engine/compositor/mask_filter.dart';
4042
part 'engine/compositor/n_way_canvas.dart';
4143
part 'engine/compositor/path.dart';
4244
part 'engine/compositor/painting.dart';
@@ -46,6 +48,7 @@ part 'engine/compositor/picture_recorder.dart';
4648
part 'engine/compositor/platform_message.dart';
4749
part 'engine/compositor/raster_cache.dart';
4850
part 'engine/compositor/rasterizer.dart';
51+
part 'engine/compositor/skia_object_cache.dart';
4952
part 'engine/compositor/surface.dart';
5053
part 'engine/compositor/text.dart';
5154
part 'engine/compositor/util.dart';

lib/web_ui/lib/src/engine/compositor/canvas.dart

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
65
part of engine;
76

87
/// A Dart wrapper around Skia's SKCanvas.
@@ -168,7 +167,7 @@ class SkCanvas {
168167
void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) {
169168
final SkParagraph skParagraph = paragraph as SkParagraph;
170169
skCanvas.callMethod('drawParagraph', <dynamic>[
171-
skParagraph.skParagraph,
170+
skParagraph.skiaObject,
172171
offset.dx,
173172
offset.dy,
174173
]);
@@ -183,7 +182,8 @@ class SkCanvas {
183182

184183
void drawPicture(ui.Picture picture) {
185184
final SkPicture skPicture = picture as SkPicture;
186-
skCanvas.callMethod('drawPicture', <js.JsObject?>[skPicture.skPicture]);
185+
skCanvas.callMethod(
186+
'drawPicture', <js.JsObject?>[skPicture.skPicture.skiaObject]);
187187
}
188188

189189
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/58824
@@ -211,8 +211,8 @@ class SkCanvas {
211211

212212
void drawShadow(ui.Path path, ui.Color color, double elevation,
213213
bool transparentOccluder) {
214-
drawSkShadow(skCanvas, path as SkPath, color, elevation, transparentOccluder,
215-
ui.window.devicePixelRatio);
214+
drawSkShadow(skCanvas, path as SkPath, color, elevation,
215+
transparentOccluder, ui.window.devicePixelRatio);
216216
}
217217

218218
void drawVertices(
@@ -243,7 +243,6 @@ class SkCanvas {
243243
}
244244

245245
void saveLayer(ui.Rect bounds, SkPaint paint) {
246-
assert(bounds != null, 'Use saveLayerWithoutBounds'); // ignore: unnecessary_null_comparison
247246
skCanvas.callMethod('saveLayer', <js.JsObject?>[
248247
makeSkRect(bounds),
249248
paint.skiaObject,
@@ -260,7 +259,7 @@ class SkCanvas {
260259
'saveLayer',
261260
<dynamic>[
262261
null,
263-
skImageFilter.skImageFilter,
262+
skImageFilter.skiaObject,
264263
0,
265264
makeSkRect(bounds),
266265
],

lib/web_ui/lib/src/engine/compositor/color_filter.dart

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,52 @@
66
part of engine;
77

88
/// A [ui.ColorFilter] backed by Skia's [SkColorFilter].
9-
class SkColorFilter {
10-
js.JsObject? skColorFilter;
11-
12-
SkColorFilter.mode(EngineColorFilter filter) {
13-
setSharedSkColor1(filter._color!);
14-
skColorFilter =
15-
canvasKit['SkColorFilter'].callMethod('MakeBlend', <dynamic>[
16-
sharedSkColor1,
17-
makeSkBlendMode(filter._blendMode),
18-
]);
19-
}
9+
class SkColorFilter extends ResurrectableSkiaObject {
10+
final EngineColorFilter _engineFilter;
11+
12+
SkColorFilter.mode(EngineColorFilter filter) : _engineFilter = filter;
13+
14+
SkColorFilter.matrix(EngineColorFilter filter) : _engineFilter = filter;
15+
16+
SkColorFilter.linearToSrgbGamma(EngineColorFilter filter)
17+
: _engineFilter = filter;
18+
19+
SkColorFilter.srgbToLinearGamma(EngineColorFilter filter)
20+
: _engineFilter = filter;
2021

21-
SkColorFilter.matrix(EngineColorFilter filter) {
22-
// TODO(het): Find a way to remove these array conversions.
23-
final js.JsArray<double> colorMatrix = js.JsArray<double>();
24-
colorMatrix.length = 20;
25-
for (int i = 0; i < 20; i++) {
26-
colorMatrix[i] = filter._matrix![i];
22+
js.JsObject _createSkiaObjectFromFilter() {
23+
switch (_engineFilter._type) {
24+
case EngineColorFilter._TypeMode:
25+
setSharedSkColor1(_engineFilter._color!);
26+
return canvasKit['SkColorFilter'].callMethod('MakeBlend', <dynamic>[
27+
sharedSkColor1,
28+
makeSkBlendMode(_engineFilter._blendMode),
29+
]);
30+
case EngineColorFilter._TypeMatrix:
31+
final js.JsArray<double> colorMatrix = js.JsArray<double>();
32+
colorMatrix.length = 20;
33+
for (int i = 0; i < 20; i++) {
34+
colorMatrix[i] = _engineFilter._matrix![i];
35+
}
36+
return canvasKit['SkColorFilter']
37+
.callMethod('MakeMatrix', <js.JsArray>[colorMatrix]);
38+
case EngineColorFilter._TypeLinearToSrgbGamma:
39+
return canvasKit['SkColorFilter'].callMethod('MakeLinearToSRGBGamma');
40+
case EngineColorFilter._TypeSrgbToLinearGamma:
41+
return canvasKit['SkColorFilter'].callMethod('MakeSRGBToLinearGamma');
42+
default:
43+
throw StateError(
44+
'Unknown mode ${_engineFilter._type} for ColorFilter.');
2745
}
28-
skColorFilter = canvasKit['SkColorFilter']
29-
.callMethod('MakeMatrix', <js.JsArray>[colorMatrix]);
3046
}
3147

32-
SkColorFilter.linearToSrgbGamma(EngineColorFilter filter) {
33-
skColorFilter =
34-
canvasKit['SkColorFilter'].callMethod('MakeLinearToSRGBGamma');
48+
@override
49+
js.JsObject createDefault() {
50+
return _createSkiaObjectFromFilter();
3551
}
3652

37-
SkColorFilter.srgbToLinearGamma(EngineColorFilter filter) {
38-
skColorFilter =
39-
canvasKit['SkColorFilter'].callMethod('MakeSRGBToLinearGamma');
53+
@override
54+
js.JsObject resurrect() {
55+
return _createSkiaObjectFromFilter();
4056
}
4157
}

lib/web_ui/lib/src/engine/compositor/image_filter.dart

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,35 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
65
part of engine;
76

87
/// The CanvasKit implementation of [ui.ImageFilter].
98
///
109
/// Currently only supports `blur`.
11-
class SkImageFilter implements ui.ImageFilter {
12-
js.JsObject? skImageFilter;
13-
10+
class SkImageFilter extends ResurrectableSkiaObject implements ui.ImageFilter {
1411
SkImageFilter.blur({double sigmaX = 0.0, double sigmaY = 0.0})
1512
: _sigmaX = sigmaX,
16-
_sigmaY = sigmaY {
17-
skImageFilter = canvasKit['SkImageFilter'].callMethod(
18-
'MakeBlur',
19-
<dynamic>[
20-
sigmaX,
21-
sigmaY,
22-
canvasKit['TileMode']['Clamp'],
23-
null,
24-
],
25-
);
26-
}
13+
_sigmaY = sigmaY;
2714

2815
final double _sigmaX;
2916
final double _sigmaY;
3017

18+
@override
19+
js.JsObject createDefault() => _initSkiaObject();
20+
21+
@override
22+
js.JsObject resurrect() => _initSkiaObject();
23+
24+
js.JsObject _initSkiaObject() => canvasKit['SkImageFilter'].callMethod(
25+
'MakeBlur',
26+
<dynamic>[
27+
_sigmaX,
28+
_sigmaY,
29+
canvasKit['TileMode']['Clamp'],
30+
null,
31+
],
32+
);
33+
3134
@override
3235
bool operator ==(dynamic other) {
3336
if (other is! SkImageFilter) {

lib/web_ui/lib/src/engine/compositor/layer.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ class ClipPathLayer extends ContainerLayer {
150150
assert(needsPainting);
151151

152152
paintContext.internalNodesCanvas.save();
153-
paintContext.internalNodesCanvas.clipPath(_clipPath, _clipBehavior != ui.Clip.hardEdge);
153+
paintContext.internalNodesCanvas
154+
.clipPath(_clipPath, _clipBehavior != ui.Clip.hardEdge);
154155

155156
if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
156157
paintContext.internalNodesCanvas.saveLayer(paintBounds, null);

lib/web_ui/lib/src/engine/compositor/layer_scene_builder.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
65
part of engine;
76

87
class LayerScene implements ui.Scene {
@@ -49,7 +48,8 @@ class LayerSceneBuilder implements ui.SceneBuilder {
4948
bool isComplexHint = false,
5049
bool willChangeHint = false,
5150
}) {
52-
currentLayer!.add(PictureLayer(picture as SkPicture, offset, isComplexHint, willChangeHint));
51+
currentLayer!.add(PictureLayer(
52+
picture as SkPicture, offset, isComplexHint, willChangeHint));
5353
}
5454

5555
@override
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
part of engine;
6+
7+
/// The CanvasKit implementation of [ui.MaskFilter].
8+
class SkMaskFilter extends ResurrectableSkiaObject {
9+
SkMaskFilter.blur(ui.BlurStyle blurStyle, double sigma)
10+
: _blurStyle = blurStyle,
11+
_sigma = sigma;
12+
13+
final ui.BlurStyle _blurStyle;
14+
final double _sigma;
15+
16+
@override
17+
js.JsObject createDefault() => _initSkiaObject();
18+
19+
@override
20+
js.JsObject resurrect() => _initSkiaObject();
21+
22+
js.JsObject _initSkiaObject() {
23+
js.JsObject skBlurStyle;
24+
switch (_blurStyle) {
25+
case ui.BlurStyle.normal:
26+
skBlurStyle = canvasKit['BlurStyle']['Normal'];
27+
break;
28+
case ui.BlurStyle.solid:
29+
skBlurStyle = canvasKit['BlurStyle']['Solid'];
30+
break;
31+
case ui.BlurStyle.outer:
32+
skBlurStyle = canvasKit['BlurStyle']['Outer'];
33+
break;
34+
case ui.BlurStyle.inner:
35+
skBlurStyle = canvasKit['BlurStyle']['Inner'];
36+
break;
37+
}
38+
39+
return canvasKit
40+
.callMethod('MakeBlurMaskFilter', <dynamic>[skBlurStyle, _sigma, true]);
41+
}
42+
}

0 commit comments

Comments
 (0)