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:
parent
9302d6af77
commit
6a59a5a43a
16
qemu-display/examples/list.rs
Normal file
16
qemu-display/examples/list.rs
Normal 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(())
|
||||
}
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 _)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user