Skip to content

Commit

Permalink
CanvasKit: memory management for image and shader classes (flutter#20349
Browse files Browse the repository at this point in the history
)

* memory-manage images and shaders
  • Loading branch information
yjbanov authored Aug 11, 2020
1 parent 49f647f commit be78eba
Show file tree
Hide file tree
Showing 14 changed files with 481 additions and 151 deletions.
3 changes: 2 additions & 1 deletion ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/picture_recorder.dar
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/platform_message.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/raster_cache.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/rasterizer.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/shader.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/skia_object_cache.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/surface.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/compositor/text.dart
Expand Down Expand Up @@ -489,7 +490,6 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/services/buffers.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/services/message_codec.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/services/message_codecs.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/services/serialization.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/shader.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/shadow.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/backdrop_filter.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/canvas.dart
Expand All @@ -514,6 +514,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/recording_canvas.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/render_vertices.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/scene.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/scene_builder.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/shader.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/surface.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/surface_stats.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/surface/transform.dart
Expand Down
3 changes: 2 additions & 1 deletion lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ part 'engine/compositor/picture_recorder.dart';
part 'engine/compositor/platform_message.dart';
part 'engine/compositor/raster_cache.dart';
part 'engine/compositor/rasterizer.dart';
part 'engine/compositor/shader.dart';
part 'engine/compositor/skia_object_cache.dart';
part 'engine/compositor/surface.dart';
part 'engine/compositor/text.dart';
Expand Down Expand Up @@ -90,7 +91,6 @@ part 'engine/services/buffers.dart';
part 'engine/services/message_codec.dart';
part 'engine/services/message_codecs.dart';
part 'engine/services/serialization.dart';
part 'engine/shader.dart';
part 'engine/shadow.dart';
part 'engine/surface/backdrop_filter.dart';
part 'engine/surface/canvas.dart';
Expand All @@ -115,6 +115,7 @@ part 'engine/surface/recording_canvas.dart';
part 'engine/surface/render_vertices.dart';
part 'engine/surface/scene.dart';
part 'engine/surface/scene_builder.dart';
part 'engine/surface/shader.dart';
part 'engine/surface/surface.dart';
part 'engine/surface/surface_stats.dart';
part 'engine/surface/transform.dart';
Expand Down
30 changes: 24 additions & 6 deletions lib/web_ui/lib/src/engine/compositor/canvaskit_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,11 @@ class SkImage {
external void delete();
external int width();
external int height();
external SkShader makeShader(SkTileMode tileModeX, SkTileMode tileModeY);
external SkShader makeShader(
SkTileMode tileModeX,
SkTileMode tileModeY,
Float32List? matrix, // 3x3 matrix
);
}

@JS()
Expand Down Expand Up @@ -677,10 +681,24 @@ class SkShaderNamespace {
Float32List? matrix, // 3x3 matrix
int flags,
);

external SkShader MakeSweepGradient(
double cx,
double cy,
List<Float32List> colors,
Float32List colorStops,
SkTileMode tileMode,
Float32List? matrix, // 3x3 matrix
int flags,
double startAngle,
double endAngle,
);
}

@JS()
class SkShader {}
class SkShader {
external void delete();
}

