From 8b9a70505beb7d00f57a973b1c67511d0f594038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 9 May 2023 12:33:21 +0400 Subject: [PATCH] Implement experimental D3D Texture2D sharing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- qemu-display/src/console_listener.rs | 97 ++++++++++++++++++++++++++++ qemu-rdw/src/display.rs | 41 ++++++++++++ 2 files changed, 138 insertions(+) diff --git a/qemu-display/src/console_listener.rs b/qemu-display/src/console_listener.rs index 91b59c0..0413a11 100644 --- a/qemu-display/src/console_listener.rs +++ b/qemu-display/src/console_listener.rs @@ -50,6 +50,28 @@ pub struct UpdateMap { pub h: i32, } +#[cfg(windows)] +#[derive(Debug)] +pub struct ScanoutD3dTexture2d { + pub handle: u64, + pub tex_width: u32, + pub tex_height: u32, + pub y0_top: bool, + pub x: u32, + pub y: u32, + pub w: u32, + pub h: u32, +} + +#[cfg(windows)] +#[derive(Debug, Copy, Clone)] +pub struct UpdateD3dTexture2d { + pub x: i32, + pub y: i32, + pub w: i32, + pub h: i32, +} + #[cfg(unix)] #[derive(Debug)] pub struct ScanoutDMABUF { @@ -122,6 +144,12 @@ pub trait ConsoleListenerHandler: 'static + Send + Sync { #[cfg(windows)] async fn update_map(&mut self, update: UpdateMap); + #[cfg(windows)] + async fn scanout_d3d11_texture2d(&mut self, scanout: ScanoutD3dTexture2d); + + #[cfg(windows)] + async fn update_d3d11_texture2d(&mut self, update: UpdateD3dTexture2d); + #[cfg(unix)] async fn scanout_dmabuf(&mut self, scanout: ScanoutDMABUF); @@ -237,6 +265,75 @@ impl ConsoleListener { )) } + #[cfg(windows)] + async fn scanout_d3d11_texture2d( + &mut self, + handle: u64, + tex_width: u32, + tex_height: u32, + y0_top: bool, + x: u32, + y: u32, + w: u32, + h: u32, + ) -> zbus::fdo::Result<()> { + let texture = ScanoutD3dTexture2d { + handle, + tex_width, + tex_height, + y0_top, + x, + y, + w, + h, + }; + self.handler.scanout_d3d11_texture2d(texture).await; + Ok(()) + } + + #[cfg(not(windows))] + async fn scanout_d3d11_texture2d( + &mut self, + _handle: u64, + _tex_width: u32, + _tex_height: u32, + _y0_top: bool, + _x: u32, + _y: u32, + _w: u32, + _h: u32, + ) -> zbus::fdo::Result<()> { + Err(zbus::fdo::Error::NotSupported( + "D3D is not support on !windows".into(), + )) + } + + #[cfg(windows)] + async fn update_d3d11_texture2d( + &mut self, + x: i32, + y: i32, + w: i32, + h: i32, + ) -> zbus::fdo::Result<()> { + let up = UpdateD3dTexture2d { x, y, w, h }; + self.handler.update_d3d11_texture2d(up).await; + Ok(()) + } + + #[cfg(not(windows))] + async fn update_d3d11_texture2d( + &mut self, + _x: i32, + _y: i32, + _w: i32, + _h: i32, + ) -> zbus::fdo::Result<()> { + Err(zbus::fdo::Error::NotSupported( + "D3d is not support on !windows".into(), + )) + } + #[cfg(not(unix))] #[dbus_interface(name = "ScanoutDMABUF")] async fn scanout_dmabuf( diff --git a/qemu-rdw/src/display.rs b/qemu-rdw/src/display.rs index e34a9fd..6ca1ab0 100644 --- a/qemu-rdw/src/display.rs +++ b/qemu-rdw/src/display.rs @@ -248,6 +248,26 @@ mod imp { let bytes = map.as_bytes(); this.obj().update_area(u.x as _, u.y as _, u.w as _, u.h as _, stride as _, &bytes[u.y as usize * stride as usize + u.x as usize * 4..]); } + #[cfg(windows)] + ScanoutD3dTexture2d(s) => { + log::debug!("{s:?}"); + this.obj().set_display_size(Some((s.w as _, s.h as _))); + this.obj().set_d3d11_texture2d_scanout(rdw::RdwD3d11Texture2dScanout { + handle: s.handle as _, + tex_width: s.tex_width, + tex_height: s.tex_height, + y0_top: s.y0_top, + x: s.x, + y: s.y, + w: s.w, + h: s.h, + }); + } + #[cfg(windows)] + UpdateD3dTexture2d { wait_tx, .. } => { + this.obj().render(); + let _ = wait_tx.send(()); + } #[cfg(unix)] ScanoutDMABUF(s) => { log::trace!("{s:?}"); @@ -337,6 +357,13 @@ enum ConsoleEvent { ScanoutMap(qemu_display::ScanoutMap), #[cfg(windows)] UpdateMap(qemu_display::UpdateMap), + #[cfg(windows)] + ScanoutD3dTexture2d(qemu_display::ScanoutD3dTexture2d), + #[cfg(windows)] + UpdateD3dTexture2d { + _update: qemu_display::UpdateD3dTexture2d, + wait_tx: futures::channel::oneshot::Sender<()>, + }, #[cfg(unix)] ScanoutDMABUF(qemu_display::ScanoutDMABUF), #[cfg(unix)] @@ -382,6 +409,20 @@ impl ConsoleListenerHandler for ConsoleHandler { self.send(ConsoleEvent::UpdateMap(update)); } + #[cfg(windows)] + async fn scanout_d3d11_texture2d(&mut self, scanout: qemu_display::ScanoutD3dTexture2d) { + self.send(ConsoleEvent::ScanoutD3dTexture2d(scanout)); + } + + #[cfg(windows)] + async fn update_d3d11_texture2d(&mut self, _update: qemu_display::UpdateD3dTexture2d) { + let (wait_tx, wait_rx) = futures::channel::oneshot::channel(); + self.send(ConsoleEvent::UpdateD3dTexture2d { _update, wait_tx }); + if let Err(e) = wait_rx.await { + log::warn!("wait update d3d texture2d failed: {}", e); + } + } + #[cfg(unix)] async fn scanout_dmabuf(&mut self, scanout: qemu_display::ScanoutDMABUF) { self.send(ConsoleEvent::ScanoutDMABUF(scanout));