mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-11-24 04:12:20 +08:00
enable dxgi https://github.com/rustdesk/rustdesk/issues/79, may fix https://github.com/rustdesk/rustdesk/issues/169
This commit is contained in:
parent
7282a462f4
commit
49dff161dd
@ -47,9 +47,9 @@ fn generate_bindings(
|
||||
) {
|
||||
let mut b = bindgen::builder()
|
||||
.header(ffi_header.to_str().unwrap())
|
||||
.whitelist_type("^[vV].*")
|
||||
.whitelist_var("^[vV].*")
|
||||
.whitelist_function("^[vV].*")
|
||||
.allowlist_type("^[vV].*")
|
||||
.allowlist_var("^[vV].*")
|
||||
.allowlist_function("^[vV].*")
|
||||
.rustified_enum("^v.*")
|
||||
.trust_clang_mangling(false)
|
||||
.layout_tests(false) // breaks 32/64-bit compat
|
||||
|
@ -25,20 +25,35 @@ use winapi::{
|
||||
D3D11_CPU_ACCESS_READ, D3D11_SDK_VERSION, D3D11_USAGE_STAGING,
|
||||
},
|
||||
um::d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
|
||||
um::unknwnbase::IUnknown,
|
||||
um::wingdi::*,
|
||||
um::winnt::HRESULT,
|
||||
um::winuser::*,
|
||||
};
|
||||
|
||||
//TODO: Split up into files.
|
||||
pub struct ComPtr<T>(*mut T);
|
||||
impl<T> ComPtr<T> {
|
||||
fn is_null(&self) -> bool {
|
||||
self.0.is_null()
|
||||
}
|
||||
}
|
||||
impl<T> Drop for ComPtr<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if !self.is_null() {
|
||||
(*(self.0 as *mut IUnknown)).Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Capturer {
|
||||
device: *mut ID3D11Device,
|
||||
device: ComPtr<ID3D11Device>,
|
||||
display: Display,
|
||||
context: *mut ID3D11DeviceContext,
|
||||
duplication: *mut IDXGIOutputDuplication,
|
||||
context: ComPtr<ID3D11DeviceContext>,
|
||||
duplication: ComPtr<IDXGIOutputDuplication>,
|
||||
fastlane: bool,
|
||||
surface: *mut IDXGISurface,
|
||||
surface: ComPtr<IDXGISurface>,
|
||||
data: *const u8,
|
||||
len: usize,
|
||||
width: usize,
|
||||
@ -62,7 +77,7 @@ impl Capturer {
|
||||
} else {
|
||||
wrap_hresult(unsafe {
|
||||
D3D11CreateDevice(
|
||||
display.adapter as *mut _,
|
||||
display.adapter.0 as *mut _,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
ptr::null_mut(), // No software rasterizer.
|
||||
0, // No device flags.
|
||||
@ -75,6 +90,8 @@ impl Capturer {
|
||||
)
|
||||
})
|
||||
};
|
||||
let device = ComPtr(device);
|
||||
let context = ComPtr(context);
|
||||
|
||||
if res.is_err() {
|
||||
gdi_capturer = display.create_gdi();
|
||||
@ -84,7 +101,7 @@ impl Capturer {
|
||||
}
|
||||
} else {
|
||||
res = wrap_hresult(unsafe {
|
||||
let hres = (*display.inner).DuplicateOutput(device as *mut _, &mut duplication);
|
||||
let hres = (*display.inner.0).DuplicateOutput(device.0 as *mut _, &mut duplication);
|
||||
if hres != S_OK {
|
||||
gdi_capturer = display.create_gdi();
|
||||
println!("Fallback to GDI");
|
||||
@ -124,17 +141,7 @@ impl Capturer {
|
||||
});
|
||||
}
|
||||
|
||||
if let Err(err) = res {
|
||||
unsafe {
|
||||
if !device.is_null() {
|
||||
(*device).Release();
|
||||
}
|
||||
if !context.is_null() {
|
||||
(*context).Release();
|
||||
}
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
res?;
|
||||
|
||||
if !duplication.is_null() {
|
||||
unsafe {
|
||||
@ -145,9 +152,9 @@ impl Capturer {
|
||||
Ok(Capturer {
|
||||
device,
|
||||
context,
|
||||
duplication,
|
||||
duplication: ComPtr(duplication),
|
||||
fastlane: desc.DesktopImageInSystemMemory == TRUE,
|
||||
surface: ptr::null_mut(),
|
||||
surface: ComPtr(ptr::null_mut()),
|
||||
width: display.width() as usize,
|
||||
height: display.height() as usize,
|
||||
display,
|
||||
@ -179,36 +186,23 @@ impl Capturer {
|
||||
let mut info = mem::MaybeUninit::uninit().assume_init();
|
||||
self.data = ptr::null();
|
||||
|
||||
wrap_hresult((*self.duplication).AcquireNextFrame(timeout, &mut info, &mut frame))?;
|
||||
wrap_hresult((*self.duplication.0).AcquireNextFrame(timeout, &mut info, &mut frame))?;
|
||||
let frame = ComPtr(frame);
|
||||
|
||||
if *info.LastPresentTime.QuadPart() == 0 {
|
||||
return Err(std::io::ErrorKind::WouldBlock.into());
|
||||
}
|
||||
|
||||
let mut rect = mem::MaybeUninit::uninit().assume_init();
|
||||
if self.fastlane {
|
||||
let mut rect = mem::MaybeUninit::uninit().assume_init();
|
||||
let res = wrap_hresult((*self.duplication).MapDesktopSurface(&mut rect));
|
||||
|
||||
(*frame).Release();
|
||||
|
||||
if let Err(err) = res {
|
||||
Err(err)
|
||||
} else {
|
||||
self.data = rect.pBits;
|
||||
self.len = self.height * rect.Pitch as usize;
|
||||
Ok(())
|
||||
}
|
||||
wrap_hresult((*self.duplication.0).MapDesktopSurface(&mut rect))?;
|
||||
} else {
|
||||
self.surface = ptr::null_mut();
|
||||
self.surface = self.ohgodwhat(frame)?;
|
||||
|
||||
let mut rect = mem::MaybeUninit::uninit().assume_init();
|
||||
wrap_hresult((*self.surface).Map(&mut rect, DXGI_MAP_READ))?;
|
||||
|
||||
self.data = rect.pBits;
|
||||
self.len = self.height * rect.Pitch as usize;
|
||||
Ok(())
|
||||
self.surface = ComPtr(self.ohgodwhat(frame.0)?);
|
||||
wrap_hresult((*self.surface.0).Map(&mut rect, DXGI_MAP_READ))?;
|
||||
}
|
||||
self.data = rect.pBits;
|
||||
self.len = self.height * rect.Pitch as usize;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// copy from GPU memory to system memory
|
||||
@ -218,9 +212,10 @@ impl Capturer {
|
||||
&IID_ID3D11Texture2D,
|
||||
&mut texture as *mut *mut _ as *mut *mut _,
|
||||
);
|
||||
let texture = ComPtr(texture);
|
||||
|
||||
let mut texture_desc = mem::MaybeUninit::uninit().assume_init();
|
||||
(*texture).GetDesc(&mut texture_desc);
|
||||
(*texture.0).GetDesc(&mut texture_desc);
|
||||
|
||||
texture_desc.Usage = D3D11_USAGE_STAGING;
|
||||
texture_desc.BindFlags = 0;
|
||||
@ -228,33 +223,23 @@ impl Capturer {
|
||||
texture_desc.MiscFlags = 0;
|
||||
|
||||
let mut readable = ptr::null_mut();
|
||||
let res = wrap_hresult((*self.device).CreateTexture2D(
|
||||
wrap_hresult((*self.device.0).CreateTexture2D(
|
||||
&mut texture_desc,
|
||||
ptr::null(),
|
||||
&mut readable,
|
||||
));
|
||||
))?;
|
||||
(*readable).SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
|
||||
let readable = ComPtr(readable);
|
||||
|
||||
if let Err(err) = res {
|
||||
(*frame).Release();
|
||||
(*texture).Release();
|
||||
(*readable).Release();
|
||||
Err(err)
|
||||
} else {
|
||||
(*readable).SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
|
||||
let mut surface = ptr::null_mut();
|
||||
(*readable.0).QueryInterface(
|
||||
&IID_IDXGISurface,
|
||||
&mut surface as *mut *mut _ as *mut *mut _,
|
||||
);
|
||||
|
||||
let mut surface = ptr::null_mut();
|
||||
(*readable).QueryInterface(
|
||||
&IID_IDXGISurface,
|
||||
&mut surface as *mut *mut _ as *mut *mut _,
|
||||
);
|
||||
(*self.context.0).CopyResource(readable.0 as *mut _, texture.0 as *mut _);
|
||||
|
||||
(*self.context).CopyResource(readable as *mut _, texture as *mut _);
|
||||
|
||||
(*frame).Release();
|
||||
(*texture).Release();
|
||||
(*readable).Release();
|
||||
Ok(surface)
|
||||
}
|
||||
Ok(surface)
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, timeout: UINT) -> io::Result<&'a [u8]> {
|
||||
@ -271,17 +256,7 @@ impl Capturer {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.fastlane {
|
||||
(*self.duplication).UnMapDesktopSurface();
|
||||
} else {
|
||||
if !self.surface.is_null() {
|
||||
(*self.surface).Unmap();
|
||||
(*self.surface).Release();
|
||||
self.surface = ptr::null_mut();
|
||||
}
|
||||
}
|
||||
|
||||
(*self.duplication).ReleaseFrame();
|
||||
self.unmap();
|
||||
self.load_frame(timeout)?;
|
||||
slice::from_raw_parts(self.data, self.len)
|
||||
}
|
||||
@ -301,31 +276,32 @@ impl Capturer {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Capturer {
|
||||
fn drop(&mut self) {
|
||||
fn unmap(&self) {
|
||||
unsafe {
|
||||
if !self.surface.is_null() {
|
||||
(*self.surface).Unmap();
|
||||
(*self.surface).Release();
|
||||
}
|
||||
if !self.duplication.is_null() {
|
||||
(*self.duplication).Release();
|
||||
}
|
||||
if !self.device.is_null() {
|
||||
(*self.device).Release();
|
||||
}
|
||||
if !self.context.is_null() {
|
||||
(*self.context).Release();
|
||||
(*self.duplication.0).ReleaseFrame();
|
||||
if self.fastlane {
|
||||
(*self.duplication.0).UnMapDesktopSurface();
|
||||
} else {
|
||||
if !self.surface.is_null() {
|
||||
(*self.surface.0).Unmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Capturer {
|
||||
fn drop(&mut self) {
|
||||
if !self.duplication.is_null() {
|
||||
self.unmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Displays {
|
||||
factory: *mut IDXGIFactory1,
|
||||
adapter: *mut IDXGIAdapter1,
|
||||
factory: ComPtr<IDXGIFactory1>,
|
||||
adapter: ComPtr<IDXGIAdapter1>,
|
||||
/// Index of the CURRENT adapter.
|
||||
nadapter: UINT,
|
||||
/// Index of the NEXT display to fetch.
|
||||
@ -345,8 +321,8 @@ impl Displays {
|
||||
};
|
||||
|
||||
Ok(Displays {
|
||||
factory,
|
||||
adapter,
|
||||
factory: ComPtr(factory),
|
||||
adapter: ComPtr(adapter),
|
||||
nadapter: 0,
|
||||
ndisplay: 0,
|
||||
})
|
||||
@ -370,8 +346,8 @@ impl Displays {
|
||||
}
|
||||
// let is_primary = (d.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) > 0;
|
||||
let mut disp = Display {
|
||||
inner: std::ptr::null_mut(),
|
||||
adapter: std::ptr::null_mut(),
|
||||
inner: ComPtr(std::ptr::null_mut()),
|
||||
adapter: ComPtr(std::ptr::null_mut()),
|
||||
desc: unsafe { std::mem::zeroed() },
|
||||
gdi: true,
|
||||
};
|
||||
@ -416,18 +392,15 @@ impl Displays {
|
||||
|
||||
let output = unsafe {
|
||||
let mut output = ptr::null_mut();
|
||||
(*self.adapter).EnumOutputs(self.ndisplay, &mut output);
|
||||
output
|
||||
(*self.adapter.0).EnumOutputs(self.ndisplay, &mut output);
|
||||
ComPtr(output)
|
||||
};
|
||||
|
||||
// If the current adapter is done, we free it.
|
||||
// We return None so the caller gets the next adapter and tries again.
|
||||
|
||||
if output.is_null() {
|
||||
unsafe {
|
||||
(*self.adapter).Release();
|
||||
self.adapter = ptr::null_mut();
|
||||
}
|
||||
self.adapter = ComPtr(ptr::null_mut());
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -439,7 +412,7 @@ impl Displays {
|
||||
|
||||
let desc = unsafe {
|
||||
let mut desc = mem::MaybeUninit::uninit().assume_init();
|
||||
(*output).GetDesc(&mut desc);
|
||||
(*output.0).GetDesc(&mut desc);
|
||||
desc
|
||||
};
|
||||
|
||||
@ -447,28 +420,24 @@ impl Displays {
|
||||
|
||||
let mut inner: *mut IDXGIOutput1 = ptr::null_mut();
|
||||
unsafe {
|
||||
(*output).QueryInterface(&IID_IDXGIOutput1, &mut inner as *mut *mut _ as *mut *mut _);
|
||||
(*output).Release();
|
||||
(*output.0).QueryInterface(&IID_IDXGIOutput1, &mut inner as *mut *mut _ as *mut *mut _);
|
||||
}
|
||||
|
||||
// If it's null, we have an error.
|
||||
// So we act like the adapter is done.
|
||||
|
||||
if inner.is_null() {
|
||||
unsafe {
|
||||
(*self.adapter).Release();
|
||||
self.adapter = ptr::null_mut();
|
||||
}
|
||||
self.adapter = ComPtr(ptr::null_mut());
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(*self.adapter).AddRef();
|
||||
(*self.adapter.0).AddRef();
|
||||
}
|
||||
|
||||
Some(Some(Display {
|
||||
inner,
|
||||
adapter: self.adapter,
|
||||
inner: ComPtr(inner),
|
||||
adapter: ComPtr(self.adapter.0),
|
||||
desc,
|
||||
gdi: false,
|
||||
}))
|
||||
@ -488,8 +457,8 @@ impl Iterator for Displays {
|
||||
|
||||
self.adapter = unsafe {
|
||||
let mut adapter = ptr::null_mut();
|
||||
(*self.factory).EnumAdapters1(self.nadapter, &mut adapter);
|
||||
adapter
|
||||
(*self.factory.0).EnumAdapters1(self.nadapter, &mut adapter);
|
||||
ComPtr(adapter)
|
||||
};
|
||||
|
||||
if let Some(res) = self.read_and_invalidate() {
|
||||
@ -502,20 +471,9 @@ impl Iterator for Displays {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Displays {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
(*self.factory).Release();
|
||||
if !self.adapter.is_null() {
|
||||
(*self.adapter).Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Display {
|
||||
inner: *mut IDXGIOutput1,
|
||||
adapter: *mut IDXGIAdapter1,
|
||||
inner: ComPtr<IDXGIOutput1>,
|
||||
adapter: ComPtr<IDXGIAdapter1>,
|
||||
desc: DXGI_OUTPUT_DESC,
|
||||
gdi: bool,
|
||||
}
|
||||
@ -569,18 +527,6 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Display {
|
||||
fn drop(&mut self) {
|
||||
if self.inner.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
(*self.inner).Release();
|
||||
(*self.adapter).Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_hresult(x: HRESULT) -> io::Result<()> {
|
||||
use std::io::ErrorKind::*;
|
||||
Err((match x {
|
||||
|
@ -99,23 +99,9 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
*SWITCH.lock().unwrap() = false;
|
||||
sp.send(msg_out);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
if !c.is_gdi() {
|
||||
// dxgi duplicateoutput has no output if display no change, so we use gdi this as workaround
|
||||
if c.set_gdi() {
|
||||
// dgx capture release has memory leak somehow, so use gdi always before fixing it, just sacrificing some cpu
|
||||
/*
|
||||
if let Ok(frame) = c.frame(wait as _) {
|
||||
handle_one_frame(&sp, &frame, 0, &mut vpx)?;
|
||||
}
|
||||
c.cancel_gdi();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
let start = time::Instant::now();
|
||||
|
||||
let mut crc = (0, 0);
|
||||
let start = time::Instant::now();
|
||||
let mut last_sent = time::Instant::now();
|
||||
let mut last_check_displays = time::Instant::now();
|
||||
while sp.ok() {
|
||||
|
Loading…
Reference in New Issue
Block a user