// This needs to be bound to top-level because SkPaint is initialized
// with `new`. Also in Dart you can't write this:
Expand Down Expand Up @@ -1556,7 +1574,7 @@ class TypefaceFontProviderNamespace {
Timer? _skObjectCollector;
List<SkDeletable> _skObjectDeleteQueue = <SkDeletable>[];

final SkObjectFinalizationRegistry skObjectFinalizationRegistry = SkObjectFinalizationRegistry(js.allowInterop((SkDeletable deletable) {
final SkObjectFinalizationRegistry<SkDeletable> skObjectFinalizationRegistry = SkObjectFinalizationRegistry<SkDeletable>(js.allowInterop((SkDeletable deletable) {
_skObjectDeleteQueue.add(deletable);
_skObjectCollector ??= _scheduleSkObjectCollection();
}));
Expand Down Expand Up @@ -1589,7 +1607,7 @@ Timer _scheduleSkObjectCollection() => Timer(Duration.zero, () {
html.window.performance.measure('SkObject collection', 'SkObject collection-start', 'SkObject collection-end');
});

typedef SkObjectFinalizer = void Function(SkDeletable deletable);
typedef SkObjectFinalizer<T> = void Function(T key);

/// Any Skia object that has a `delete` method.
@JS()
Expand All @@ -1613,8 +1631,8 @@ class SkDeletable {
/// 5. The finalizer function is called with the SkPaint as the sole argument.
/// 6. We call `delete` on SkPaint.
@JS('window.FinalizationRegistry')
class SkObjectFinalizationRegistry {
external SkObjectFinalizationRegistry(SkObjectFinalizer finalizer);
class SkObjectFinalizationRegistry<T> {
external SkObjectFinalizationRegistry(SkObjectFinalizer<T> finalizer);
external void register(Object ckObject, Object skObject);
}

Expand Down
33 changes: 22 additions & 11 deletions lib/web_ui/lib/src/engine/compositor/image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ void skiaInstantiateWebImageCodec(String src, Callback<ui.Codec> callback,
class CkAnimatedImage implements ui.Image {
final SkAnimatedImage _skAnimatedImage;

CkAnimatedImage(this._skAnimatedImage);
// Use a box because `SkImage` may be deleted either due to this object
// being garbage-collected, or by an explicit call to [delete].
late final SkiaObjectBox box;

CkAnimatedImage(this._skAnimatedImage) {
box = SkiaObjectBox(this, _skAnimatedImage as SkDeletable);
}

@override
void dispose() {
_skAnimatedImage.delete();
box.delete();
}

int get frameCount => _skAnimatedImage.getFrameCount();
Expand Down Expand Up @@ -77,11 +83,17 @@ class CkAnimatedImage implements ui.Image {
class CkImage implements ui.Image {
final SkImage skImage;

CkImage(this.skImage);
// Use a box because `SkImage` may be deleted either due to this object
// being garbage-collected, or by an explicit call to [delete].
late final SkiaObjectBox box;

CkImage(this.skImage) {
box = SkiaObjectBox(this, skImage as SkDeletable);
}

@override
void dispose() {
skImage.delete();
box.delete();
}

@override
Expand All @@ -99,26 +111,25 @@ class CkImage implements ui.Image {

/// A [Codec] that wraps an `SkAnimatedImage`.
class CkAnimatedImageCodec implements ui.Codec {
CkAnimatedImage? animatedImage;
CkAnimatedImage animatedImage;

CkAnimatedImageCodec(this.animatedImage);

@override
void dispose() {
animatedImage!.dispose();
animatedImage = null;
animatedImage.dispose();
}

@override
int get frameCount => animatedImage!.frameCount;
int get frameCount => animatedImage.frameCount;

@override
int get repetitionCount => animatedImage!.repetitionCount;
int get repetitionCount => animatedImage.repetitionCount;

@override
Future<ui.FrameInfo> getNextFrame() {
final Duration duration = animatedImage!.decodeNextFrame();
final CkImage image = animatedImage!.currentFrameAsImage;
final Duration duration = animatedImage.decodeNextFrame();
final CkImage image = animatedImage.currentFrameAsImage;
return Future<ui.FrameInfo>.value(AnimatedImageFrameInfo(duration, image));
}
}
Expand Down
10 changes: 5 additions & 5 deletions lib/web_ui/lib/src/engine/compositor/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,17 @@ class CkPaint extends ManagedSkiaObject<SkPaint> implements ui.Paint {
bool _invertColors = false;

@override
ui.Shader? get shader => _shader as ui.Shader?;
ui.Shader? get shader => _shader;
@override
set shader(ui.Shader? value) {
if (_shader == value) {
return;
}
_shader = value as EngineShader?;
skiaObject.setShader(_shader?.createSkiaShader());
_shader = value as CkShader?;
skiaObject.setShader(_shader?.skiaObject);
}

EngineShader? _shader;
CkShader? _shader;

@override
ui.MaskFilter? get maskFilter => _maskFilter;
Expand Down Expand Up @@ -222,7 +222,7 @@ class CkPaint extends ManagedSkiaObject<SkPaint> implements ui.Paint {
paint.setStrokeWidth(_strokeWidth);
paint.setAntiAlias(_isAntiAlias);
paint.setColorInt(_color.value);
paint.setShader(_shader?.createSkiaShader());
paint.setShader(_shader?.skiaObject);
paint.setMaskFilter(_ckMaskFilter?.skiaObject);
paint.setColorFilter(_ckColorFilter?.skiaObject);
paint.setImageFilter(_imageFilter?.skiaObject);
Expand Down
Loading

0 comments on commit be78eba

Please sign in to comment.