Framework support for checkerboardOffscreenLayers (#10054)

See https://github.com/flutter/flutter/issues/9473
This commit is contained in:
Jason Simmons 2017-05-12 14:41:07 -07:00 committed by GitHub
parent b4e0e541ec
commit 91b1a07656
8 changed files with 108 additions and 9 deletions

View file

@ -36,6 +36,7 @@ class GalleryApp extends StatefulWidget {
this.updateUrlFetcher, this.updateUrlFetcher,
this.enablePerformanceOverlay: true, this.enablePerformanceOverlay: true,
this.checkerboardRasterCacheImages: true, this.checkerboardRasterCacheImages: true,
this.checkerboardOffscreenLayers: true,
this.onSendFeedback, this.onSendFeedback,
Key key} Key key}
) : super(key: key); ) : super(key: key);
@ -46,6 +47,8 @@ class GalleryApp extends StatefulWidget {
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
final bool checkerboardOffscreenLayers;
final VoidCallback onSendFeedback; final VoidCallback onSendFeedback;
@override @override
@ -56,6 +59,7 @@ class GalleryAppState extends State<GalleryApp> {
bool _useLightTheme = true; bool _useLightTheme = true;
bool _showPerformanceOverlay = false; bool _showPerformanceOverlay = false;
bool _checkerboardRasterCacheImages = false; bool _checkerboardRasterCacheImages = false;
bool _checkerboardOffscreenLayers = false;
double _timeDilation = 1.0; double _timeDilation = 1.0;
TargetPlatform _platform; TargetPlatform _platform;
@ -95,6 +99,12 @@ class GalleryAppState extends State<GalleryApp> {
_checkerboardRasterCacheImages = value; _checkerboardRasterCacheImages = value;
}); });
} : null, } : null,
checkerboardOffscreenLayers: _checkerboardOffscreenLayers,
onCheckerboardOffscreenLayersChanged: widget.checkerboardOffscreenLayers ? (bool value) {
setState(() {
_checkerboardOffscreenLayers = value;
});
} : null,
onPlatformChanged: (TargetPlatform value) { onPlatformChanged: (TargetPlatform value) {
setState(() { setState(() {
_platform = value == defaultTargetPlatform ? null : value; _platform = value == defaultTargetPlatform ? null : value;
@ -134,6 +144,7 @@ class GalleryAppState extends State<GalleryApp> {
theme: (_useLightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme).copyWith(platform: _platform ?? defaultTargetPlatform), theme: (_useLightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme).copyWith(platform: _platform ?? defaultTargetPlatform),
showPerformanceOverlay: _showPerformanceOverlay, showPerformanceOverlay: _showPerformanceOverlay,
checkerboardRasterCacheImages: _checkerboardRasterCacheImages, checkerboardRasterCacheImages: _checkerboardRasterCacheImages,
checkerboardOffscreenLayers: _checkerboardOffscreenLayers,
routes: _kRoutes, routes: _kRoutes,
home: home, home: home,
); );

View file

@ -98,6 +98,8 @@ class GalleryDrawer extends StatelessWidget {
this.onShowPerformanceOverlayChanged, this.onShowPerformanceOverlayChanged,
this.checkerboardRasterCacheImages, this.checkerboardRasterCacheImages,
this.onCheckerboardRasterCacheImagesChanged, this.onCheckerboardRasterCacheImagesChanged,
this.checkerboardOffscreenLayers,
this.onCheckerboardOffscreenLayersChanged,
this.onPlatformChanged, this.onPlatformChanged,
this.onSendFeedback, this.onSendFeedback,
}) : super(key: key) { }) : super(key: key) {
@ -117,6 +119,9 @@ class GalleryDrawer extends StatelessWidget {
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged; final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged;
final bool checkerboardOffscreenLayers;
final ValueChanged<bool> onCheckerboardOffscreenLayersChanged;
final ValueChanged<TargetPlatform> onPlatformChanged; final ValueChanged<TargetPlatform> onPlatformChanged;
final VoidCallback onSendFeedback; final VoidCallback onSendFeedback;
@ -299,6 +304,23 @@ class GalleryDrawer extends StatelessWidget {
)); ));
} }
if (onCheckerboardOffscreenLayersChanged != null) {
allDrawerItems.insert(8, new ListTile(
leading: const Icon(Icons.assessment),
title: const Text('Checkerboard Offscreen Layers'),
trailing: new Checkbox(
value: checkerboardOffscreenLayers,
onChanged: (bool value) {
onCheckerboardOffscreenLayersChanged(!checkerboardOffscreenLayers);
},
),
selected: checkerboardOffscreenLayers,
onTap: () {
onCheckerboardOffscreenLayersChanged(!checkerboardOffscreenLayers);
},
));
}
return new Drawer(child: new ListView(primary: false, children: allDrawerItems)); return new Drawer(child: new ListView(primary: false, children: allDrawerItems));
} }
} }

