mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add flag to disable overlays (flutter/engine#28312)
This commit is contained in:
parent
966e12ab0b
commit
44ae2eb7a0
@ -27,11 +27,18 @@ class HtmlViewEmbedder {
|
||||
HtmlViewEmbedder._();
|
||||
|
||||
/// The maximum number of overlay surfaces that can be live at once.
|
||||
static const int maximumOverlaySurfaces = int.fromEnvironment(
|
||||
'FLUTTER_WEB_MAXIMUM_OVERLAYS',
|
||||
static const int maximumSurfaces = int.fromEnvironment(
|
||||
'FLUTTER_WEB_MAXIMUM_SURFACES',
|
||||
defaultValue: 8,
|
||||
);
|
||||
|
||||
/// If `true`, overlay canvases are disabled.
|
||||
///
|
||||
/// This causes all drawing to go to a single canvas, with all of the platform
|
||||
/// views rendered over top. This may result in incorrect rendering with
|
||||
/// platform views.
|
||||
static const bool disableOverlays = maximumSurfaces <= 1;
|
||||
|
||||
/// The picture recorder shared by all platform views which paint to the
|
||||
/// backup surface.
|
||||
CkPictureRecorder? _backupPictureRecorder;
|
||||
@ -86,6 +93,9 @@ class HtmlViewEmbedder {
|
||||
}
|
||||
|
||||
List<CkCanvas> getCurrentCanvases() {
|
||||
if (disableOverlays) {
|
||||
return const <CkCanvas>[];
|
||||
}
|
||||
final Set<CkCanvas> canvases = <CkCanvas>{};
|
||||
for (int i = 0; i < _compositionOrder.length; i++) {
|
||||
final int viewId = _compositionOrder[i];
|
||||
@ -95,21 +105,23 @@ class HtmlViewEmbedder {
|
||||
}
|
||||
|
||||
void prerollCompositeEmbeddedView(int viewId, EmbeddedViewParams params) {
|
||||
_ensureOverlayInitialized(viewId);
|
||||
if (_viewsUsingBackupSurface.contains(viewId)) {
|
||||
if (_backupPictureRecorder == null) {
|
||||
// Only initialize the picture recorder for the backup surface once.
|
||||
if (!disableOverlays) {
|
||||
_ensureOverlayInitialized(viewId);
|
||||
if (_viewsUsingBackupSurface.contains(viewId)) {
|
||||
if (_backupPictureRecorder == null) {
|
||||
// Only initialize the picture recorder for the backup surface once.
|
||||
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
|
||||
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize);
|
||||
pictureRecorder.recordingCanvas!.clear(const ui.Color(0x00000000));
|
||||
_backupPictureRecorder = pictureRecorder;
|
||||
}
|
||||
_pictureRecorders[viewId] = _backupPictureRecorder!;
|
||||
} else {
|
||||
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
|
||||
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize);
|
||||
pictureRecorder.recordingCanvas!.clear(const ui.Color(0x00000000));
|
||||
_backupPictureRecorder = pictureRecorder;
|
||||
_pictureRecorders[viewId] = pictureRecorder;
|
||||
}
|
||||
_pictureRecorders[viewId] = _backupPictureRecorder!;
|
||||
} else {
|
||||
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
|
||||
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize);
|
||||
pictureRecorder.recordingCanvas!.clear(const ui.Color(0x00000000));
|
||||
_pictureRecorders[viewId] = pictureRecorder;
|
||||
}
|
||||
_compositionOrder.add(viewId);
|
||||
|
||||
@ -121,14 +133,26 @@ class HtmlViewEmbedder {
|
||||
_viewsToRecomposite.add(viewId);
|
||||
}
|
||||
|
||||
/// Prepares to composite [viewId].
|
||||
///
|
||||
/// If this returns a [CkCanvas], then that canvas should be the new leaf
|
||||
/// node. Otherwise, keep the same leaf node.
|
||||
CkCanvas? compositeEmbeddedView(int viewId) {
|
||||
// Do nothing if this view doesn't need to be composited.
|
||||
if (!_viewsToRecomposite.contains(viewId)) {
|
||||
return _pictureRecorders[viewId]!.recordingCanvas;
|
||||
if (!disableOverlays) {
|
||||
return _pictureRecorders[viewId]!.recordingCanvas;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
_compositeWithParams(viewId, _currentCompositionParams[viewId]!);
|
||||
_viewsToRecomposite.remove(viewId);
|
||||
return _pictureRecorders[viewId]!.recordingCanvas;
|
||||
if (!disableOverlays) {
|
||||
return _pictureRecorders[viewId]!.recordingCanvas;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void _compositeWithParams(int viewId, EmbeddedViewParams params) {
|
||||
@ -351,26 +375,29 @@ class HtmlViewEmbedder {
|
||||
|
||||
void submitFrame() {
|
||||
bool _didPaintBackupSurface = false;
|
||||
for (int i = 0; i < _compositionOrder.length; i++) {
|
||||
final int viewId = _compositionOrder[i];
|
||||
if (_viewsUsingBackupSurface.contains(viewId)) {
|
||||
// Only draw the picture to the backup surface once.
|
||||
if (!_didPaintBackupSurface) {
|
||||
final SurfaceFrame backupFrame =
|
||||
SurfaceFactory.instance.backupSurface.acquireFrame(_frameSize);
|
||||
backupFrame.skiaCanvas
|
||||
.drawPicture(_backupPictureRecorder!.endRecording());
|
||||
_backupPictureRecorder = null;
|
||||
backupFrame.submit();
|
||||
_didPaintBackupSurface = true;
|
||||
if (!disableOverlays) {
|
||||
for (int i = 0; i < _compositionOrder.length; i++) {
|
||||
final int viewId = _compositionOrder[i];
|
||||
if (_viewsUsingBackupSurface.contains(viewId)) {
|
||||
// Only draw the picture to the backup surface once.
|
||||
if (!_didPaintBackupSurface) {
|
||||
final SurfaceFrame backupFrame =
|
||||
SurfaceFactory.instance.backupSurface.acquireFrame(_frameSize);
|
||||
backupFrame.skiaCanvas
|
||||
.drawPicture(_backupPictureRecorder!.endRecording());
|
||||
_backupPictureRecorder = null;
|
||||
backupFrame.submit();
|
||||
_didPaintBackupSurface = true;
|
||||
}
|
||||
} else {
|
||||
final SurfaceFrame frame =
|
||||
_overlays[viewId]!.acquireFrame(_frameSize);
|
||||
final CkCanvas canvas = frame.skiaCanvas;
|
||||
canvas.drawPicture(
|
||||
_pictureRecorders[viewId]!.endRecording(),
|
||||
);
|
||||
frame.submit();
|
||||
}
|
||||
} else {
|
||||
final SurfaceFrame frame = _overlays[viewId]!.acquireFrame(_frameSize);
|
||||
final CkCanvas canvas = frame.skiaCanvas;
|
||||
canvas.drawPicture(
|
||||
_pictureRecorders[viewId]!.endRecording(),
|
||||
);
|
||||
frame.submit();
|
||||
}
|
||||
}
|
||||
if (listEquals(_compositionOrder, _activeCompositionOrder)) {
|
||||
@ -396,11 +423,13 @@ class HtmlViewEmbedder {
|
||||
|
||||
unusedViews.remove(viewId);
|
||||
final html.Element platformViewRoot = _viewClipChains[viewId]!.root;
|
||||
final html.Element overlay = _overlays[viewId]!.htmlElement;
|
||||
platformViewRoot.remove();
|
||||
skiaSceneHost!.append(platformViewRoot);
|
||||
overlay.remove();
|
||||
skiaSceneHost!.append(overlay);
|
||||
if (!disableOverlays) {
|
||||
final html.Element overlay = _overlays[viewId]!.htmlElement;
|
||||
overlay.remove();
|
||||
skiaSceneHost!.append(overlay);
|
||||
}
|
||||
_activeCompositionOrder.add(viewId);
|
||||
}
|
||||
if (_didPaintBackupSurface) {
|
||||
|
||||
@ -363,7 +363,8 @@ class TransformEngineLayer extends ContainerLayer
|
||||
void preroll(PrerollContext prerollContext, Matrix4 matrix) {
|
||||
final Matrix4 childMatrix = matrix.multiplied(_transform);
|
||||
prerollContext.mutatorsStack.pushTransform(_transform);
|
||||
final ui.Rect childPaintBounds = prerollChildren(prerollContext, childMatrix);
|
||||
final ui.Rect childPaintBounds =
|
||||
prerollChildren(prerollContext, childMatrix);
|
||||
paintBounds = transformRect(_transform, childPaintBounds);
|
||||
prerollContext.mutatorsStack.pop();
|
||||
}
|
||||
@ -602,7 +603,10 @@ class PlatformViewLayer extends Layer {
|
||||
|
||||
@override
|
||||
void paint(PaintContext paintContext) {
|
||||
final CkCanvas? canvas = paintContext.viewEmbedder!.compositeEmbeddedView(viewId);
|
||||
paintContext.leafNodesCanvas = canvas;
|
||||
final CkCanvas? canvas =
|
||||
paintContext.viewEmbedder!.compositeEmbeddedView(viewId);
|
||||
if (canvas != null) {
|
||||
paintContext.leafNodesCanvas = canvas;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import 'surface.dart';
|
||||
class SurfaceFactory {
|
||||
/// The cache singleton.
|
||||
static final SurfaceFactory instance =
|
||||
SurfaceFactory(HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
SurfaceFactory(HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
SurfaceFactory(this.maximumSurfaces)
|
||||
: assert(maximumSurfaces >= 2,
|
||||
'The maximum number of surfaces must be at least 2');
|
||||
: assert(maximumSurfaces >= 1,
|
||||
'The maximum number of surfaces must be at least 1');
|
||||
|
||||
/// The base surface to paint on. This is the default surface which will be
|
||||
/// painted to. If there are no platform views, then this surface will receive
|
||||
|
||||
@ -213,7 +213,7 @@ void testMain() {
|
||||
|
||||
// Initialize all platform views to be used in the test.
|
||||
final List<int> platformViewIds = <int>[];
|
||||
for (int i = 0; i < HtmlViewEmbedder.maximumOverlaySurfaces * 2; i++) {
|
||||
for (int i = 0; i < HtmlViewEmbedder.maximumSurfaces * 2; i++) {
|
||||
ui.platformViewRegistry.registerViewFactory(
|
||||
'test-platform-view',
|
||||
(int viewId) => html.DivElement()..id = 'view-$i',
|
||||
@ -242,8 +242,8 @@ void testMain() {
|
||||
// Frame 1:
|
||||
// Render: up to cache size platform views.
|
||||
// Expect: main canvas plus platform view overlays.
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumSurfaces);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
// Frame 2:
|
||||
// Render: zero platform views.
|
||||
@ -256,15 +256,15 @@ void testMain() {
|
||||
// Render: less than cache size platform views.
|
||||
// Expect: overlays reused.
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumOverlaySurfaces - 2);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces - 1);
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumSurfaces - 2);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces - 1);
|
||||
|
||||
// Frame 4:
|
||||
// Render: more platform views than max cache size.
|
||||
// Expect: main canvas, backup overlay, maximum overlays.
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumOverlaySurfaces * 2);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
renderTestScene(viewCount: HtmlViewEmbedder.maximumSurfaces * 2);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
// Frame 5:
|
||||
// Render: zero platform views.
|
||||
@ -346,21 +346,21 @@ void testMain() {
|
||||
// Render: Views 1-10
|
||||
// Expect: main canvas plus platform view overlays; empty cache.
|
||||
renderTestScene(<int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
// Frame 2:
|
||||
// Render: Views 2-11
|
||||
// Expect: main canvas plus platform view overlays; empty cache.
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
renderTestScene(<int>[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
// Frame 3:
|
||||
// Render: Views 3-12
|
||||
// Expect: main canvas plus platform view overlays; empty cache.
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
renderTestScene(<int>[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumOverlaySurfaces);
|
||||
expect(countCanvases(), HtmlViewEmbedder.maximumSurfaces);
|
||||
|
||||
// TODO(yjbanov): skipped due to https://github.com/flutter/flutter/issues/73867
|
||||
}, skip: isSafari);
|
||||
|
||||
@ -19,10 +19,10 @@ void testMain() {
|
||||
group('$SurfaceFactory', () {
|
||||
setUpCanvasKitTest();
|
||||
|
||||
test('cannot be created with size less than 2', () {
|
||||
test('cannot be created with size less than 1', () {
|
||||
expect(() => SurfaceFactory(-1), throwsAssertionError);
|
||||
expect(() => SurfaceFactory(0), throwsAssertionError);
|
||||
expect(() => SurfaceFactory(1), throwsAssertionError);
|
||||
expect(SurfaceFactory(1), isNotNull);
|
||||
expect(SurfaceFactory(2), isNotNull);
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user