mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-08 07:41:29 +03:00
add zero copy mode hareware codec for windows (#6778)
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
@@ -22,6 +22,9 @@ use winapi::{
|
||||
|
||||
use crate::RotationMode::*;
|
||||
|
||||
use crate::{AdapterDevice, Frame, PixelBuffer};
|
||||
use std::ffi::c_void;
|
||||
|
||||
pub struct ComPtr<T>(*mut T);
|
||||
impl<T> ComPtr<T> {
|
||||
fn is_null(&self) -> bool {
|
||||
@@ -45,12 +48,15 @@ pub struct Capturer {
|
||||
duplication: ComPtr<IDXGIOutputDuplication>,
|
||||
fastlane: bool,
|
||||
surface: ComPtr<IDXGISurface>,
|
||||
texture: ComPtr<ID3D11Texture2D>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
rotated: Vec<u8>,
|
||||
gdi_capturer: Option<CapturerGDI>,
|
||||
gdi_buffer: Vec<u8>,
|
||||
saved_raw_data: Vec<u8>, // for faster compare and copy
|
||||
output_texture: bool,
|
||||
adapter_desc1: DXGI_ADAPTER_DESC1,
|
||||
}
|
||||
|
||||
impl Capturer {
|
||||
@@ -60,12 +66,14 @@ impl Capturer {
|
||||
let mut duplication = ptr::null_mut();
|
||||
#[allow(invalid_value)]
|
||||
let mut desc = unsafe { mem::MaybeUninit::uninit().assume_init() };
|
||||
#[allow(invalid_value)]
|
||||
let mut adapter_desc1 = unsafe { mem::MaybeUninit::uninit().assume_init() };
|
||||
let mut gdi_capturer = None;
|
||||
|
||||
let mut res = if display.gdi {
|
||||
wrap_hresult(1)
|
||||
} else {
|
||||
wrap_hresult(unsafe {
|
||||
let res = wrap_hresult(unsafe {
|
||||
D3D11CreateDevice(
|
||||
display.adapter.0 as *mut _,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
@@ -78,7 +86,12 @@ impl Capturer {
|
||||
ptr::null_mut(),
|
||||
&mut context,
|
||||
)
|
||||
})
|
||||
});
|
||||
if res.is_ok() {
|
||||
wrap_hresult(unsafe { (*display.adapter.0).GetDesc1(&mut adapter_desc1) })
|
||||
} else {
|
||||
res
|
||||
}
|
||||
};
|
||||
let device = ComPtr(device);
|
||||
let context = ComPtr(context);
|
||||
@@ -145,6 +158,7 @@ impl Capturer {
|
||||
duplication: ComPtr(duplication),
|
||||
fastlane: desc.DesktopImageInSystemMemory == TRUE,
|
||||
surface: ComPtr(ptr::null_mut()),
|
||||
texture: ComPtr(ptr::null_mut()),
|
||||
width: display.width() as usize,
|
||||
height: display.height() as usize,
|
||||
display,
|
||||
@@ -152,6 +166,8 @@ impl Capturer {
|
||||
gdi_capturer,
|
||||
gdi_buffer: Vec::new(),
|
||||
saved_raw_data: Vec::new(),
|
||||
output_texture: false,
|
||||
adapter_desc1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -169,6 +185,11 @@ impl Capturer {
|
||||
self.gdi_capturer.take();
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpucodec")]
|
||||
pub fn set_output_texture(&mut self, texture: bool) {
|
||||
self.output_texture = texture;
|
||||
}
|
||||
|
||||
unsafe fn load_frame(&mut self, timeout: UINT) -> io::Result<(*const u8, i32)> {
|
||||
let mut frame = ptr::null_mut();
|
||||
#[allow(invalid_value)]
|
||||
@@ -230,7 +251,21 @@ impl Capturer {
|
||||
Ok(surface)
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, timeout: UINT) -> io::Result<&'a [u8]> {
|
||||
pub fn frame<'a>(&'a mut self, timeout: UINT) -> io::Result<Frame<'a>> {
|
||||
if self.output_texture {
|
||||
Ok(Frame::Texture(self.get_texture(timeout)?))
|
||||
} else {
|
||||
let width = self.width;
|
||||
let height = self.height;
|
||||
Ok(Frame::PixelBuffer(PixelBuffer::new(
|
||||
self.get_pixelbuffer(timeout)?,
|
||||
width,
|
||||
height,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pixelbuffer<'a>(&'a mut self, timeout: UINT) -> io::Result<&'a [u8]> {
|
||||
unsafe {
|
||||
// Release last frame.
|
||||
// No error checking needed because we don't care.
|
||||
@@ -293,6 +328,34 @@ impl Capturer {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_texture(&mut self, timeout: UINT) -> io::Result<*mut c_void> {
|
||||
unsafe {
|
||||
if self.duplication.0.is_null() {
|
||||
return Err(std::io::ErrorKind::AddrNotAvailable.into());
|
||||
}
|
||||
(*self.duplication.0).ReleaseFrame();
|
||||
let mut frame = ptr::null_mut();
|
||||
#[allow(invalid_value)]
|
||||
let mut info = mem::MaybeUninit::uninit().assume_init();
|
||||
|
||||
wrap_hresult((*self.duplication.0).AcquireNextFrame(timeout, &mut info, &mut frame))?;
|
||||
let frame = ComPtr(frame);
|
||||
|
||||
if info.AccumulatedFrames == 0 || *info.LastPresentTime.QuadPart() == 0 {
|
||||
return Err(std::io::ErrorKind::WouldBlock.into());
|
||||
}
|
||||
|
||||
let mut texture: *mut ID3D11Texture2D = ptr::null_mut();
|
||||
(*frame.0).QueryInterface(
|
||||
&IID_ID3D11Texture2D,
|
||||
&mut texture as *mut *mut _ as *mut *mut _,
|
||||
);
|
||||
let texture = ComPtr(texture);
|
||||
self.texture = texture;
|
||||
Ok(self.texture.0 as *mut c_void)
|
||||
}
|
||||
}
|
||||
|
||||
fn unmap(&self) {
|
||||
unsafe {
|
||||
(*self.duplication.0).ReleaseFrame();
|
||||
@@ -305,6 +368,15 @@ impl Capturer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device(&self) -> AdapterDevice {
|
||||
AdapterDevice {
|
||||
device: self.device.0 as _,
|
||||
vendor_id: self.adapter_desc1.VendorId,
|
||||
luid: ((self.adapter_desc1.AdapterLuid.HighPart as i64) << 32)
|
||||
| self.adapter_desc1.AdapterLuid.LowPart as i64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Capturer {
|
||||
@@ -547,6 +619,22 @@ impl Display {
|
||||
self.desc.DesktopCoordinates.top,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "gpucodec")]
|
||||
pub fn adapter_luid(&self) -> Option<i64> {
|
||||
unsafe {
|
||||
if !self.adapter.is_null() {
|
||||
#[allow(invalid_value)]
|
||||
let mut adapter_desc1 = mem::MaybeUninit::uninit().assume_init();
|
||||
if wrap_hresult((*self.adapter.0).GetDesc1(&mut adapter_desc1)).is_ok() {
|
||||
let luid = ((adapter_desc1.AdapterLuid.HighPart as i64) << 32)
|
||||
| adapter_desc1.AdapterLuid.LowPart as i64;
|
||||
return Some(luid);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_hresult(x: HRESULT) -> io::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user