From 8c06a2a47d25e9cdecadb798dbc47965a2b0467d Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 29 Dec 2022 18:12:59 -0800 Subject: [PATCH 01/12] [web] use a render target instead of a new surface for Picture.toImage --- .../src/engine/canvaskit/canvaskit_api.dart | 5 +++++ .../lib/src/engine/canvaskit/picture.dart | 21 +++---------------- .../lib/src/engine/canvaskit/surface.dart | 16 ++++++++++++++ .../src/engine/canvaskit/surface_factory.dart | 4 ---- .../test/canvaskit/surface_factory_test.dart | 4 ---- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart index fc226bfa7632f..10507f347be41 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart @@ -118,6 +118,11 @@ extension CanvasKitExtension on CanvasKit { int height, ColorSpace colorSpace, ); + external SkSurface? MakeRenderTarget( + SkGrContext grContext, + int width, + int height, + ); external SkSurface MakeSWCanvasSurface(DomCanvasElement canvas); /// Creates an image from decoded pixels represented as a list of bytes. diff --git a/lib/web_ui/lib/src/engine/canvaskit/picture.dart b/lib/web_ui/lib/src/engine/canvaskit/picture.dart index 87a94db734c97..f0f0684f0988a 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/picture.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/picture.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:typed_data'; - import 'package:ui/ui.dart' as ui; import '../profiler.dart'; @@ -102,26 +100,13 @@ class CkPicture extends ManagedSkiaObject implements ui.Picture { @override ui.Image toImageSync(int width, int height) { assert(debugCheckNotDisposed('Cannot convert picture to image.')); - final Surface surface = SurfaceFactory.instance.pictureToImageSurface; - final CkSurface ckSurface = - surface.createOrUpdateSurface(ui.Size(width.toDouble(), height.toDouble())); + final CkSurface ckSurface = SurfaceFactory.instance.baseSurface + .createRenderTargetSurface(ui.Size(width.toDouble(), height.toDouble())); final CkCanvas ckCanvas = ckSurface.getCanvas(); ckCanvas.clear(const ui.Color(0x00000000)); ckCanvas.drawPicture(this); final SkImage skImage = ckSurface.surface.makeImageSnapshot(); - final SkImageInfo imageInfo = SkImageInfo( - alphaType: canvasKit.AlphaType.Premul, - colorType: canvasKit.ColorType.RGBA_8888, - colorSpace: SkColorSpaceSRGB, - width: width, - height: height, - ); - final Uint8List pixels = skImage.readPixels(0, 0, imageInfo); - final SkImage? rasterImage = canvasKit.MakeImage(imageInfo, pixels, 4 * width); - if (rasterImage == null) { - throw StateError('Unable to convert image pixels into SkImage.'); - } - return CkImage(rasterImage); + return CkImage(skImage); } @override diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index ff9d829f7aea6..fb06253f175b8 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -140,6 +140,22 @@ class Surface { ui.Size? _currentSurfaceSize; double _currentDevicePixelRatio = -1; + CkSurface createRenderTargetSurface(ui.Size size) { + if (_grContext == null) { + print('How did this even happen!'); + } + final SkSurface? skSurface = canvasKit.MakeRenderTarget( + _grContext!, + size.width.ceil(), + size.height.ceil(), + ); + if (skSurface == null) { + return _makeSoftwareCanvasSurface( + htmlCanvas!, 'Failed to initialize WebGL surface'); + } + return CkSurface(skSurface, _glContext); + } + /// Creates a and SkSurface for the given [size]. CkSurface createOrUpdateSurface(ui.Size size) { if (size.isEmpty) { diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart b/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart index c0a1b4f3c5119..c202825b4eedf 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart @@ -46,10 +46,6 @@ class SurfaceFactory { /// all painting commands. final Surface baseSurface = Surface(); - /// A surface used specifically for `Picture.toImage` calls, which can be - /// reused in order to avoid creating too many WebGL contexts. - late final Surface pictureToImageSurface = Surface(); - /// The maximum number of surfaces which can be live at once. final int maximumSurfaces; diff --git a/lib/web_ui/test/canvaskit/surface_factory_test.dart b/lib/web_ui/test/canvaskit/surface_factory_test.dart index d9da96d693ffe..05db21472386c 100644 --- a/lib/web_ui/test/canvaskit/surface_factory_test.dart +++ b/lib/web_ui/test/canvaskit/surface_factory_test.dart @@ -26,10 +26,6 @@ void testMain() { expect(SurfaceFactory(2).maximumSurfaces, 2); }); - test('has a Surface dedicated to Picture.toImage', () { - expect(SurfaceFactory(1).pictureToImageSurface, isNotNull); - }); - test('getSurface', () { final SurfaceFactory factory = SurfaceFactory(3); expect(factory.baseSurface, isNotNull); From 6b8cec38a6a6b553cf765d576cb0729b6157b0a8 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 4 Jan 2023 09:10:09 -0800 Subject: [PATCH 02/12] setup grcontext if missing --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index fb06253f175b8..e99ec4608df33 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -141,8 +141,10 @@ class Surface { double _currentDevicePixelRatio = -1; CkSurface createRenderTargetSurface(ui.Size size) { + // If the GrContext hasn't been setup yet then we need to force initialization + // of the canvas and initial surface. if (_grContext == null) { - print('How did this even happen!'); + _createNewCanvas(size); } final SkSurface? skSurface = canvasKit.MakeRenderTarget( _grContext!, From 749cf7131ca9fb39e243ffddf671b50aeab15e33 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 4 Jan 2023 10:08:48 -0800 Subject: [PATCH 03/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index e99ec4608df33..80d11e4c6128c 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -143,8 +143,15 @@ class Surface { CkSurface createRenderTargetSurface(ui.Size size) { // If the GrContext hasn't been setup yet then we need to force initialization // of the canvas and initial surface. - if (_grContext == null) { - _createNewCanvas(size); + if (_surface == null) { + assert(_grContext == null); + assert(_glContext == null); + _createNewCanvas(window.physicalSize); + _currentCanvasPhysicalSize = window.physicalSize; + _currentDevicePixelRatio = window.devicePixelRatio; + _currentSurfaceSize = window.physicalSize; + _translateCanvas(); + _surface = _createNewSurface(window.physicalSize); } final SkSurface? skSurface = canvasKit.MakeRenderTarget( _grContext!, From 8679c530f6edc87fb1ed0a63065e75755b64358b Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 13 Jan 2023 13:14:22 -0800 Subject: [PATCH 04/12] dispose --- lib/web_ui/lib/src/engine/canvaskit/picture.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/web_ui/lib/src/engine/canvaskit/picture.dart b/lib/web_ui/lib/src/engine/canvaskit/picture.dart index f0f0684f0988a..4d377f9c23453 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/picture.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/picture.dart @@ -106,6 +106,7 @@ class CkPicture extends ManagedSkiaObject implements ui.Picture { ckCanvas.clear(const ui.Color(0x00000000)); ckCanvas.drawPicture(this); final SkImage skImage = ckSurface.surface.makeImageSnapshot(); + ckSurface.dispose(); return CkImage(skImage); } From df4bcd261e6b877d843b1cf1ff299f9af26ef848 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 13 Jan 2023 13:18:32 -0800 Subject: [PATCH 05/12] Add unit test for MakeRenderTarget --- .../test/canvaskit/canvaskit_api_test.dart | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart index 94add854d0fe5..91d8c564cf0da 100644 --- a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart +++ b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart @@ -1807,4 +1807,28 @@ void _paragraphTests() { expect(skSurface, isNotNull); }, skip: isFirefox); // Intended: Headless firefox has no webgl support https://github.com/flutter/flutter/issues/109265 + + test('MakeRenderTarget test', () { + final DomCanvasElement canvas = createDomCanvasElement( + width: 100, + height: 100, + ); + + final int glContext = canvasKit.GetWebGLContext( + canvas, + SkWebGLContextOptions( + antialias: 0, + majorVersion: webGLVersion.toDouble(), + ), + ).toInt(); + final SkGrContext grContext = canvasKit.MakeGrContext(glContext); + final SkSurface? surface = canvasKit.MakeRenderTarget(grContext, 1, 1); + + if (isFirefox) { + // Fails when there is no webgl support. + expect(surface, isNull); + } else { + expect(surface, isNotNull); + } + }); } From 1d72eb880a6d26ca2384b4525a9b654130cd2957 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 17 Jan 2023 09:47:45 -0800 Subject: [PATCH 06/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index 6a613d132996d..d77e576d1e3df 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -145,14 +145,10 @@ class Surface { // If the GrContext hasn't been setup yet then we need to force initialization // of the canvas and initial surface. if (_surface == null) { - assert(_grContext == null); - assert(_glContext == null); - _createNewCanvas(window.physicalSize); - _currentCanvasPhysicalSize = window.physicalSize; - _currentDevicePixelRatio = window.devicePixelRatio; - _currentSurfaceSize = window.physicalSize; - _translateCanvas(); - _surface = _createNewSurface(window.physicalSize); + // TODO(jonahwilliams): this is somewhat wasteful. We should probably + // eagerly setup this surface instead of delaying until the first frame? + // Or at least cache the estimated window size. + createOrUpdateSurface(const ui.Size(1, 1)); } final SkSurface? skSurface = canvasKit.MakeRenderTarget( _grContext!, From 22f94b1458d9cd9467b7178be742141762920d86 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 23 Jan 2023 17:53:43 -0800 Subject: [PATCH 07/12] ++ --- lib/web_ui/test/canvaskit/canvaskit_api_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart index ab3c895ec33bd..64923292496d6 100644 --- a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart +++ b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart @@ -1821,7 +1821,7 @@ void _paragraphTests() { majorVersion: webGLVersion.toDouble(), ), ).toInt(); - final SkGrContext grContext = canvasKit.MakeGrContext(glContext); + final SkGrContext grContext = canvasKit.MakeGrContext(glContext.toDouble()); final SkSurface? surface = canvasKit.MakeRenderTarget(grContext, 1, 1); if (isFirefox) { From b86e621172f80822b2c078876e3d70f645f9ec6f Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 23 Jan 2023 18:44:59 -0800 Subject: [PATCH 08/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index 61993b3dbb85e..225a29158806d 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -150,6 +150,11 @@ class Surface { // Or at least cache the estimated window size. createOrUpdateSurface(const ui.Size(1, 1)); } + // No context means software rendering. + if (_grContext == null) { + return _makeSoftwareCanvasSurface( + htmlCanvas!, 'Failed to initialize WebGL surface'); + } final SkSurface? skSurface = canvasKit.MakeRenderTarget( _grContext!, size.width.ceil(), From e84c819aa8d3b599779569dfe2e641366254b747 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 24 Jan 2023 09:59:25 -0800 Subject: [PATCH 09/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 3 ++- lib/web_ui/test/canvaskit/canvaskit_api_test.dart | 9 ++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index 225a29158806d..8dd6413c194eb 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -151,7 +151,8 @@ class Surface { createOrUpdateSurface(const ui.Size(1, 1)); } // No context means software rendering. - if (_grContext == null) { + if (_glContext == null ||_grContext == null || + webGLVersion == -1 || configuration.canvasKitForceCpuOnly) { return _makeSoftwareCanvasSurface( htmlCanvas!, 'Failed to initialize WebGL surface'); } diff --git a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart index 64923292496d6..22ba3ca6d2c5e 100644 --- a/lib/web_ui/test/canvaskit/canvaskit_api_test.dart +++ b/lib/web_ui/test/canvaskit/canvaskit_api_test.dart @@ -1824,11 +1824,6 @@ void _paragraphTests() { final SkGrContext grContext = canvasKit.MakeGrContext(glContext.toDouble()); final SkSurface? surface = canvasKit.MakeRenderTarget(grContext, 1, 1); - if (isFirefox) { - // Fails when there is no webgl support. - expect(surface, isNull); - } else { - expect(surface, isNotNull); - } - }); + expect(surface, isNotNull); + }, skip: isFirefox); // Intended: Headless firefox has no webgl support https://github.com/flutter/flutter/issues/109265 } From 96b96050ed1b951b94fe4f5cf42cab691a4c3cd4 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 24 Jan 2023 10:41:16 -0800 Subject: [PATCH 10/12] ++ --- .../lib/src/engine/canvaskit/picture.dart | 38 ++++++++++++++++++ .../lib/src/engine/canvaskit/surface.dart | 40 ++++++++++--------- .../src/engine/canvaskit/surface_factory.dart | 4 ++ 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/picture.dart b/lib/web_ui/lib/src/engine/canvaskit/picture.dart index 4d377f9c23453..afbc734ff1163 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/picture.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/picture.dart @@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; + import 'package:ui/ui.dart' as ui; +import '../../engine.dart'; +import '../configuration.dart'; import '../profiler.dart'; import '../util.dart'; import 'canvas.dart'; @@ -99,7 +103,16 @@ class CkPicture extends ManagedSkiaObject implements ui.Picture { @override ui.Image toImageSync(int width, int height) { + SurfaceFactory.instance.baseSurface.ensureSurface(); + if (SurfaceFactory.instance.baseSurface.usingSoftwareBackend) { + return toImageSyncSoftware(width, height); + } + return toImageSyncGPU(width, height); + } + + ui.Image toImageSyncGPU(int width, int height) { assert(debugCheckNotDisposed('Cannot convert picture to image.')); + final CkSurface ckSurface = SurfaceFactory.instance.baseSurface .createRenderTargetSurface(ui.Size(width.toDouble(), height.toDouble())); final CkCanvas ckCanvas = ckSurface.getCanvas(); @@ -110,6 +123,31 @@ class CkPicture extends ManagedSkiaObject implements ui.Picture { return CkImage(skImage); } + ui.Image toImageSyncSoftware(int width, int height) { + assert(debugCheckNotDisposed('Cannot convert picture to image.')); + + final Surface surface = SurfaceFactory.instance.pictureToImageSurface; + final CkSurface ckSurface = + surface.createOrUpdateSurface(ui.Size(width.toDouble(), height.toDouble())); + final CkCanvas ckCanvas = ckSurface.getCanvas(); + ckCanvas.clear(const ui.Color(0x00000000)); + ckCanvas.drawPicture(this); + final SkImage skImage = ckSurface.surface.makeImageSnapshot(); + final SkImageInfo imageInfo = SkImageInfo( + alphaType: canvasKit.AlphaType.Premul, + colorType: canvasKit.ColorType.RGBA_8888, + colorSpace: SkColorSpaceSRGB, + width: width.toDouble(), + height: height.toDouble(), + ); + final Uint8List pixels = skImage.readPixels(0, 0, imageInfo); + final SkImage? rasterImage = canvasKit.MakeImage(imageInfo, pixels, (4 * width).toDouble()); + if (rasterImage == null) { + throw StateError('Unable to convert image pixels into SkImage.'); + } + return CkImage(rasterImage); + } + @override bool get isResurrectionExpensive => true; diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index 8dd6413c194eb..93e618973ad79 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -141,30 +141,34 @@ class Surface { ui.Size? _currentSurfaceSize; double _currentDevicePixelRatio = -1; - CkSurface createRenderTargetSurface(ui.Size size) { + /// This is only valid after the first frame or if [ensureSurface] has been + /// called + bool get usingSoftwareBackend => _glContext == null || + _grContext == null || webGLVersion == -1 || !configuration.canvasKitForceCpuOnly; + + /// Ensure that the initial surface, gl/grcontext have been populated so + /// that software rendering can be detected. + void ensureSurface() { // If the GrContext hasn't been setup yet then we need to force initialization // of the canvas and initial surface. - if (_surface == null) { - // TODO(jonahwilliams): this is somewhat wasteful. We should probably - // eagerly setup this surface instead of delaying until the first frame? - // Or at least cache the estimated window size. - createOrUpdateSurface(const ui.Size(1, 1)); - } - // No context means software rendering. - if (_glContext == null ||_grContext == null || - webGLVersion == -1 || configuration.canvasKitForceCpuOnly) { - return _makeSoftwareCanvasSurface( - htmlCanvas!, 'Failed to initialize WebGL surface'); + if (_surface != null) { + return; } - final SkSurface? skSurface = canvasKit.MakeRenderTarget( + // TODO(jonahwilliams): this is somewhat wasteful. We should probably + // eagerly setup this surface instead of delaying until the first frame? + // Or at least cache the estimated window size. + createOrUpdateSurface(const ui.Size(1, 1)); + } + + /// This method is not supported if software rendering is used. + CkSurface createRenderTargetSurface(ui.Size size) { + assert(!usingSoftwareBackend); + + final SkSurface skSurface = canvasKit.MakeRenderTarget( _grContext!, size.width.ceil(), size.height.ceil(), - ); - if (skSurface == null) { - return _makeSoftwareCanvasSurface( - htmlCanvas!, 'Failed to initialize WebGL surface'); - } + )!; return CkSurface(skSurface, _glContext); } diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart b/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart index c202825b4eedf..08e863074360a 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface_factory.dart @@ -49,6 +49,10 @@ class SurfaceFactory { /// The maximum number of surfaces which can be live at once. final int maximumSurfaces; + /// A surface used specifically for `Picture.toImage` when software rendering + /// is supported. + late final Surface pictureToImageSurface = Surface(); + /// The maximum number of assignable overlays. /// /// This is just `maximumSurfaces - 1` (the maximum number of surfaces minus From 3411d93d538ceb796f1c8c8b8167556e5479371b Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 24 Jan 2023 11:27:26 -0800 Subject: [PATCH 11/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/picture.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/picture.dart b/lib/web_ui/lib/src/engine/canvaskit/picture.dart index afbc734ff1163..bd147b59ec7f0 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/picture.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/picture.dart @@ -6,8 +6,6 @@ import 'dart:typed_data'; import 'package:ui/ui.dart' as ui; -import '../../engine.dart'; -import '../configuration.dart'; import '../profiler.dart'; import '../util.dart'; import 'canvas.dart'; From af8d6b8d124cc9ebec485bbf2aa8a80a212f6e4c Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 24 Jan 2023 20:53:19 -0800 Subject: [PATCH 12/12] ++ --- lib/web_ui/lib/src/engine/canvaskit/surface.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvaskit/surface.dart b/lib/web_ui/lib/src/engine/canvaskit/surface.dart index 93e618973ad79..1d24687d118ef 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/surface.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/surface.dart @@ -144,11 +144,15 @@ class Surface { /// This is only valid after the first frame or if [ensureSurface] has been /// called bool get usingSoftwareBackend => _glContext == null || - _grContext == null || webGLVersion == -1 || !configuration.canvasKitForceCpuOnly; + _grContext == null || webGLVersion == -1 || configuration.canvasKitForceCpuOnly; - /// Ensure that the initial surface, gl/grcontext have been populated so + /// Ensure that the initial surface exists and has a size of at least [size]. + /// + /// If not provided, [size] defaults to 1x1. + /// + /// This also ensures that the gl/grcontext have been populated so /// that software rendering can be detected. - void ensureSurface() { + void ensureSurface([ui.Size size = const ui.Size(1, 1)]) { // If the GrContext hasn't been setup yet then we need to force initialization // of the canvas and initial surface. if (_surface != null) { @@ -157,7 +161,7 @@ class Surface { // TODO(jonahwilliams): this is somewhat wasteful. We should probably // eagerly setup this surface instead of delaying until the first frame? // Or at least cache the estimated window size. - createOrUpdateSurface(const ui.Size(1, 1)); + createOrUpdateSurface(size); } /// This method is not supported if software rendering is used.