@@ -14,7 +14,6 @@ import '../svg.dart';
1414import '../util.dart' ;
1515import '../vector_math.dart' ;
1616import 'canvas.dart' ;
17- import 'layer.dart' ;
1817import 'overlay_scene_optimizer.dart' ;
1918import 'painting.dart' ;
2019import '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.
981907class 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