Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f3b11bc

Browse files
Revert "Reland "[canvaskit] Further improve overlay optimization by splitting pictures"" (#55501)
Reverts #55464 The PR caused a large regression in a web benchmark.
1 parent 7e5eded commit f3b11bc

File tree

10 files changed

+656
-1184
lines changed

10 files changed

+656
-1184
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43580,7 +43580,6 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.da
4358043580
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer.dart + ../../../flutter/LICENSE
4358143581
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart + ../../../flutter/LICENSE
4358243582
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart + ../../../flutter/LICENSE
43583-
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart + ../../../flutter/LICENSE
4358443583
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/mask_filter.dart + ../../../flutter/LICENSE
4358543584
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/multi_surface_rasterizer.dart + ../../../flutter/LICENSE
4358643585
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/n_way_canvas.dart + ../../../flutter/LICENSE
@@ -46452,7 +46451,6 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/image_web_codecs.dart
4645246451
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer.dart
4645346452
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_scene_builder.dart
4645446453
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart
46455-
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/layer_visitor.dart
4645646454
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/mask_filter.dart
4645746455
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/multi_surface_rasterizer.dart
4645846456
FILE: ../../../flutter/lib/web_ui/lib/src/engine/canvaskit/n_way_canvas.dart

lib/web_ui/lib/src/engine.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export 'engine/canvaskit/image_web_codecs.dart';
3333
export 'engine/canvaskit/layer.dart';
3434
export 'engine/canvaskit/layer_scene_builder.dart';
3535
export 'engine/canvaskit/layer_tree.dart';
36-
export 'engine/canvaskit/layer_visitor.dart';
3736
export 'engine/canvaskit/mask_filter.dart';
3837
export 'engine/canvaskit/multi_surface_rasterizer.dart';
3938
export 'engine/canvaskit/n_way_canvas.dart';

lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart

Lines changed: 58 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import '../svg.dart';
1414
import '../util.dart';
1515
import '../vector_math.dart';
1616
import 'canvas.dart';
17-
import 'layer.dart';
1817
import 'overlay_scene_optimizer.dart';
1918
import 'painting.dart';
2019
import 'path.dart';
@@ -67,9 +66,6 @@ class HtmlViewEmbedder {
6766
/// Returns the most recent rendering. Only used in tests.
6867
Rendering get debugActiveRendering => _activeRendering;
6968

70-
/// If [debugOverlayOptimizationBounds] is true, this canvas will draw
71-
/// semitransparent rectangles showing the computed bounds of the platform
72-
/// views and pictures in the scene.
7369
DisplayCanvas? debugBoundsCanvas;
7470

7571
/// The size of the frame, in physical pixels.
@@ -79,23 +75,27 @@ class HtmlViewEmbedder {
7975
_frameSize = size;
8076
}
8177

82-
/// Returns a list of recording canvases which the pictures in the upcoming
83-
/// paint step will be drawn into. These recording canvases are combined into
84-
/// an N-way canvas for the rasterizer to record clip and transform operations
85-
/// during the measure step.
86-
Iterable<CkCanvas> getPictureCanvases() {
87-
return _context.measuringPictureRecorders.values
88-
.map((CkPictureRecorder r) => r.recordingCanvas!);
89-
}
90-
91-
/// Returns a list of canvases for the optimized rendering. These are used in
92-
/// the paint step.
93-
Iterable<CkCanvas> getOptimizedCanvases() {
94-
return _context.optimizedCanvasRecorders!
78+
/// Returns a list of canvases which will be overlaid on top of the "base"
79+
/// canvas after a platform view is composited into the scene.
80+
///
81+
/// The engine asks for the overlay canvases immediately before the paint
82+
/// phase, after the preroll phase. In the preroll phase we must be
83+
/// conservative and assume that every platform view which is prerolled is
84+
/// also composited, and therefore requires an overlay canvas. However, not
85+
/// every platform view which is prerolled ends up being composited (it may be
86+
/// clipped out and not actually drawn). This means that we may end up
87+
/// overallocating canvases. This isn't a problem in practice, however, as
88+
/// unused recording canvases are simply deleted at the end of the frame.
89+
Iterable<CkCanvas> getOverlayCanvases() {
90+
return _context.pictureRecordersCreatedDuringPreroll
9591
.map((CkPictureRecorder r) => r.recordingCanvas!);
9692
}
9793

9894
void prerollCompositeEmbeddedView(int viewId, EmbeddedViewParams params) {
95+
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
96+
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize.toSize());
97+
_context.pictureRecordersCreatedDuringPreroll.add(pictureRecorder);
98+
9999
// Do nothing if the params didn't change.
100100
if (_currentCompositionParams[viewId] == params) {
101101
// If the view was prerolled but not composited, then it needs to be
@@ -109,38 +109,30 @@ class HtmlViewEmbedder {
109109
_viewsToRecomposite.add(viewId);
110110
}
111111

112-
/// Record that a picture recorder is needed for [picture] to be measured.
113-
void prerollPicture(PictureLayer picture) {
114-
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
115-
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize.toSize());
116-
_context.measuringPictureRecorders[picture] = pictureRecorder;
117-
}
118-
119-
/// Returns the canvas that was created to measure [picture].
120-
CkCanvas getMeasuringCanvasFor(PictureLayer picture) {
121-
return _context.measuringPictureRecorders[picture]!.recordingCanvas!;
122-
}
123-
124-
/// Adds the picture recorder associated with [picture] to the unoptimized
125-
/// scene.
126-
void addPictureToUnoptimizedScene(PictureLayer picture) {
127-
final CkPictureRecorder recorder =
128-
_context.measuringPictureRecorders[picture]!;
129-
_context.sceneElements.add(PictureSceneElement(picture, recorder));
130-
}
131-
132112
/// Prepares to composite [viewId].
133-
void compositeEmbeddedView(int viewId) {
113+
///
114+
/// If this returns a [CkCanvas], then that canvas should be the new leaf
115+
/// node. Otherwise, keep the same leaf node.
116+
CkCanvas? compositeEmbeddedView(int viewId) {
134117
// Ensure platform view with `viewId` is injected into the `rasterizer.view`.
135118
rasterizer.view.dom.injectPlatformView(viewId);
136119

120+
final int overlayIndex = _context.viewCount;
137121
_compositionOrder.add(viewId);
138-
_context.sceneElements.add(PlatformViewSceneElement(viewId));
122+
_context.viewCount++;
123+
124+
CkPictureRecorder? recorderToUseForRendering;
125+
if (overlayIndex < _context.pictureRecordersCreatedDuringPreroll.length) {
126+
recorderToUseForRendering =
127+
_context.pictureRecordersCreatedDuringPreroll[overlayIndex];
128+
_context.pictureRecorders.add(recorderToUseForRendering);
129+
}
139130

140131
if (_viewsToRecomposite.contains(viewId)) {
141132
_compositeWithParams(viewId, _currentCompositionParams[viewId]!);
142133
_viewsToRecomposite.remove(viewId);
143134
}
135+
return recorderToUseForRendering?.recordingCanvas;
144136
}
145137

146138
void _compositeWithParams(int platformViewId, EmbeddedViewParams params) {
@@ -363,57 +355,14 @@ class HtmlViewEmbedder {
363355
sceneHost.append(_svgPathDefs!);
364356
}
365357

366-
/// Optimizes the scene to use the fewest possible canvases. This sets up
367-
/// the final paint pass to paint the pictures into the optimized canvases.
368-
void optimizeRendering() {
369-
final Map<CkPicture, PictureLayer> scenePictureToRawPicture =
370-
<CkPicture, PictureLayer>{};
371-
final Iterable<SceneElement> unoptimizedRendering =
372-
_context.sceneElements.map<SceneElement>((SceneElement element) {
373-
if (element is PictureSceneElement) {
374-
final CkPicture scenePicture = element.pictureRecorder.endRecording();
375-
if (scenePicture.cullRect.isEmpty) {
376-
element.picture.isCulled = true;
377-
}
378-
element.scenePicture = scenePicture;
379-
scenePictureToRawPicture[scenePicture] = element.picture;
380-
return element;
381-
} else {
382-
return element;
383-
}
384-
});
358+
Future<void> submitFrame(CkPicture basePicture) async {
359+
final List<CkPicture> pictures = <CkPicture>[basePicture];
360+
for (final CkPictureRecorder recorder in _context.pictureRecorders) {
361+
pictures.add(recorder.endRecording());
362+
}
385363
Rendering rendering = createOptimizedRendering(
386-
unoptimizedRendering, _currentCompositionParams);
364+
pictures, _compositionOrder, _currentCompositionParams);
387365
rendering = _modifyRenderingForMaxCanvases(rendering);
388-
_context.optimizedRendering = rendering;
389-
// Create new picture recorders for the optimized render canvases and record
390-
// which pictures go in which canvas.
391-
final List<CkPictureRecorder> optimizedCanvasRecorders =
392-
<CkPictureRecorder>[];
393-
final Map<PictureLayer, CkPictureRecorder> pictureToOptimizedCanvasMap =
394-
<PictureLayer, CkPictureRecorder>{};
395-
for (final RenderingRenderCanvas renderCanvas in rendering.canvases) {
396-
final CkPictureRecorder pictureRecorder = CkPictureRecorder();
397-
pictureRecorder.beginRecording(ui.Offset.zero & _frameSize.toSize());
398-
optimizedCanvasRecorders.add(pictureRecorder);
399-
for (final CkPicture picture in renderCanvas.pictures) {
400-
pictureToOptimizedCanvasMap[scenePictureToRawPicture[picture]!] =
401-
pictureRecorder;
402-
}
403-
}
404-
_context.optimizedCanvasRecorders = optimizedCanvasRecorders;
405-
_context.pictureToOptimizedCanvasMap = pictureToOptimizedCanvasMap;
406-
}
407-
408-
/// Returns the canvas that this picture layer should draw into in the
409-
/// optimized scene.
410-
CkCanvas getOptimizedCanvasFor(PictureLayer picture) {
411-
assert(_context.optimizedRendering != null);
412-
return _context.pictureToOptimizedCanvasMap![picture]!.recordingCanvas!;
413-
}
414-
415-
Future<void> submitFrame() async {
416-
final Rendering rendering = _context.optimizedRendering!;
417366
_updateDomForNewRendering(rendering);
418367
if (rendering.equalsForRendering(_activeRendering)) {
419368
// Copy the display canvases to the new rendering.
@@ -426,17 +375,13 @@ class HtmlViewEmbedder {
426375
_activeRendering = rendering;
427376

428377
final List<RenderingRenderCanvas> renderCanvases = rendering.canvases;
429-
int renderCanvasIndex = 0;
430378
for (final RenderingRenderCanvas renderCanvas in renderCanvases) {
431-
final CkPicture renderPicture = _context
432-
.optimizedCanvasRecorders![renderCanvasIndex++]
433-
.endRecording();
434379
await rasterizer.rasterizeToCanvas(
435-
renderCanvas.displayCanvas!, <CkPicture>[renderPicture]);
380+
renderCanvas.displayCanvas!, renderCanvas.pictures);
436381
}
437382

438383
for (final CkPictureRecorder recorder
439-
in _context.measuringPictureRecorders.values) {
384+
in _context.pictureRecordersCreatedDuringPreroll) {
440385
if (recorder.isRecording) {
441386
recorder.endRecording();
442387
}
@@ -448,11 +393,11 @@ class HtmlViewEmbedder {
448393
debugBoundsCanvas ??= rasterizer.displayFactory.getCanvas();
449394
final CkPictureRecorder boundsRecorder = CkPictureRecorder();
450395
final CkCanvas boundsCanvas = boundsRecorder.beginRecording(
451-
ui.Rect.fromLTWH(
452-
0,
453-
0,
454-
_frameSize.width.toDouble(),
455-
_frameSize.height.toDouble(),
396+
ui.Rect.fromLTWH(
397+
0,
398+
0,
399+
_frameSize.width.toDouble(),
400+
_frameSize.height.toDouble(),
456401
),
457402
);
458403
final CkPaint platformViewBoundsPaint = CkPaint()
@@ -958,45 +903,20 @@ class MutatorsStack extends Iterable<Mutator> {
958903
Iterable<Mutator> get reversed => _mutators;
959904
}
960905

961-
sealed class SceneElement {}
962-
963-
class PictureSceneElement extends SceneElement {
964-
PictureSceneElement(this.picture, this.pictureRecorder);
965-
966-
final PictureLayer picture;
967-
final CkPictureRecorder pictureRecorder;
968-
969-
/// The picture as it would be painted in the final scene, with clips and
970-
/// transforms applied. This is set by [optimizeRendering].
971-
CkPicture? scenePicture;
972-
}
973-
974-
class PlatformViewSceneElement extends SceneElement {
975-
PlatformViewSceneElement(this.viewId);
976-
977-
final int viewId;
978-
}
979-
980906
/// The state for the current frame.
981907
class EmbedderFrameContext {
982-
/// Picture recorders which were created d the final bounds of the picture in the scene.
983-
final Map<PictureLayer, CkPictureRecorder> measuringPictureRecorders =
984-
<PictureLayer, CkPictureRecorder>{};
985-
986-
/// List of picture recorders and platform view ids in the order they were
987-
/// painted.
988-
final List<SceneElement> sceneElements = <SceneElement>[];
989-
990-
/// The optimized rendering for this frame. This is set by calling
991-
/// [optimizeRendering].
992-
Rendering? optimizedRendering;
993-
994-
/// The picture recorders for the optimized rendering. This is set by calling
995-
/// [optimizeRendering].
996-
List<CkPictureRecorder>? optimizedCanvasRecorders;
997-
998-
/// A map from the original PictureLayer to the picture recorder it should go
999-
/// into in the optimized rendering. This is set by calling
1000-
/// [optimizedRendering].
1001-
Map<PictureLayer, CkPictureRecorder>? pictureToOptimizedCanvasMap;
908+
/// Picture recorders which were created during the preroll phase.
909+
///
910+
/// These picture recorders will be "claimed" in the paint phase by platform
911+
/// views being composited into the scene.
912+
final List<CkPictureRecorder> pictureRecordersCreatedDuringPreroll =
913+
<CkPictureRecorder>[];
914+
915+
/// Picture recorders which were actually used in the paint phase.
916+
///
917+
/// This is a subset of [_pictureRecordersCreatedDuringPreroll].
918+
final List<CkPictureRecorder> pictureRecorders = <CkPictureRecorder>[];
919+
920+
/// The number of platform views in this frame.
921+
int viewCount = 0;
1002922
}

0 commit comments

Comments
 (0)