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:
fufesou 2024-05-28 16:42:30 +08:00 committed by GitHub
parent 010b17509a
commit 72ec86b58d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 481 additions and 282 deletions

View File

@ -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

View File

@ -19,7 +19,6 @@ path = "src/naming.rs"
[features]
inline = []
cli = []
flutter_texture_render = []
use_samplerate = ["samplerate"]
use_rubato = ["rubato"]
use_dasp = ["dasp"]

View File

@ -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)

View File

@ -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) {

View File

@ -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

View File

@ -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';

View File

@ -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";

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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() {}
}

View File

@ -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,

View File

@ -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 {

View File

@ -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]

View File

@ -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.

View File

@ -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(

View File

@ -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");

View File

@ -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

View File

@ -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",

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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")]

View File

@ -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]);
}
}