Implement experimental D3D Texture2D sharing

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2023-05-09 12:33:21 +04:00
parent 4126bd092c
commit 8b9a70505b
2 changed files with 138 additions and 0 deletions

View File

@ -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<H: ConsoleListenerHandler> ConsoleListener<H> {
))
}
#[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(

View File

@ -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));