@@ -20,6 +20,7 @@ typedef RenderResult = ({
20
20
// composite pictures into the canvases in the DOM tree it builds.
21
21
abstract class PictureRenderer {
22
22
FutureOr <RenderResult > renderPictures (List <ScenePicture > picture);
23
+ ScenePicture clipPicture (ScenePicture picture, ui.Rect clip);
23
24
}
24
25
25
26
class _SceneRender {
@@ -43,15 +44,16 @@ class _SceneRender {
43
44
44
45
// This class builds a DOM tree that composites an `EngineScene`.
45
46
class EngineSceneView {
46
- factory EngineSceneView (PictureRenderer pictureRenderer) {
47
+ factory EngineSceneView (PictureRenderer pictureRenderer, ui. FlutterView flutterView ) {
47
48
final DomElement sceneElement = createDomElement ('flt-scene' );
48
- return EngineSceneView ._(pictureRenderer, sceneElement);
49
+ return EngineSceneView ._(pictureRenderer, flutterView, sceneElement);
49
50
}
50
51
51
- EngineSceneView ._(this .pictureRenderer, this .sceneElement);
52
+ EngineSceneView ._(this .pictureRenderer, this .flutterView, this . sceneElement);
52
53
53
54
final PictureRenderer pictureRenderer;
54
55
final DomElement sceneElement;
56
+ final ui.FlutterView flutterView;
55
57
56
58
List <SliceContainer > containers = < SliceContainer > [];
57
59
@@ -87,19 +89,37 @@ class EngineSceneView {
87
89
}
88
90
89
91
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
+ );
90
98
final List <LayerSlice > slices = scene.rootLayer.slices;
91
99
final List <ScenePicture > picturesToRender = < ScenePicture > [];
100
+ final List <ScenePicture > originalPicturesToRender = < ScenePicture > [];
92
101
for (final LayerSlice slice in slices) {
93
102
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
+ }
95
115
}
96
116
}
97
117
final Map <ScenePicture , DomImageBitmap > renderMap;
98
118
if (picturesToRender.isNotEmpty) {
99
119
final RenderResult renderResult = await pictureRenderer.renderPictures (picturesToRender);
100
120
renderMap = < ScenePicture , DomImageBitmap > {
101
121
for (int i = 0 ; i < picturesToRender.length; i++ )
102
- picturesToRender [i]: renderResult.imageBitmaps[i],
122
+ originalPicturesToRender [i]: renderResult.imageBitmaps[i],
103
123
};
104
124
recorder? .recordRasterStart (renderResult.rasterStartMicros);
105
125
recorder? .recordRasterFinish (renderResult.rasterEndMicros);
@@ -115,6 +135,11 @@ class EngineSceneView {
115
135
for (final LayerSlice slice in slices) {
116
136
switch (slice) {
117
137
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
+ }
118
143
PictureSliceContainer ? container;
119
144
for (int j = 0 ; j < reusableContainers.length; j++ ) {
120
145
final SliceContainer ? candidate = reusableContainers[j];
@@ -125,13 +150,14 @@ class EngineSceneView {
125
150
}
126
151
}
127
152
153
+ final ui.Rect clippedBounds = slice.picture.cullRect.intersect (screenBounds);
128
154
if (container != null ) {
129
- container.bounds = slice.picture.cullRect ;
155
+ container.bounds = clippedBounds ;
130
156
} else {
131
- container = PictureSliceContainer (slice.picture.cullRect );
157
+ container = PictureSliceContainer (clippedBounds );
132
158
}
133
159
container.updateContents ();
134
- container.renderBitmap (renderMap[slice.picture] ! );
160
+ container.renderBitmap (bitmap );
135
161
newContainers.add (container);
136
162
137
163
case PlatformViewSlice ():
0 commit comments