1
0
mirror of https://gitlab.com/marcandre.lureau/qemu-display.git synced 2025-04-14 08:44:46 +00:00

qemu-display: replace hand-written win32 mmap

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2025-01-13 14:45:19 +04:00
parent 9302d6af77
commit 6a59a5a43a
4 changed files with 30 additions and 181 deletions

View File

@ -0,0 +1,16 @@
use std::error::Error;
use futures::StreamExt;
use qemu_display::Display;
use zbus::Connection;
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
tracing_subscriber::fmt::init();
let conn = Connection::session().await?;
let display = Display::new::<()>(&conn, None).await?;
let owner = display.receive_owner_changed().await?.next().await;
dbg!(owner);
Ok(())
}

View File

@ -1,9 +1,10 @@
#[cfg(windows)]
use crate::win32::{Fd, Mmap};
use crate::win32::Fd;
use derivative::Derivative;
#[cfg(unix)]
use memmap2::Mmap;
use std::ops::Drop;
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, FromRawHandle, OwnedHandle};
#[cfg(unix)]
use std::os::{
fd::{AsFd, OwnedFd},
@ -41,7 +42,7 @@ pub struct ScanoutMap {
#[cfg(unix)]
pub fd: OwnedFd,
#[cfg(windows)]
pub handle: u64,
pub handle: OwnedHandle,
pub offset: u32,
pub width: u32,
pub height: u32,
@ -52,9 +53,6 @@ pub struct ScanoutMap {
#[derive(Debug)]
pub struct ScanoutMmap {
scanout: ScanoutMap,
#[cfg(unix)]
mmap: Mmap,
#[cfg(windows)]
mmap: Mmap,
}
@ -64,20 +62,15 @@ impl ScanoutMap {
let offset = self.offset;
#[cfg(unix)]
let mmap = {
let fd = self.fd.as_raw_fd();
unsafe {
memmap2::MmapOptions::new()
.len(len)
.offset(offset.into())
.map(fd)
}?
};
let desc = self.fd.as_raw_fd();
#[cfg(windows)]
let mmap = {
let handle = windows::Win32::Foundation::HANDLE(self.handle as _); // taking ownership
Mmap::new(handle, offset.try_into().unwrap(), len)?
let desc = self.handle.as_raw_handle();
let mmap = unsafe {
memmap2::MmapOptions::new()
.len(len)
.offset(offset.into())
.map(desc)?
};
Ok(ScanoutMmap {
@ -426,6 +419,7 @@ impl<H: ConsoleListenerMapHandler> ConsoleListenerMap<H> {
stride: u32,
format: u32,
) -> zbus::fdo::Result<()> {
let handle = unsafe { OwnedHandle::from_raw_handle(handle as _) };
let map = ScanoutMap {
handle,
offset,

View File

@ -1,13 +1,9 @@
use std::io;
use tracing::warn;
use windows::Win32::{
Foundation::{CloseHandle, HANDLE},
Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW},
System::{
Memory::{MapViewOfFile, UnmapViewOfFile, FILE_MAP_READ, MEMORY_MAPPED_VIEW_ADDRESS},
Threading::PROCESS_ACCESS_RIGHTS,
},
System::Threading::PROCESS_ACCESS_RIGHTS,
};
#[cfg(feature = "qmp")]
@ -122,48 +118,3 @@ pub(crate) fn unix_stream_get_peer_pid(stream: &UnixStream) -> Result<u32, std::
Ok(ret)
}
#[derive(Debug)]
pub(crate) struct Mmap {
handle: HANDLE,
ptr: MEMORY_MAPPED_VIEW_ADDRESS,
offset: isize,
size: usize,
}
#[cfg(windows)]
impl Drop for Mmap {
fn drop(&mut self) {
unsafe {
if let Err(err) = UnmapViewOfFile(self.ptr) {
warn!("error while unmap: {}", err);
}
if let Err(err) = CloseHandle(self.handle) {
warn!("error while closing mmap: {}", err);
}
}
}
}
#[cfg(windows)]
impl Mmap {
// FIXME: remove and replace with memmap2, use offset properly
pub(crate) fn new(handle: HANDLE, offset: usize, size: usize) -> std::io::Result<Self> {
let ptr = unsafe { MapViewOfFile(handle, FILE_MAP_READ, 0, 0, offset + size) };
if ptr.Value.is_null() {
return Err(io::Error::last_os_error());
}
Ok(Self {
handle,
ptr,
offset: offset.try_into().unwrap(),
size,
})
}
pub(crate) fn as_ref(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(self.ptr.Value.cast::<u8>().offset(self.offset), self.size)
}
}
}

View File

@ -18,10 +18,6 @@ mod imp {
use qemu_display::ScanoutMmap;
#[cfg(any(windows, unix))]
use std::cell::RefCell;
#[cfg(windows)]
use std::ffi::c_void;
#[cfg(windows)]
use windows::Win32::Foundation::{CloseHandle, HANDLE};
#[repr(C)]
pub struct RdwDisplayQemuClass {
@ -49,36 +45,6 @@ mod imp {
type Type = Display;
}
#[cfg(windows)]
#[derive(Debug)]
struct MemoryMap {
handle: HANDLE,
ptr: *const c_void,
offset: isize,
size: usize,
}
#[cfg(windows)]
impl Drop for MemoryMap {
fn drop(&mut self) {
unsafe {
use windows::Win32::System::Memory::UnmapViewOfFile;
UnmapViewOfFile(self.ptr);
CloseHandle(self.handle);
}
}
}
#[cfg(windows)]
impl MemoryMap {
fn as_bytes(&self) -> &[u8] {
unsafe {
std::slice::from_raw_parts(self.ptr.cast::<u8>().offset(self.offset), self.size)
}
}
}
#[derive(Debug, Default)]
pub struct Display {
pub(crate) console: OnceCell<Console>,
@ -319,7 +285,6 @@ mod imp {
Some(&u.data),
);
}
#[cfg(unix)]
ScanoutMap { scanout, wait_tx } => {
log::debug!("{scanout:?}");
if scanout.format != 0x20020888 {
@ -343,7 +308,6 @@ mod imp {
this.scanout_map.replace(map);
let _ = wait_tx.send(());
}
#[cfg(unix)]
UpdateMap(u) => {
log::debug!("{u:?}");
let scanout_map = this.scanout_map.borrow();
@ -365,82 +329,6 @@ mod imp {
);
}
#[cfg(windows)]
ScanoutMap { scanout, wait_tx } => {
use windows::Win32::System::Memory::{
MapViewOfFile, FILE_MAP_READ,
};
log::debug!("{s:?}");
if scanout.format != 0x20020888 {
log::warn!(
"Format not yet supported: {:X}",
scanout.format
);
continue;
}
let handle = HANDLE(scanout.handle as _);
let size =
scanout.height as usize * scanout.stride as usize;
let offset = scanout.offset as isize;
let ptr = unsafe {
MapViewOfFile(
handle,
FILE_MAP_READ,
0,
0,
scanout.offset as usize + size,
)
};
if ptr.is_null() {
log::warn!("Failed to map scanout!");
continue;
}
let map = MemoryMap {
ptr,
handle,
offset,
size,
};
this.obj().set_display_size(Some((
scanout.width as _,
scanout.height as _,
)));
this.obj().update_area(
0,
0,
scanout.width as _,
scanout.height as _,
scanout.stride as _,
Some(map.as_bytes()),
);
this.scanout_map.replace(Some((map, scanout.stride)));
let _ = wait_tx.send(());
}
#[cfg(windows)]
UpdateMap(u) => {
log::debug!("{u:?}");
let scanout_map = this.scanout_map.borrow();
let Some((map, stride)) = scanout_map.as_ref() else {
log::warn!("No mapped scanout!");
continue;
};
let stride = *stride;
let bytes = map.as_bytes();
this.obj().update_area(
u.x as _,
u.y as _,
u.w as _,
u.h as _,
stride as _,
Some(
&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 _)));