Skip to content

Commit 8a038a6

Browse files
authored
[skwasm] use temporary RawPaint objects (attempt #2) (flutter#55035)
Relands flutter#54917. The change is the same as before, except now the native resources for `SkwasmColorFilter` and `SkwasmImageFilter` classes are no longer GC'd. Instead, we use manually managed native handles (vended and scoped by `withRawColorFilter` and `withRawImageFilter`). The bug in the previous PR was that filter objects were disposed with the paint while the framework continued holding onto them. When GC kicked the finalization registry, it attempted to double-free the filters.
1 parent 3dc8b71 commit 8a038a6

File tree

6 files changed

+379
-350
lines changed

6 files changed

+379
-350
lines changed

lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart

+100-60
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,33 @@ class SkwasmCanvas implements SceneCanvas {
2929

3030
@override
3131
void saveLayer(ui.Rect? bounds, ui.Paint paint) {
32-
paint as SkwasmPaint;
32+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
3333
if (bounds != null) {
3434
withStackScope((StackScope s) {
35-
canvasSaveLayer(_handle, s.convertRectToNative(bounds), paint.handle, nullptr);
35+
canvasSaveLayer(_handle, s.convertRectToNative(bounds), paintHandle, nullptr);
3636
});
3737
} else {
38-
canvasSaveLayer(_handle, nullptr, paint.handle, nullptr);
38+
canvasSaveLayer(_handle, nullptr, paintHandle, nullptr);
3939
}
40+
paintDispose(paintHandle);
4041
}
4142

4243
@override
4344
void saveLayerWithFilter(ui.Rect? bounds, ui.Paint paint, ui.ImageFilter imageFilter) {
4445
final SkwasmImageFilter nativeFilter = SkwasmImageFilter.fromUiFilter(imageFilter);
45-
paint as SkwasmPaint;
46+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
4647
if (bounds != null) {
4748
withStackScope((StackScope s) {
48-
canvasSaveLayer(_handle, s.convertRectToNative(bounds), paint.handle, nativeFilter.handle);
49+
nativeFilter.withRawImageFilter((nativeFilterHandle) {
50+
canvasSaveLayer(_handle, s.convertRectToNative(bounds), paintHandle, nativeFilterHandle);
51+
});
4952
});
5053
} else {
51-
canvasSaveLayer(_handle, nullptr, paint.handle, nativeFilter.handle);
54+
nativeFilter.withRawImageFilter((nativeFilterHandle) {
55+
canvasSaveLayer(_handle, nullptr, paintHandle, nativeFilterHandle);
56+
});
5257
}
58+
paintDispose(paintHandle);
5359
}
5460

5561
@override
@@ -111,136 +117,158 @@ class SkwasmCanvas implements SceneCanvas {
111117

112118
@override
113119
void drawLine(ui.Offset p1, ui.Offset p2, ui.Paint paint) {
114-
paint as SkwasmPaint;
115-
canvasDrawLine(_handle, p1.dx, p1.dy, p2.dx, p2.dy, paint.handle);
120+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
121+
canvasDrawLine(_handle, p1.dx, p1.dy, p2.dx, p2.dy, paintHandle);
122+
paintDispose(paintHandle);
116123
}
117124

118125
@override
119126
void drawPaint(ui.Paint paint) {
120-
paint as SkwasmPaint;
121-
canvasDrawPaint(_handle, paint.handle);
127+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
128+
canvasDrawPaint(_handle, paintHandle);
129+
paintDispose(paintHandle);
122130
}
123131

124132
@override
125133
void drawRect(ui.Rect rect, ui.Paint paint) {
126-
paint as SkwasmPaint;
134+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
127135
withStackScope((StackScope s) {
128136
canvasDrawRect(
129137
_handle,
130138
s.convertRectToNative(rect),
131-
paint.handle
139+
paintHandle
132140
);
133141
});
142+
paintDispose(paintHandle);
134143
}
135144

136145
@override
137146
void drawRRect(ui.RRect rrect, ui.Paint paint) {
138-
paint as SkwasmPaint;
147+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
139148
withStackScope((StackScope s) {
140149
canvasDrawRRect(
141150
_handle,
142151
s.convertRRectToNative(rrect),
143-
paint.handle
152+
paintHandle
144153
);
145154
});
155+
paintDispose(paintHandle);
146156
}
147157

148158
@override
149159
void drawDRRect(ui.RRect outer, ui.RRect inner, ui.Paint paint) {
150-
paint as SkwasmPaint;
160+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
151161
withStackScope((StackScope s) {
152162
canvasDrawDRRect(
153163
_handle,
154164
s.convertRRectToNative(outer),
155165
s.convertRRectToNative(inner),
156-
paint.handle
166+
paintHandle
157167
);
158168
});
169+
paintDispose(paintHandle);
159170
}
160171

161172
@override
162173
void drawOval(ui.Rect rect, ui.Paint paint) {
163-
paint as SkwasmPaint;
174+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
164175
withStackScope((StackScope s) {
165-
canvasDrawOval(_handle, s.convertRectToNative(rect), paint.handle);
176+
canvasDrawOval(_handle, s.convertRectToNative(rect), paintHandle);
166177
});
178+
paintDispose(paintHandle);
167179
}
168180

169181
@override
170182
void drawCircle(ui.Offset center, double radius, ui.Paint paint) {
171-
paint as SkwasmPaint;
172-
canvasDrawCircle(_handle, center.dx, center.dy, radius, paint.handle);
183+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
184+
canvasDrawCircle(_handle, center.dx, center.dy, radius, paintHandle);
185+
paintDispose(paintHandle);
173186
}
174187

175188
@override
176189
void drawArc(ui.Rect rect, double startAngle, double sweepAngle,
177190
bool useCenter, ui.Paint paint) {
178-
paint as SkwasmPaint;
191+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
179192
withStackScope((StackScope s) {
180193
canvasDrawArc(
181194
_handle,
182195
s.convertRectToNative(rect),
183196
ui.toDegrees(startAngle),
184197
ui.toDegrees(sweepAngle),
185198
useCenter,
186-
paint.handle
199+
paintHandle,
187200
);
188201
});
202+
paintDispose(paintHandle);
189203
}
190204

191205
@override
192206
void drawPath(ui.Path path, ui.Paint paint) {
193-
paint as SkwasmPaint;
194207
path as SkwasmPath;
195-
canvasDrawPath(_handle, path.handle, paint.handle);
208+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
209+
canvasDrawPath(_handle, path.handle, paintHandle);
210+
paintDispose(paintHandle);
196211
}
197212

198213
@override
199-
void drawImage(ui.Image image, ui.Offset offset, ui.Paint paint) =>
214+
void drawImage(ui.Image image, ui.Offset offset, ui.Paint paint) {
215+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
200216
canvasDrawImage(
201217
_handle,
202218
(image as SkwasmImage).handle,
203219
offset.dx,
204220
offset.dy,
205-
(paint as SkwasmPaint).handle,
221+
paintHandle,
206222
paint.filterQuality.index,
207223
);
224+
paintDispose(paintHandle);
225+
}
208226

209227
@override
210228
void drawImageRect(
211229
ui.Image image,
212230
ui.Rect src,
213231
ui.Rect dst,
214-
ui.Paint paint) => withStackScope((StackScope scope) {
215-
final Pointer<Float> sourceRect = scope.convertRectToNative(src);
216-
final Pointer<Float> destRect = scope.convertRectToNative(dst);
217-
canvasDrawImageRect(
218-
_handle,
219-
(image as SkwasmImage).handle,
220-
sourceRect,
221-
destRect,
222-
(paint as SkwasmPaint).handle,
223-
paint.filterQuality.index,
224-
);
225-
});
232+
ui.Paint paint,
233+
) {
234+
withStackScope((StackScope scope) {
235+
final Pointer<Float> sourceRect = scope.convertRectToNative(src);
236+
final Pointer<Float> destRect = scope.convertRectToNative(dst);
237+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
238+
canvasDrawImageRect(
239+
_handle,
240+
(image as SkwasmImage).handle,
241+
sourceRect,
242+
destRect,
243+
paintHandle,
244+
paint.filterQuality.index,
245+
);
246+
paintDispose(paintHandle);
247+
});
248+
}
226249

227250
@override
228251
void drawImageNine(
229252
ui.Image image,
230253
ui.Rect center,
231254
ui.Rect dst,
232-
ui.Paint paint) => withStackScope((StackScope scope) {
233-
final Pointer<Int32> centerRect = scope.convertIRectToNative(center);
234-
final Pointer<Float> destRect = scope.convertRectToNative(dst);
235-
canvasDrawImageNine(
236-
_handle,
237-
(image as SkwasmImage).handle,
238-
centerRect,
239-
destRect,
240-
(paint as SkwasmPaint).handle,
241-
paint.filterQuality.index,
242-
);
243-
});
255+
ui.Paint paint,
256+
) {
257+
withStackScope((StackScope scope) {
258+
final Pointer<Int32> centerRect = scope.convertIRectToNative(center);
259+
final Pointer<Float> destRect = scope.convertRectToNative(dst);
260+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
261+
canvasDrawImageNine(
262+
_handle,
263+
(image as SkwasmImage).handle,
264+
centerRect,
265+
destRect,
266+
paintHandle,
267+
paint.filterQuality.index,
268+
);
269+
paintDispose(paintHandle);
270+
});
271+
}
244272

245273
@override
246274
void drawPicture(ui.Picture picture) {
@@ -264,13 +292,15 @@ class SkwasmCanvas implements SceneCanvas {
264292
ui.Paint paint
265293
) => withStackScope((StackScope scope) {
266294
final RawPointArray rawPoints = scope.convertPointArrayToNative(points);
295+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
267296
canvasDrawPoints(
268297
_handle,
269298
pointMode.index,
270299
rawPoints,
271300
points.length,
272-
(paint as SkwasmPaint).handle,
301+
paintHandle,
273302
);
303+
paintDispose(paintHandle);
274304
});
275305

276306
@override
@@ -280,26 +310,32 @@ class SkwasmCanvas implements SceneCanvas {
280310
ui.Paint paint
281311
) => withStackScope((StackScope scope) {
282312
final RawPointArray rawPoints = scope.convertDoublesToNative(points);
313+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
283314
canvasDrawPoints(
284315
_handle,
285316
pointMode.index,
286317
rawPoints,
287318
points.length ~/ 2,
288-
(paint as SkwasmPaint).handle,
319+
paintHandle,
289320
);
321+
paintDispose(paintHandle);
290322
});
291323

292324
@override
293325
void drawVertices(
294326
ui.Vertices vertices,
295327
ui.BlendMode blendMode,
296328
ui.Paint paint,
297-
) => canvasDrawVertices(
298-
_handle,
299-
(vertices as SkwasmVertices).handle,
300-
blendMode.index,
301-
(paint as SkwasmPaint).handle,
302-
);
329+
) {
330+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
331+
canvasDrawVertices(
332+
_handle,
333+
(vertices as SkwasmVertices).handle,
334+
blendMode.index,
335+
paintHandle,
336+
);
337+
paintDispose(paintHandle);
338+
}
303339

304340
@override
305341
void drawAtlas(
@@ -319,6 +355,7 @@ class SkwasmCanvas implements SceneCanvas {
319355
final RawRect rawCullRect = cullRect != null
320356
? scope.convertRectToNative(cullRect)
321357
: nullptr;
358+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
322359
canvasDrawAtlas(
323360
_handle,
324361
(atlas as SkwasmImage).handle,
@@ -328,8 +365,9 @@ class SkwasmCanvas implements SceneCanvas {
328365
transforms.length,
329366
(blendMode ?? ui.BlendMode.src).index,
330367
rawCullRect,
331-
(paint as SkwasmPaint).handle,
368+
paintHandle,
332369
);
370+
paintDispose(paintHandle);
333371
});
334372

335373
@override
@@ -350,6 +388,7 @@ class SkwasmCanvas implements SceneCanvas {
350388
final RawRect rawCullRect = cullRect != null
351389
? scope.convertRectToNative(cullRect)
352390
: nullptr;
391+
final paintHandle = (paint as SkwasmPaint).toRawPaint();
353392
canvasDrawAtlas(
354393
_handle,
355394
(atlas as SkwasmImage).handle,
@@ -359,8 +398,9 @@ class SkwasmCanvas implements SceneCanvas {
359398
rstTransforms.length ~/ 4,
360399
(blendMode ?? ui.BlendMode.src).index,
361400
rawCullRect,
362-
(paint as SkwasmPaint).handle,
401+
paintHandle,
363402
);
403+
paintDispose(paintHandle);
364404
});
365405

366406
@override

0 commit comments

Comments
 (0)