View file

@ -76,6 +76,8 @@ class GalleryHome extends StatefulWidget {
this.onShowPerformanceOverlayChanged, this.onShowPerformanceOverlayChanged,
this.checkerboardRasterCacheImages, this.checkerboardRasterCacheImages,
this.onCheckerboardRasterCacheImagesChanged, this.onCheckerboardRasterCacheImagesChanged,
this.checkerboardOffscreenLayers,
this.onCheckerboardOffscreenLayersChanged,
this.onPlatformChanged, this.onPlatformChanged,
this.onSendFeedback, this.onSendFeedback,
}) : super(key: key) { }) : super(key: key) {
@ -95,6 +97,9 @@ class GalleryHome extends StatefulWidget {
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged; final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged;
final bool checkerboardOffscreenLayers;
final ValueChanged<bool> onCheckerboardOffscreenLayersChanged;
final ValueChanged<TargetPlatform> onPlatformChanged; final ValueChanged<TargetPlatform> onPlatformChanged;
final VoidCallback onSendFeedback; final VoidCallback onSendFeedback;
@ -161,6 +166,8 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState
onShowPerformanceOverlayChanged: widget.onShowPerformanceOverlayChanged, onShowPerformanceOverlayChanged: widget.onShowPerformanceOverlayChanged,
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages, checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
onCheckerboardRasterCacheImagesChanged: widget.onCheckerboardRasterCacheImagesChanged, onCheckerboardRasterCacheImagesChanged: widget.onCheckerboardRasterCacheImagesChanged,
checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
onCheckerboardOffscreenLayersChanged: widget.onCheckerboardOffscreenLayersChanged,
onPlatformChanged: widget.onPlatformChanged, onPlatformChanged: widget.onPlatformChanged,
onSendFeedback: widget.onSendFeedback, onSendFeedback: widget.onSendFeedback,
), ),

View file

@ -60,6 +60,7 @@ class MaterialApp extends StatefulWidget {
this.debugShowMaterialGrid: false, this.debugShowMaterialGrid: false,
this.showPerformanceOverlay: false, this.showPerformanceOverlay: false,
this.checkerboardRasterCacheImages: false, this.checkerboardRasterCacheImages: false,
this.checkerboardOffscreenLayers: false,
this.showSemanticsDebugger: false, this.showSemanticsDebugger: false,
this.debugShowCheckedModeBanner: true this.debugShowCheckedModeBanner: true
}) : super(key: key) { }) : super(key: key) {
@ -135,6 +136,9 @@ class MaterialApp extends StatefulWidget {
/// Turns on checkerboarding of raster cache images. /// Turns on checkerboarding of raster cache images.
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
/// Turns on checkerboarding of layers rendered to offscreen bitmaps.
final bool checkerboardOffscreenLayers;
/// Turns on an overlay that shows the accessibility information /// Turns on an overlay that shows the accessibility information
/// reported by the framework. /// reported by the framework.
final bool showSemanticsDebugger; final bool showSemanticsDebugger;
@ -240,6 +244,7 @@ class _MaterialAppState extends State<MaterialApp> {
onLocaleChanged: widget.onLocaleChanged, onLocaleChanged: widget.onLocaleChanged,
showPerformanceOverlay: widget.showPerformanceOverlay, showPerformanceOverlay: widget.showPerformanceOverlay,
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages, checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
showSemanticsDebugger: widget.showSemanticsDebugger, showSemanticsDebugger: widget.showSemanticsDebugger,
debugShowCheckedModeBanner: widget.debugShowCheckedModeBanner debugShowCheckedModeBanner: widget.debugShowCheckedModeBanner
) )

View file

@ -163,6 +163,7 @@ class PerformanceOverlayLayer extends Layer {
@required this.optionsMask, @required this.optionsMask,
@required this.rasterizerThreshold, @required this.rasterizerThreshold,
@required this.checkerboardRasterCacheImages, @required this.checkerboardRasterCacheImages,
@required this.checkerboardOffscreenLayers,
}); });
/// The rectangle in this layer's coordinate system that the overlay should occupy. /// The rectangle in this layer's coordinate system that the overlay should occupy.
@ -193,12 +194,23 @@ class PerformanceOverlayLayer extends Layer {
/// that aid it in making better decisions about caching. /// that aid it in making better decisions about caching.
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
/// Whether the compositor should checkerboard layers that are rendered to offscreen
/// bitmaps. This can be useful for debugging rendering performance.
///
/// Render target switches are caused by using opacity layers (via a [FadeTransition] or
/// [Opacity] widget), clips, shader mask layers, etc. Selecting a new render target
/// and merging it with the rest of the scene has a performance cost. This can sometimes
/// be avoided by using equivalent widgets that do not require these layers (for example,
/// replacing an [Opacity] widget with an [widgets.Image] using a [BlendMode]).
final bool checkerboardOffscreenLayers;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
assert(optionsMask != null); assert(optionsMask != null);
builder.addPerformanceOverlay(optionsMask, overlayRect.shift(layerOffset)); builder.addPerformanceOverlay(optionsMask, overlayRect.shift(layerOffset));
builder.setRasterizerTracingThreshold(rasterizerThreshold); builder.setRasterizerTracingThreshold(rasterizerThreshold);
builder.setCheckerboardRasterCacheImages(checkerboardRasterCacheImages); builder.setCheckerboardRasterCacheImages(checkerboardRasterCacheImages);
builder.setCheckerboardOffscreenLayers(checkerboardOffscreenLayers);
} }
} }

