mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-03-25 14:11:14 +03: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:
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user