-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
When running an application on iOS with one platform view, its expect that we have to break the flutter frame into foreground/background in order to correctly place the platform view within the visual hierarchy. Locally I've observed that when targeting impeller, both the background and foreground frame seem to do exactly the same amount of work. Furthermore, If I add an expensive widget that does not intersect the PlatformView at all - I would expect one of the flutter render passes to slow down. Instead, both slow down.
This seems to me like we are clipping or splitting incorrectly, and might be doing far too much work. Potentially doing most of the work to draw most of the tree at least twice.
There don't seem to be any major rendering artifacts, besides the scrolling issue, so it could be that whatever clipping we use to break apart the scene happens too late in the Impeller backend.
Example app used was flutter/plugins/packages/google_maps_flutter
Apply the following diff:
diff --git a/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart b/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart
index 3f56f4079..e935db23f 100644
--- a/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart
+++ b/packages/google_maps_flutter/google_maps_flutter/example/lib/map_ui.dart
@@ -4,6 +4,7 @@
// ignore_for_file: public_member_api_docs
+import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:google_maps_flutter/google_maps_flutter.dart';
@@ -308,6 +309,10 @@ class MapUiBodyState extends State<MapUiBody> {
Expanded(
child: ListView(
children: <Widget>[
+ CustomPaint(
+ size: const Size(400, 400),
+ painter: QRPainter(),
+ ),
Text('camera bearing: ${_position.bearing}'),
Text(
'camera target: ${_position.target.latitude.toStringAsFixed(4)},'
@@ -354,3 +359,35 @@ class MapUiBodyState extends State<MapUiBody> {
});
}
}
+
+// Draw a "QR" like-code with 400x400 squarees.
+class QRPainter extends CustomPainter {
+ static final math.Random _random = math.Random(12455);
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ final double boxWidth = size.width / 400;
+ final double boxHeight = size.height / 400;
+ for (int i = 0; i < 400; i++) {
+ for (int j = 0; j < 400; j++) {
+ final Rect rect = Rect.fromLTWH(i * boxWidth, j * boxHeight, boxWidth, boxHeight);
+ if (_random.nextBool()) {
+ canvas.drawRect(rect, Paint()
+ ..style = PaintingStyle.fill
+ ..color = Colors.red
+ );
+ } else {
+ canvas.drawCircle(rect.center, 1, Paint()
+ ..style = PaintingStyle.fill
+ ..color = Colors.blue
+ );
+ }
+ }
+ }
+ }
+
+ @override
+ bool shouldRepaint(covariant CustomPainter oldDelegate) {
+ return false;
+ }
+}And run the app, selecting the first option.
Notice the timeline:
From casual observation, it seems odd to me that we use both a display list builder and skcanvas in https://github.com/flutter/engine/blob/main/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm#L597-L598 . Unsure if that is related.