View file

@ -59,18 +59,21 @@ enum PerformanceOverlayOption {
class RenderPerformanceOverlay extends RenderBox { class RenderPerformanceOverlay extends RenderBox {
/// Creates a performance overlay render object. /// Creates a performance overlay render object.
/// ///
/// The [optionsMask], [rasterizerThreshold] and [checkerboardRasterCacheImages] /// The [optionsMask], [rasterizerThreshold], [checkerboardRasterCacheImages],
/// arguments must not be null. /// and [checkerboardOffscreenLayers] arguments must not be null.
RenderPerformanceOverlay({ RenderPerformanceOverlay({
int optionsMask: 0, int optionsMask: 0,
int rasterizerThreshold: 0, int rasterizerThreshold: 0,
bool checkerboardRasterCacheImages: false, bool checkerboardRasterCacheImages: false,
bool checkerboardOffscreenLayers: false,
}) : _optionsMask = optionsMask, }) : _optionsMask = optionsMask,
_rasterizerThreshold = rasterizerThreshold, _rasterizerThreshold = rasterizerThreshold,
_checkerboardRasterCacheImages = checkerboardRasterCacheImages { _checkerboardRasterCacheImages = checkerboardRasterCacheImages,
_checkerboardOffscreenLayers = checkerboardOffscreenLayers {
assert(optionsMask != null); assert(optionsMask != null);
assert(rasterizerThreshold != null); assert(rasterizerThreshold != null);
assert(checkerboardRasterCacheImages != null); assert(checkerboardRasterCacheImages != null);
assert(checkerboardOffscreenLayers != null);
} }
/// The mask is created by shifting 1 by the index of the specific /// The mask is created by shifting 1 by the index of the specific
@ -109,6 +112,17 @@ class RenderPerformanceOverlay extends RenderBox {
markNeedsPaint(); markNeedsPaint();
} }
/// Whether the compositor should checkerboard layers rendered to offscreen bitmaps.
bool get checkerboardOffscreenLayers => _checkerboardOffscreenLayers;
bool _checkerboardOffscreenLayers;
set checkerboardOffscreenLayers(bool value) {
assert(value != null);
if (value == _checkerboardOffscreenLayers)
return;
_checkerboardOffscreenLayers = value;
markNeedsPaint();
}
@override @override
bool get sizedByParent => true; bool get sizedByParent => true;
@ -160,6 +174,7 @@ class RenderPerformanceOverlay extends RenderBox {
optionsMask: optionsMask, optionsMask: optionsMask,
rasterizerThreshold: rasterizerThreshold, rasterizerThreshold: rasterizerThreshold,
checkerboardRasterCacheImages: checkerboardRasterCacheImages, checkerboardRasterCacheImages: checkerboardRasterCacheImages,
checkerboardOffscreenLayers: checkerboardOffscreenLayers,
)); ));
} }
} }

View file

