mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-27 14:59:02 +08:00
refact: texture render as an option (#8168)
* refact: texture render as an option Signed-off-by: fufesou <linlong1266@gmail.com> * refact: texture render, translation Signed-off-by: fufesou <linlong1266@gmail.com> * refact: texture render as option Signed-off-by: fufesou <linlong1266@gmail.com> * Update ui_interface.rs --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
parent
010b17509a
commit
72ec86b58d
7
.github/workflows/flutter-build.yml
vendored
7
.github/workflows/flutter-build.yml
vendored
@ -548,13 +548,14 @@ jobs:
|
||||
- {
|
||||
target: x86_64-apple-darwin,
|
||||
os: macos-13, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
|
||||
extra-build-args: "--disable-flutter-texture-render",
|
||||
extra-build-args: "",
|
||||
arch: x86_64,
|
||||
}
|
||||
- {
|
||||
target: aarch64-apple-darwin,
|
||||
os: macos-latest,
|
||||
extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
||||
# extra-build-args: "--disable-flutter-texture-render", # disable this for mac, because we see a lot of users reporting flickering both on arm and x64, and we can not confirm if texture rendering has better performance if htere is no vram, https://github.com/rustdesk/rustdesk/issues/6296
|
||||
extra-build-args: "",
|
||||
arch: aarch64,
|
||||
}
|
||||
steps:
|
||||
@ -1124,7 +1125,7 @@ jobs:
|
||||
export JOBS=""
|
||||
fi
|
||||
echo $JOBS
|
||||
cargo build --lib $JOBS --features hwcodec,flutter,flutter_texture_render --release
|
||||
cargo build --lib $JOBS --features hwcodec,flutter --release
|
||||
rm -rf target/release/deps target/release/build
|
||||
rm -rf ~/.cargo
|
||||
|
||||
|
@ -19,7 +19,6 @@ path = "src/naming.rs"
|
||||
[features]
|
||||
inline = []
|
||||
cli = []
|
||||
flutter_texture_render = []
|
||||
use_samplerate = ["samplerate"]
|
||||
use_rubato = ["rubato"]
|
||||
use_dasp = ["dasp"]
|
||||
|
4
build.py
4
build.py
@ -111,8 +111,6 @@ def make_parser():
|
||||
'Available: PrivacyMode. Special value is "ALL" and empty "". Default is empty.')
|
||||
parser.add_argument('--flutter', action='store_true',
|
||||
help='Build flutter package', default=False)
|
||||
parser.add_argument('--disable-flutter-texture-render', action='store_true',
|
||||
help='Build flutter package', default=False)
|
||||
parser.add_argument(
|
||||
'--hwcodec',
|
||||
action='store_true',
|
||||
@ -278,8 +276,6 @@ def get_features(args):
|
||||
features.append('vram')
|
||||
if args.flutter:
|
||||
features.append('flutter')
|
||||
if not args.disable_flutter_texture_render:
|
||||
features.append('flutter_texture_render')
|
||||
if args.unix_file_copy_paste:
|
||||
features.append('unix-file-copy-paste')
|
||||
print("features:", features)
|
||||
|
@ -12,7 +12,6 @@ import 'package:flutter_hbb/common/formatter/id_formatter.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart';
|
||||
import 'package:flutter_hbb/main.dart';
|
||||
import 'package:flutter_hbb/models/desktop_render_texture.dart';
|
||||
import 'package:flutter_hbb/models/peer_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
@ -2799,11 +2798,6 @@ sessionRefreshVideo(SessionID sessionId, PeerInfo pi) async {
|
||||
}
|
||||
}
|
||||
|
||||
bool isChooseDisplayToOpenInNewWindow(PeerInfo pi, SessionID sessionId) =>
|
||||
pi.isSupportMultiDisplay &&
|
||||
useTextureRender &&
|
||||
bind.sessionGetDisplaysAsIndividualWindows(sessionId: sessionId) == 'Y';
|
||||
|
||||
Future<List<Rect>> getScreenListWayland() async {
|
||||
final screenRectList = <Rect>[];
|
||||
if (isMainDesktopWindow) {
|
||||
|
@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/models/desktop_render_texture.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
@ -227,8 +226,7 @@ List<(String, String)> otherDefaultSettings() {
|
||||
if ((isDesktop || isWebDesktop)) ('Zoom cursor', kOptionZoomCursor),
|
||||
('Show quality monitor', kOptionShowQualityMonitor),
|
||||
('Mute', kOptionDisableAudio),
|
||||
if (isDesktop)
|
||||
('Enable file copy and paste', kOptionEnableFileCopyPaste),
|
||||
if (isDesktop) ('Enable file copy and paste', kOptionEnableFileCopyPaste),
|
||||
('Disable clipboard', kOptionDisableClipboard),
|
||||
('Lock after session end', kOptionLockAfterSessionEnd),
|
||||
('Privacy mode', kOptionPrivacyMode),
|
||||
@ -236,12 +234,12 @@ List<(String, String)> otherDefaultSettings() {
|
||||
('True color (4:4:4)', kOptionI444),
|
||||
('Reverse mouse wheel', kKeyReverseMouseWheel),
|
||||
('swap-left-right-mouse', kOptionSwapLeftRightMouse),
|
||||
if (isDesktop && useTextureRender)
|
||||
if (isDesktop && bind.mainGetUseTextureRender())
|
||||
(
|
||||
'Show displays as individual windows',
|
||||
kKeyShowDisplaysAsIndividualWindows
|
||||
),
|
||||
if (isDesktop && useTextureRender)
|
||||
if (isDesktop && bind.mainGetUseTextureRender())
|
||||
(
|
||||
'Use all my displays for the remote session',
|
||||
kKeyUseAllMyDisplaysForTheRemoteSession
|
||||
|
@ -8,7 +8,6 @@ import 'package:flutter_hbb/common/widgets/dialog.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/models/model.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/desktop_render_texture.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
bool isEditOsPassword = false;
|
||||
@ -581,7 +580,7 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
||||
child: Text(translate('Lock after session end'))));
|
||||
}
|
||||
|
||||
if (useTextureRender &&
|
||||
if (bind.mainGetUseTextureRender() &&
|
||||
pi.isSupportMultiDisplay &&
|
||||
PrivacyModeState.find(id).isEmpty &&
|
||||
pi.displaysCount.value > 1 &&
|
||||
@ -600,7 +599,9 @@ Future<List<TToggleMenu>> toolbarDisplayToggle(
|
||||
}
|
||||
|
||||
final isMultiScreens = !isWeb && (await getScreenRectList()).length > 1;
|
||||
if (useTextureRender && pi.isSupportMultiDisplay && isMultiScreens) {
|
||||
if (bind.mainGetUseTextureRender() &&
|
||||
pi.isSupportMultiDisplay &&
|
||||
isMultiScreens) {
|
||||
final value = bind.sessionGetUseAllMyDisplaysForTheRemoteSession(
|
||||
sessionId: ffi.sessionId) ==
|
||||
'Y';
|
||||
|
@ -73,6 +73,7 @@ const String kOptionViewStyle = "view_style";
|
||||
const String kOptionScrollStyle = "scroll_style";
|
||||
const String kOptionImageQuality = "image_quality";
|
||||
const String kOptionOpenNewConnInTabs = "enable-open-new-connections-in-tabs";
|
||||
const String kOptionTextureRender = "use-texture-render";
|
||||
const String kOptionOpenInTabs = "allow-open-in-tabs";
|
||||
const String kOptionOpenInWindows = "allow-open-in-windows";
|
||||
const String kOptionForceAlwaysRelay = "force-always-relay";
|
||||
@ -153,6 +154,8 @@ const String kKeyUseAllMyDisplaysForTheRemoteSession =
|
||||
const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar';
|
||||
const String kKeyReverseMouseWheel = "reverse_mouse_wheel";
|
||||
|
||||
const String kMsgboxTextWaitingForImage = 'Connected, waiting for image...';
|
||||
|
||||
// the executable name of the portable version
|
||||
const String kEnvPortableExecutable = "RUSTDESK_APPNAME";
|
||||
|
||||
|
@ -387,10 +387,25 @@ class _GeneralState extends State<_General> {
|
||||
isServer: false,
|
||||
),
|
||||
// though this is related to GUI, but opengl problem affects all users, so put in config rather than local
|
||||
if (isLinux)
|
||||
Tooltip(
|
||||
message: translate('software_render_tip'),
|
||||
child: _OptionCheckBox(
|
||||
context,
|
||||
"Always use software rendering",
|
||||
kOptionAllowAlwaysSoftwareRender,
|
||||
),
|
||||
),
|
||||
Tooltip(
|
||||
message: translate('software_render_tip'),
|
||||
child: _OptionCheckBox(context, "Always use software rendering",
|
||||
kOptionAllowAlwaysSoftwareRender),
|
||||
message: translate('texture_render_tip'),
|
||||
child: _OptionCheckBox(
|
||||
context,
|
||||
"Use texture rendering",
|
||||
kOptionTextureRender,
|
||||
optGetter: bind.mainGetUseTextureRender,
|
||||
optSetter: (k, v) async =>
|
||||
await bind.mainSetLocalOption(key: k, value: v ? 'Y' : 'N'),
|
||||
),
|
||||
),
|
||||
if (!bind.isCustomClient())
|
||||
_OptionCheckBox(
|
||||
@ -426,7 +441,7 @@ class _GeneralState extends State<_General> {
|
||||
context,
|
||||
'Remove wallpaper during incoming sessions',
|
||||
kOptionAllowRemoveWallpaper,
|
||||
update: () {
|
||||
update: (bool v) {
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
@ -457,8 +472,8 @@ class _GeneralState extends State<_General> {
|
||||
context,
|
||||
'Enable hardware codec',
|
||||
kOptionEnableHwcodec,
|
||||
update: () {
|
||||
if (mainGetBoolOptionSync(kOptionEnableHwcodec)) {
|
||||
update: (bool v) {
|
||||
if (v) {
|
||||
bind.mainCheckHwcodec();
|
||||
}
|
||||
},
|
||||
@ -941,7 +956,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
|
||||
List<Widget> directIp(BuildContext context) {
|
||||
TextEditingController controller = TextEditingController();
|
||||
update() => setState(() {});
|
||||
update(bool v) => setState(() {});
|
||||
RxBool applyEnabled = false.obs;
|
||||
return [
|
||||
_OptionCheckBox(context, 'Enable direct IP access', kOptionDirectServer,
|
||||
@ -1102,7 +1117,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
|
||||
List<Widget> autoDisconnect(BuildContext context) {
|
||||
TextEditingController controller = TextEditingController();
|
||||
update() => setState(() {});
|
||||
update(bool v) => setState(() {});
|
||||
RxBool applyEnabled = false.obs;
|
||||
return [
|
||||
_OptionCheckBox(
|
||||
@ -1803,33 +1818,41 @@ Widget _Card(
|
||||
}
|
||||
|
||||
// ignore: non_constant_identifier_names
|
||||
Widget _OptionCheckBox(BuildContext context, String label, String key,
|
||||
{Function()? update,
|
||||
bool reverse = false,
|
||||
bool enabled = true,
|
||||
Icon? checkedIcon,
|
||||
bool? fakeValue,
|
||||
bool isServer = true}) {
|
||||
bool value =
|
||||
isServer ? mainGetBoolOptionSync(key) : mainGetLocalBoolOptionSync(key);
|
||||
Widget _OptionCheckBox(
|
||||
BuildContext context,
|
||||
String label,
|
||||
String key, {
|
||||
Function(bool)? update,
|
||||
bool reverse = false,
|
||||
bool enabled = true,
|
||||
Icon? checkedIcon,
|
||||
bool? fakeValue,
|
||||
bool isServer = true,
|
||||
bool Function()? optGetter,
|
||||
Future<void> Function(String, bool)? optSetter,
|
||||
}) {
|
||||
getOpt() => optGetter != null
|
||||
? optGetter()
|
||||
: (isServer
|
||||
? mainGetBoolOptionSync(key)
|
||||
: mainGetLocalBoolOptionSync(key));
|
||||
bool value = getOpt();
|
||||
final isOptFixed = isOptionFixed(key);
|
||||
if (reverse) value = !value;
|
||||
var ref = value.obs;
|
||||
onChanged(option) async {
|
||||
if (option != null) {
|
||||
if (reverse) option = !option;
|
||||
isServer
|
||||
? await mainSetBoolOption(key, option)
|
||||
: await mainSetLocalBoolOption(key, option);
|
||||
final readOption = isServer
|
||||
? mainGetBoolOptionSync(key)
|
||||
: mainGetLocalBoolOptionSync(key);
|
||||
final setter =
|
||||
optSetter ?? (isServer ? mainSetBoolOption : mainSetLocalBoolOption);
|
||||
await setter(key, option);
|
||||
final readOption = getOpt();
|
||||
if (reverse) {
|
||||
ref.value = !readOption;
|
||||
} else {
|
||||
ref.value = readOption;
|
||||
}
|
||||
update?.call();
|
||||
update?.call(readOption);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ import '../../common.dart';
|
||||
import '../../common/widgets/dialog.dart';
|
||||
import '../../common/widgets/toolbar.dart';
|
||||
import '../../models/model.dart';
|
||||
import '../../models/desktop_render_texture.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
import '../../common/shared_state.dart';
|
||||
import '../../utils/image.dart';
|
||||
@ -593,12 +592,11 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||
onHover: (evt) {},
|
||||
child: child);
|
||||
});
|
||||
|
||||
if (c.imageOverflow.isTrue && c.scrollStyle == ScrollStyle.scrollbar) {
|
||||
final paintWidth = c.getDisplayWidth() * s;
|
||||
final paintHeight = c.getDisplayHeight() * s;
|
||||
final paintSize = Size(paintWidth, paintHeight);
|
||||
final paintWidget = useTextureRender
|
||||
final paintWidget = m.useTextureRender
|
||||
? _BuildPaintTextureRender(
|
||||
c, s, Offset.zero, paintSize, isViewOriginal())
|
||||
: _buildScrollbarNonTextureRender(m, paintSize, s);
|
||||
@ -619,7 +617,7 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||
));
|
||||
} else {
|
||||
if (c.size.width > 0 && c.size.height > 0) {
|
||||
final paintWidget = useTextureRender
|
||||
final paintWidget = m.useTextureRender
|
||||
? _BuildPaintTextureRender(
|
||||
c,
|
||||
s,
|
||||
|
@ -7,7 +7,6 @@ import 'package:flutter_hbb/common/widgets/audio_input.dart';
|
||||
import 'package:flutter_hbb/common/widgets/toolbar.dart';
|
||||
import 'package:flutter_hbb/models/chat_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/models/desktop_render_texture.dart';
|
||||
import 'package:flutter_hbb/consts.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
import 'package:flutter_hbb/plugin/widgets/desc_ui.dart';
|
||||
@ -615,14 +614,14 @@ class _MonitorMenu extends StatelessWidget {
|
||||
bind.mainGetUserDefaultOption(key: kKeyShowMonitorsToolbar) == 'Y';
|
||||
|
||||
bool get supportIndividualWindows =>
|
||||
useTextureRender && ffi.ffiModel.pi.isSupportMultiDisplay;
|
||||
!isWeb && ffi.ffiModel.pi.isSupportMultiDisplay;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => showMonitorsToolbar
|
||||
? buildMultiMonitorMenu()
|
||||
: Obx(() => buildMonitorMenu());
|
||||
? buildMultiMonitorMenu(context)
|
||||
: Obx(() => buildMonitorMenu(context));
|
||||
|
||||
Widget buildMonitorMenu() {
|
||||
Widget buildMonitorMenu(BuildContext context) {
|
||||
final width = SimpleWrapper<double>(0);
|
||||
final monitorsIcon =
|
||||
globalMonitorsWidget(width, Colors.white, Colors.black38);
|
||||
@ -636,20 +635,23 @@ class _MonitorMenu extends StatelessWidget {
|
||||
menuStyle: MenuStyle(
|
||||
padding:
|
||||
MaterialStatePropertyAll(EdgeInsets.symmetric(horizontal: 6))),
|
||||
menuChildrenGetter: () => [buildMonitorSubmenuWidget()]);
|
||||
menuChildrenGetter: () => [buildMonitorSubmenuWidget(context)]);
|
||||
}
|
||||
|
||||
Widget buildMultiMonitorMenu() {
|
||||
return Row(children: buildMonitorList(true));
|
||||
Widget buildMultiMonitorMenu(BuildContext context) {
|
||||
return Row(children: buildMonitorList(context, true));
|
||||
}
|
||||
|
||||
Widget buildMonitorSubmenuWidget() {
|
||||
Widget buildMonitorSubmenuWidget(BuildContext context) {
|
||||
final m = Provider.of<ImageModel>(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(children: buildMonitorList(false)),
|
||||
supportIndividualWindows ? Divider() : Offstage(),
|
||||
supportIndividualWindows ? chooseDisplayBehavior() : Offstage(),
|
||||
Row(children: buildMonitorList(context, false)),
|
||||
supportIndividualWindows && m.useTextureRender ? Divider() : Offstage(),
|
||||
supportIndividualWindows && m.useTextureRender
|
||||
? chooseDisplayBehavior()
|
||||
: Offstage(),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -680,7 +682,7 @@ class _MonitorMenu extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
|
||||
List<Widget> buildMonitorList(bool isMulti) {
|
||||
List<Widget> buildMonitorList(BuildContext context, bool isMulti) {
|
||||
final List<Widget> monitorList = [];
|
||||
final pi = ffi.ffiModel.pi;
|
||||
|
||||
@ -735,7 +737,10 @@ class _MonitorMenu extends StatelessWidget {
|
||||
for (int i = 0; i < pi.displays.length; i++) {
|
||||
monitorList.add(buildMonitorButton(i));
|
||||
}
|
||||
if (supportIndividualWindows && pi.displays.length > 1) {
|
||||
final m = Provider.of<ImageModel>(context);
|
||||
if (supportIndividualWindows &&
|
||||
m.useTextureRender &&
|
||||
pi.displays.length > 1) {
|
||||
monitorList.add(buildMonitorButton(kAllDisplayValue));
|
||||
}
|
||||
return monitorList;
|
||||
@ -818,7 +823,12 @@ class _MonitorMenu extends StatelessWidget {
|
||||
}
|
||||
RxInt display = CurrentDisplayState.find(id);
|
||||
if (display.value != i) {
|
||||
if (isChooseDisplayToOpenInNewWindow(pi, ffi.sessionId)) {
|
||||
final isChooseDisplayToOpenInNewWindow = pi.isSupportMultiDisplay &&
|
||||
bind.mainGetUseTextureRender() &&
|
||||
bind.sessionGetDisplaysAsIndividualWindows(
|
||||
sessionId: ffi.sessionId) ==
|
||||
'Y';
|
||||
if (isChooseDisplayToOpenInNewWindow) {
|
||||
openMonitorInNewTabOrWindow(i, ffi.id, pi);
|
||||
} else {
|
||||
openMonitorInTheSameTab(i, ffi, pi, updateCursorPos: !isMulti);
|
||||
|
@ -11,15 +11,10 @@ import './platform_model.dart';
|
||||
import 'package:texture_rgba_renderer/texture_rgba_renderer.dart'
|
||||
if (dart.library.html) 'package:flutter_hbb/web/texture_rgba_renderer.dart';
|
||||
|
||||
// Feature flutter_texture_render need to be enabled if feature vram is enabled.
|
||||
final useTextureRender = !isWeb &&
|
||||
(bind.mainHasPixelbufferTextureRender() || bind.mainHasGpuTextureRender());
|
||||
|
||||
class _PixelbufferTexture {
|
||||
int _textureKey = -1;
|
||||
int _display = 0;
|
||||
SessionID? _sessionId;
|
||||
final support = bind.mainHasPixelbufferTextureRender();
|
||||
bool _destroying = false;
|
||||
int? _id;
|
||||
|
||||
@ -28,26 +23,24 @@ class _PixelbufferTexture {
|
||||
int get display => _display;
|
||||
|
||||
create(int d, SessionID sessionId, FFI ffi) {
|
||||
if (support) {
|
||||
_display = d;
|
||||
_textureKey = bind.getNextTextureKey();
|
||||
_sessionId = sessionId;
|
||||
_display = d;
|
||||
_textureKey = bind.getNextTextureKey();
|
||||
_sessionId = sessionId;
|
||||
|
||||
textureRenderer.createTexture(_textureKey).then((id) async {
|
||||
_id = id;
|
||||
if (id != -1) {
|
||||
ffi.textureModel.setRgbaTextureId(display: d, id: id);
|
||||
final ptr = await textureRenderer.getTexturePtr(_textureKey);
|
||||
platformFFI.registerPixelbufferTexture(sessionId, display, ptr);
|
||||
debugPrint(
|
||||
"create pixelbuffer texture: peerId: ${ffi.id} display:$_display, textureId:$id, texturePtr:$ptr");
|
||||
}
|
||||
});
|
||||
}
|
||||
textureRenderer.createTexture(_textureKey).then((id) async {
|
||||
_id = id;
|
||||
if (id != -1) {
|
||||
ffi.textureModel.setRgbaTextureId(display: d, id: id);
|
||||
final ptr = await textureRenderer.getTexturePtr(_textureKey);
|
||||
platformFFI.registerPixelbufferTexture(sessionId, display, ptr);
|
||||
debugPrint(
|
||||
"create pixelbuffer texture: peerId: ${ffi.id} display:$_display, textureId:$id, texturePtr:$ptr");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
destroy(bool unregisterTexture, FFI ffi) async {
|
||||
if (!_destroying && support && _textureKey != -1 && _sessionId != null) {
|
||||
if (!_destroying && _textureKey != -1 && _sessionId != null) {
|
||||
_destroying = true;
|
||||
if (unregisterTexture) {
|
||||
platformFFI.registerPixelbufferTexture(_sessionId!, display, 0);
|
||||
|
@ -244,7 +244,7 @@ class FfiModel with ChangeNotifier {
|
||||
handleMsgBox({
|
||||
'type': 'success',
|
||||
'title': 'Successful',
|
||||
'text': 'Connected, waiting for image...',
|
||||
'text': kMsgboxTextWaitingForImage,
|
||||
'link': '',
|
||||
}, sessionId, peerId);
|
||||
updatePrivacyMode(data.updatePrivacyMode, sessionId, peerId);
|
||||
@ -380,12 +380,22 @@ class FfiModel with ChangeNotifier {
|
||||
_handleSyncPeerOption(evt, peerId);
|
||||
} else if (name == 'follow_current_display') {
|
||||
handleFollowCurrentDisplay(evt, sessionId, peerId);
|
||||
} else if (name == 'use_texture_render') {
|
||||
_handleUseTextureRender(evt, sessionId, peerId);
|
||||
} else {
|
||||
debugPrint('Unknown event name: $name');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_handleUseTextureRender(
|
||||
Map<String, dynamic> evt, SessionID sessionId, String peerId) {
|
||||
parent.target?.imageModel.setUseTextureRender(evt['v'] == 'Y');
|
||||
waitForFirstImage.value = true;
|
||||
showConnectedWaitingForImage(parent.target!.dialogManager, sessionId,
|
||||
'success', 'Successful', kMsgboxTextWaitingForImage);
|
||||
}
|
||||
|
||||
_handleSyncPeerOption(Map<String, dynamic> evt, String peer) {
|
||||
final k = evt['k'];
|
||||
final v = evt['v'];
|
||||
@ -572,7 +582,7 @@ class FfiModel with ChangeNotifier {
|
||||
showElevationError(sessionId, type, title, text, dialogManager);
|
||||
} else if (type == 'relay-hint' || type == 'relay-hint2') {
|
||||
showRelayHintDialog(sessionId, type, title, text, dialogManager, peerId);
|
||||
} else if (text == 'Connected, waiting for image...') {
|
||||
} else if (text == kMsgboxTextWaitingForImage) {
|
||||
showConnectedWaitingForImage(dialogManager, sessionId, type, title, text);
|
||||
} else if (title == 'Privacy mode') {
|
||||
final hasRetry = evt['hasRetry'] == 'true';
|
||||
@ -1156,6 +1166,8 @@ class ImageModel with ChangeNotifier {
|
||||
|
||||
late final SessionID sessionId;
|
||||
|
||||
bool _useTextureRender = false;
|
||||
|
||||
WeakReference<FFI> parent;
|
||||
|
||||
final List<Function(String)> callbacksOnFirstImage = [];
|
||||
@ -1164,6 +1176,8 @@ class ImageModel with ChangeNotifier {
|
||||
sessionId = parent.target!.sessionId;
|
||||
}
|
||||
|
||||
get useTextureRender => _useTextureRender;
|
||||
|
||||
addCallbackOnFirstImage(Function(String) cb) => callbacksOnFirstImage.add(cb);
|
||||
|
||||
onRgba(int display, Uint8List rgba) {
|
||||
@ -1233,6 +1247,19 @@ class ImageModel with ChangeNotifier {
|
||||
return min(xscale, yscale) / 1.5;
|
||||
}
|
||||
|
||||
updateUserTextureRender() {
|
||||
final preValue = _useTextureRender;
|
||||
_useTextureRender = isDesktop && bind.mainGetUseTextureRender();
|
||||
if (preValue != _useTextureRender) {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
setUseTextureRender(bool value) {
|
||||
_useTextureRender = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void disposeImage() {
|
||||
_image?.dispose();
|
||||
_image = null;
|
||||
@ -2387,7 +2414,7 @@ class FFI {
|
||||
sessionId: sessionId, displays: Int32List.fromList(displays));
|
||||
ffiModel.pi.currentDisplay = display;
|
||||
}
|
||||
if (connType == ConnType.defaultConn && useTextureRender) {
|
||||
if (isDesktop && connType == ConnType.defaultConn) {
|
||||
textureModel.updateCurrentDisplay(display ?? 0);
|
||||
}
|
||||
final stream = bind.sessionStart(sessionId: sessionId, id: id);
|
||||
@ -2409,9 +2436,8 @@ class FFI {
|
||||
}
|
||||
}
|
||||
|
||||
final hasPixelBufferTextureRender = bind.mainHasPixelbufferTextureRender();
|
||||
imageModel.updateUserTextureRender();
|
||||
final hasGpuTextureRender = bind.mainHasGpuTextureRender();
|
||||
|
||||
final SimpleWrapper<bool> isToNewWindowNotified = SimpleWrapper(false);
|
||||
// Preserved for the rgba data.
|
||||
stream.listen((message) {
|
||||
@ -2460,7 +2486,7 @@ class FFI {
|
||||
}
|
||||
} else if (message is EventToUI_Rgba) {
|
||||
final display = message.field0;
|
||||
if (hasPixelBufferTextureRender) {
|
||||
if (imageModel.useTextureRender) {
|
||||
debugPrint("EventToUI_Rgba display:$display");
|
||||
textureModel.setTextureType(display: display, gpuTexture: false);
|
||||
onEvent2UIRgba();
|
||||
|
@ -1414,10 +1414,6 @@ class RustdeskImpl {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
bool mainHasPixelbufferTextureRender({dynamic hint}) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mainHasFileClipboard({dynamic hint}) {
|
||||
return false;
|
||||
}
|
||||
@ -1608,5 +1604,9 @@ class RustdeskImpl {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
bool mainGetUseTextureRender({dynamic hint}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
void dispose() {}
|
||||
}
|
||||
|
@ -2053,6 +2053,7 @@ pub mod keys {
|
||||
pub const OPTION_ENABLE_CONFIRM_CLOSING_TABS: &str = "enable-confirm-closing-tabs";
|
||||
pub const OPTION_ENABLE_OPEN_NEW_CONNECTIONS_IN_TABS: &str =
|
||||
"enable-open-new-connections-in-tabs";
|
||||
pub const OPTION_TEXTURE_RENDER: &str = "use-texture-render";
|
||||
pub const OPTION_ENABLE_CHECK_UPDATE: &str = "enable-check-update";
|
||||
pub const OPTION_SYNC_AB_WITH_RECENT_SESSIONS: &str = "sync-ab-with-recent-sessions";
|
||||
pub const OPTION_SYNC_AB_TAGS: &str = "sync-ab-tags";
|
||||
@ -2133,6 +2134,7 @@ pub mod keys {
|
||||
OPTION_LANGUAGE,
|
||||
OPTION_ENABLE_CONFIRM_CLOSING_TABS,
|
||||
OPTION_ENABLE_OPEN_NEW_CONNECTIONS_IN_TABS,
|
||||
OPTION_TEXTURE_RENDER,
|
||||
OPTION_SYNC_AB_WITH_RECENT_SESSIONS,
|
||||
OPTION_SYNC_AB_TAGS,
|
||||
OPTION_FILTER_AB_BY_INTERSECTION,
|
||||
|
@ -419,7 +419,7 @@ impl Encoder {
|
||||
impl Decoder {
|
||||
pub fn supported_decodings(
|
||||
id_for_perfer: Option<&str>,
|
||||
_flutter: bool,
|
||||
_use_texture_render: bool,
|
||||
_luid: Option<i64>,
|
||||
mark_unsupported: &Vec<CodecFormat>,
|
||||
) -> SupportedDecoding {
|
||||
@ -454,7 +454,7 @@ impl Decoder {
|
||||
};
|
||||
}
|
||||
#[cfg(feature = "vram")]
|
||||
if enable_vram_option() && _flutter {
|
||||
if enable_vram_option() && _use_texture_render {
|
||||
decoding.ability_h264 |= if VRamDecoder::available(CodecFormat::H264, _luid).len() > 0 {
|
||||
1
|
||||
} else {
|
||||
|
@ -88,6 +88,11 @@ impl ImageRgb {
|
||||
pub fn stride(&self) -> usize {
|
||||
self.stride
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_stride(&mut self, stride: usize) {
|
||||
self.stride = stride;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -39,7 +39,7 @@ use hbb_common::{
|
||||
},
|
||||
get_version_number, log,
|
||||
message_proto::{option_message::BoolOption, *},
|
||||
protobuf::Message as _,
|
||||
protobuf::{Message as _, MessageField},
|
||||
rand,
|
||||
rendezvous_proto::*,
|
||||
socket_client,
|
||||
@ -61,6 +61,7 @@ use crate::{
|
||||
check_port,
|
||||
common::input::{MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP},
|
||||
create_symmetric_key_msg, decode_id_pk, get_rs_pk, is_keyboard_mode_supported, secure_tcp,
|
||||
ui_interface::use_texture_render,
|
||||
ui_session_interface::{InvokeUiSession, Session},
|
||||
};
|
||||
|
||||
@ -1035,16 +1036,23 @@ pub struct VideoHandler {
|
||||
}
|
||||
|
||||
impl VideoHandler {
|
||||
#[cfg(feature = "flutter")]
|
||||
pub fn get_adapter_luid() -> Option<i64> {
|
||||
crate::flutter::get_adapter_luid()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "flutter"))]
|
||||
pub fn get_adapter_luid() -> Option<i64> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Create a new video handler.
|
||||
pub fn new(format: CodecFormat, _display: usize) -> Self {
|
||||
#[cfg(all(feature = "vram", feature = "flutter"))]
|
||||
let luid = crate::flutter::get_adapter_luid();
|
||||
#[cfg(not(all(feature = "vram", feature = "flutter")))]
|
||||
let luid = Default::default();
|
||||
let luid = Self::get_adapter_luid();
|
||||
log::info!("new video handler for display #{_display}, format: {format:?}, luid: {luid:?}");
|
||||
VideoHandler {
|
||||
decoder: Decoder::new(format, luid),
|
||||
rgb: ImageRgb::new(ImageFormat::ARGB, crate::DST_STRIDE_RGBA),
|
||||
rgb: ImageRgb::new(ImageFormat::ARGB, crate::get_dst_stride_rgba()),
|
||||
texture: std::ptr::null_mut(),
|
||||
recorder: Default::default(),
|
||||
record: false,
|
||||
@ -1096,10 +1104,9 @@ impl VideoHandler {
|
||||
|
||||
/// Reset the decoder, change format if it is Some
|
||||
pub fn reset(&mut self, format: Option<CodecFormat>) {
|
||||
#[cfg(all(feature = "flutter", feature = "vram"))]
|
||||
let luid = crate::flutter::get_adapter_luid();
|
||||
#[cfg(not(all(feature = "flutter", feature = "vram")))]
|
||||
let luid = None;
|
||||
#[cfg(target_os = "macos")]
|
||||
self.rgb.set_stride(crate::get_dst_stride_rgba());
|
||||
let luid = Self::get_adapter_luid();
|
||||
let format = format.unwrap_or(self.decoder.format());
|
||||
self.decoder = Decoder::new(format, luid);
|
||||
self.fail_counter = 0;
|
||||
@ -1637,16 +1644,19 @@ impl LoginConfigHandler {
|
||||
if view_only || self.get_toggle_option("disable-clipboard") {
|
||||
msg.disable_clipboard = BoolOption::Yes.into();
|
||||
}
|
||||
msg.supported_decoding =
|
||||
hbb_common::protobuf::MessageField::some(Decoder::supported_decodings(
|
||||
Some(&self.id),
|
||||
cfg!(feature = "flutter"),
|
||||
self.adapter_luid,
|
||||
&self.mark_unsupported,
|
||||
));
|
||||
msg.supported_decoding = MessageField::some(self.get_supported_decoding());
|
||||
Some(msg)
|
||||
}
|
||||
|
||||
pub fn get_supported_decoding(&self) -> SupportedDecoding {
|
||||
Decoder::supported_decodings(
|
||||
Some(&self.id),
|
||||
use_texture_render(),
|
||||
self.adapter_luid,
|
||||
&self.mark_unsupported,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_option_message_after_login(&self) -> Option<OptionMessage> {
|
||||
if self.conn_type.eq(&ConnType::FILE_TRANSFER)
|
||||
|| self.conn_type.eq(&ConnType::PORT_FORWARD)
|
||||
@ -2036,7 +2046,7 @@ impl LoginConfigHandler {
|
||||
pub fn update_supported_decodings(&self) -> Message {
|
||||
let decoding = scrap::codec::Decoder::supported_decodings(
|
||||
Some(&self.id),
|
||||
cfg!(feature = "flutter"),
|
||||
use_texture_render(),
|
||||
self.adapter_luid,
|
||||
&self.mark_unsupported,
|
||||
);
|
||||
@ -2065,7 +2075,7 @@ pub enum MediaData {
|
||||
VideoFrame(Box<VideoFrame>),
|
||||
AudioFrame(Box<AudioFrame>),
|
||||
AudioFormat(AudioFormat),
|
||||
Reset(usize),
|
||||
Reset(Option<usize>),
|
||||
RecordScreen(bool, usize, i32, i32, String),
|
||||
}
|
||||
|
||||
@ -2241,8 +2251,16 @@ where
|
||||
}
|
||||
}
|
||||
MediaData::Reset(display) => {
|
||||
if let Some(handler_controler) = handler_controller_map.get_mut(&display) {
|
||||
handler_controler.handler.reset(None);
|
||||
if let Some(display) = display {
|
||||
if let Some(handler_controler) =
|
||||
handler_controller_map.get_mut(&display)
|
||||
{
|
||||
handler_controler.handler.reset(None);
|
||||
}
|
||||
} else {
|
||||
for (_, handler_controler) in handler_controller_map.iter_mut() {
|
||||
handler_controler.handler.reset(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
MediaData::RecordScreen(start, display, w, h, id) => {
|
||||
@ -2945,6 +2963,7 @@ pub enum Data {
|
||||
ElevateWithLogon(String, String),
|
||||
NewVoiceCall,
|
||||
CloseVoiceCall,
|
||||
ResetDecoder(Option<usize>),
|
||||
}
|
||||
|
||||
/// Keycode for key events.
|
||||
|
@ -843,6 +843,9 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
.on_voice_call_closed("Closed manually by the peer");
|
||||
allow_err!(peer.send(&msg).await);
|
||||
}
|
||||
Data::ResetDecoder(display) => {
|
||||
self.video_sender.send(MediaData::Reset(display)).ok();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
@ -1371,7 +1374,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
||||
Some(misc::Union::SwitchDisplay(s)) => {
|
||||
self.handler.handle_peer_switch_display(&s);
|
||||
self.video_sender
|
||||
.send(MediaData::Reset(s.display as _))
|
||||
.send(MediaData::Reset(Some(s.display as _)))
|
||||
.ok();
|
||||
if s.width > 0 && s.height > 0 {
|
||||
self.handler.set_display(
|
||||
|
@ -158,13 +158,6 @@ pub type NotifyMessageBox = fn(String, String, String, String) -> dyn Future<Out
|
||||
pub const CLIPBOARD_NAME: &'static str = "clipboard";
|
||||
pub const CLIPBOARD_INTERVAL: u64 = 333;
|
||||
|
||||
#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))]
|
||||
// https://developer.apple.com/forums/thread/712709
|
||||
// Memory alignment should be multiple of 64.
|
||||
pub const DST_STRIDE_RGBA: usize = 64;
|
||||
#[cfg(not(all(target_os = "macos", feature = "flutter_texture_render")))]
|
||||
pub const DST_STRIDE_RGBA: usize = 1;
|
||||
|
||||
// the executable name of the portable version
|
||||
pub const PORTABLE_APPNAME_RUNTIME_ENV_KEY: &str = "RUSTDESK_APPNAME";
|
||||
|
||||
@ -1622,6 +1615,24 @@ fn read_custom_client_advanced_settings(
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn get_dst_stride_rgba() -> usize {
|
||||
// https://developer.apple.com/forums/thread/712709
|
||||
// Memory alignment should be multiple of 64.
|
||||
if crate::ui_interface::use_texture_render() {
|
||||
64
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub fn get_dst_stride_rgba() -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
pub fn read_custom_client(config: &str) {
|
||||
let Ok(data) = decode64(config) else {
|
||||
log::error!("Failed to decode custom client config");
|
||||
|
278
src/flutter.rs
278
src/flutter.rs
@ -4,7 +4,7 @@ use crate::{
|
||||
ui_session_interface::{io_loop, InvokeUiSession, Session},
|
||||
};
|
||||
use flutter_rust_bridge::StreamSink;
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use hbb_common::dlopen::{
|
||||
symbor::{Library, Symbol},
|
||||
Error as LibError,
|
||||
@ -16,15 +16,15 @@ use hbb_common::{
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
use std::os::raw::c_void;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::CString,
|
||||
os::raw::{c_char, c_int},
|
||||
os::raw::{c_char, c_int, c_void},
|
||||
str::FromStr,
|
||||
sync::{Arc, RwLock},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, RwLock,
|
||||
},
|
||||
};
|
||||
|
||||
/// tag "main" for [Desktop Main Page] and [Mobile (Client and Server)] (the mobile don't need multiple windows, only one global event stream is needed)
|
||||
@ -48,22 +48,22 @@ lazy_static::lazy_static! {
|
||||
static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", feature = "flutter_texture_render"))]
|
||||
#[cfg(target_os = "windows")]
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result<Library, LibError> = Library::open("texture_rgba_renderer_plugin.dll");
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "flutter_texture_render"))]
|
||||
#[cfg(target_os = "linux")]
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result<Library, LibError> = Library::open("libtexture_rgba_renderer_plugin.so");
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result<Library, LibError> = Library::open_self();
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "windows", feature = "vram"))]
|
||||
#[cfg(target_os = "windows")]
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref TEXTURE_GPU_RENDERER_PLUGIN: Result<Library, LibError> = Library::open("flutter_gpu_texture_renderer_plugin.dll");
|
||||
}
|
||||
@ -168,11 +168,9 @@ pub unsafe extern "C" fn get_rustdesk_app_name(buffer: *mut u16, length: i32) ->
|
||||
#[derive(Default)]
|
||||
struct SessionHandler {
|
||||
event_stream: Option<StreamSink<EventToUI>>,
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
renderer: VideoRenderer,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
enum RenderType {
|
||||
PixelBuffer,
|
||||
@ -180,22 +178,32 @@ enum RenderType {
|
||||
Texture,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct FlutterHandler {
|
||||
// ui session id -> display handler data
|
||||
session_handlers: Arc<RwLock<HashMap<SessionID, SessionHandler>>>,
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
display_rgbas: Arc<RwLock<HashMap<usize, RgbaData>>>,
|
||||
peer_info: Arc<RwLock<PeerInfo>>,
|
||||
#[cfg(any(
|
||||
not(feature = "flutter_texture_render"),
|
||||
all(feature = "flutter_texture_render", feature = "plugin_framework")
|
||||
))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
hooks: Arc<RwLock<HashMap<String, SessionHook>>>,
|
||||
use_texture_render: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Default for FlutterHandler {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
session_handlers: Default::default(),
|
||||
display_rgbas: Default::default(),
|
||||
peer_info: Default::default(),
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
hooks: Default::default(),
|
||||
use_texture_render: Arc::new(
|
||||
AtomicBool::new(crate::ui_interface::use_texture_render()),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
#[derive(Default, Clone)]
|
||||
struct RgbaData {
|
||||
// SAFETY: [rgba] is guarded by [rgba_valid], and it's safe to reach [rgba] with `rgba_valid == true`.
|
||||
@ -204,7 +212,6 @@ struct RgbaData {
|
||||
valid: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(
|
||||
texture_rgba: *mut c_void,
|
||||
buffer: *const u8,
|
||||
@ -221,15 +228,11 @@ pub type FlutterGpuTextureRendererPluginCApiSetTexture =
|
||||
#[cfg(feature = "vram")]
|
||||
pub type FlutterGpuTextureRendererPluginCApiGetAdapterLuid = unsafe extern "C" fn() -> i64;
|
||||
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
pub(super) type TextureRgbaPtr = usize;
|
||||
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
struct DisplaySessionInfo {
|
||||
// TextureRgba pointer in flutter native.
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
texture_rgba_ptr: TextureRgbaPtr,
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
size: (usize, usize),
|
||||
#[cfg(feature = "vram")]
|
||||
gpu_output_ptr: usize,
|
||||
@ -237,21 +240,19 @@ struct DisplaySessionInfo {
|
||||
}
|
||||
|
||||
// Video Texture Renderer in Flutter
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
#[derive(Clone)]
|
||||
struct VideoRenderer {
|
||||
is_support_multi_ui_session: bool,
|
||||
map_display_sessions: Arc<RwLock<HashMap<usize, DisplaySessionInfo>>>,
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
on_rgba_func: Option<Symbol<'static, FlutterRgbaRendererPluginOnRgba>>,
|
||||
#[cfg(feature = "vram")]
|
||||
on_texture_func: Option<Symbol<'static, FlutterGpuTextureRendererPluginCApiSetTexture>>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
impl Default for VideoRenderer {
|
||||
fn default() -> Self {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let on_rgba_func = match &*TEXTURE_RGBA_RENDERER_PLUGIN {
|
||||
Ok(lib) => {
|
||||
let find_sym_res = unsafe {
|
||||
@ -295,7 +296,7 @@ impl Default for VideoRenderer {
|
||||
Self {
|
||||
map_display_sessions: Default::default(),
|
||||
is_support_multi_ui_session: false,
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
on_rgba_func,
|
||||
#[cfg(feature = "vram")]
|
||||
on_texture_func,
|
||||
@ -303,10 +304,8 @@ impl Default for VideoRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "flutter_texture_render", feature = "vram"))]
|
||||
impl VideoRenderer {
|
||||
#[inline]
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
fn set_size(&mut self, display: usize, width: usize, height: usize) {
|
||||
let mut sessions_lock = self.map_display_sessions.write().unwrap();
|
||||
if let Some(info) = sessions_lock.get_mut(&display) {
|
||||
@ -326,7 +325,6 @@ impl VideoRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
fn register_pixelbuffer_texture(&self, display: usize, ptr: usize) {
|
||||
let mut sessions_lock = self.map_display_sessions.write().unwrap();
|
||||
if ptr == 0 {
|
||||
@ -378,7 +376,6 @@ impl VideoRenderer {
|
||||
if info.gpu_output_ptr != usize::default() {
|
||||
info.gpu_output_ptr = usize::default();
|
||||
}
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
if info.texture_rgba_ptr != usize::default() {
|
||||
return;
|
||||
}
|
||||
@ -400,9 +397,7 @@ impl VideoRenderer {
|
||||
sessions_lock.insert(
|
||||
display,
|
||||
DisplaySessionInfo {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
texture_rgba_ptr: usize::default(),
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
size: (0, 0),
|
||||
gpu_output_ptr: ptr,
|
||||
notify_render_type: None,
|
||||
@ -413,7 +408,7 @@ impl VideoRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
pub fn on_rgba(&self, display: usize, rgba: &scrap::ImageRgb) -> bool {
|
||||
let mut write_lock = self.map_display_sessions.write().unwrap();
|
||||
let opt_info = if !self.is_support_multi_ui_session {
|
||||
@ -498,10 +493,7 @@ impl VideoRenderer {
|
||||
|
||||
impl SessionHandler {
|
||||
pub fn on_waiting_for_image_dialog_show(&self) {
|
||||
#[cfg(any(feature = "flutter_texture_render"))]
|
||||
{
|
||||
self.renderer.reset_all_display_render_type();
|
||||
}
|
||||
self.renderer.reset_all_display_render_type();
|
||||
// rgba array render will notify every frame
|
||||
}
|
||||
}
|
||||
@ -583,6 +575,11 @@ impl FlutterHandler {
|
||||
let _ = hooks.remove(key);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn update_use_texture_render(&self) {
|
||||
self.use_texture_render
|
||||
.store(crate::ui_interface::use_texture_render(), Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
impl InvokeUiSession for FlutterHandler {
|
||||
@ -769,60 +766,27 @@ impl InvokeUiSession for FlutterHandler {
|
||||
fn adapt_size(&self) {}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
fn on_rgba(&self, display: usize, rgba: &mut scrap::ImageRgb) {
|
||||
// Give a chance for plugins or etc to hook a rgba data.
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
for (key, hook) in self.hooks.read().unwrap().iter() {
|
||||
match hook {
|
||||
SessionHook::OnSessionRgba(cb) => {
|
||||
cb(key.to_owned(), rgba);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the current rgba is not fetched by flutter, i.e., is valid.
|
||||
// We give up sending a new event to flutter.
|
||||
let mut rgba_write_lock = self.display_rgbas.write().unwrap();
|
||||
if let Some(rgba_data) = rgba_write_lock.get_mut(&display) {
|
||||
if rgba_data.valid {
|
||||
return;
|
||||
} else {
|
||||
rgba_data.valid = true;
|
||||
}
|
||||
// Return the rgba buffer to the video handler for reusing allocated rgba buffer.
|
||||
std::mem::swap::<Vec<u8>>(&mut rgba.raw, &mut rgba_data.data);
|
||||
if self.use_texture_render.load(Ordering::Relaxed) {
|
||||
self.on_rgba_flutter_texture_render(display, rgba);
|
||||
} else {
|
||||
let mut rgba_data = RgbaData::default();
|
||||
std::mem::swap::<Vec<u8>>(&mut rgba.raw, &mut rgba_data.data);
|
||||
rgba_data.valid = true;
|
||||
rgba_write_lock.insert(display, rgba_data);
|
||||
}
|
||||
drop(rgba_write_lock);
|
||||
|
||||
// Non-texture-render UI does not support multiple displays in the one UI session.
|
||||
// It's Ok to notify each session for now.
|
||||
for h in self.session_handlers.read().unwrap().values() {
|
||||
if let Some(stream) = &h.event_stream {
|
||||
stream.add(EventToUI::Rgba(display));
|
||||
}
|
||||
self.on_rgba_soft_render(display, rgba);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
fn on_rgba(&self, display: usize, rgba: &mut scrap::ImageRgb) {
|
||||
for (_, session) in self.session_handlers.read().unwrap().iter() {
|
||||
if session.renderer.on_rgba(display, rgba) {
|
||||
if let Some(stream) = &session.event_stream {
|
||||
stream.add(EventToUI::Rgba(display));
|
||||
}
|
||||
}
|
||||
}
|
||||
self.on_rgba_soft_render(display, rgba);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(feature = "vram")]
|
||||
fn on_texture(&self, display: usize, texture: *mut c_void) {
|
||||
if !self.use_texture_render.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
for (_, session) in self.session_handlers.read().unwrap().iter() {
|
||||
if session.renderer.on_texture(display, texture) {
|
||||
if let Some(stream) = &session.event_stream {
|
||||
@ -845,17 +809,17 @@ impl InvokeUiSession for FlutterHandler {
|
||||
let features = serde_json::ser::to_string(&features).unwrap_or("".to_owned());
|
||||
let resolutions = serialize_resolutions(&pi.resolutions.resolutions);
|
||||
*self.peer_info.write().unwrap() = pi.clone();
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
{
|
||||
self.session_handlers
|
||||
.write()
|
||||
.unwrap()
|
||||
.values_mut()
|
||||
.for_each(|h| {
|
||||
h.renderer.is_support_multi_ui_session =
|
||||
crate::common::is_support_multi_ui_session(&pi.version);
|
||||
});
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let is_support_multi_ui_session = crate::common::is_support_multi_ui_session(&pi.version);
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let is_support_multi_ui_session = false;
|
||||
self.session_handlers
|
||||
.write()
|
||||
.unwrap()
|
||||
.values_mut()
|
||||
.for_each(|h| {
|
||||
h.renderer.is_support_multi_ui_session = is_support_multi_ui_session;
|
||||
});
|
||||
self.push_event(
|
||||
"peer_info",
|
||||
&[
|
||||
@ -1028,7 +992,6 @@ impl InvokeUiSession for FlutterHandler {
|
||||
|
||||
#[inline]
|
||||
fn get_rgba(&self, _display: usize) -> *const u8 {
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
if let Some(rgba_data) = self.display_rgbas.read().unwrap().get(&_display) {
|
||||
if rgba_data.valid {
|
||||
return rgba_data.data.as_ptr();
|
||||
@ -1039,13 +1002,65 @@ impl InvokeUiSession for FlutterHandler {
|
||||
|
||||
#[inline]
|
||||
fn next_rgba(&self, _display: usize) {
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
if let Some(rgba_data) = self.display_rgbas.write().unwrap().get_mut(&_display) {
|
||||
rgba_data.valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FlutterHandler {
|
||||
#[inline]
|
||||
fn on_rgba_soft_render(&self, display: usize, rgba: &mut scrap::ImageRgb) {
|
||||
// Give a chance for plugins or etc to hook a rgba data.
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
for (key, hook) in self.hooks.read().unwrap().iter() {
|
||||
match hook {
|
||||
SessionHook::OnSessionRgba(cb) => {
|
||||
cb(key.to_owned(), rgba);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the current rgba is not fetched by flutter, i.e., is valid.
|
||||
// We give up sending a new event to flutter.
|
||||
let mut rgba_write_lock = self.display_rgbas.write().unwrap();
|
||||
if let Some(rgba_data) = rgba_write_lock.get_mut(&display) {
|
||||
if rgba_data.valid {
|
||||
return;
|
||||
} else {
|
||||
rgba_data.valid = true;
|
||||
}
|
||||
// Return the rgba buffer to the video handler for reusing allocated rgba buffer.
|
||||
std::mem::swap::<Vec<u8>>(&mut rgba.raw, &mut rgba_data.data);
|
||||
} else {
|
||||
let mut rgba_data = RgbaData::default();
|
||||
std::mem::swap::<Vec<u8>>(&mut rgba.raw, &mut rgba_data.data);
|
||||
rgba_data.valid = true;
|
||||
rgba_write_lock.insert(display, rgba_data);
|
||||
}
|
||||
drop(rgba_write_lock);
|
||||
|
||||
// Non-texture-render UI does not support multiple displays in the one UI session.
|
||||
// It's Ok to notify each session for now.
|
||||
for h in self.session_handlers.read().unwrap().values() {
|
||||
if let Some(stream) = &h.event_stream {
|
||||
stream.add(EventToUI::Rgba(display));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
fn on_rgba_flutter_texture_render(&self, display: usize, rgba: &mut scrap::ImageRgb) {
|
||||
for (_, session) in self.session_handlers.read().unwrap().iter() {
|
||||
if session.renderer.on_rgba(display, rgba) {
|
||||
if let Some(stream) = &session.event_stream {
|
||||
stream.add(EventToUI::Rgba(display));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is only used for the default connection session.
|
||||
pub fn session_add_existed(peer_id: String, session_id: SessionID) -> ResultType<()> {
|
||||
sessions::insert_peer_session_id(peer_id, ConnType::DEFAULT_CONN, session_id);
|
||||
@ -1116,17 +1131,12 @@ pub fn session_add(
|
||||
Some(switch_uuid.to_string())
|
||||
};
|
||||
|
||||
#[cfg(feature = "vram")]
|
||||
let adapter_luid = get_adapter_luid();
|
||||
#[cfg(not(feature = "vram"))]
|
||||
let adapter_luid = None;
|
||||
|
||||
session.lc.write().unwrap().initialize(
|
||||
id.to_owned(),
|
||||
conn_type,
|
||||
switch_uuid,
|
||||
force_relay,
|
||||
adapter_luid,
|
||||
get_adapter_luid(),
|
||||
shared_password,
|
||||
);
|
||||
|
||||
@ -1172,14 +1182,11 @@ pub fn session_start_(
|
||||
if let Some(session) = sessions::get_session_by_session_id(session_id) {
|
||||
let is_first_ui_session = session.session_handlers.read().unwrap().len() == 1;
|
||||
if !is_connected && is_first_ui_session {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
log::info!(
|
||||
"Session {} start, render by flutter texture rgba plugin",
|
||||
id
|
||||
"Session {} start, use texture render: {}",
|
||||
id,
|
||||
session.use_texture_render.load(Ordering::Relaxed)
|
||||
);
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
log::info!("Session {} start, render by flutter paint widget", id);
|
||||
|
||||
let session = (*session).clone();
|
||||
std::thread::spawn(move || {
|
||||
let round = session.connection_round_state.lock().unwrap().new_round();
|
||||
@ -1437,14 +1444,13 @@ fn char_to_session_id(c: *const char) -> ResultType<SessionID> {
|
||||
SessionID::from_str(str).map_err(|e| anyhow!("{:?}", e))
|
||||
}
|
||||
|
||||
pub fn session_get_rgba_size(_session_id: SessionID, _display: usize) -> usize {
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
if let Some(session) = sessions::get_session_by_session_id(&_session_id) {
|
||||
pub fn session_get_rgba_size(session_id: SessionID, display: usize) -> usize {
|
||||
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
|
||||
return session
|
||||
.display_rgbas
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&_display)
|
||||
.get(&display)
|
||||
.map_or(0, |rgba| rgba.data.len());
|
||||
}
|
||||
0
|
||||
@ -1468,34 +1474,32 @@ pub fn session_next_rgba(session_id: SessionID, display: usize) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn session_set_size(_session_id: SessionID, _display: usize, _width: usize, _height: usize) {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
pub fn session_set_size(session_id: SessionID, display: usize, width: usize, height: usize) {
|
||||
for s in sessions::get_sessions() {
|
||||
if let Some(h) = s
|
||||
.ui_handler
|
||||
.session_handlers
|
||||
.write()
|
||||
.unwrap()
|
||||
.get_mut(&_session_id)
|
||||
.get_mut(&session_id)
|
||||
{
|
||||
h.renderer.set_size(_display, _width, _height);
|
||||
h.renderer.set_size(display, width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn session_register_pixelbuffer_texture(_session_id: SessionID, _display: usize, _ptr: usize) {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
pub fn session_register_pixelbuffer_texture(session_id: SessionID, display: usize, ptr: usize) {
|
||||
for s in sessions::get_sessions() {
|
||||
if let Some(h) = s
|
||||
.ui_handler
|
||||
.session_handlers
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(&_session_id)
|
||||
.get(&session_id)
|
||||
{
|
||||
h.renderer.register_pixelbuffer_texture(_display, _ptr);
|
||||
h.renderer.register_pixelbuffer_texture(display, ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1518,8 +1522,17 @@ pub fn session_register_gpu_texture(_session_id: SessionID, _display: usize, _ou
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(feature = "vram"))]
|
||||
pub fn get_adapter_luid() -> Option<i64> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "vram")]
|
||||
pub fn get_adapter_luid() -> Option<i64> {
|
||||
if !crate::ui_interface::use_texture_render() {
|
||||
return None;
|
||||
}
|
||||
let get_adapter_luid_func = match &*TEXTURE_GPU_RENDERER_PLUGIN {
|
||||
Ok(lib) => {
|
||||
let find_sym_res = unsafe {
|
||||
@ -1713,7 +1726,6 @@ pub fn try_sync_peer_option(
|
||||
|
||||
// sessions mod is used to avoid the big lock of sessions' map.
|
||||
pub mod sessions {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
use std::collections::HashSet;
|
||||
|
||||
use super::*;
|
||||
@ -1781,14 +1793,6 @@ pub mod sessions {
|
||||
for (peer_key, s) in SESSIONS.write().unwrap().iter_mut() {
|
||||
let mut write_lock = s.ui_handler.session_handlers.write().unwrap();
|
||||
let remove_ret = write_lock.remove(id);
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
if remove_ret.is_some() {
|
||||
if write_lock.is_empty() {
|
||||
remove_peer_key = Some(peer_key.clone());
|
||||
}
|
||||
break;
|
||||
}
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
match remove_ret {
|
||||
Some(_) => {
|
||||
if write_lock.is_empty() {
|
||||
@ -1804,7 +1808,6 @@ pub mod sessions {
|
||||
SESSIONS.write().unwrap().remove(&remove_peer_key?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
fn check_remove_unused_displays(
|
||||
current: Option<usize>,
|
||||
session_id: &SessionID,
|
||||
@ -1852,7 +1855,6 @@ pub mod sessions {
|
||||
s.capture_displays(vec![], vec![], value);
|
||||
} else {
|
||||
// Check if other displays are needed.
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
if value.len() == 1 {
|
||||
check_remove_unused_displays(
|
||||
Some(value[0] as _),
|
||||
@ -1892,16 +1894,14 @@ pub mod sessions {
|
||||
session_id: SessionID,
|
||||
) -> bool {
|
||||
if let Some(s) = SESSIONS.read().unwrap().get(&(peer_id, conn_type)) {
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
let h = SessionHandler::default();
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
let mut h = SessionHandler::default();
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
{
|
||||
h.renderer.is_support_multi_ui_session = crate::common::is_support_multi_ui_session(
|
||||
&s.ui_handler.peer_info.read().unwrap().version,
|
||||
);
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let is_support_multi_ui_session = crate::common::is_support_multi_ui_session(
|
||||
&s.ui_handler.peer_info.read().unwrap().version,
|
||||
);
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let is_support_multi_ui_session = false;
|
||||
h.renderer.is_support_multi_ui_session = is_support_multi_ui_session;
|
||||
let _ = s
|
||||
.ui_handler
|
||||
.session_handlers
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
client::file_trait::FileManager,
|
||||
common::{is_keyboard_mode_supported, make_fd_to_json},
|
||||
flutter::{
|
||||
self, session_add, session_add_existed, session_start_, sessions, try_sync_peer_option,
|
||||
self, session_add, session_add_existed, session_start_, sessions, try_sync_peer_option, FlutterHandler,
|
||||
},
|
||||
input::*,
|
||||
ui_interface::{self, *},
|
||||
@ -711,9 +711,8 @@ pub fn session_change_resolution(session_id: SessionID, display: i32, width: i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_set_size(_session_id: SessionID, _display: usize, _width: usize, _height: usize) {
|
||||
#[cfg(feature = "flutter_texture_render")]
|
||||
super::flutter::session_set_size(_session_id, _display, _width, _height)
|
||||
pub fn session_set_size(session_id: SessionID, display: usize, width: usize, height: usize) {
|
||||
super::flutter::session_set_size(session_id, display, width, height)
|
||||
}
|
||||
|
||||
pub fn session_send_selected_session_id(session_id: SessionID, sid: String) {
|
||||
@ -774,13 +773,13 @@ pub fn main_show_option(_key: String) -> SyncReturn<bool> {
|
||||
|
||||
pub fn main_set_option(key: String, value: String) {
|
||||
if key.eq("custom-rendezvous-server") {
|
||||
set_option(key, value);
|
||||
set_option(key, value.clone());
|
||||
#[cfg(target_os = "android")]
|
||||
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
|
||||
crate::common::test_rendezvous_server();
|
||||
} else {
|
||||
set_option(key, value);
|
||||
set_option(key, value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,12 +891,25 @@ pub fn main_get_local_option(key: String) -> SyncReturn<String> {
|
||||
SyncReturn(get_local_option(key))
|
||||
}
|
||||
|
||||
pub fn main_get_use_texture_render() -> SyncReturn<bool> {
|
||||
SyncReturn(use_texture_render())
|
||||
}
|
||||
|
||||
pub fn main_get_env(key: String) -> SyncReturn<String> {
|
||||
SyncReturn(std::env::var(key).unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn main_set_local_option(key: String, value: String) {
|
||||
set_local_option(key, value)
|
||||
let is_texture_render_key = key.eq(config::keys::OPTION_TEXTURE_RENDER);
|
||||
set_local_option(key, value.clone());
|
||||
if is_texture_render_key {
|
||||
let session_event = [("v", &value)];
|
||||
for session in sessions::get_sessions() {
|
||||
session.push_event("use_texture_render", &session_event, &[]);
|
||||
session.use_texture_render_changed();
|
||||
session.ui_handler.update_use_texture_render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We do use use `main_get_local_option` and `main_set_local_option`.
|
||||
@ -1824,10 +1836,6 @@ pub fn main_hide_docker() -> SyncReturn<bool> {
|
||||
SyncReturn(true)
|
||||
}
|
||||
|
||||
pub fn main_has_pixelbuffer_texture_render() -> SyncReturn<bool> {
|
||||
SyncReturn(cfg!(feature = "flutter_texture_render"))
|
||||
}
|
||||
|
||||
pub fn main_has_file_clipboard() -> SyncReturn<bool> {
|
||||
let ret = cfg!(any(
|
||||
target_os = "windows",
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "清除 Wayland 的屏幕选择后,您可以重新选择分享的屏幕。"),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "是否确认清除 Wayland 的分享屏幕选择?"),
|
||||
("android_new_voice_call_tip", "收到新的语音呼叫请求。如果您接受,音频将切换为语音通信。"),
|
||||
("texture_render_tip", "使用纹理渲染,使图片更加流畅。"),
|
||||
("Use texture rendering", "使用纹理渲染"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Po vymazání výběru obrazovky můžete znovu vybrat obrazovku, kterou chcete sdílet."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Opravdu chcete vymazat výběr obrazovky Wayland?"),
|
||||
("android_new_voice_call_tip", "Byl přijat nový požadavek na hlasové volání. Pokud hovor přijmete, přepne se zvuk na hlasovou komunikaci."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Nachdem Sie die Bildschirmauswahl gelöscht haben, können Sie den freizugebenden Bildschirm erneut auswählen."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Sind Sie sicher, dass Sie die Auswahl des Wayland-Bildschirms löschen möchten?"),
|
||||
("android_new_voice_call_tip", "Eine neue Sprachanrufanfrage wurde empfangen. Wenn Sie die Anfrage annehmen, wird der Ton auf Sprachkommunikation umgeschaltet."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -228,5 +228,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "After clearing the screen selection, you can reselect the screen to share."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Are you sure to clear the Wayland screen selection?"),
|
||||
("android_new_voice_call_tip", "A new voice call request was received. If you accept, the audio will switch to voice communication."),
|
||||
("texture_render_tip", "Use texture rendering to make the pictures smoother."),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Tras borrar la selección de pantalla, puedes volver a seleccionarla para compartir."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "¿Seguro que deseas borrar la selección de pantalla Wayland?"),
|
||||
("android_new_voice_call_tip", "Se ha recibido una nueva solicitud de llamada de voz. Si aceptas el audio cambiará a comunicación de voz."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "پس از پاک کردن صفحه انتخابی، می توانید صفحه را برای اشتراک گذاری مجدد انتخاب کنید"),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "را پاک می کنید؟ Wayland آیا مطمئن هستید که انتخاب صفحه"),
|
||||
("android_new_voice_call_tip", "یک درخواست تماس صوتی جدید دریافت شد. اگر بپذیرید، صدا به ارتباط صوتی تغییر خواهد کرد."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Dopo aver annullato la selezione schermo, è possibile selezionare nuovamente lo schermo da condividere."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Sei sicuro di voler annullare la selezione schermo Wayland?"),
|
||||
("android_new_voice_call_tip", "È stata ricevuta una nuova richiesta di chiamata vocale. Se accetti, l'audio passerà alla comunicazione vocale."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Pēc ekrāna atlases notīrīšanas varat atkārtoti atlasīt ekrānu, ko kopīgot."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Vai tiešām notīrīt Wayland ekrāna atlasi?"),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Nadat je de schermselectie hebt gewist, kun je het scherm dat je wilt delen opnieuw selecteren."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Weet je zeker dat je de Wayland-schermselectie wilt wissen?"),
|
||||
("android_new_voice_call_tip", "Er is een nieuwe spraakoproep ontvangen. Als u het aanvaardt, schakelt de audio over naar spraakcommunicatie."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "После отмены можно заново выбрать экран для демонстрации."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Отменить выбор экрана Wayland?"),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Po vymazaní výberu obrazovky môžete znova vybrať obrazovku, ktorú chcete zdieľať."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Určite ste si istý, že chcete vyčistiť výber obrazovky Wayland?"),
|
||||
("android_new_voice_call_tip", "Bola prijatá nová žiadosť o hlasový hovor. Ak ho prijmete, zvuk sa prepne na hlasovú komunikáciu."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "清除 Wayland 的螢幕選擇後,您可以重新選擇分享的螢幕。"),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "是否確認清除 Wayland 的分享螢幕選擇?"),
|
||||
("android_new_voice_call_tip", "收到新的語音通話請求。如果您接受,音訊將切換為語音通訊。"),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", "Після очищення вибору екрана ви можете повторно вибрати екран для поширення."),
|
||||
("confirm_clear_Wayland_screen_selection_tip", "Ви впевнені, що хочете очистити вибір екрана Wayland?"),
|
||||
("android_new_voice_call_tip", "Отримано новий запит на голосовий дзвінок. Якщо ви приймете його, аудіо перемкнеться на голосовий звʼязок."),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -613,5 +613,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("clear_Wayland_screen_selection_tip", ""),
|
||||
("confirm_clear_Wayland_screen_selection_tip", ""),
|
||||
("android_new_voice_call_tip", ""),
|
||||
("texture_render_tip", ""),
|
||||
("Use texture rendering", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ use scrap::{
|
||||
codec::{Encoder, EncoderCfg, Quality},
|
||||
record::{Recorder, RecorderContext},
|
||||
vpxcodec::{VpxEncoderConfig, VpxVideoCodecId},
|
||||
CodecFormat, Display, EncodeInput, Frame, TraitCapturer,
|
||||
CodecFormat, Display, EncodeInput, TraitCapturer,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use std::sync::Once;
|
||||
|
@ -169,6 +169,26 @@ pub fn get_option<T: AsRef<str>>(key: T) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn use_texture_render() -> bool {
|
||||
cfg!(feature = "flutter")
|
||||
&& LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y"
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
pub fn use_texture_render() -> bool {
|
||||
cfg!(feature = "flutter")
|
||||
&& LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N"
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
pub fn use_texture_render() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_local_option(key: String) -> String {
|
||||
LocalConfig::get_option(&key)
|
||||
@ -898,7 +918,8 @@ pub fn has_vram() -> bool {
|
||||
#[cfg(feature = "flutter")]
|
||||
#[inline]
|
||||
pub fn supported_hwdecodings() -> (bool, bool) {
|
||||
let decoding = scrap::codec::Decoder::supported_decodings(None, true, None, &vec![]);
|
||||
let decoding =
|
||||
scrap::codec::Decoder::supported_decodings(None, use_texture_render(), None, &vec![]);
|
||||
#[allow(unused_mut)]
|
||||
let (mut h264, mut h265) = (decoding.ability_h264 > 0, decoding.ability_h265 > 0);
|
||||
#[cfg(feature = "vram")]
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
common::{get_supported_keyboard_modes, is_keyboard_mode_supported},
|
||||
input::{MOUSE_BUTTON_LEFT, MOUSE_TYPE_DOWN, MOUSE_TYPE_UP, MOUSE_TYPE_WHEEL},
|
||||
ui_interface::use_texture_render,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
@ -448,7 +449,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
let mark_unsupported = self.lc.read().unwrap().mark_unsupported.clone();
|
||||
let decoder = scrap::codec::Decoder::supported_decodings(
|
||||
None,
|
||||
cfg!(feature = "flutter"),
|
||||
use_texture_render(),
|
||||
luid,
|
||||
&mark_unsupported,
|
||||
);
|
||||
@ -469,6 +470,11 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
|
||||
pub fn use_texture_render_changed(&self) {
|
||||
self.send(Data::ResetDecoder(None));
|
||||
self.change_prefer_codec();
|
||||
}
|
||||
|
||||
pub fn restart_remote_device(&self) {
|
||||
let mut lc = self.lc.write().unwrap();
|
||||
lc.restarting_remote_device = true;
|
||||
@ -732,8 +738,7 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
msg_out.set_misc(misc);
|
||||
self.send(Data::Message(msg_out));
|
||||
|
||||
#[cfg(not(feature = "flutter_texture_render"))]
|
||||
{
|
||||
if !use_texture_render() {
|
||||
self.capture_displays(vec![], vec![], vec![display]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user