@@ -14,7 +14,6 @@ import '../svg.dart';
14
14
import '../util.dart' ;
15
15
import '../vector_math.dart' ;
16
16
import 'canvas.dart' ;
17
- import 'layer.dart' ;
18
17
import 'overlay_scene_optimizer.dart' ;
19
18
import 'painting.dart' ;
20
19
import 'path.dart' ;
@@ -67,9 +66,6 @@ class HtmlViewEmbedder {
67
66
/// Returns the most recent rendering. Only used in tests.
68
67
Rendering get debugActiveRendering => _activeRendering;
69
68
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.
73
69
DisplayCanvas ? debugBoundsCanvas;
74
70
75
71
/// The size of the frame, in physical pixels.
@@ -79,23 +75,27 @@ class HtmlViewEmbedder {
79
75
_frameSize = size;
80
76
}
81
77
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
95
91
.map ((CkPictureRecorder r) => r.recordingCanvas! );
96
92
}
97
93
98
94
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
+
99
99
// Do nothing if the params didn't change.
100
100
if (_currentCompositionParams[viewId] == params) {
101
101
// If the view was prerolled but not composited, then it needs to be
@@ -109,38 +109,30 @@ class HtmlViewEmbedder {
109
109
_viewsToRecomposite.add (viewId);
110
110
}
111
111
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
-
132
112
/// 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) {
134
117
// Ensure platform view with `viewId` is injected into the `rasterizer.view`.
135
118
rasterizer.view.dom.injectPlatformView (viewId);
136
119
120
+ final int overlayIndex = _context.viewCount;
137
121
_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
+ }
139
130
140
131
if (_viewsToRecomposite.contains (viewId)) {
141
132
_compositeWithParams (viewId, _currentCompositionParams[viewId]! );
142
133
_viewsToRecomposite.remove (viewId);
143
134
}
135
+ return recorderToUseForRendering? .recordingCanvas;
144
136
}
145
137
146
138
void _compositeWithParams (int platformViewId, EmbeddedViewParams params) {
@@ -363,57 +355,14 @@ class HtmlViewEmbedder {
363
355
sceneHost.append (_svgPathDefs! );
364
356
}
365
357
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
+ }
385
363
Rendering rendering = createOptimizedRendering (
386
- unoptimizedRendering , _currentCompositionParams);
364
+ pictures, _compositionOrder , _currentCompositionParams);
387
365
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! ;
417
366
_updateDomForNewRendering (rendering);
418
367
if (rendering.equalsForRendering (_activeRendering)) {
419
368
// Copy the display canvases to the new rendering.
@@ -426,17 +375,13 @@ class HtmlViewEmbedder {
426
375
_activeRendering = rendering;
427
376
428
377
final List <RenderingRenderCanvas > renderCanvases = rendering.canvases;
429
- int renderCanvasIndex = 0 ;
430
378
for (final RenderingRenderCanvas renderCanvas in renderCanvases) {
431
- final CkPicture renderPicture = _context
432
- .optimizedCanvasRecorders! [renderCanvasIndex++ ]
433
- .endRecording ();
434
379
await rasterizer.rasterizeToCanvas (
435
- renderCanvas.displayCanvas! , < CkPicture > [renderPicture] );
380
+ renderCanvas.displayCanvas! , renderCanvas.pictures );
436
381
}
437
382
438
383
for (final CkPictureRecorder recorder
439
- in _context.measuringPictureRecorders.values ) {
384
+ in _context.pictureRecordersCreatedDuringPreroll ) {
440
385
if (recorder.isRecording) {
441
386
recorder.endRecording ();
442
387
}
@@ -448,11 +393,11 @@ class HtmlViewEmbedder {
448
393
debugBoundsCanvas ?? = rasterizer.displayFactory.getCanvas ();
449
394
final CkPictureRecorder boundsRecorder = CkPictureRecorder ();
450
395
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 (),
456
401
),
457
402
);
458
403
final CkPaint platformViewBoundsPaint = CkPaint ()
@@ -958,45 +903,20 @@ class MutatorsStack extends Iterable<Mutator> {
958
903
Iterable <Mutator > get reversed => _mutators;
959
904
}
960
905
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
-
980
906
/// The state for the current frame.
981
907
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 ;
1002
922
}
0 commit comments