@ -49,12 +49,14 @@ class WidgetsApp extends StatefulWidget {
this.onLocaleChanged, this.onLocaleChanged,
this.showPerformanceOverlay: false, this.showPerformanceOverlay: false,
this.checkerboardRasterCacheImages: false, this.checkerboardRasterCacheImages: false,
this.checkerboardOffscreenLayers: false,
this.showSemanticsDebugger: false, this.showSemanticsDebugger: false,
this.debugShowCheckedModeBanner: true this.debugShowCheckedModeBanner: true
}) : assert(color != null), }) : assert(color != null),
assert(onGenerateRoute != null), assert(onGenerateRoute != null),
assert(showPerformanceOverlay != null), assert(showPerformanceOverlay != null),
assert(checkerboardRasterCacheImages != null), assert(checkerboardRasterCacheImages != null),
assert(checkerboardOffscreenLayers != null),
assert(showSemanticsDebugger != null), assert(showSemanticsDebugger != null),
super(key: key); super(key: key);
@ -89,8 +91,15 @@ class WidgetsApp extends StatefulWidget {
final bool showPerformanceOverlay; final bool showPerformanceOverlay;
/// Checkerboards raster cache images. /// Checkerboards raster cache images.
///
/// See [PerformanceOverlay.checkerboardRasterCacheImages].
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
/// Checkerboards layers rendered to offscreen bitmaps.
///
/// See [PerformanceOverlay.checkerboardOffscreenLayers].
final bool checkerboardOffscreenLayers;
/// Turns on an overlay that shows the accessibility information /// Turns on an overlay that shows the accessibility information
/// reported by the framework. /// reported by the framework.
final bool showSemanticsDebugger; final bool showSemanticsDebugger;
@ -220,9 +229,14 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
// options are set. // options are set.
if (widget.showPerformanceOverlay || WidgetsApp.showPerformanceOverlayOverride) { if (widget.showPerformanceOverlay || WidgetsApp.showPerformanceOverlayOverride) {
performanceOverlay = new PerformanceOverlay.allEnabled( performanceOverlay = new PerformanceOverlay.allEnabled(
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages); checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
} else if (widget.checkerboardRasterCacheImages) { checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
performanceOverlay = const PerformanceOverlay(checkerboardRasterCacheImages: true); );
} else if (widget.checkerboardRasterCacheImages || widget.checkerboardOffscreenLayers) {
performanceOverlay = new PerformanceOverlay(
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
);
} }
if (performanceOverlay != null) { if (performanceOverlay != null) {

View file

@ -31,13 +31,15 @@ class PerformanceOverlay extends LeafRenderObjectWidget {
Key key, Key key,
this.optionsMask: 0, this.optionsMask: 0,
this.rasterizerThreshold: 0, this.rasterizerThreshold: 0,
this.checkerboardRasterCacheImages: false this.checkerboardRasterCacheImages: false,
this.checkerboardOffscreenLayers: false,
}) : super(key: key); }) : super(key: key);
/// Create a performance overlay that displays all available statistics /// Create a performance overlay that displays all available statistics
PerformanceOverlay.allEnabled({ Key key, PerformanceOverlay.allEnabled({ Key key,
this.rasterizerThreshold: 0, this.rasterizerThreshold: 0,
this.checkerboardRasterCacheImages: false }) this.checkerboardRasterCacheImages: false,
this.checkerboardOffscreenLayers: false })
: optionsMask = ( : optionsMask = (
1 << PerformanceOverlayOption.displayRasterizerStatistics.index | 1 << PerformanceOverlayOption.displayRasterizerStatistics.index |
1 << PerformanceOverlayOption.visualizeRasterizerStatistics.index | 1 << PerformanceOverlayOption.visualizeRasterizerStatistics.index |
@ -91,11 +93,22 @@ class PerformanceOverlay extends LeafRenderObjectWidget {
/// that aid it in making better decisions about caching. /// that aid it in making better decisions about caching.
final bool checkerboardRasterCacheImages; final bool checkerboardRasterCacheImages;
/// Whether the compositor should checkerboard layers that are rendered to offscreen
/// bitmaps. This can be useful for debugging rendering performance.
///
/// Render target switches are caused by using opacity layers (via a [FadeTransition] or
/// [Opacity] widget), clips, shader mask layers, etc. Selecting a new render target
/// and merging it with the rest of the scene has a performance cost. This can sometimes
/// be avoided by using equivalent widgets that do not require these layers (for example,
/// replacing an [Opacity] widget with an [widgets.Image] using a [BlendMode]).
final bool checkerboardOffscreenLayers;
@override @override
RenderPerformanceOverlay createRenderObject(BuildContext context) => new RenderPerformanceOverlay( RenderPerformanceOverlay createRenderObject(BuildContext context) => new RenderPerformanceOverlay(
optionsMask: optionsMask, optionsMask: optionsMask,
rasterizerThreshold: rasterizerThreshold, rasterizerThreshold: rasterizerThreshold,
checkerboardRasterCacheImages: checkerboardRasterCacheImages checkerboardRasterCacheImages: checkerboardRasterCacheImages,
checkerboardOffscreenLayers: checkerboardOffscreenLayers,
); );
@override @override