Unverified Commit 08fe78ff authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] write SkSL file to local file (#53859)

parent 98e7791e
......@@ -165,6 +165,12 @@ class CommandHelp {
'Toggle CanvasKit rendering.',
);
CommandHelpOption _M;
CommandHelpOption get M => _M ??= _makeOption(
'M',
'Write SkSL shaders to a unique file in the project directory.',
);
CommandHelpOption _makeOption(String key, String description, [
String inParenthesis = '',
]) {
......
......@@ -103,6 +103,9 @@ abstract class ResidentWebRunner extends ResidentRunner {
/// WebServer device is debuggable when running with --start-paused.
bool get deviceIsDebuggable => device.device is! WebServerDevice || debuggingOptions.startPaused;
@override
bool get supportsWriteSkSL => false;
bool get _enableDwds => debuggingEnabled;
ConnectionResult _connectionResult;
......
......@@ -20,6 +20,7 @@ import 'base/utils.dart';
import 'build_info.dart';
import 'codegen.dart';
import 'compile.dart';
import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'device.dart';
......@@ -673,6 +674,7 @@ abstract class ResidentRunner {
bool get isRunningRelease => debuggingOptions.buildInfo.isRelease;
bool get supportsServiceProtocol => isRunningDebug || isRunningProfile;
bool get supportsCanvasKit => false;
bool get supportsWriteSkSL => supportsServiceProtocol;
// Returns the Uri of the first connected device for mobile,
// and only connected device for web.
......@@ -740,6 +742,37 @@ abstract class ResidentRunner {
throw Exception('Canvaskit not supported by this runner.');
}
/// Write the SkSL shaders to a zip file in build directory.
Future<void> writeSkSL() async {
if (!supportsWriteSkSL) {
throw Exception('writeSkSL is not supported by this runner.');
}
final Map<String, Object> data = await flutterDevices.first.views.first.getSkSLs();
if (data.isEmpty) {
globals.logger.printStatus(
'No data was receieved. To ensure SkSL data can be generated use a '
'physical device then:\n'
' 1. Pass "--cache-sksl" as an argument to flutter run.\n'
' 2. Interact with the application to force shaders to be compiled.\n'
);
return;
}
final File outputFile = globals.fsUtils.getUniqueFile(
globals.fs.currentDirectory,
'flutter',
'sksl',
);
final Device device = flutterDevices.first.device;
final Map<String, Object> manifest = <String, Object>{
'platform': getNameForTargetPlatform(await flutterDevices.first.device.targetPlatform),
'name': device.name,
'engineRevision': globals.flutterVersion.engineRevision,
'data': data,
};
outputFile.writeAsStringSync(json.encode(manifest));
globals.logger.printStatus('Wrote SkSL data to ${outputFile.path}.');
}
/// The resident runner API for interaction with the reloadMethod vmservice
/// request.
///
......@@ -1094,6 +1127,9 @@ abstract class ResidentRunner {
if (supportsCanvasKit){
commandHelp.k.print();
}
if (supportsWriteSkSL) {
commandHelp.M.print();
}
commandHelp.v.print();
// `P` should precede `a`
commandHelp.P.print();
......@@ -1262,6 +1298,12 @@ class TerminalHandler {
return true;
}
return false;
case 'M':
if (residentRunner.supportsWriteSkSL) {
await residentRunner.writeSkSL();
return true;
}
return false;
case 'p':
if (residentRunner.supportsServiceProtocol && residentRunner.isRunningDebug) {
await residentRunner.debugToggleDebugPaintSizeEnabled();
......
......@@ -1530,6 +1530,16 @@ class FlutterView extends ServiceObject {
});
}
Future<Map<String, Object>> getSkSLs() async {
final Map<String, dynamic> response = await owner.vmService.vm.invokeRpcRaw(
'_flutter.getSkSLs',
params: <String, dynamic>{
'viewId': id,
},
);
return response['SkSLs'] as Map<String, Object>;
}
bool get hasIsolate => _uiIsolate != null;
Future<void> flushUIThreadTasks() async {
......
......@@ -14,6 +14,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' as io;
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
......@@ -387,6 +388,8 @@ void main() {
expect(residentRunner.isRunningDebug, true);
// does not support CanvasKit
expect(residentRunner.supportsCanvasKit, false);
// does support SkSL
expect(residentRunner.supportsWriteSkSL, true);
// commands
expect(testLogger.statusText, equals(
<dynamic>[
......@@ -406,6 +409,7 @@ void main() {
commandHelp.p,
commandHelp.o,
commandHelp.z,
commandHelp.M,
commandHelp.v,
commandHelp.P,
commandHelp.a,
......@@ -415,11 +419,42 @@ void main() {
));
}));
test('ResidentRunner does not support CanvasKit', () => testbed.run(() async {
test('ResidentRunner does support CanvasKit', () => testbed.run(() async {
expect(() => residentRunner.toggleCanvaskit(),
throwsA(isA<Exception>()));
}));
test('ResidentRunner handles writeSkSL returning no data', () => testbed.run(() async {
when(mockFlutterView.getSkSLs()).thenAnswer((Invocation invocation) async {
return <String, Object>{};
});
await residentRunner.writeSkSL();
expect(testLogger.statusText, contains('No data was receieved'));
}));
test('ResidentRunner can write SkSL data to a unique file with engine revision, platform, and device name', () => testbed.run(() async {
when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
return TargetPlatform.android_arm;
});
when(mockDevice.name).thenReturn('test device');
when(mockFlutterView.getSkSLs()).thenAnswer((Invocation invocation) async {
return <String, Object>{
'A': 'B',
};
});
await residentRunner.writeSkSL();
expect(testLogger.statusText, contains('flutter_01.sksl'));
expect(globals.fs.file('flutter_01.sksl'), exists);
expect(json.decode(globals.fs.file('flutter_01.sksl').readAsStringSync()), <String, Object>{
'platform': 'android-arm',
'name': 'test device',
'engineRevision': '42.2', // From FakeFlutterVersion
'data': <String, Object>{'A': 'B'}
});
}));
test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockDevice.takeScreenshot(any))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment