@@ -20,6 +20,7 @@ typedef RenderResult = ({
2020// composite pictures into the canvases in the DOM tree it builds.
2121abstract class PictureRenderer {
2222 FutureOr <RenderResult > renderPictures (List <ScenePicture > picture);
23+ ScenePicture clipPicture (ScenePicture picture, ui.Rect clip);
2324}
2425
2526class _SceneRender {
@@ -43,15 +44,16 @@ class _SceneRender {
4344
4445// This class builds a DOM tree that composites an `EngineScene`.
4546class EngineSceneView {
46- factory EngineSceneView (PictureRenderer pictureRenderer) {
47+ factory EngineSceneView (PictureRenderer pictureRenderer, ui. FlutterView flutterView ) {
4748 final DomElement sceneElement = createDomElement ('flt-scene' );
48- return EngineSceneView ._(pictureRenderer, sceneElement);
49+ return EngineSceneView ._(pictureRenderer, flutterView, sceneElement);
4950 }
5051
51- EngineSceneView ._(this .pictureRenderer, this .sceneElement);
52+ EngineSceneView ._(this .pictureRenderer, this .flutterView, this . sceneElement);
5253
5354 final PictureRenderer pictureRenderer;
5455 final DomElement sceneElement;
56+ final ui.FlutterView flutterView;
5557
5658 List <SliceContainer > containers = < SliceContainer > [];
5759
@@ -87,19 +89,37 @@ class EngineSceneView {
8789 }
8890
8991 Future <void > _renderScene (EngineScene scene, FrameTimingRecorder ? recorder) async {
92+ final ui.Rect screenBounds = ui.Rect .fromLTWH (
93+ 0 ,
94+ 0 ,
95+ flutterView.physicalSize.width,
96+ flutterView.physicalSize.height,
97+ );
9098 final List <LayerSlice > slices = scene.rootLayer.slices;
9199 final List <ScenePicture > picturesToRender = < ScenePicture > [];
100+ final List <ScenePicture > originalPicturesToRender = < ScenePicture > [];
92101 for (final LayerSlice slice in slices) {
93102 if (slice is PictureSlice ) {
94- picturesToRender.add (slice.picture);
103+ final ui.Rect clippedRect = slice.picture.cullRect.intersect (screenBounds);
104+ if (clippedRect.isEmpty) {
105+ // This picture is completely offscreen, so don't render it at all
106+ continue ;
107+ } else if (clippedRect == slice.picture.cullRect) {
108+ // The picture doesn't need to be clipped, just render the original
109+ originalPicturesToRender.add (slice.picture);
110+ picturesToRender.add (slice.picture);
111+ } else {
112+ originalPicturesToRender.add (slice.picture);
113+ picturesToRender.add (pictureRenderer.clipPicture (slice.picture, clippedRect));
114+ }
95115 }
96116 }
97117 final Map <ScenePicture , DomImageBitmap > renderMap;
98118 if (picturesToRender.isNotEmpty) {
99119 final RenderResult renderResult = await pictureRenderer.renderPictures (picturesToRender);
100120 renderMap = < ScenePicture , DomImageBitmap > {
101121 for (int i = 0 ; i < picturesToRender.length; i++ )
102- picturesToRender [i]: renderResult.imageBitmaps[i],
122+ originalPicturesToRender [i]: renderResult.imageBitmaps[i],
103123 };
104124 recorder? .recordRasterStart (renderResult.rasterStartMicros);
105125 recorder? .recordRasterFinish (renderResult.rasterEndMicros);
@@ -115,6 +135,11 @@ class EngineSceneView {
115135 for (final LayerSlice slice in slices) {
116136 switch (slice) {
117137 case PictureSlice ():
138+ final DomImageBitmap ? bitmap = renderMap[slice.picture];
139+ if (bitmap == null ) {
140+ // We didn't render this slice because no part of it is visible.
141+ continue ;
142+ }
118143 PictureSliceContainer ? container;
119144 for (int j = 0 ; j < reusableContainers.length; j++ ) {
120145 final SliceContainer ? candidate = reusableContainers[j];
@@ -125,13 +150,14 @@ class EngineSceneView {
125150 }
126151 }
127152
153+ final ui.Rect clippedBounds = slice.picture.cullRect.intersect (screenBounds);
128154 if (container != null ) {
129- container.bounds = slice.picture.cullRect ;
155+ container.bounds = clippedBounds ;
130156 } else {
131- container = PictureSliceContainer (slice.picture.cullRect );
157+ container = PictureSliceContainer (clippedBounds );
132158 }
133159 container.updateContents ();
134- container.renderBitmap (renderMap[slice.picture] ! );
160+ container.renderBitmap (bitmap );
135161 newContainers.add (container);
136162
137163 case PlatformViewSlice ():
0 commit comments