mirror of
https://github.com/Cateners/tiny_computer.git
synced 2026-05-20 16:35:47 +08:00
virgl support
This commit is contained in:
Binary file not shown.
@@ -103,7 +103,7 @@ class SettingPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _SettingPageState extends State<SettingPage> {
|
class _SettingPageState extends State<SettingPage> {
|
||||||
|
|
||||||
final List<bool> _expandState = [false, false, false, false, false];
|
final List<bool> _expandState = [false, false, false, false, false, false];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -306,7 +306,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
switch (value) {
|
switch (value) {
|
||||||
case true: {
|
case true: {
|
||||||
G.streamServerPty = Pty.start("/system/bin/sh");
|
G.streamServerPty = Pty.start("/system/bin/sh");
|
||||||
G.streamServerPty.write(const Utf8Encoder().convert("${G.dataPath}/bin/mediamtx ${G.dataPath}/bin/mediamtx.yml & pid=\$(echo \$!)\n"));
|
G.streamServerPty.write(const Utf8Encoder().convert("${G.dataPath}/bin/mediamtx ${G.dataPath}/bin/mediamtx.yml\nexit\n"));
|
||||||
G.streamServerPty.exitCode.then((value) {
|
G.streamServerPty.exitCode.then((value) {
|
||||||
G.isStreamServerStarted = false;
|
G.isStreamServerStarted = false;
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@@ -314,7 +314,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case false: {
|
case false: {
|
||||||
G.streamServerPty.write(const Utf8Encoder().convert("kill \$pid\nexit\n"));
|
G.streamServerPty.write(const Utf8Encoder().convert("${String.fromCharCode(3)}exit\n"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -363,6 +363,63 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
],))),
|
],))),
|
||||||
ExpansionPanel(
|
ExpansionPanel(
|
||||||
isExpanded: _expandState[4],
|
isExpanded: _expandState[4],
|
||||||
|
headerBuilder: ((context, isExpanded) {
|
||||||
|
return const ListTile(title: Text("virgl加速"), subtitle: Text("实验性功能"));
|
||||||
|
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
|
||||||
|
const Text("""virgl加速可部分利用设备GPU提升系统图形处理表现,但由于设备差异也可能导致容器系统及软件运行不稳定甚至异常退出。
|
||||||
|
|
||||||
|
请先开启测试按钮启动virgl服务器,如果按钮没有自动关闭说明至少启动没问题;
|
||||||
|
|
||||||
|
不过运行情况依然无法保证。
|
||||||
|
"""),
|
||||||
|
SizedBox.fromSize(size: const Size.square(16)),
|
||||||
|
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglCommand") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "virgl服务器参数"),
|
||||||
|
onChanged: (value) async {
|
||||||
|
await G.prefs.setString("defaultVirglCommand", value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox.fromSize(size: const Size.square(8)),
|
||||||
|
SwitchListTile(title: const Text("测试"), subtitle: const Text("启动virgl_test_server"), value: G.isVirglServerStarted, onChanged:(value) {
|
||||||
|
switch (value) {
|
||||||
|
case true: {
|
||||||
|
G.virglServerPty = Pty.start("/system/bin/sh");
|
||||||
|
G.virglServerPty.write(const Utf8Encoder().convert("export CONTAINER_DIR=${G.dataPath}/containers/0\n${G.dataPath}/bin/virgl_test_server ${Util.getGlobal("defaultVirglCommand")}\nexit\n"));
|
||||||
|
G.virglServerPty.exitCode.then((value) {
|
||||||
|
G.isVirglServerStarted = false;
|
||||||
|
setState(() {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case false: {
|
||||||
|
G.virglServerPty.write(const Utf8Encoder().convert("${String.fromCharCode(3)}exit\n"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
G.isVirglServerStarted = value;
|
||||||
|
setState(() {});
|
||||||
|
},),
|
||||||
|
SizedBox.fromSize(size: const Size.square(16)),
|
||||||
|
TextFormField(maxLines: null, initialValue: Util.getGlobal("defaultVirglOpt") as String, decoration: const InputDecoration(border: OutlineInputBorder(), labelText: "图形环境变量"),
|
||||||
|
onChanged: (value) async {
|
||||||
|
await G.prefs.setString("defaultVirglOpt", value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox.fromSize(size: const Size.square(8)),
|
||||||
|
SwitchListTile(title: const Text("启用virgl加速"), subtitle: const Text("下次启动时生效"), value: Util.getGlobal("virgl") as bool, onChanged:(value) {
|
||||||
|
if (value && Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) {
|
||||||
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text("观看十次视频广告永久解锁><"))
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
G.prefs.setBool("virgl", value);
|
||||||
|
setState(() {});
|
||||||
|
},),
|
||||||
|
SizedBox.fromSize(size: const Size.square(16)),
|
||||||
|
],))),
|
||||||
|
ExpansionPanel(
|
||||||
|
isExpanded: _expandState[5],
|
||||||
headerBuilder: ((context, isExpanded) {
|
headerBuilder: ((context, isExpanded) {
|
||||||
return const ListTile(title: Text("广告记录"), subtitle: Text("在这里看广告"));
|
return const ListTile(title: Text("广告记录"), subtitle: Text("在这里看广告"));
|
||||||
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
|
}), body: Padding(padding: const EdgeInsets.all(12), child: Column(children: [
|
||||||
@@ -375,9 +432,7 @@ class _SettingPageState extends State<SettingPage> {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text("你获得了 ${bonus["name"]}*${bonus["amount"]}"))
|
SnackBar(content: Text("你获得了 ${bonus["name"]}*${bonus["amount"]}"))
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {});
|
||||||
|
|
||||||
});
|
|
||||||
}, () {
|
}, () {
|
||||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@@ -466,6 +521,11 @@ class _InfoPageState extends State<InfoPage> {
|
|||||||
但是软件没有权限
|
但是软件没有权限
|
||||||
不能帮你修复
|
不能帮你修复
|
||||||
|
|
||||||
|
如果你的系统版本大于等于android 13
|
||||||
|
那么很可能一些网页应用如jupyter notebook
|
||||||
|
bilibili客户端等等不可用
|
||||||
|
可以去全局设置开启getifaddrs桥接
|
||||||
|
|
||||||
如果你给了存储权限
|
如果你给了存储权限
|
||||||
那么通过主目录下的文件夹
|
那么通过主目录下的文件夹
|
||||||
就可以访问手机存储
|
就可以访问手机存储
|
||||||
@@ -989,6 +1049,7 @@ SOFTWARE.
|
|||||||
关闭横幅广告: 观看5个广告
|
关闭横幅广告: 观看5个广告
|
||||||
终端最大行数修改: 观看6个广告
|
终端最大行数修改: 观看6个广告
|
||||||
推流参数修改: 观看8个广告
|
推流参数修改: 观看8个广告
|
||||||
|
启用virgl加速: 观看10个广告
|
||||||
|
|
||||||
我设置了每天最多可以看5个广告。
|
我设置了每天最多可以看5个广告。
|
||||||
只要看满1个广告, 就可以在本次使用期间临时解锁全部功能。
|
只要看满1个广告, 就可以在本次使用期间临时解锁全部功能。
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ class Util {
|
|||||||
Directory.fromRawPath(const Utf8Encoder().convert(dir)).createSync(recursive: true);
|
Directory.fromRawPath(const Utf8Encoder().convert(dir)).createSync(recursive: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> execute(String str) async {
|
static Future<int> execute(String str) async {
|
||||||
Pty pty = Pty.start(
|
Pty pty = Pty.start(
|
||||||
"/system/bin/sh"
|
"/system/bin/sh"
|
||||||
);
|
);
|
||||||
pty.write(const Utf8Encoder().convert("$str\nexit\n"));
|
pty.write(const Utf8Encoder().convert("$str\nexit \$!\n"));
|
||||||
await pty.exitCode;
|
return await pty.exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void termWrite(String str) {
|
static void termWrite(String str) {
|
||||||
@@ -85,7 +85,11 @@ class Util {
|
|||||||
//int vip = 0 用户等级,vip免广告,你要改吗?(ToT)
|
//int vip = 0 用户等级,vip免广告,你要改吗?(ToT)
|
||||||
//bool isStickyKey = true 终端ctrl, shift, alt键是否粘滞
|
//bool isStickyKey = true 终端ctrl, shift, alt键是否粘滞
|
||||||
//String defaultFFmpegCommand 默认推流命令
|
//String defaultFFmpegCommand 默认推流命令
|
||||||
|
//String defaultVirglCommand 默认virgl参数
|
||||||
|
//String defaultVirglOpt 默认virgl环境变量
|
||||||
//bool reinstallBootstrap = false 下次启动是否重装引导包
|
//bool reinstallBootstrap = false 下次启动是否重装引导包
|
||||||
|
//bool getifaddrsBridge = false 下次启动是否桥接getifaddrsBridge
|
||||||
|
//bool virgl = false 下次启动是否启用virgl
|
||||||
//? int bootstrapVersion: 启动包版本
|
//? int bootstrapVersion: 启动包版本
|
||||||
//String[] containersInfo: 所有容器信息(json)
|
//String[] containersInfo: 所有容器信息(json)
|
||||||
//{name, boot:"\$DATA_DIR/bin/proot ...", vnc:"startnovnc", vncUrl:"...", commands:[{name:"更新和升级", command:"apt update -y && apt upgrade -y"},
|
//{name, boot:"\$DATA_DIR/bin/proot ...", vnc:"startnovnc", vncUrl:"...", commands:[{name:"更新和升级", command:"apt update -y && apt upgrade -y"},
|
||||||
@@ -111,7 +115,10 @@ class Util {
|
|||||||
case "isStickyKey" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true);
|
case "isStickyKey" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(true);
|
||||||
case "reinstallBootstrap" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
|
case "reinstallBootstrap" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
|
||||||
case "getifaddrsBridge" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
|
case "getifaddrsBridge" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
|
||||||
|
case "virgl" : return b ? G.prefs.getBool(key)! : (value){G.prefs.setBool(key, value); return value;}(false);
|
||||||
case "defaultFFmpegCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("-hide_banner -an -max_delay 1000000 -r 30 -f android_camera -camera_index 0 -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream");
|
case "defaultFFmpegCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("-hide_banner -an -max_delay 1000000 -r 30 -f android_camera -camera_index 0 -i 0:0 -vf scale=iw/2:-1 -rtsp_transport udp -f rtsp rtsp://127.0.0.1:8554/stream");
|
||||||
|
case "defaultVirglCommand" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("--socket-path=\$CONTAINER_DIR/tmp/.virgl_test");
|
||||||
|
case "defaultVirglOpt" : return b ? G.prefs.getString(key)! : (value){G.prefs.setString(key, value); return value;}("GALLIUM_DRIVER=virpipe MESA_GL_VERSION_OVERRIDE=4.0");
|
||||||
case "containersInfo" : return G.prefs.getStringList(key)!;
|
case "containersInfo" : return G.prefs.getStringList(key)!;
|
||||||
case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast<String>());
|
case "adsBonus" : return b ? G.prefs.getStringList(key)! : (value){G.prefs.setStringList(key, value); return value;}([].cast<String>());
|
||||||
}
|
}
|
||||||
@@ -403,6 +410,7 @@ class D {
|
|||||||
"enableTerminalCommands" : 3,
|
"enableTerminalCommands" : 3,
|
||||||
"changeTermMaxLines" : 6,
|
"changeTermMaxLines" : 6,
|
||||||
"changeFFmpegCommand" : 8,
|
"changeFFmpegCommand" : 8,
|
||||||
|
"enableVirgl" : 10,
|
||||||
|
|
||||||
"unlockOnce" : 1, //临时解锁需要看的广告数
|
"unlockOnce" : 1, //临时解锁需要看的广告数
|
||||||
"unlockToday" : 2, //当日解锁需要看的广告数
|
"unlockToday" : 2, //当日解锁需要看的广告数
|
||||||
@@ -443,9 +451,12 @@ class G {
|
|||||||
static int adsWatchedThisTime = 0; //本次启动应用看的广告数
|
static int adsWatchedThisTime = 0; //本次启动应用看的广告数
|
||||||
static bool isStreamServerStarted = false;
|
static bool isStreamServerStarted = false;
|
||||||
static bool isStreaming = false;
|
static bool isStreaming = false;
|
||||||
static int? streamingId;
|
//static int? streamingPid;
|
||||||
static String streamingOutput = "";
|
static String streamingOutput = "";
|
||||||
static late Pty streamServerPty;
|
static late Pty streamServerPty;
|
||||||
|
static bool isVirglServerStarted = false;
|
||||||
|
static late Pty virglServerPty;
|
||||||
|
//static int? virglPid;
|
||||||
static ValueNotifier<int> pageIndex = ValueNotifier(0); //主界面索引
|
static ValueNotifier<int> pageIndex = ValueNotifier(0); //主界面索引
|
||||||
static ValueNotifier<bool> terminalPageChange = ValueNotifier(true); //更改值,用于刷新小键盘
|
static ValueNotifier<bool> terminalPageChange = ValueNotifier(true); //更改值,用于刷新小键盘
|
||||||
static ValueNotifier<bool> bannerAdsChange = ValueNotifier(true); //更改值,用于刷新banner广告
|
static ValueNotifier<bool> bannerAdsChange = ValueNotifier(true); //更改值,用于刷新banner广告
|
||||||
@@ -686,6 +697,9 @@ done
|
|||||||
if (Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) {
|
if (Util.shouldWatchAds(D.adsRequired["enableTerminalCommands"]!)) {
|
||||||
await G.prefs.setBool("isTerminalCommandsEnabled", false);
|
await G.prefs.setBool("isTerminalCommandsEnabled", false);
|
||||||
}
|
}
|
||||||
|
if (Util.shouldWatchAds(D.adsRequired["enableVirgl"]!)) {
|
||||||
|
await G.prefs.setBool("virgl", false);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +743,13 @@ exit
|
|||||||
Util.execute("${G.dataPath}/bin/getifaddrs_bridge_server ${G.dataPath}/containers/${G.currentContainer}/tmp/.getifaddrs-bridge");
|
Util.execute("${G.dataPath}/bin/getifaddrs_bridge_server ${G.dataPath}/containers/${G.currentContainer}/tmp/.getifaddrs-bridge");
|
||||||
extraOpt += "LD_PRELOAD=/home/tiny/.local/share/tiny/extra/getifaddrs_bridge_client_lib.so ";
|
extraOpt += "LD_PRELOAD=/home/tiny/.local/share/tiny/extra/getifaddrs_bridge_client_lib.so ";
|
||||||
}
|
}
|
||||||
|
if (Util.getGlobal("virgl")) {
|
||||||
|
Util.execute("""
|
||||||
|
export DATA_DIR=${G.dataPath}
|
||||||
|
export CONTAINER_DIR=\$DATA_DIR/containers/${G.currentContainer}
|
||||||
|
${G.dataPath}/bin/virgl_test_server ${Util.getGlobal("defaultVirglCommand")}""");
|
||||||
|
extraOpt += "${Util.getGlobal("defaultVirglOpt")} ";
|
||||||
|
}
|
||||||
Util.termWrite(
|
Util.termWrite(
|
||||||
"""
|
"""
|
||||||
export DATA_DIR=${G.dataPath}
|
export DATA_DIR=${G.dataPath}
|
||||||
|
|||||||
Reference in New Issue
Block a user