[canvaskit] Use transferToImageBitmap
instead of createImageBitmap
(#163175)
Use `transferToImageBitmap` instead of `createImageBitmap` if we have an `OffscreenCanvas`. Now that we are sizing the `OffscreenCanvas` exactly to the frame size, we can use `transferToImageBitmap`, which should be zero-copy and therefore faster than `createImageBitmap`. In testing, this speeds things up a little bit but we still drop frames compared to multi-Surface rasterization. Helps with https://github.com/flutter/flutter/issues/162618 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
7d22606cda
commit
934af97328
@ -149,17 +149,18 @@ class Surface extends DisplayCanvas {
|
|||||||
|
|
||||||
if (browserSupportsCreateImageBitmap) {
|
if (browserSupportsCreateImageBitmap) {
|
||||||
JSObject bitmapSource;
|
JSObject bitmapSource;
|
||||||
|
DomImageBitmap bitmap;
|
||||||
if (useOffscreenCanvas) {
|
if (useOffscreenCanvas) {
|
||||||
bitmapSource = _offscreenCanvas! as JSObject;
|
bitmap = _offscreenCanvas!.transferToImageBitmap();
|
||||||
} else {
|
} else {
|
||||||
bitmapSource = _canvasElement! as JSObject;
|
bitmapSource = _canvasElement! as JSObject;
|
||||||
|
bitmap = await createImageBitmap(bitmapSource, (
|
||||||
|
x: 0,
|
||||||
|
y: _pixelHeight - bitmapSize.height,
|
||||||
|
width: bitmapSize.width,
|
||||||
|
height: bitmapSize.height,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
final DomImageBitmap bitmap = await createImageBitmap(bitmapSource, (
|
|
||||||
x: 0,
|
|
||||||
y: _pixelHeight - bitmapSize.height,
|
|
||||||
width: bitmapSize.width,
|
|
||||||
height: bitmapSize.height,
|
|
||||||
));
|
|
||||||
canvas.render(bitmap);
|
canvas.render(bitmap);
|
||||||
} else {
|
} else {
|
||||||
// If the browser doesn't support `createImageBitmap` (e.g. Safari 14)
|
// If the browser doesn't support `createImageBitmap` (e.g. Safari 14)
|
||||||
|
@ -287,6 +287,41 @@ void testMain() {
|
|||||||
skip: !Surface.offscreenCanvasSupported,
|
skip: !Surface.offscreenCanvasSupported,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('uses transferToImageBitmap for bitmap creation', () async {
|
||||||
|
final Surface surface = Surface();
|
||||||
|
surface.ensureSurface(const BitmapSize(10, 10));
|
||||||
|
final DomOffscreenCanvas offscreenCanvas = surface.debugGetOffscreenCanvas()!;
|
||||||
|
final Object originalTransferToImageBitmap = js_util.getProperty(
|
||||||
|
offscreenCanvas,
|
||||||
|
'transferToImageBitmap',
|
||||||
|
);
|
||||||
|
js_util.setProperty(
|
||||||
|
offscreenCanvas,
|
||||||
|
'originalTransferToImageBitmap',
|
||||||
|
originalTransferToImageBitmap,
|
||||||
|
);
|
||||||
|
int transferToImageBitmapCalls = 0;
|
||||||
|
js_util.setProperty(
|
||||||
|
offscreenCanvas,
|
||||||
|
'transferToImageBitmap',
|
||||||
|
js_util.allowInterop(() {
|
||||||
|
transferToImageBitmapCalls++;
|
||||||
|
return js_util.callMethod<Object>(offscreenCanvas, 'originalTransferToImageBitmap', []);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
final RenderCanvas renderCanvas = RenderCanvas();
|
||||||
|
final CkPictureRecorder recorder = CkPictureRecorder();
|
||||||
|
final CkCanvas canvas = recorder.beginRecording(const ui.Rect.fromLTRB(0, 0, 10, 10));
|
||||||
|
canvas.drawCircle(
|
||||||
|
const ui.Offset(5, 5),
|
||||||
|
3,
|
||||||
|
CkPaint()..color = const ui.Color.fromARGB(255, 255, 0, 0),
|
||||||
|
);
|
||||||
|
final CkPicture picture = recorder.endRecording();
|
||||||
|
await surface.rasterizeToCanvas(const BitmapSize(10, 10), renderCanvas, <CkPicture>[picture]);
|
||||||
|
expect(transferToImageBitmapCalls, 1);
|
||||||
|
}, skip: !Surface.offscreenCanvasSupported);
|
||||||
|
|
||||||
test('can recover from MakeSWCanvasSurface failure', () async {
|
test('can recover from MakeSWCanvasSurface failure', () async {
|
||||||
debugOverrideJsConfiguration(
|
debugOverrideJsConfiguration(
|
||||||
<String, Object?>{'canvasKitForceCpuOnly': true}.jsify() as JsFlutterConfiguration?,
|
<String, Object?>{'canvasKitForceCpuOnly': true}.jsify() as JsFlutterConfiguration?,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user