From 54bebee35fef2f2c2746a0ddfcb3f9bab5badfc5 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 18 Feb 2023 11:16:07 +0800 Subject: [PATCH 01/17] wip: texture windows --- Cargo.lock | 1 + Cargo.toml | 3 ++- src/flutter.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 115845b50..eb5461a6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4860,6 +4860,7 @@ dependencies = [ "include_dir", "jni 0.19.0", "lazy_static", + "libloading", "libpulse-binding", "libpulse-simple-binding", "mac_address", diff --git a/Cargo.toml b/Cargo.toml index f685e3f2e..0a7af0cbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ default-run = "rustdesk" [lib] name = "librustdesk" -crate-type = ["cdylib", "staticlib", "rlib"] +crate-type = ["cdylib"] [[bin]] name = "naming" @@ -67,6 +67,7 @@ url = { version = "2.1", features = ["serde"] } reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } chrono = "0.4.23" cidr-utils = "0.5.9" +libloading = "0.7.4" [target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies] cpal = "0.13.5" diff --git a/src/flutter.rs b/src/flutter.rs index bad6e0008..cab7a900d 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -8,6 +8,8 @@ use hbb_common::{ bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, ResultType, }; +use libc::c_void; +use libloading::Library; use serde_json::json; use std::sync::atomic::{AtomicBool, Ordering}; use std::{ @@ -115,6 +117,58 @@ pub struct FlutterHandler { // We must check the `rgba_valid` before reading [rgba]. pub rgba: Arc>>, pub rgba_valid: Arc, + pub renderer: Arc> +} +// pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void , buffer: *const u8 , width: c_int, height: c_int); + +extern "C" { + fn FlutterRgbaRendererPluginOnRgba(texture_rgba: *mut c_void , buffer: *const u8 , width: c_int, height: c_int); +} + +// Video Texture Renderer in Flutter +#[derive(Default, Clone)] +pub struct VideoRenderer { + // TextureRgba pointer in flutter native. + ptr: usize, + width: i32, + height: i32, + // on_rgba_func: FlutterRgbaRendererPluginOnRgba +} + +// impl Default for VideoRenderer { +// fn default() -> Self { +// unsafe { +// let lib = Library::new("texture_rgba_renderer_plugin").expect("`libtexture_rgba_renderer_plugin` not found, please add `texture_rgba_renderer` in your project"); +// let func = lib.get(b"FlutterRgbaRendererPluginOnRgba"); +// } + +// } +// } + + + +impl VideoRenderer { + pub fn new(ptr: usize) -> Self { + Self { + ptr, + ..Default::default() + } + } + + pub fn set_size(&mut self, width: i32, height: i32) { + self.width = width; + self.height = height; + } + + pub fn on_rgba(&self, rgba: *const u8) { + if self.ptr == usize::default() { + return; + } + #[cfg(target_os = "windows")] + unsafe { + FlutterRgbaRendererPluginOnRgba(self.ptr as _, rgba, self.width as _, self.height as _); + } + } } impl FlutterHandler { @@ -156,6 +210,10 @@ impl FlutterHandler { } serde_json::ser::to_string(&msg_vec).unwrap_or("".to_owned()) } + + pub fn register_texture(&self, ptr: usize) { + self.renderer.write().unwrap().ptr = ptr; + } } impl InvokeUiSession for FlutterHandler { @@ -324,9 +382,12 @@ impl InvokeUiSession for FlutterHandler { self.rgba_valid.store(true, Ordering::Relaxed); // Return the rgba buffer to the video handler for reusing allocated rgba buffer. std::mem::swap::>(data, &mut *self.rgba.write().unwrap()); + #[cfg(not(any(target_os = "windows")))] if let Some(stream) = &*self.event_stream.read().unwrap() { stream.add(EventToUI::Rgba); } + #[cfg(any(target_os = "windows"))] + self.renderer.read().unwrap().on_rgba(self.rgba.read().unwrap().as_ptr()); } fn set_peer_info(&self, pi: &PeerInfo) { @@ -741,3 +802,13 @@ pub fn session_next_rgba(id: *const char) { } } } + +#[no_mangle] +pub fn session_register_texture(id: *const char, ptr: usize) { + let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; + if let Ok(id) = id.to_str() { + if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + return session.register_texture(ptr); + } + } +} \ No newline at end of file From ea07b9690e8cc3ae7e7c8e88dd01a50117e789e6 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sat, 18 Feb 2023 11:47:18 +0800 Subject: [PATCH 02/17] fix: rgba compile --- src/flutter.rs | 69 ++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/flutter.rs b/src/flutter.rs index cab7a900d..2888ffe75 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -9,7 +9,7 @@ use hbb_common::{ ResultType, }; use libc::c_void; -use libloading::Library; +use libloading::{Library, Symbol}; use serde_json::json; use std::sync::atomic::{AtomicBool, Ordering}; use std::{ @@ -29,6 +29,18 @@ lazy_static::lazy_static! { pub static ref CUR_SESSION_ID: RwLock = Default::default(); pub static ref SESSIONS: RwLock>> = Default::default(); pub static ref GLOBAL_EVENT_STREAM: RwLock>> = Default::default(); // rust to dart event channel + #[cfg(not(any(target_os = "ios", target_os = "android")))] + pub static ref TEXURE_RGBA_RENDERER_PLUGIN: Library = { + unsafe { + #[cfg(target_os = "windows")] + let lib = Library::new("texture_rgba_renderer_plugin.dll"); + #[cfg(target_os = "macos")] + let lib = Library::new("texture_rgba_renderer_plugin.dylib"); + #[cfg(target_os = "linux")] + let lib = Library::new("texture_rgba_renderer_plugin.so"); + lib.expect("`libtexture_rgba_renderer_plugin` not found, please add `texture_rgba_renderer` in your flutter project") + } + }; } /// FFI for rustdesk core's main entry. @@ -117,35 +129,33 @@ pub struct FlutterHandler { // We must check the `rgba_valid` before reading [rgba]. pub rgba: Arc>>, pub rgba_valid: Arc, - pub renderer: Arc> -} -// pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void , buffer: *const u8 , width: c_int, height: c_int); - -extern "C" { - fn FlutterRgbaRendererPluginOnRgba(texture_rgba: *mut c_void , buffer: *const u8 , width: c_int, height: c_int); + pub renderer: VideoRenderer, } +pub type FlutterRgbaRendererPluginOnRgba = + unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); // Video Texture Renderer in Flutter -#[derive(Default, Clone)] +#[derive(Clone)] pub struct VideoRenderer { // TextureRgba pointer in flutter native. ptr: usize, width: i32, height: i32, - // on_rgba_func: FlutterRgbaRendererPluginOnRgba + on_rgba_func: Symbol<'static, FlutterRgbaRendererPluginOnRgba>, } -// impl Default for VideoRenderer { -// fn default() -> Self { -// unsafe { -// let lib = Library::new("texture_rgba_renderer_plugin").expect("`libtexture_rgba_renderer_plugin` not found, please add `texture_rgba_renderer` in your project"); -// let func = lib.get(b"FlutterRgbaRendererPluginOnRgba"); -// } - -// } -// } - - +impl Default for VideoRenderer { + fn default() -> Self { + unsafe { + Self { + on_rgba_func: TEXURE_RGBA_RENDERER_PLUGIN + .get::(b"FlutterRgbaRendererPluginOnRgba") + .expect("Symbol FlutterRgbaRendererPluginOnRgba not found."), + ..Default::default() + } + } + } +} impl VideoRenderer { pub fn new(ptr: usize) -> Self { @@ -164,10 +174,8 @@ impl VideoRenderer { if self.ptr == usize::default() { return; } - #[cfg(target_os = "windows")] - unsafe { - FlutterRgbaRendererPluginOnRgba(self.ptr as _, rgba, self.width as _, self.height as _); - } + let func = self.on_rgba_func.clone(); + unsafe {func(self.ptr as _, rgba, self.width as _, self.height as _)}; } } @@ -211,8 +219,8 @@ impl FlutterHandler { serde_json::ser::to_string(&msg_vec).unwrap_or("".to_owned()) } - pub fn register_texture(&self, ptr: usize) { - self.renderer.write().unwrap().ptr = ptr; + pub fn register_texture(&mut self, ptr: usize) { + self.renderer.ptr = ptr; } } @@ -382,12 +390,13 @@ impl InvokeUiSession for FlutterHandler { self.rgba_valid.store(true, Ordering::Relaxed); // Return the rgba buffer to the video handler for reusing allocated rgba buffer. std::mem::swap::>(data, &mut *self.rgba.write().unwrap()); - #[cfg(not(any(target_os = "windows")))] + #[cfg(any(target_os = "android", target_os = "ios"))] if let Some(stream) = &*self.event_stream.read().unwrap() { stream.add(EventToUI::Rgba); } - #[cfg(any(target_os = "windows"))] - self.renderer.read().unwrap().on_rgba(self.rgba.read().unwrap().as_ptr()); + #[cfg(not(any(target_os = "android", target_os = "ios")))] + self.renderer + .on_rgba(self.rgba.read().unwrap().as_ptr()); } fn set_peer_info(&self, pi: &PeerInfo) { @@ -811,4 +820,4 @@ pub fn session_register_texture(id: *const char, ptr: usize) { return session.register_texture(ptr); } } -} \ No newline at end of file +} From d3455f3ce2711e8af6631df25511f28548278720 Mon Sep 17 00:00:00 2001 From: Kingtous Date: Sun, 19 Feb 2023 15:25:30 +0800 Subject: [PATCH 03/17] feat: adapt for the latest renderer plugin --- flutter/lib/common.dart | 5 +++ flutter/lib/desktop/pages/remote_page.dart | 42 ++++++++++++++++++---- flutter/lib/models/model.dart | 17 ++++----- flutter/lib/models/native_model.dart | 13 +++++++ src/flutter.rs | 28 ++++++++++----- src/ui/remote.rs | 2 +- src/ui_session_interface.rs | 2 +- 7 files changed, 85 insertions(+), 24 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index ff8dfbb09..6d3e4c3b7 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -19,6 +19,7 @@ import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:flutter_hbb/utils/platform_channel.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; +import 'package:texture_rgba_renderer/texture_rgba_renderer.dart'; import 'package:uni_links/uni_links.dart'; import 'package:uni_links_desktop/uni_links_desktop.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -44,6 +45,10 @@ var isWeb = false; var isWebDesktop = false; var version = ""; int androidVersion = 0; +/// Incriment count for textureId. +int _textureId = 0; +int get newTextureId => _textureId ++; +final textureRenderer = TextureRgbaRenderer(); /// only available for Windows target int windowsBuildNumber = 0; diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index f9db985d9..df9874172 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -63,6 +63,8 @@ class _RemotePageState extends State late RxBool _zoomCursor; late RxBool _remoteCursorMoved; late RxBool _keyboardEnabled; + late RxInt _textureId; + late int _textureKey; final _blockableOverlayState = BlockableOverlayState(); @@ -85,6 +87,8 @@ class _RemotePageState extends State _showRemoteCursor = ShowRemoteCursorState.find(id); _keyboardEnabled = KeyboardEnabledState.find(id); _remoteCursorMoved = RemoteCursorMovedState.find(id); + _textureKey = newTextureId; + _textureId = RxInt(-1); } void _removeStates(String id) { @@ -119,6 +123,16 @@ class _RemotePageState extends State if (!Platform.isLinux) { Wakelock.enable(); } + // Register texture. + _textureId.value = -1; + textureRenderer.createTexture(_textureKey).then((id) async { + if (id != -1) { + final ptr = await textureRenderer.getTexturePtr(_textureKey); + debugPrint("id: $id, texture_key: $_textureKey"); + platformFFI.registerTexture(widget.id, ptr); + _textureId.value = id; + } + }); _ffi.ffiModel.updateEventListener(widget.id); _ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); // Session option should be set after models.dart/FFI.start @@ -198,6 +212,7 @@ class _RemotePageState extends State Wakelock.disable(); } Get.delete(tag: widget.id); + textureRenderer.closeTexture(_textureKey); super.dispose(); _removeStates(widget.id); } @@ -346,6 +361,7 @@ class _RemotePageState extends State cursorOverImage: _cursorOverImage, keyboardEnabled: _keyboardEnabled, remoteCursorMoved: _remoteCursorMoved, + textureId: _textureId, listenerBuilder: (child) => _buildRawPointerMouseRegion(child, enterView, leaveView), ); @@ -383,6 +399,7 @@ class ImagePaint extends StatefulWidget { final RxBool cursorOverImage; final RxBool keyboardEnabled; final RxBool remoteCursorMoved; + final RxInt textureId; final Widget Function(Widget)? listenerBuilder; ImagePaint( @@ -392,6 +409,7 @@ class ImagePaint extends StatefulWidget { required this.cursorOverImage, required this.keyboardEnabled, required this.remoteCursorMoved, + required this.textureId, this.listenerBuilder}) : super(key: key); @@ -466,9 +484,15 @@ class _ImagePaintState extends State { final imageWidth = c.getDisplayWidth() * s; final imageHeight = c.getDisplayHeight() * s; final imageSize = Size(imageWidth, imageHeight); - final imageWidget = CustomPaint( - size: imageSize, - painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), + print("width: $imageWidth/$imageHeight"); + // final imageWidget = CustomPaint( + // size: imageSize, + // painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), + // ); + final imageWidget = SizedBox( + width: imageHeight, + height: imageHeight, + child: Obx(() => Texture(textureId: widget.textureId.value)), ); return NotificationListener( @@ -493,9 +517,15 @@ class _ImagePaintState extends State { context, _buildListener(imageWidget), c.size, imageSize)), )); } else { - final imageWidget = CustomPaint( - size: Size(c.size.width, c.size.height), - painter: ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s), + // final imageWidget = CustomPaint( + // size: Size(c.size.width, c.size.height), + // painter: ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s), + // ); + final imageWidget = Center( + child: AspectRatio( + aspectRatio: c.size.width / c.size.height, + child: Obx(() => Texture(textureId: widget.textureId.value)), + ), ); return mouseRegion(child: _buildListener(imageWidget)); } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 1afb5b147..0b6f14636 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -1446,14 +1446,15 @@ class FFI { } } else if (message is EventToUI_Rgba) { // Fetch the image buffer from rust codes. - final sz = platformFFI.getRgbaSize(id); - if (sz == null || sz == 0) { - return; - } - final rgba = platformFFI.getRgba(id, sz); - if (rgba != null) { - imageModel.onRgba(rgba); - } + // final sz = platformFFI.getRgbaSize(id); + // if (sz == null || sz == 0) { + // return; + // } + // final rgba = platformFFI.getRgba(id, sz); + // if (rgba != null) { + // imageModel.onRgba(rgba); + // } + // imageModel.onRgba(rgba); } } debugPrint('Exit session event loop'); diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index ba62b775e..13f5b4587 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -30,6 +30,9 @@ typedef F4Dart = int Function(Pointer); typedef F5 = Void Function(Pointer); typedef F5Dart = void Function(Pointer); typedef HandleEvent = Future Function(Map evt); +// pub fn session_register_texture(id: *const char, ptr: usize) +typedef F6 = Void Function(Pointer, Uint64); +typedef F6Dart = void Function(Pointer, int); /// FFI wrapper around the native Rust core. /// Hides the platform differences. @@ -52,6 +55,8 @@ class PlatformFFI { F3? _session_get_rgba; F4Dart? _session_get_rgba_size; F5Dart? _session_next_rgba; + F6Dart? _session_register_texture; + static get localeName => Platform.localeName; @@ -130,6 +135,13 @@ class PlatformFFI { malloc.free(a); } + void registerTexture(String id, int ptr) { + if (_session_register_texture == null) return; + final a = id.toNativeUtf8(); + _session_register_texture!(a, ptr); + malloc.free(a); + } + /// Init the FFI class, loads the native Rust core library. Future init(String appType) async { _appType = appType; @@ -150,6 +162,7 @@ class PlatformFFI { dylib.lookupFunction("session_get_rgba_size"); _session_next_rgba = dylib.lookupFunction("session_next_rgba"); + _session_register_texture = dylib.lookupFunction("session_register_texture"); try { // SYSTEM user failed _dir = (await getApplicationDocumentsDirectory()).path; diff --git a/src/flutter.rs b/src/flutter.rs index 2888ffe75..f5d764e66 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -8,7 +8,7 @@ use hbb_common::{ bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, ResultType, }; -use libc::c_void; +use libc::{c_void}; use libloading::{Library, Symbol}; use serde_json::json; use std::sync::atomic::{AtomicBool, Ordering}; @@ -37,7 +37,7 @@ lazy_static::lazy_static! { #[cfg(target_os = "macos")] let lib = Library::new("texture_rgba_renderer_plugin.dylib"); #[cfg(target_os = "linux")] - let lib = Library::new("texture_rgba_renderer_plugin.so"); + let lib = Library::new("libtexture_rgba_renderer_plugin.so"); lib.expect("`libtexture_rgba_renderer_plugin` not found, please add `texture_rgba_renderer` in your flutter project") } }; @@ -129,7 +129,8 @@ pub struct FlutterHandler { // We must check the `rgba_valid` before reading [rgba]. pub rgba: Arc>>, pub rgba_valid: Arc, - pub renderer: VideoRenderer, + pub renderer: Arc>, + peer_info: Arc> } pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); @@ -148,10 +149,12 @@ impl Default for VideoRenderer { fn default() -> Self { unsafe { Self { + ptr: 0, + width: 0, + height: 0, on_rgba_func: TEXURE_RGBA_RENDERER_PLUGIN .get::(b"FlutterRgbaRendererPluginOnRgba") .expect("Symbol FlutterRgbaRendererPluginOnRgba not found."), - ..Default::default() } } } @@ -220,7 +223,7 @@ impl FlutterHandler { } pub fn register_texture(&mut self, ptr: usize) { - self.renderer.ptr = ptr; + self.renderer.write().unwrap().ptr = ptr; } } @@ -381,6 +384,7 @@ impl InvokeUiSession for FlutterHandler { // unused in flutter fn adapt_size(&self) {} + #[inline] fn on_rgba(&self, data: &mut Vec) { // If the current rgba is not fetched by flutter, i.e., is valid. // We give up sending a new event to flutter. @@ -390,13 +394,15 @@ impl InvokeUiSession for FlutterHandler { self.rgba_valid.store(true, Ordering::Relaxed); // Return the rgba buffer to the video handler for reusing allocated rgba buffer. std::mem::swap::>(data, &mut *self.rgba.write().unwrap()); - #[cfg(any(target_os = "android", target_os = "ios"))] if let Some(stream) = &*self.event_stream.read().unwrap() { stream.add(EventToUI::Rgba); } #[cfg(not(any(target_os = "android", target_os = "ios")))] - self.renderer + { + self.renderer.read().unwrap() .on_rgba(self.rgba.read().unwrap().as_ptr()); + self.next_rgba(); + } } fn set_peer_info(&self, pi: &PeerInfo) { @@ -410,6 +416,9 @@ impl InvokeUiSession for FlutterHandler { features.insert("privacy_mode", 0); } let features = serde_json::ser::to_string(&features).unwrap_or("".to_owned()); + *self.peer_info.write().unwrap() = pi.clone(); + let curr_display = &pi.displays[pi.current_display as usize]; + self.renderer.write().unwrap().set_size(curr_display.width, curr_display.height); self.push_event( "peer_info", vec![ @@ -426,6 +435,7 @@ impl InvokeUiSession for FlutterHandler { } fn set_displays(&self, displays: &Vec) { + self.peer_info.write().unwrap().displays = displays.clone(); self.push_event( "sync_peer_info", vec![("displays", &Self::make_displays_msg(displays))], @@ -457,6 +467,8 @@ impl InvokeUiSession for FlutterHandler { } fn switch_display(&self, display: &SwitchDisplay) { + let curr_display = &self.peer_info.read().unwrap().displays[display.display as usize]; + self.renderer.write().unwrap().set_size(curr_display.width, curr_display.height); self.push_event( "switch_display", vec![ @@ -521,7 +533,7 @@ impl InvokeUiSession for FlutterHandler { } #[inline] - fn next_rgba(&mut self) { + fn next_rgba(&self) { self.rgba_valid.store(false, Ordering::Relaxed); } } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 4794efb65..7b31c84e9 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -298,7 +298,7 @@ impl InvokeUiSession for SciterHandler { std::ptr::null() } - fn next_rgba(&mut self) {} + fn next_rgba(&self) {} } pub struct SciterSession(Session); diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 5a83ee572..5fbf2f4e7 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -798,7 +798,7 @@ pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default { fn on_voice_call_waiting(&self); fn on_voice_call_incoming(&self); fn get_rgba(&self) -> *const u8; - fn next_rgba(&mut self); + fn next_rgba(&self); } impl Deref for Session { From 5acedecf0c09546ec368ca22fa7367ec7b9c0ae5 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 21 Feb 2023 21:56:46 +0800 Subject: [PATCH 04/17] texture paint Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 33 ++++++--- flutter/lib/models/model.dart | 45 +++++++---- src/flutter.rs | 86 ++++++++++++++-------- src/flutter_ffi.rs | 6 ++ 4 files changed, 115 insertions(+), 55 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index df9874172..4a2f5c0e8 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -126,9 +126,9 @@ class _RemotePageState extends State // Register texture. _textureId.value = -1; textureRenderer.createTexture(_textureKey).then((id) async { + debugPrint("id: $id, texture_key: $_textureKey"); if (id != -1) { final ptr = await textureRenderer.getTexturePtr(_textureKey); - debugPrint("id: $id, texture_key: $_textureKey"); platformFFI.registerTexture(widget.id, ptr); _textureId.value = id; } @@ -197,6 +197,8 @@ class _RemotePageState extends State @override void dispose() { debugPrint("REMOTE PAGE dispose ${widget.id}"); + platformFFI.registerTexture(widget.id, 0); + textureRenderer.closeTexture(_textureKey); // ensure we leave this session, this is a double check bind.sessionEnterOrLeave(id: widget.id, enter: false); DesktopMultiWindow.removeListener(this); @@ -212,7 +214,6 @@ class _RemotePageState extends State Wakelock.disable(); } Get.delete(tag: widget.id); - textureRenderer.closeTexture(_textureKey); super.dispose(); _removeStates(widget.id); } @@ -484,15 +485,14 @@ class _ImagePaintState extends State { final imageWidth = c.getDisplayWidth() * s; final imageHeight = c.getDisplayHeight() * s; final imageSize = Size(imageWidth, imageHeight); - print("width: $imageWidth/$imageHeight"); // final imageWidget = CustomPaint( // size: imageSize, // painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), // ); final imageWidget = SizedBox( - width: imageHeight, + width: imageWidth, height: imageHeight, - child: Obx(() => Texture(textureId: widget.textureId.value)), + child: Obx(() => Texture(textureId: widget.textureId.value)), ); return NotificationListener( @@ -521,13 +521,22 @@ class _ImagePaintState extends State { // size: Size(c.size.width, c.size.height), // painter: ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s), // ); - final imageWidget = Center( - child: AspectRatio( - aspectRatio: c.size.width / c.size.height, - child: Obx(() => Texture(textureId: widget.textureId.value)), - ), - ); - return mouseRegion(child: _buildListener(imageWidget)); + if (c.size.width > 0 && c.size.height > 0) { + final imageWidget = Stack( + children: [ + Positioned( + left: c.x, + top: c.y, + width: c.getDisplayWidth() * s, + height: c.getDisplayHeight() * s, + child: Texture(textureId: widget.textureId.value), + ) + ], + ); + return mouseRegion(child: _buildListener(imageWidget)); + } else { + return Container(); + } } } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 0b6f14636..a38db2a90 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -252,6 +252,8 @@ class FfiModel with ChangeNotifier { parent.target?.cursorModel.updateDisplayOrigin(_display.x, _display.y); } + _updateSessionWidthHeight(peerId, display.width, display.height); + try { CurrentDisplayState.find(peerId).value = _pi.currentDisplay; } catch (e) { @@ -367,6 +369,10 @@ class FfiModel with ChangeNotifier { }); } + _updateSessionWidthHeight(String id, int width, int height) { + bind.sessionSetSize(id: id, width: display.width, height: display.height); + } + /// Handle the peer info event based on [evt]. handlePeerInfo(Map evt, String peerId) async { // recent peer updated by handle_peer_info(ui_session_interface.rs) --> handle_peer_info(client.rs) --> save_config(client.rs) @@ -420,6 +426,7 @@ class FfiModel with ChangeNotifier { stateGlobal.displaysCount.value = _pi.displays.length; if (_pi.currentDisplay < _pi.displays.length) { _display = _pi.displays[_pi.currentDisplay]; + _updateSessionWidthHeight(peerId, display.width, display.height); } if (displays.isNotEmpty) { parent.target?.dialogManager.showLoading( @@ -485,19 +492,18 @@ class ImageModel with ChangeNotifier { WeakReference parent; - final List _callbacksOnFirstImage = []; + final List callbacksOnFirstImage = []; ImageModel(this.parent); - addCallbackOnFirstImage(Function(String) cb) => - _callbacksOnFirstImage.add(cb); + addCallbackOnFirstImage(Function(String) cb) => callbacksOnFirstImage.add(cb); onRgba(Uint8List rgba) { if (_waitForImage[id]!) { _waitForImage[id] = false; parent.target?.dialogManager.dismissAll(); if (isDesktop) { - for (final cb in _callbacksOnFirstImage) { + for (final cb in callbacksOnFirstImage) { cb(id); } } @@ -1445,16 +1451,27 @@ class FFI { debugPrint('json.decode fail1(): $e, ${message.field0}'); } } else if (message is EventToUI_Rgba) { - // Fetch the image buffer from rust codes. - // final sz = platformFFI.getRgbaSize(id); - // if (sz == null || sz == 0) { - // return; - // } - // final rgba = platformFFI.getRgba(id, sz); - // if (rgba != null) { - // imageModel.onRgba(rgba); - // } - // imageModel.onRgba(rgba); + if (Platform.isAndroid || Platform.isIOS) { + // Fetch the image buffer from rust codes. + final sz = platformFFI.getRgbaSize(id); + if (sz == null || sz == 0) { + return; + } + final rgba = platformFFI.getRgba(id, sz); + if (rgba != null) { + imageModel.onRgba(rgba); + } + } else { + if (_waitForImage[id]!) { + _waitForImage[id] = false; + dialogManager.dismissAll(); + for (final cb in imageModel.callbacksOnFirstImage) { + cb(id); + } + await canvasModel.updateViewStyle(); + await canvasModel.updateScrollStyle(); + } + } } } debugPrint('Exit session event loop'); diff --git a/src/flutter.rs b/src/flutter.rs index f5d764e66..a5689bce6 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -5,12 +5,13 @@ use crate::{ }; use flutter_rust_bridge::StreamSink; use hbb_common::{ - bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, - ResultType, + bail, config::LocalConfig, get_version_number, libc::c_void, message_proto::*, + rendezvous_proto::ConnType, ResultType, }; -use libc::{c_void}; use libloading::{Library, Symbol}; use serde_json::json; + +#[cfg(any(target_os = "android", target_os = "ios"))] use std::sync::atomic::{AtomicBool, Ordering}; use std::{ collections::HashMap, @@ -30,7 +31,7 @@ lazy_static::lazy_static! { pub static ref SESSIONS: RwLock>> = Default::default(); pub static ref GLOBAL_EVENT_STREAM: RwLock>> = Default::default(); // rust to dart event channel #[cfg(not(any(target_os = "ios", target_os = "android")))] - pub static ref TEXURE_RGBA_RENDERER_PLUGIN: Library = { + pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Library = { unsafe { #[cfg(target_os = "windows")] let lib = Library::new("texture_rgba_renderer_plugin.dll"); @@ -127,21 +128,26 @@ pub struct FlutterHandler { pub event_stream: Arc>>>, // SAFETY: [rgba] is guarded by [rgba_valid], and it's safe to reach [rgba] with `rgba_valid == true`. // We must check the `rgba_valid` before reading [rgba]. + #[cfg(any(target_os = "android", target_os = "ios"))] pub rgba: Arc>>, + #[cfg(any(target_os = "android", target_os = "ios"))] pub rgba_valid: Arc, - pub renderer: Arc>, - peer_info: Arc> + #[cfg(not(any(target_os = "android", target_os = "ios")))] + notify_rendered: Arc>, + renderer: Arc>, + peer_info: Arc>, } pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); // Video Texture Renderer in Flutter #[derive(Clone)] -pub struct VideoRenderer { +struct VideoRenderer { // TextureRgba pointer in flutter native. ptr: usize, width: i32, height: i32, + data_len: usize, on_rgba_func: Symbol<'static, FlutterRgbaRendererPluginOnRgba>, } @@ -152,7 +158,8 @@ impl Default for VideoRenderer { ptr: 0, width: 0, height: 0, - on_rgba_func: TEXURE_RGBA_RENDERER_PLUGIN + data_len: 0, + on_rgba_func: TEXTURE_RGBA_RENDERER_PLUGIN .get::(b"FlutterRgbaRendererPluginOnRgba") .expect("Symbol FlutterRgbaRendererPluginOnRgba not found."), } @@ -161,24 +168,30 @@ impl Default for VideoRenderer { } impl VideoRenderer { - pub fn new(ptr: usize) -> Self { - Self { - ptr, - ..Default::default() - } - } - + #[inline] pub fn set_size(&mut self, width: i32, height: i32) { self.width = width; self.height = height; + self.data_len = if width > 0 && height > 0 { + (width * height * 4) as usize + } else { + 0 + }; } - pub fn on_rgba(&self, rgba: *const u8) { - if self.ptr == usize::default() { + pub fn on_rgba(&self, rgba: &Vec) { + if self.ptr == usize::default() || rgba.len() != self.data_len { return; } let func = self.on_rgba_func.clone(); - unsafe {func(self.ptr as _, rgba, self.width as _, self.height as _)}; + unsafe { + func( + self.ptr as _, + rgba.as_ptr() as _, + self.width as _, + self.height as _, + ) + }; } } @@ -222,9 +235,16 @@ impl FlutterHandler { serde_json::ser::to_string(&msg_vec).unwrap_or("".to_owned()) } + #[inline] pub fn register_texture(&mut self, ptr: usize) { self.renderer.write().unwrap().ptr = ptr; } + + #[inline] + pub fn set_size(&mut self, width: i32, height: i32) { + *self.notify_rendered.write().unwrap() = false; + self.renderer.write().unwrap().set_size(width, height); + } } impl InvokeUiSession for FlutterHandler { @@ -385,6 +405,7 @@ impl InvokeUiSession for FlutterHandler { fn adapt_size(&self) {} #[inline] + #[cfg(any(target_os = "android", target_os = "ios"))] fn on_rgba(&self, data: &mut Vec) { // If the current rgba is not fetched by flutter, i.e., is valid. // We give up sending a new event to flutter. @@ -397,11 +418,18 @@ impl InvokeUiSession for FlutterHandler { if let Some(stream) = &*self.event_stream.read().unwrap() { stream.add(EventToUI::Rgba); } - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - self.renderer.read().unwrap() - .on_rgba(self.rgba.read().unwrap().as_ptr()); - self.next_rgba(); + } + + #[inline] + #[cfg(not(any(target_os = "android", target_os = "ios")))] + fn on_rgba(&self, data: &mut Vec) { + self.renderer.read().unwrap().on_rgba(data); + if *self.notify_rendered.read().unwrap() { + return; + } + if let Some(stream) = &*self.event_stream.read().unwrap() { + stream.add(EventToUI::Rgba); + *self.notify_rendered.write().unwrap() = true; } } @@ -417,8 +445,6 @@ impl InvokeUiSession for FlutterHandler { } let features = serde_json::ser::to_string(&features).unwrap_or("".to_owned()); *self.peer_info.write().unwrap() = pi.clone(); - let curr_display = &pi.displays[pi.current_display as usize]; - self.renderer.write().unwrap().set_size(curr_display.width, curr_display.height); self.push_event( "peer_info", vec![ @@ -467,8 +493,6 @@ impl InvokeUiSession for FlutterHandler { } fn switch_display(&self, display: &SwitchDisplay) { - let curr_display = &self.peer_info.read().unwrap().displays[display.display as usize]; - self.renderer.write().unwrap().set_size(curr_display.width, curr_display.height); self.push_event( "switch_display", vec![ @@ -526,6 +550,7 @@ impl InvokeUiSession for FlutterHandler { #[inline] fn get_rgba(&self) -> *const u8 { + #[cfg(any(target_os = "android", target_os = "ios"))] if self.rgba_valid.load(Ordering::Relaxed) { return self.rgba.read().unwrap().as_ptr(); } @@ -534,6 +559,7 @@ impl InvokeUiSession for FlutterHandler { #[inline] fn next_rgba(&self) { + #[cfg(any(target_os = "android", target_os = "ios"))] self.rgba_valid.store(false, Ordering::Relaxed); } } @@ -793,8 +819,10 @@ pub fn set_cur_session_id(id: String) { } #[no_mangle] -pub fn session_get_rgba_size(id: *const char) -> usize { - let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; +pub fn session_get_rgba_size(_id: *const char) -> usize { + #[cfg(any(target_os = "android", target_os = "ios"))] + let id = unsafe { std::ffi::CStr::from_ptr(_id as _) }; + #[cfg(any(target_os = "android", target_os = "ios"))] if let Ok(id) = id.to_str() { if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { return session.rgba.read().unwrap().len(); diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 7eeb96b5c..c55866dbe 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -529,6 +529,12 @@ pub fn session_switch_sides(id: String) { } } +pub fn session_set_size(id: String, width: i32, height: i32) { + if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) { + session.set_size(width, height); + } +} + pub fn main_get_sound_inputs() -> Vec { #[cfg(not(any(target_os = "android", target_os = "ios")))] return get_sound_inputs(); From 77c4a14845604775751359b51cc5be2b8ae90c23 Mon Sep 17 00:00:00 2001 From: fufesou Date: Tue, 21 Feb 2023 23:46:13 +0800 Subject: [PATCH 05/17] flutter texture render, mid commit Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 61 ++++---- flutter/lib/models/model.dart | 23 +-- libs/scrap/src/common/codec.rs | 26 ++-- libs/scrap/src/common/convert.rs | 158 ++++++++++++++++----- libs/scrap/src/common/hwcodec.rs | 22 ++- libs/scrap/src/common/mediacodec.rs | 52 +++++-- libs/scrap/src/common/mod.rs | 7 + libs/scrap/src/common/vpxcodec.rs | 82 +++++++---- src/client.rs | 7 +- src/flutter.rs | 16 ++- src/flutter_ffi.rs | 11 ++ 11 files changed, 322 insertions(+), 143 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 4a2f5c0e8..c78ffb439 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -65,6 +65,7 @@ class _RemotePageState extends State late RxBool _keyboardEnabled; late RxInt _textureId; late int _textureKey; + final useTextureRender = bind.mainUseTextureRender(); final _blockableOverlayState = BlockableOverlayState(); @@ -363,6 +364,7 @@ class _RemotePageState extends State keyboardEnabled: _keyboardEnabled, remoteCursorMoved: _remoteCursorMoved, textureId: _textureId, + useTextureRender: useTextureRender, listenerBuilder: (child) => _buildRawPointerMouseRegion(child, enterView, leaveView), ); @@ -401,6 +403,7 @@ class ImagePaint extends StatefulWidget { final RxBool keyboardEnabled; final RxBool remoteCursorMoved; final RxInt textureId; + final bool useTextureRender; final Widget Function(Widget)? listenerBuilder; ImagePaint( @@ -411,6 +414,7 @@ class ImagePaint extends StatefulWidget { required this.keyboardEnabled, required this.remoteCursorMoved, required this.textureId, + required this.useTextureRender, this.listenerBuilder}) : super(key: key); @@ -485,15 +489,19 @@ class _ImagePaintState extends State { final imageWidth = c.getDisplayWidth() * s; final imageHeight = c.getDisplayHeight() * s; final imageSize = Size(imageWidth, imageHeight); - // final imageWidget = CustomPaint( - // size: imageSize, - // painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), - // ); - final imageWidget = SizedBox( - width: imageWidth, - height: imageHeight, - child: Obx(() => Texture(textureId: widget.textureId.value)), - ); + late final Widget imageWidget; + if (widget.useTextureRender) { + imageWidget = SizedBox( + width: imageWidth, + height: imageHeight, + child: Obx(() => Texture(textureId: widget.textureId.value)), + ); + } else { + imageWidget = CustomPaint( + size: imageSize, + painter: ImagePainter(image: m.image, x: 0, y: 0, scale: s), + ); + } return NotificationListener( onNotification: (notification) { @@ -517,22 +525,27 @@ class _ImagePaintState extends State { context, _buildListener(imageWidget), c.size, imageSize)), )); } else { - // final imageWidget = CustomPaint( - // size: Size(c.size.width, c.size.height), - // painter: ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s), - // ); + late final Widget imageWidget; if (c.size.width > 0 && c.size.height > 0) { - final imageWidget = Stack( - children: [ - Positioned( - left: c.x, - top: c.y, - width: c.getDisplayWidth() * s, - height: c.getDisplayHeight() * s, - child: Texture(textureId: widget.textureId.value), - ) - ], - ); + if (widget.useTextureRender) { + imageWidget = Stack( + children: [ + Positioned( + left: c.x, + top: c.y, + width: c.getDisplayWidth() * s, + height: c.getDisplayHeight() * s, + child: Texture(textureId: widget.textureId.value), + ) + ], + ); + } else { + imageWidget = CustomPaint( + size: Size(c.size.width, c.size.height), + painter: + ImagePainter(image: m.image, x: c.x / s, y: c.y / s, scale: s), + ); + } return mouseRegion(child: _buildListener(imageWidget)); } else { return Container(); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index a38db2a90..5ef72a0af 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -1438,6 +1438,7 @@ class FFI { final stream = bind.sessionStart(id: id); final cb = ffiModel.startEventListener(id); () async { + final useTextureRender = bind.mainUseTextureRender(); // Preserved for the rgba data. await for (final message in stream) { if (message is EventToUI_Event) { @@ -1451,17 +1452,7 @@ class FFI { debugPrint('json.decode fail1(): $e, ${message.field0}'); } } else if (message is EventToUI_Rgba) { - if (Platform.isAndroid || Platform.isIOS) { - // Fetch the image buffer from rust codes. - final sz = platformFFI.getRgbaSize(id); - if (sz == null || sz == 0) { - return; - } - final rgba = platformFFI.getRgba(id, sz); - if (rgba != null) { - imageModel.onRgba(rgba); - } - } else { + if (useTextureRender) { if (_waitForImage[id]!) { _waitForImage[id] = false; dialogManager.dismissAll(); @@ -1471,6 +1462,16 @@ class FFI { await canvasModel.updateViewStyle(); await canvasModel.updateScrollStyle(); } + } else { + // Fetch the image buffer from rust codes. + final sz = platformFFI.getRgbaSize(id); + if (sz == null || sz == 0) { + return; + } + final rgba = platformFFI.getRgba(id, sz); + if (rgba != null) { + imageModel.onRgba(rgba); + } } } } diff --git a/libs/scrap/src/common/codec.rs b/libs/scrap/src/common/codec.rs index acfd4c674..3adc24a14 100644 --- a/libs/scrap/src/common/codec.rs +++ b/libs/scrap/src/common/codec.rs @@ -11,7 +11,7 @@ use crate::hwcodec::*; use crate::mediacodec::{ MediaCodecDecoder, MediaCodecDecoders, H264_DECODER_SUPPORT, H265_DECODER_SUPPORT, }; -use crate::vpxcodec::*; +use crate::{vpxcodec::*, ImageFormat}; use hbb_common::{ anyhow::anyhow, @@ -306,16 +306,17 @@ impl Decoder { pub fn handle_video_frame( &mut self, frame: &video_frame::Union, + fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { match frame { video_frame::Union::Vp9s(vp9s) => { - Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, rgb) + Decoder::handle_vp9s_video_frame(&mut self.vpx, vp9s, fmt, rgb) } #[cfg(feature = "hwcodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.hw.h264 { - Decoder::handle_hw_video_frame(decoder, h264s, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h264s, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h264!")) } @@ -323,7 +324,7 @@ impl Decoder { #[cfg(feature = "hwcodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.hw.h265 { - Decoder::handle_hw_video_frame(decoder, h265s, rgb, &mut self.i420) + Decoder::handle_hw_video_frame(decoder, h265s, fmt, rgb, &mut self.i420) } else { Err(anyhow!("don't support h265!")) } @@ -331,7 +332,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H264s(h264s) => { if let Some(decoder) = &mut self.media_codec.h264 { - Decoder::handle_mediacodec_video_frame(decoder, h264s, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h264s, fmt, rgb) } else { Err(anyhow!("don't support h264!")) } @@ -339,7 +340,7 @@ impl Decoder { #[cfg(feature = "mediacodec")] video_frame::Union::H265s(h265s) => { if let Some(decoder) = &mut self.media_codec.h265 { - Decoder::handle_mediacodec_video_frame(decoder, h265s, rgb) + Decoder::handle_mediacodec_video_frame(decoder, h265s, fmt, rgb) } else { Err(anyhow!("don't support h265!")) } @@ -351,6 +352,7 @@ impl Decoder { fn handle_vp9s_video_frame( decoder: &mut VpxDecoder, vp9s: &EncodedVideoFrames, + fmt: ImageFormat, rgb: &mut Vec, ) -> ResultType { let mut last_frame = Image::new(); @@ -367,7 +369,7 @@ impl Decoder { if last_frame.is_null() { Ok(false) } else { - last_frame.rgb(1, true, rgb); + last_frame.to(fmt, 1, rgb); Ok(true) } } @@ -376,14 +378,15 @@ impl Decoder { fn handle_hw_video_frame( decoder: &mut HwDecoder, frames: &EncodedVideoFrames, - rgb: &mut Vec, + fmt: ImageFormat, + raw: &mut Vec, i420: &mut Vec, ) -> ResultType { let mut ret = false; for h264 in frames.frames.iter() { for image in decoder.decode(&h264.data)? { // TODO: just process the last frame - if image.bgra(rgb, i420).is_ok() { + if image.to_fmt(fmt, raw, i420).is_ok() { ret = true; } } @@ -395,11 +398,12 @@ impl Decoder { fn handle_mediacodec_video_frame( decoder: &mut MediaCodecDecoder, frames: &EncodedVideoFrames, - rgb: &mut Vec, + fmt: ImageFormat, + raw: &mut Vec, ) -> ResultType { let mut ret = false; for h264 in frames.frames.iter() { - return decoder.decode(&h264.data, rgb); + return decoder.decode(&h264.data, fmt, raw); } return Ok(false); } diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index 2b0223a0a..a2177805e 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -103,6 +103,19 @@ extern "C" { height: c_int, ) -> c_int; + pub fn I420ToABGR( + src_y: *const u8, + src_stride_y: c_int, + src_u: *const u8, + src_stride_u: c_int, + src_v: *const u8, + src_stride_v: c_int, + dst_rgba: *mut u8, + dst_stride_rgba: c_int, + width: c_int, + height: c_int, + ) -> c_int; + pub fn NV12ToARGB( src_y: *const u8, src_stride_y: c_int, @@ -246,6 +259,7 @@ pub unsafe fn nv12_to_i420( #[cfg(feature = "hwcodec")] pub mod hw { use hbb_common::{anyhow::anyhow, ResultType}; + use crate::ImageFormat; #[cfg(target_os = "windows")] use hwcodec::{ffmpeg::ffmpeg_linesize_offset_length, AVPixelFormat}; @@ -315,7 +329,8 @@ pub mod hw { } #[cfg(target_os = "windows")] - pub fn hw_nv12_to_bgra( + pub fn hw_nv12_to( + fmt: ImageFormat, width: usize, height: usize, src_y: &[u8], @@ -355,18 +370,39 @@ pub mod hw { width as _, height as _, ); - super::I420ToARGB( - i420_offset_y, - i420_stride_y, - i420_offset_u, - i420_stride_u, - i420_offset_v, - i420_stride_v, - dst.as_mut_ptr(), - (width * 4) as _, - width as _, - height as _, - ); + match fmt { + ImageFormat::ARGB => { + super::I420ToARGB( + i420_offset_y, + i420_stride_y, + i420_offset_u, + i420_stride_u, + i420_offset_v, + i420_stride_v, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ); + } + ImageFormat::ABGR => { + super::I420ToABGR( + i420_offset_y, + i420_stride_y, + i420_offset_u, + i420_stride_u, + i420_offset_v, + i420_stride_v, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ); + } + _ => { + return Err(anyhow!("unsupported image format")); + } + } return Ok(()); }; } @@ -374,7 +410,8 @@ pub mod hw { } #[cfg(not(target_os = "windows"))] - pub fn hw_nv12_to_bgra( + pub fn hw_nv12_to( + fmt: ImageFormat, width: usize, height: usize, src_y: &[u8], @@ -387,23 +424,46 @@ pub mod hw { ) -> ResultType<()> { dst.resize(width * height * 4, 0); unsafe { - match super::NV12ToARGB( - src_y.as_ptr(), - src_stride_y as _, - src_uv.as_ptr(), - src_stride_uv as _, - dst.as_mut_ptr(), - (width * 4) as _, - width as _, - height as _, - ) { - 0 => Ok(()), - _ => Err(anyhow!("NV12ToARGB failed")), + match fmt { + ImageFormat::ARGB => { + match super::NV12ToARGB( + src_y.as_ptr(), + src_stride_y as _, + src_uv.as_ptr(), + src_stride_uv as _, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ) { + 0 => Ok(()), + _ => Err(anyhow!("NV12ToARGB failed")), + } + } + ImageFormat::ABGR => { + match super::NV12ToABGR( + src_y.as_ptr(), + src_stride_y as _, + src_uv.as_ptr(), + src_stride_uv as _, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ) { + 0 => Ok(()), + _ => Err(anyhow!("NV12ToABGR failed")), + } + } + _ => { + Err(anyhow!("unsupported image format")); + } } } } - pub fn hw_i420_to_bgra( + pub fn hw_i420_to( + fmt: ImageFormat, width: usize, height: usize, src_y: &[u8], @@ -419,18 +479,38 @@ pub mod hw { let src_v = src_v.as_ptr(); dst.resize(width * height * 4, 0); unsafe { - super::I420ToARGB( - src_y, - src_stride_y as _, - src_u, - src_stride_u as _, - src_v, - src_stride_v as _, - dst.as_mut_ptr(), - (width * 4) as _, - width as _, - height as _, - ); + match fmt { + ImageFormat::ARGB => { + super::I420ToARGB( + src_y, + src_stride_y as _, + src_u, + src_stride_u as _, + src_v, + src_stride_v as _, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ); + } + ImageFormat::ABGR => { + super::I420ToABGR( + src_y, + src_stride_y as _, + src_u, + src_stride_u as _, + src_v, + src_stride_v as _, + dst.as_mut_ptr(), + (width * 4) as _, + width as _, + height as _, + ); + } + _ => { + } + } }; } } diff --git a/libs/scrap/src/common/hwcodec.rs b/libs/scrap/src/common/hwcodec.rs index 27b157b79..d2b9f414f 100644 --- a/libs/scrap/src/common/hwcodec.rs +++ b/libs/scrap/src/common/hwcodec.rs @@ -1,6 +1,6 @@ use crate::{ codec::{EncoderApi, EncoderCfg}, - hw, HW_STRIDE_ALIGN, + hw, ImageFormat, HW_STRIDE_ALIGN, }; use hbb_common::{ anyhow::{anyhow, Context}, @@ -236,22 +236,24 @@ pub struct HwDecoderImage<'a> { } impl HwDecoderImage<'_> { - pub fn bgra(&self, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { + pub fn to_fmt(&self, fmt: ImageFormat, fmt_data: &mut Vec, i420: &mut Vec) -> ResultType<()> { let frame = self.frame; match frame.pixfmt { - AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to_bgra( + AVPixelFormat::AV_PIX_FMT_NV12 => hw::hw_nv12_to( + fmt, frame.width as _, frame.height as _, &frame.data[0], &frame.data[1], frame.linesize[0] as _, frame.linesize[1] as _, - bgra, + fmt_data, i420, HW_STRIDE_ALIGN, ), AVPixelFormat::AV_PIX_FMT_YUV420P => { - hw::hw_i420_to_bgra( + hw::hw_i420_to( + fmt, frame.width as _, frame.height as _, &frame.data[0], @@ -260,12 +262,20 @@ impl HwDecoderImage<'_> { frame.linesize[0] as _, frame.linesize[1] as _, frame.linesize[2] as _, - bgra, + fmt_data, ); return Ok(()); } } } + + pub fn bgra(&self, bgra: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(ImageFormat::ARGB, bgra, i420) + } + + pub fn rgba(&self, rgba: &mut Vec, i420: &mut Vec) -> ResultType<()> { + self.to_fmt(ImageFormat::ABGR, rgba, i420) + } } fn get_config(k: &str) -> ResultType { diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 406baecb5..77c21ffcf 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -8,9 +8,10 @@ use std::{ time::Duration, }; +use crate::ImageFormat; use crate::{ codec::{EncoderApi, EncoderCfg}, - I420ToARGB, + I420ToABGR, I420ToARGB, }; /// MediaCodec mime type name @@ -50,7 +51,7 @@ impl MediaCodecDecoder { MediaCodecDecoders { h264, h265 } } - pub fn decode(&mut self, data: &[u8], rgb: &mut Vec) -> ResultType { + pub fn decode(&mut self, data: &[u8], fmt: ImageFormat, raw: &mut Vec) -> ResultType { match self.dequeue_input_buffer(Duration::from_millis(10))? { Some(mut input_buffer) => { let mut buf = input_buffer.buffer_mut(); @@ -83,23 +84,44 @@ impl MediaCodecDecoder { let bps = 4; let u = buf.len() * 2 / 3; let v = buf.len() * 5 / 6; - rgb.resize(h * w * bps, 0); + raw.resize(h * w * bps, 0); let y_ptr = buf.as_ptr(); let u_ptr = buf[u..].as_ptr(); let v_ptr = buf[v..].as_ptr(); unsafe { - I420ToARGB( - y_ptr, - stride, - u_ptr, - stride / 2, - v_ptr, - stride / 2, - rgb.as_mut_ptr(), - (w * bps) as _, - w as _, - h as _, - ); + match fmt { + ImageFormat::ARGB => { + I420ToARGB( + y_ptr, + stride, + u_ptr, + stride / 2, + v_ptr, + stride / 2, + raw.as_mut_ptr(), + (w * bps) as _, + w as _, + h as _, + ); + } + ImageFormat::ARGB => { + I420ToABGR( + y_ptr, + stride, + u_ptr, + stride / 2, + v_ptr, + stride / 2, + raw.as_mut_ptr(), + (w * bps) as _, + w as _, + h as _, + ); + } + _ => { + bail!("Unsupported image format"); + } + } } self.release_output_buffer(output_buffer, false)?; Ok(true) diff --git a/libs/scrap/src/common/mod.rs b/libs/scrap/src/common/mod.rs index 45aafe7c5..c7da57734 100644 --- a/libs/scrap/src/common/mod.rs +++ b/libs/scrap/src/common/mod.rs @@ -43,6 +43,13 @@ pub const HW_STRIDE_ALIGN: usize = 0; // recommended by av_frame_get_buffer pub mod record; mod vpx; +#[derive(Copy, Clone)] +pub enum ImageFormat { + Raw, + ABGR, + ARGB, +} + #[inline] pub fn would_block_if_equal(old: &mut Vec, b: &[u8]) -> std::io::Result<()> { // does this really help? diff --git a/libs/scrap/src/common/vpxcodec.rs b/libs/scrap/src/common/vpxcodec.rs index 5164886a1..7a65b193d 100644 --- a/libs/scrap/src/common/vpxcodec.rs +++ b/libs/scrap/src/common/vpxcodec.rs @@ -6,8 +6,8 @@ use hbb_common::anyhow::{anyhow, Context}; use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame}; use hbb_common::{get_time, ResultType}; -use crate::codec::EncoderApi; use crate::STRIDE_ALIGN; +use crate::{codec::EncoderApi, ImageFormat}; use super::vpx::{vp8e_enc_control_id::*, vpx_codec_err_t::*, *}; use hbb_common::bytes::Bytes; @@ -417,7 +417,7 @@ impl VpxDecoder { Ok(Self { ctx }) } - pub fn decode2rgb(&mut self, data: &[u8], rgba: bool) -> Result> { + pub fn decode2rgb(&mut self, data: &[u8], fmt: ImageFormat) -> Result> { let mut img = Image::new(); for frame in self.decode(data)? { drop(img); @@ -431,7 +431,7 @@ impl VpxDecoder { Ok(Vec::new()) } else { let mut out = Default::default(); - img.rgb(1, rgba, &mut out); + img.to(fmt, 1, &mut out); Ok(out) } } @@ -539,40 +539,60 @@ impl Image { self.inner().stride[iplane] } - pub fn rgb(&self, stride_align: usize, rgba: bool, dst: &mut Vec) { + pub fn to(&self, fmt: ImageFormat, stride_align: usize, dst: &mut Vec) { let h = self.height(); let mut w = self.width(); - let bps = if rgba { 4 } else { 3 }; + let bps = match fmt { + ImageFormat::Raw => 3, + ImageFormat::ARGB | ImageFormat::ABGR => 4, + }; w = (w + stride_align - 1) & !(stride_align - 1); dst.resize(h * w * bps, 0); let img = self.inner(); unsafe { - if rgba { - super::I420ToARGB( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - dst.as_mut_ptr(), - (w * bps) as _, - self.width() as _, - self.height() as _, - ); - } else { - super::I420ToRAW( - img.planes[0], - img.stride[0], - img.planes[1], - img.stride[1], - img.planes[2], - img.stride[2], - dst.as_mut_ptr(), - (w * bps) as _, - self.width() as _, - self.height() as _, - ); + match fmt { + ImageFormat::Raw => { + super::I420ToRAW( + img.planes[0], + img.stride[0], + img.planes[1], + img.stride[1], + img.planes[2], + img.stride[2], + dst.as_mut_ptr(), + (w * bps) as _, + self.width() as _, + self.height() as _, + ); + } + ImageFormat::ARGB => { + super::I420ToARGB( + img.planes[0], + img.stride[0], + img.planes[1], + img.stride[1], + img.planes[2], + img.stride[2], + dst.as_mut_ptr(), + (w * bps) as _, + self.width() as _, + self.height() as _, + ); + } + ImageFormat::ABGR => { + super::I420ToABGR( + img.planes[0], + img.stride[0], + img.planes[1], + img.stride[1], + img.planes[2], + img.stride[2], + dst.as_mut_ptr(), + (w * bps) as _, + self.width() as _, + self.height() as _, + ); + } } } } diff --git a/src/client.rs b/src/client.rs index aa3523185..9f4cef831 100644 --- a/src/client.rs +++ b/src/client.rs @@ -45,6 +45,7 @@ use scrap::{ codec::{Decoder, DecoderCfg}, record::{Recorder, RecorderContext}, VpxDecoderConfig, VpxVideoCodecId, + ImageFormat, }; use crate::{ @@ -943,7 +944,11 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - let res = self.decoder.handle_video_frame(frame, &mut self.rgb); + #[cfg(feature = "flutter_texture_render")] + let fmt = ImageFormat::ARGB; + #[cfg(not(feature = "flutter_texture_render"))] + let fmt = ImageFormat::ABGR; + let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); if self.record { self.recorder .lock() diff --git a/src/flutter.rs b/src/flutter.rs index a5689bce6..f78e1bd92 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -128,19 +128,21 @@ pub struct FlutterHandler { pub event_stream: Arc>>>, // SAFETY: [rgba] is guarded by [rgba_valid], and it's safe to reach [rgba] with `rgba_valid == true`. // We must check the `rgba_valid` before reading [rgba]. - #[cfg(any(target_os = "android", target_os = "ios"))] + #[cfg(not(feature = "flutter_texture_render"))] pub rgba: Arc>>, - #[cfg(any(target_os = "android", target_os = "ios"))] + #[cfg(not(feature = "flutter_texture_render"))] pub rgba_valid: Arc, - #[cfg(not(any(target_os = "android", target_os = "ios")))] + #[cfg(feature = "flutter_texture_render")] notify_rendered: Arc>, renderer: Arc>, peer_info: Arc>, } +#[cfg(feature = "flutter_texture_render")] pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); // Video Texture Renderer in Flutter +#[cfg(feature = "flutter_texture_render")] #[derive(Clone)] struct VideoRenderer { // TextureRgba pointer in flutter native. @@ -151,6 +153,7 @@ struct VideoRenderer { on_rgba_func: Symbol<'static, FlutterRgbaRendererPluginOnRgba>, } +#[cfg(feature = "flutter_texture_render")] impl Default for VideoRenderer { fn default() -> Self { unsafe { @@ -167,6 +170,7 @@ impl Default for VideoRenderer { } } +#[cfg(feature = "flutter_texture_render")] impl VideoRenderer { #[inline] pub fn set_size(&mut self, width: i32, height: i32) { @@ -236,11 +240,13 @@ impl FlutterHandler { } #[inline] + #[cfg(feature = "flutter_texture_render")] pub fn register_texture(&mut self, ptr: usize) { self.renderer.write().unwrap().ptr = ptr; } #[inline] + #[cfg(feature = "flutter_texture_render")] pub fn set_size(&mut self, width: i32, height: i32) { *self.notify_rendered.write().unwrap() = false; self.renderer.write().unwrap().set_size(width, height); @@ -405,7 +411,7 @@ impl InvokeUiSession for FlutterHandler { fn adapt_size(&self) {} #[inline] - #[cfg(any(target_os = "android", target_os = "ios"))] + #[cfg(not(feature = "flutter_texture_render"))] fn on_rgba(&self, data: &mut Vec) { // If the current rgba is not fetched by flutter, i.e., is valid. // We give up sending a new event to flutter. @@ -421,7 +427,7 @@ impl InvokeUiSession for FlutterHandler { } #[inline] - #[cfg(not(any(target_os = "android", target_os = "ios")))] + #[cfg(feature = "flutter_texture_render")] fn on_rgba(&self, data: &mut Vec) { self.renderer.read().unwrap().on_rgba(data); if *self.notify_rendered.read().unwrap() { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index c55866dbe..d8861eb0a 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1306,6 +1306,17 @@ pub fn main_hide_docker() -> SyncReturn { SyncReturn(true) } +pub fn main_use_texture_render() -> SyncReturn { + #[cfg(not(feature = "flutter_texture_render"))] + { + SyncReturn(false) + } + #[cfg(feature = "flutter_texture_render")] + { + SyncReturn(true) + } +} + pub fn cm_start_listen_ipc_thread() { #[cfg(not(any(target_os = "android", target_os = "ios")))] crate::flutter::connection_manager::start_listen_ipc_thread(); From 173e3bcd0d9d3a05ee8081cd52983906b8ad9d3f Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 22 Feb 2023 09:43:57 +0800 Subject: [PATCH 06/17] debug win, without hwcodec Signed-off-by: fufesou --- Cargo.toml | 1 + libs/scrap/src/common/mediacodec.rs | 3 +- src/client.rs | 4 +-- src/flutter.rs | 45 ++++++++++++++++++++--------- src/flutter_ffi.rs | 7 +++-- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0a7af0cbc..050a0cd47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ inline = [] hbbs = [] cli = [] with_rc = ["simple_rc"] +flutter_texture_render = [] appimage = [] flatpak = [] use_samplerate = ["samplerate"] diff --git a/libs/scrap/src/common/mediacodec.rs b/libs/scrap/src/common/mediacodec.rs index 77c21ffcf..7bda0b69d 100644 --- a/libs/scrap/src/common/mediacodec.rs +++ b/libs/scrap/src/common/mediacodec.rs @@ -1,5 +1,4 @@ -use hbb_common::anyhow::Error; -use hbb_common::{bail, ResultType}; +use hbb_common::{log, anyhow::Error, bail, ResultType}; use ndk::media::media_codec::{MediaCodec, MediaCodecDirection, MediaFormat}; use std::ops::Deref; use std::{ diff --git a/src/client.rs b/src/client.rs index 9f4cef831..0c2cf09cd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -945,9 +945,9 @@ impl VideoHandler { match &vf.union { Some(frame) => { #[cfg(feature = "flutter_texture_render")] - let fmt = ImageFormat::ARGB; - #[cfg(not(feature = "flutter_texture_render"))] let fmt = ImageFormat::ABGR; + #[cfg(not(feature = "flutter_texture_render"))] + let fmt = ImageFormat::ARGB; let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); if self.record { self.recorder diff --git a/src/flutter.rs b/src/flutter.rs index f78e1bd92..c232d891d 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -4,14 +4,17 @@ use crate::{ ui_session_interface::{io_loop, InvokeUiSession, Session}, }; use flutter_rust_bridge::StreamSink; +#[cfg(feature = "flutter_texture_render")] +use hbb_common::libc::c_void; use hbb_common::{ - bail, config::LocalConfig, get_version_number, libc::c_void, message_proto::*, - rendezvous_proto::ConnType, ResultType, + bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, + ResultType, }; +#[cfg(feature = "flutter_texture_render")] use libloading::{Library, Symbol}; use serde_json::json; -#[cfg(any(target_os = "android", target_os = "ios"))] +#[cfg(not(feature = "flutter_texture_render"))] use std::sync::atomic::{AtomicBool, Ordering}; use std::{ collections::HashMap, @@ -30,7 +33,10 @@ lazy_static::lazy_static! { pub static ref CUR_SESSION_ID: RwLock = Default::default(); pub static ref SESSIONS: RwLock>> = Default::default(); pub static ref GLOBAL_EVENT_STREAM: RwLock>> = Default::default(); // rust to dart event channel - #[cfg(not(any(target_os = "ios", target_os = "android")))] +} + +#[cfg(feature = "flutter_texture_render")] +lazy_static::lazy_static! { pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Library = { unsafe { #[cfg(target_os = "windows")] @@ -134,6 +140,7 @@ pub struct FlutterHandler { pub rgba_valid: Arc, #[cfg(feature = "flutter_texture_render")] notify_rendered: Arc>, + #[cfg(feature = "flutter_texture_render")] renderer: Arc>, peer_info: Arc>, } @@ -556,7 +563,7 @@ impl InvokeUiSession for FlutterHandler { #[inline] fn get_rgba(&self) -> *const u8 { - #[cfg(any(target_os = "android", target_os = "ios"))] + #[cfg(not(feature = "flutter_texture_render"))] if self.rgba_valid.load(Ordering::Relaxed) { return self.rgba.read().unwrap().as_ptr(); } @@ -565,7 +572,7 @@ impl InvokeUiSession for FlutterHandler { #[inline] fn next_rgba(&self) { - #[cfg(any(target_os = "android", target_os = "ios"))] + #[cfg(not(feature = "flutter_texture_render"))] self.rgba_valid.store(false, Ordering::Relaxed); } } @@ -825,23 +832,28 @@ pub fn set_cur_session_id(id: String) { } #[no_mangle] -pub fn session_get_rgba_size(_id: *const char) -> usize { - #[cfg(any(target_os = "android", target_os = "ios"))] - let id = unsafe { std::ffi::CStr::from_ptr(_id as _) }; - #[cfg(any(target_os = "android", target_os = "ios"))] +#[cfg(not(feature = "flutter_texture_render"))] +pub fn session_get_rgba_size(id: *const char) -> usize { + let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; if let Ok(id) = id.to_str() { - if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + if let Some(session) = SESSIONS.read().unwrap().get(id) { return session.rgba.read().unwrap().len(); } } 0 } +#[no_mangle] +#[cfg(feature = "flutter_texture_render")] +pub fn session_get_rgba_size(_id: *const char) -> usize { + 0 +} + #[no_mangle] pub fn session_get_rgba(id: *const char) -> *const u8 { let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; if let Ok(id) = id.to_str() { - if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + if let Some(session) = SESSIONS.read().unwrap().get(id) { return session.get_rgba(); } } @@ -852,18 +864,23 @@ pub fn session_get_rgba(id: *const char) -> *const u8 { pub fn session_next_rgba(id: *const char) { let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; if let Ok(id) = id.to_str() { - if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + if let Some(session) = SESSIONS.read().unwrap().get(id) { return session.next_rgba(); } } } #[no_mangle] +#[cfg(feature = "flutter_texture_render")] pub fn session_register_texture(id: *const char, ptr: usize) { let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; if let Ok(id) = id.to_str() { - if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + if let Some(session) = SESSIONS.read().unwrap().get(id) { return session.register_texture(ptr); } } } + +#[no_mangle] +#[cfg(not(feature = "flutter_texture_render"))] +pub fn session_register_texture(_id: *const char, _ptr: usize) {} diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index d8861eb0a..14906d568 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -529,9 +529,10 @@ pub fn session_switch_sides(id: String) { } } -pub fn session_set_size(id: String, width: i32, height: i32) { - if let Some(session) = SESSIONS.write().unwrap().get_mut(&id) { - session.set_size(width, height); +pub fn session_set_size(_id: String, _width: i32, _height: i32) { + #[cfg(feature = "flutter_texture_render")] + if let Some(session) = SESSIONS.write().unwrap().get_mut(&_id) { + session.set_size(_width, _height); } } From d70ffaa2b86b0321d65f1a419d286e1b99b00c80 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 22 Feb 2023 09:57:51 +0800 Subject: [PATCH 07/17] update pubspec Signed-off-by: fufesou --- flutter/pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index a07df9c2e..5ffe805b8 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -1563,5 +1563,5 @@ packages: source: hosted version: "0.1.1" sdks: - dart: ">=2.18.0 <3.0.0" + dart: ">=2.18.0 <4.0.0" flutter: ">=3.3.0" From ed0338b038b9ed087cae015f7db169295e30beff Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 22 Feb 2023 10:25:21 +0800 Subject: [PATCH 08/17] fix build && default flutter_texture_render Signed-off-by: fufesou --- build.py | 1 + libs/scrap/src/common/convert.rs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/build.py b/build.py index 9e490166f..727b53fe0 100755 --- a/build.py +++ b/build.py @@ -239,6 +239,7 @@ def get_features(args): features.append('hwcodec') if args.flutter: features.append('flutter') + features.append('flutter_texture_render') if args.flatpak: features.append('flatpak') if args.appimage: diff --git a/libs/scrap/src/common/convert.rs b/libs/scrap/src/common/convert.rs index a2177805e..f3ad51a21 100644 --- a/libs/scrap/src/common/convert.rs +++ b/libs/scrap/src/common/convert.rs @@ -126,6 +126,17 @@ extern "C" { width: c_int, height: c_int, ) -> c_int; + + pub fn NV12ToABGR( + src_y: *const u8, + src_stride_y: c_int, + src_uv: *const u8, + src_stride_uv: c_int, + dst_rgba: *mut u8, + dst_stride_rgba: c_int, + width: c_int, + height: c_int, + ) -> c_int; } // https://github.com/webmproject/libvpx/blob/master/vpx/src/vpx_image.c @@ -456,7 +467,7 @@ pub mod hw { } } _ => { - Err(anyhow!("unsupported image format")); + Err(anyhow!("unsupported image format")) } } } From 20021c6541b04caf1c414c7e4795ba6198349a1f Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 22 Feb 2023 11:03:40 +0800 Subject: [PATCH 09/17] fix build Signed-off-by: fufesou --- src/flutter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flutter.rs b/src/flutter.rs index c232d891d..42da3f038 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -875,7 +875,7 @@ pub fn session_next_rgba(id: *const char) { pub fn session_register_texture(id: *const char, ptr: usize) { let id = unsafe { std::ffi::CStr::from_ptr(id as _) }; if let Ok(id) = id.to_str() { - if let Some(session) = SESSIONS.read().unwrap().get(id) { + if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { return session.register_texture(ptr); } } From 8b7be688c27383c83962b064d843fbaa25e22eea Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 22 Feb 2023 22:33:17 +0800 Subject: [PATCH 10/17] macos, linux, r and b are reversed Signed-off-by: fufesou --- Cargo.lock | 327 +++++++++++-------- Cargo.toml | 1 + flutter/macos/Podfile.lock | 6 + flutter/macos/Runner/MainFlutterWindow.swift | 2 + src/flutter.rs | 82 +++-- 5 files changed, 256 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb5461a6e..14b09a9d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,9 +254,9 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -271,9 +271,9 @@ version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -377,8 +377,8 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "regex", "rustc-hash", "shlex", @@ -397,12 +397,12 @@ dependencies = [ "lazy_static", "lazycell", "peeking_take_while", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "regex", "rustc-hash", "shlex", - "syn", + "syn 1.0.105", ] [[package]] @@ -588,11 +588,11 @@ dependencies = [ "heck 0.4.0", "indexmap", "log", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "serde 1.0.149", "serde_json 1.0.89", - "syn", + "syn 1.0.105", "tempfile", "toml", ] @@ -721,9 +721,9 @@ checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck 0.4.0", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1119,10 +1119,10 @@ dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "scratch", - "syn", + "syn 1.0.105", ] [[package]] @@ -1137,9 +1137,9 @@ version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1177,10 +1177,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "strsim 0.10.0", - "syn", + "syn 1.0.105", ] [[package]] @@ -1190,8 +1190,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", - "quote", - "syn", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1373,9 +1373,9 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "082a24a9967533dc5d743c602157637116fc1b52806d694a5a45e6f32567fcdd" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1384,9 +1384,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1481,6 +1481,29 @@ dependencies = [ "libloading", ] +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "dlv-list" version = "0.3.0" @@ -1592,9 +1615,9 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9045e2676cd5af83c3b167d917b0a5c90a4d8e266e2683d6631b235c457fc27" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1604,9 +1627,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eb359f1476bf611266ac1f5355bc14aeca37b299d0ebccc038ee7058891c9cb" dependencies = [ "once_cell", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1625,9 +1648,9 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1670,10 +1693,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e" dependencies = [ "proc-macro-error", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn", + "syn 1.0.105", "synstructure", ] @@ -1747,9 +1770,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5216e387a76eebaaf11f6d871ec8a4aae0b25f05456ee21f228e024b1b3610" dependencies = [ "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -1878,11 +1901,11 @@ dependencies = [ "lazy_static", "log", "pathdiff", - "quote", + "quote 1.0.21", "regex", "serde 1.0.149", "serde_yaml", - "syn", + "syn 1.0.105", "tempfile", "thiserror", "toml", @@ -2035,9 +2058,9 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -2299,9 +2322,9 @@ dependencies = [ "itertools 0.9.0", "proc-macro-crate 0.1.5", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -2314,9 +2337,9 @@ dependencies = [ "heck 0.4.0", "proc-macro-crate 1.2.1", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -2550,9 +2573,9 @@ dependencies = [ "anyhow", "proc-macro-crate 1.2.1", "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -2856,8 +2879,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", ] [[package]] @@ -3564,9 +3587,9 @@ checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ "darling", "proc-macro-crate 1.2.1", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -3713,9 +3736,9 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -3805,9 +3828,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate 1.2.1", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -4121,9 +4144,9 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -4230,9 +4253,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", "version_check", ] @@ -4242,11 +4265,20 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "version_check", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.47" @@ -4374,13 +4406,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.47", ] [[package]] @@ -4846,6 +4887,7 @@ dependencies = [ "dbus-crossroads", "default-net", "dispatch", + "dlopen", "enigo", "errno", "evdev", @@ -5158,9 +5200,9 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5192,9 +5234,9 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5453,9 +5495,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ "heck 0.3.3", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5465,10 +5507,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.0", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "rustversion", - "syn", + "syn 1.0.105", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", ] [[package]] @@ -5477,8 +5530,8 @@ version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "unicode-ident", ] @@ -5488,10 +5541,10 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", + "unicode-xid 0.2.4", ] [[package]] @@ -5630,9 +5683,9 @@ name = "tao-macros" version = "0.1.0" source = "git+https://github.com/tauri-apps/tao?branch=muda#676bd90a80286b893d8850cc4e3813a0c4a27dcf" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5725,9 +5778,9 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5831,9 +5884,9 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -5920,9 +5973,9 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -6033,6 +6086,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.4" @@ -6177,9 +6236,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", "wasm-bindgen-shared", ] @@ -6201,7 +6260,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote", + "quote 1.0.21", "wasm-bindgen-macro-support", ] @@ -6211,9 +6270,9 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6281,8 +6340,8 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "xml-rs", ] @@ -6507,9 +6566,9 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce87ca8e3417b02dc2a8a22769306658670ec92d78f1bd420d6310a67c245c6" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -6518,9 +6577,9 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "853f69a591ecd4f810d29f17e902d40e349fb05b0b11fff63b08b826bfe39c7f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] [[package]] @@ -6962,10 +7021,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45066039ebf3330820e495e854f8b312abb68f0a39e97972d092bd72e8bb3e8e" dependencies = [ "proc-macro-crate 1.2.1", - "proc-macro2", - "quote", + "proc-macro2 1.0.47", + "quote 1.0.21", "regex", - "syn", + "syn 1.0.105", ] [[package]] @@ -7038,7 +7097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "155247a5d1ab55e335421c104ccd95d64f17cebbd02f50cdbc1c33385f9c4d81" dependencies = [ "proc-macro-crate 1.2.1", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.105", ] diff --git a/Cargo.toml b/Cargo.toml index 050a0cd47..b51930f72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ flutter_rust_bridge = { version = "1.61.1", optional = true } errno = "0.2.8" rdev = { git = "https://github.com/fufesou/rdev" } url = { version = "2.1", features = ["serde"] } +dlopen = "0.1" reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } chrono = "0.4.23" diff --git a/flutter/macos/Podfile.lock b/flutter/macos/Podfile.lock index 3187c6349..16dc0d352 100644 --- a/flutter/macos/Podfile.lock +++ b/flutter/macos/Podfile.lock @@ -21,6 +21,8 @@ PODS: - sqflite (0.0.2): - FlutterMacOS - FMDB (>= 2.7.5) + - texture_rgba_renderer (0.0.1): + - FlutterMacOS - uni_links_desktop (0.0.1): - FlutterMacOS - url_launcher_macos (0.0.1): @@ -42,6 +44,7 @@ DEPENDENCIES: - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`) - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`) + - texture_rgba_renderer (from `Flutter/ephemeral/.symlinks/plugins/texture_rgba_renderer/macos`) - uni_links_desktop (from `Flutter/ephemeral/.symlinks/plugins/uni_links_desktop/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) @@ -71,6 +74,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos sqflite: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos + texture_rgba_renderer: + :path: Flutter/ephemeral/.symlinks/plugins/texture_rgba_renderer/macos uni_links_desktop: :path: Flutter/ephemeral/.symlinks/plugins/uni_links_desktop/macos url_launcher_macos: @@ -93,6 +98,7 @@ SPEC CHECKSUMS: path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38 sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea + texture_rgba_renderer: cbed959a3c127122194a364e14b8577bd62dc8f2 uni_links_desktop: 45900fb319df48fcdea2df0756e9c2626696b026 url_launcher_macos: c04e4fa86382d4f94f6b38f14625708be3ae52e2 wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 21e870320..e9043da71 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -17,6 +17,7 @@ import url_launcher_macos import wakelock_macos import window_manager import window_size +import texture_rgba_renderer class MainFlutterWindow: NSWindow { override func awakeFromNib() { @@ -49,6 +50,7 @@ class MainFlutterWindow: NSWindow { UrlLauncherPlugin.register(with: controller.registrar(forPlugin: "UrlLauncherPlugin")) WakelockMacosPlugin.register(with: controller.registrar(forPlugin: "WakelockMacosPlugin")) WindowSizePlugin.register(with: controller.registrar(forPlugin: "WindowSizePlugin")) + TextureRgbaRendererPlugin.register(with: controller.registrar(forPlugin: "TextureRgbaRendererPlugin")) } super.awakeFromNib() diff --git a/src/flutter.rs b/src/flutter.rs index 42da3f038..51c96ddcf 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -3,15 +3,22 @@ use crate::{ flutter_ffi::EventToUI, ui_session_interface::{io_loop, InvokeUiSession, Session}, }; +#[cfg(feature = "flutter_texture_render")] +#[cfg(target_os = "macos")] +use dlopen::{ + symbor::{Library, Symbol}, + Error as LibError, +}; use flutter_rust_bridge::StreamSink; #[cfg(feature = "flutter_texture_render")] use hbb_common::libc::c_void; use hbb_common::{ - bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, - ResultType, + bail, config::LocalConfig, get_version_number, log, message_proto::*, + rendezvous_proto::ConnType, ResultType, }; #[cfg(feature = "flutter_texture_render")] -use libloading::{Library, Symbol}; +#[cfg(not(target_os = "macos"))] +use libloading::{Error as LibError, Library, Symbol}; use serde_json::json; #[cfg(not(feature = "flutter_texture_render"))] @@ -37,16 +44,16 @@ lazy_static::lazy_static! { #[cfg(feature = "flutter_texture_render")] lazy_static::lazy_static! { - pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Library = { + pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result = { + #[cfg(not(target_os = "macos"))] unsafe { #[cfg(target_os = "windows")] - let lib = Library::new("texture_rgba_renderer_plugin.dll"); - #[cfg(target_os = "macos")] - let lib = Library::new("texture_rgba_renderer_plugin.dylib"); + Library::new("texture_rgba_renderer_plugin.dll"); #[cfg(target_os = "linux")] - let lib = Library::new("libtexture_rgba_renderer_plugin.so"); - lib.expect("`libtexture_rgba_renderer_plugin` not found, please add `texture_rgba_renderer` in your flutter project") + Library::new("libtexture_rgba_renderer_plugin.so"); } + #[cfg(target_os = "macos")] + Library::open_self() }; } @@ -157,22 +164,40 @@ struct VideoRenderer { width: i32, height: i32, data_len: usize, - on_rgba_func: Symbol<'static, FlutterRgbaRendererPluginOnRgba>, + on_rgba_func: Option>, } #[cfg(feature = "flutter_texture_render")] impl Default for VideoRenderer { fn default() -> Self { - unsafe { - Self { - ptr: 0, - width: 0, - height: 0, - data_len: 0, - on_rgba_func: TEXTURE_RGBA_RENDERER_PLUGIN - .get::(b"FlutterRgbaRendererPluginOnRgba") - .expect("Symbol FlutterRgbaRendererPluginOnRgba not found."), + let on_rgba_func = match &*TEXTURE_RGBA_RENDERER_PLUGIN { + Ok(lib) => { + #[cfg(not(target_os = "macos"))] + let find_sym_res = + lib.get::(b"FlutterRgbaRendererPluginOnRgba"); + #[cfg(target_os = "macos")] + let find_sym_res = unsafe { + lib.symbol::("FlutterRgbaRendererPluginOnRgba") + }; + match find_sym_res { + Ok(sym) => Some(sym), + Err(e) => { + log::error!("Failed to find symbol FlutterRgbaRendererPluginOnRgba, {e}"); + None + } + } } + Err(e) => { + log::error!("Failed to load texture rgba renderer plugin, {e}"); + None + } + }; + Self { + ptr: 0, + width: 0, + height: 0, + data_len: 0, + on_rgba_func, } } } @@ -194,15 +219,16 @@ impl VideoRenderer { if self.ptr == usize::default() || rgba.len() != self.data_len { return; } - let func = self.on_rgba_func.clone(); - unsafe { - func( - self.ptr as _, - rgba.as_ptr() as _, - self.width as _, - self.height as _, - ) - }; + if let Some(func) = &self.on_rgba_func { + unsafe { + func( + self.ptr as _, + rgba.as_ptr() as _, + self.width as _, + self.height as _, + ) + }; + } } } From 9559a889fbefc53912b3a049d347344fb7723897 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 10:02:54 +0800 Subject: [PATCH 11/17] register plugin && fix r&b colors Signed-off-by: fufesou --- flutter/windows/runner/flutter_window.cpp | 10 ++++++++++ src/client.rs | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/flutter/windows/runner/flutter_window.cpp b/flutter/windows/runner/flutter_window.cpp index b43b9095e..2f1f36f73 100644 --- a/flutter/windows/runner/flutter_window.cpp +++ b/flutter/windows/runner/flutter_window.cpp @@ -2,6 +2,9 @@ #include +#include +#include + #include "flutter/generated_plugin_registrant.h" FlutterWindow::FlutterWindow(const flutter::DartProject& project) @@ -25,6 +28,13 @@ bool FlutterWindow::OnCreate() { return false; } RegisterPlugins(flutter_controller_->engine()); + DesktopMultiWindowSetWindowCreatedCallback([](void *controller) { + auto *flutter_view_controller = + reinterpret_cast(controller); + auto *registry = flutter_view_controller->engine(); + TextureRgbaRendererPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("TextureRgbaRendererPlugin")); + }); SetChildContent(flutter_controller_->view()->GetNativeWindow()); return true; } diff --git a/src/client.rs b/src/client.rs index 0c2cf09cd..ebfda7283 100644 --- a/src/client.rs +++ b/src/client.rs @@ -944,9 +944,10 @@ impl VideoHandler { } match &vf.union { Some(frame) => { - #[cfg(feature = "flutter_texture_render")] + // windows && flutter_texture_render, fmt is ImageFormat::ABGR + #[cfg(all(target_os = "windows", feature = "flutter_texture_render"))] let fmt = ImageFormat::ABGR; - #[cfg(not(feature = "flutter_texture_render"))] + #[cfg(not(all(target_os = "windows", feature = "flutter_texture_render")))] let fmt = ImageFormat::ARGB; let res = self.decoder.handle_video_frame(frame, fmt, &mut self.rgb); if self.record { From b8e381d79d30b7d47013ee9e0fd6bbefefcfb92d Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 10:21:31 +0800 Subject: [PATCH 12/17] win, debug Signed-off-by: fufesou --- Cargo.lock | 1 - Cargo.toml | 1 - src/flutter.rs | 56 ++++++++++++++++++++++++-------------------------- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14b09a9d2..8483cbac1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4902,7 +4902,6 @@ dependencies = [ "include_dir", "jni 0.19.0", "lazy_static", - "libloading", "libpulse-binding", "libpulse-simple-binding", "mac_address", diff --git a/Cargo.toml b/Cargo.toml index b51930f72..b424b01d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,6 @@ dlopen = "0.1" reqwest = { version = "0.11", features = ["blocking", "json", "rustls-tls"], default-features=false } chrono = "0.4.23" cidr-utils = "0.5.9" -libloading = "0.7.4" [target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies] cpal = "0.13.5" diff --git a/src/flutter.rs b/src/flutter.rs index 51c96ddcf..f2f950ad3 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -4,21 +4,18 @@ use crate::{ ui_session_interface::{io_loop, InvokeUiSession, Session}, }; #[cfg(feature = "flutter_texture_render")] -#[cfg(target_os = "macos")] +// #[cfg(target_os = "macos")] use dlopen::{ symbor::{Library, Symbol}, Error as LibError, }; use flutter_rust_bridge::StreamSink; -#[cfg(feature = "flutter_texture_render")] -use hbb_common::libc::c_void; use hbb_common::{ - bail, config::LocalConfig, get_version_number, log, message_proto::*, - rendezvous_proto::ConnType, ResultType, + bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, + ResultType, }; #[cfg(feature = "flutter_texture_render")] -#[cfg(not(target_os = "macos"))] -use libloading::{Error as LibError, Library, Symbol}; +use hbb_common::{libc::c_void, log}; use serde_json::json; #[cfg(not(feature = "flutter_texture_render"))] @@ -42,19 +39,19 @@ lazy_static::lazy_static! { pub static ref GLOBAL_EVENT_STREAM: RwLock>> = Default::default(); // rust to dart event channel } -#[cfg(feature = "flutter_texture_render")] +#[cfg(all(target_os = "windows", feature = "flutter_texture_render"))] lazy_static::lazy_static! { - pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result = { - #[cfg(not(target_os = "macos"))] - unsafe { - #[cfg(target_os = "windows")] - Library::new("texture_rgba_renderer_plugin.dll"); - #[cfg(target_os = "linux")] - Library::new("libtexture_rgba_renderer_plugin.so"); - } - #[cfg(target_os = "macos")] - Library::open_self() - }; + pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result = Library::open("texture_rgba_renderer_plugin.dll"); +} + +#[cfg(all(target_os = "linux", feature = "flutter_texture_render"))] +lazy_static::lazy_static! { + pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result = Library::open("libtexture_rgba_renderer_plugin.so"); +} + +#[cfg(all(target_os = "macos", feature = "flutter_texture_render"))] +lazy_static::lazy_static! { + pub static ref TEXTURE_RGBA_RENDERER_PLUGIN: Result = Library::open_self(); } /// FFI for rustdesk core's main entry. @@ -136,21 +133,26 @@ pub unsafe extern "C" fn free_c_args(ptr: *mut *mut c_char, len: c_int) { // Afterwards the vector will be dropped and thus freed. } +#[cfg(feature = "flutter_texture_render")] +#[derive(Default, Clone)] +pub struct FlutterHandler { + pub event_stream: Arc>>>, + notify_rendered: Arc>, + renderer: Arc>, + peer_info: Arc>, +} + +#[cfg(not(feature = "flutter_texture_render"))] #[derive(Default, Clone)] pub struct FlutterHandler { pub event_stream: Arc>>>, // SAFETY: [rgba] is guarded by [rgba_valid], and it's safe to reach [rgba] with `rgba_valid == true`. // We must check the `rgba_valid` before reading [rgba]. - #[cfg(not(feature = "flutter_texture_render"))] pub rgba: Arc>>, - #[cfg(not(feature = "flutter_texture_render"))] pub rgba_valid: Arc, - #[cfg(feature = "flutter_texture_render")] - notify_rendered: Arc>, - #[cfg(feature = "flutter_texture_render")] - renderer: Arc>, peer_info: Arc>, } + #[cfg(feature = "flutter_texture_render")] pub type FlutterRgbaRendererPluginOnRgba = unsafe extern "C" fn(texture_rgba: *mut c_void, buffer: *const u8, width: c_int, height: c_int); @@ -172,10 +174,6 @@ impl Default for VideoRenderer { fn default() -> Self { let on_rgba_func = match &*TEXTURE_RGBA_RENDERER_PLUGIN { Ok(lib) => { - #[cfg(not(target_os = "macos"))] - let find_sym_res = - lib.get::(b"FlutterRgbaRendererPluginOnRgba"); - #[cfg(target_os = "macos")] let find_sym_res = unsafe { lib.symbol::("FlutterRgbaRendererPluginOnRgba") }; From b84062b8f414317879c31558c743ca07f435838d Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 13:40:08 +0800 Subject: [PATCH 13/17] texture render, add log info Signed-off-by: fufesou --- src/flutter.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/flutter.rs b/src/flutter.rs index f2f950ad3..c501bd4a5 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -4,18 +4,17 @@ use crate::{ ui_session_interface::{io_loop, InvokeUiSession, Session}, }; #[cfg(feature = "flutter_texture_render")] -// #[cfg(target_os = "macos")] use dlopen::{ symbor::{Library, Symbol}, Error as LibError, }; use flutter_rust_bridge::StreamSink; -use hbb_common::{ - bail, config::LocalConfig, get_version_number, message_proto::*, rendezvous_proto::ConnType, - ResultType, -}; #[cfg(feature = "flutter_texture_render")] -use hbb_common::{libc::c_void, log}; +use hbb_common::libc::c_void; +use hbb_common::{ + bail, config::LocalConfig, get_version_number, log, message_proto::*, + rendezvous_proto::ConnType, ResultType, +}; use serde_json::json; #[cfg(not(feature = "flutter_texture_render"))] @@ -665,6 +664,13 @@ pub fn session_start_(id: &str, event_stream: StreamSink) -> ResultTy *session.event_stream.write().unwrap() = Some(event_stream); let session = session.clone(); std::thread::spawn(move || { + #[cfg(feature = "flutter_texture_render")] + log::info!( + "Session {} start, render by flutter texture rgba plugin", + id + ); + #[cfg(not(feature = "flutter_texture_render"))] + log::info!("Session {} start, render by flutter paint widget", id); io_loop(session); }); Ok(()) From 09aa42c53344c6d100adf481fbceec0ae64babfe Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 14:02:16 +0800 Subject: [PATCH 14/17] fix build Signed-off-by: fufesou --- src/flutter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/flutter.rs b/src/flutter.rs index c501bd4a5..d366a0eda 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -661,16 +661,16 @@ pub fn session_add( /// * `events2ui` - The events channel to ui. pub fn session_start_(id: &str, event_stream: StreamSink) -> ResultType<()> { if let Some(session) = SESSIONS.write().unwrap().get_mut(id) { + #[cfg(feature = "flutter_texture_render")] + log::info!( + "Session {} start, render by flutter texture rgba plugin", + id + ); + #[cfg(not(feature = "flutter_texture_render"))] + log::info!("Session {} start, render by flutter paint widget", id); *session.event_stream.write().unwrap() = Some(event_stream); let session = session.clone(); std::thread::spawn(move || { - #[cfg(feature = "flutter_texture_render")] - log::info!( - "Session {} start, render by flutter texture rgba plugin", - id - ); - #[cfg(not(feature = "flutter_texture_render"))] - log::info!("Session {} start, render by flutter paint widget", id); io_loop(session); }); Ok(()) From 4cb6e82893565a97f80ef97cc639c852a822391c Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 15:16:32 +0800 Subject: [PATCH 15/17] add feature flutter_texture_render for linux Signed-off-by: fufesou --- .github/workflows/flutter-nightly.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/flutter-nightly.yml b/.github/workflows/flutter-nightly.yml index ffcadd18b..b08193971 100644 --- a/.github/workflows/flutter-nightly.yml +++ b/.github/workflows/flutter-nightly.yml @@ -732,7 +732,7 @@ jobs: x86_64) # no need mock on x86_64 export VCPKG_ROOT=/opt/artifacts/vcpkg - cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; esac @@ -900,7 +900,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm64-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; armv7) cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/ @@ -910,7 +910,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; esac From 275da850ffaf5af6c57d313ce5480eee495753c2 Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 16:30:12 +0800 Subject: [PATCH 16/17] do not create texture when texture render is not enabled Signed-off-by: fufesou --- flutter/lib/desktop/pages/remote_page.dart | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index c78ffb439..e52334512 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -126,14 +126,16 @@ class _RemotePageState extends State } // Register texture. _textureId.value = -1; - textureRenderer.createTexture(_textureKey).then((id) async { - debugPrint("id: $id, texture_key: $_textureKey"); - if (id != -1) { - final ptr = await textureRenderer.getTexturePtr(_textureKey); - platformFFI.registerTexture(widget.id, ptr); - _textureId.value = id; - } - }); + if (useTextureRender) { + textureRenderer.createTexture(_textureKey).then((id) async { + debugPrint("id: $id, texture_key: $_textureKey"); + if (id != -1) { + final ptr = await textureRenderer.getTexturePtr(_textureKey); + platformFFI.registerTexture(widget.id, ptr); + _textureId.value = id; + } + }); + } _ffi.ffiModel.updateEventListener(widget.id); _ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); // Session option should be set after models.dart/FFI.start @@ -198,8 +200,10 @@ class _RemotePageState extends State @override void dispose() { debugPrint("REMOTE PAGE dispose ${widget.id}"); - platformFFI.registerTexture(widget.id, 0); - textureRenderer.closeTexture(_textureKey); + if (useTextureRender) { + platformFFI.registerTexture(widget.id, 0); + textureRenderer.closeTexture(_textureKey); + } // ensure we leave this session, this is a double check bind.sessionEnterOrLeave(id: widget.id, enter: false); DesktopMultiWindow.removeListener(this); From aeed94bb96963be3018717f2b726504bdc04f74c Mon Sep 17 00:00:00 2001 From: fufesou Date: Thu, 23 Feb 2023 18:03:40 +0800 Subject: [PATCH 17/17] update flutter-ci && restore crate-type Signed-off-by: fufesou --- .github/workflows/flutter-ci.yml | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/flutter-ci.yml b/.github/workflows/flutter-ci.yml index 2386f17dd..74e4efa99 100644 --- a/.github/workflows/flutter-ci.yml +++ b/.github/workflows/flutter-ci.yml @@ -593,7 +593,7 @@ jobs: x86_64) # no need mock on x86_64 export VCPKG_ROOT=/opt/artifacts/vcpkg - cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; esac @@ -761,7 +761,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm64-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; armv7) cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/ @@ -771,7 +771,7 @@ jobs: ln -s /usr/include /vcpkg/installed/arm-linux/include export VCPKG_ROOT=/vcpkg # disable hwcodec for compilation - cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release + cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }} --release ;; esac diff --git a/Cargo.toml b/Cargo.toml index b424b01d1..c20366983 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ default-run = "rustdesk" [lib] name = "librustdesk" -crate-type = ["cdylib"] +crate-type = ["cdylib", "staticlib", "rlib"] [[bin]] name = "naming"