mirror of
https://github.com/rustdesk/qemu-display.git
synced 2025-07-01 15:25:29 +00:00
vnc: now display the framebuffer/scanout
This commit is contained in:
parent
0f75905cc8
commit
124d893395
@ -10,4 +10,4 @@ members = [
|
|||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
zbus = { path = '/home/elmarco/src/zbus/zbus' }
|
zbus = { path = '/home/elmarco/src/zbus/zbus' }
|
||||||
zvariant = { path = '/home/elmarco/src/zbus/zvariant' }
|
zvariant = { path = '/home/elmarco/src/zbus/zvariant' }
|
||||||
vnc = { git = 'https://github.com/elmarco/rust-vnc', branch = 'server' }
|
vnc = { path = '/home/elmarco/src/rust-vnc' }
|
||||||
|
@ -12,3 +12,4 @@ vnc = "0.4.0"
|
|||||||
clap = "3.0.0-beta.2"
|
clap = "3.0.0-beta.2"
|
||||||
zbus = { version = "2.0.0-beta" }
|
zbus = { version = "2.0.0-beta" }
|
||||||
libc = "0.2.86"
|
libc = "0.2.86"
|
||||||
|
image = "0.23.14"
|
||||||
|
@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::{io, thread, time};
|
use std::{io, thread, time};
|
||||||
|
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
|
use image::GenericImage;
|
||||||
use qemu_display_listener::{Console, ConsoleEvent};
|
use qemu_display_listener::{Console, ConsoleEvent};
|
||||||
use vnc::{
|
use vnc::{
|
||||||
server::Event as VncEvent, server::FramebufferUpdate, Error as VncError, PixelFormat, Rect,
|
server::Event as VncEvent, server::FramebufferUpdate, Error as VncError, PixelFormat, Rect,
|
||||||
@ -33,28 +34,39 @@ struct Cli {
|
|||||||
address: SocketAddrArgs,
|
address: SocketAddrArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PIXMAN_X8R8G8B8: u32 = 0x20020888;
|
||||||
|
type BgraImage = image::ImageBuffer<image::Bgra<u8>, Vec<u8>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct ServerInner {
|
struct ServerInner {
|
||||||
width: u16,
|
image: BgraImage,
|
||||||
height: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
struct Server {
|
struct Server {
|
||||||
inner: Arc<Mutex<ServerInner>>,
|
inner: Arc<Mutex<ServerInner>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
fn new(width: u16, height: u16) -> Self {
|
fn new(width: u16, height: u16) -> Self {
|
||||||
|
let image = BgraImage::new(width as _, height as _);
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(Mutex::new(ServerInner { width, height })),
|
inner: Arc::new(Mutex::new(ServerInner { image })),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn width_height(&self) -> (u16, u16) {
|
||||||
|
let inner = self.inner.lock().unwrap();
|
||||||
|
(inner.image.width() as u16, inner.image.height() as u16)
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_client(&self, stream: TcpStream) -> Result<(), Box<dyn Error>> {
|
fn handle_client(&self, stream: TcpStream) -> Result<(), Box<dyn Error>> {
|
||||||
stream.set_read_timeout(Some(time::Duration::from_millis(100)))?;
|
stream.set_read_timeout(Some(time::Duration::from_millis(100)))?;
|
||||||
|
let (width, height) = self.width_height();
|
||||||
let (mut server, _share) = VncServer::from_tcp_stream(
|
let (mut server, _share) = VncServer::from_tcp_stream(
|
||||||
stream,
|
stream,
|
||||||
self.inner.lock().unwrap().width,
|
width,
|
||||||
self.inner.lock().unwrap().height,
|
height,
|
||||||
PixelFormat::rgb8888(),
|
PixelFormat::rgb8888(),
|
||||||
"qemu-vnc experiment".into(),
|
"qemu-vnc experiment".into(),
|
||||||
)?;
|
)?;
|
||||||
@ -80,13 +92,14 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_update = Some(time::Instant::now());
|
last_update = Some(time::Instant::now());
|
||||||
|
let inner = self.inner.lock().unwrap();
|
||||||
let mut fbu = FramebufferUpdate::new(&PixelFormat::rgb8888());
|
let mut fbu = FramebufferUpdate::new(&PixelFormat::rgb8888());
|
||||||
let pixel_data = vec![128; 8 * 8 * 4];
|
let pixel_data = inner.image.as_raw();
|
||||||
let rect = Rect {
|
let rect = Rect {
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
width: 8,
|
width: inner.image.width() as u16,
|
||||||
height: 8,
|
height: inner.image.height() as u16,
|
||||||
};
|
};
|
||||||
fbu.add_raw_pixels(rect, &pixel_data);
|
fbu.add_raw_pixels(rect, &pixel_data);
|
||||||
server.send(&fbu)?;
|
server.send(&fbu)?;
|
||||||
@ -105,20 +118,48 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let listener = TcpListener::bind::<std::net::SocketAddr>(args.address.into()).unwrap();
|
let listener = TcpListener::bind::<std::net::SocketAddr>(args.address.into()).unwrap();
|
||||||
let conn = Connection::new_session().expect("Failed to connect to DBus");
|
let conn = Connection::new_session().expect("Failed to connect to DBus");
|
||||||
let console = Console::new(&conn, 0).expect("Failed to get the console");
|
let console = Console::new(&conn, 0).expect("Failed to get the console");
|
||||||
let (rx, ack) = console.listen()?;
|
let (rx, _ack) = console.listen()?;
|
||||||
|
|
||||||
let server = Server::new(console.width()? as u16, console.height()? as u16);
|
let server = Server::new(console.width()? as u16, console.height()? as u16);
|
||||||
|
|
||||||
let _thread = thread::spawn(move || match rx.recv().unwrap() {
|
let srv = server.clone();
|
||||||
ConsoleEvent::ScanoutDMABUF(s) => {
|
let _thread = thread::spawn(move || loop {
|
||||||
dbg!(&s);
|
match rx.recv().unwrap() {
|
||||||
unsafe {
|
ConsoleEvent::ScanoutDMABUF(_) => {
|
||||||
libc::close(s.fd);
|
unimplemented!();
|
||||||
|
}
|
||||||
|
ConsoleEvent::Scanout(s) => {
|
||||||
|
if s.format != PIXMAN_X8R8G8B8 {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
let layout = image::flat::SampleLayout {
|
||||||
|
channels: 4,
|
||||||
|
channel_stride: 1,
|
||||||
|
width: s.width,
|
||||||
|
width_stride: 4,
|
||||||
|
height: s.height,
|
||||||
|
height_stride: s.stride as _,
|
||||||
|
};
|
||||||
|
let samples = image::flat::FlatSamples {
|
||||||
|
samples: s.data,
|
||||||
|
layout,
|
||||||
|
color_hint: None,
|
||||||
|
};
|
||||||
|
let img = match samples.try_into_buffer::<image::Bgra<u8>>() {
|
||||||
|
Ok(buf) => buf,
|
||||||
|
Err((_, samples)) => {
|
||||||
|
let view = samples.as_view::<image::Bgra<u8>>().unwrap();
|
||||||
|
let mut img = BgraImage::new(s.width, s.height);
|
||||||
|
img.copy_from(&view, 0, 0).unwrap();
|
||||||
|
img
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut inner = srv.inner.lock().unwrap();
|
||||||
|
inner.image = img;
|
||||||
|
}
|
||||||
|
e => {
|
||||||
|
dbg!(e);
|
||||||
}
|
}
|
||||||
let _ = ack.send(());
|
|
||||||
}
|
|
||||||
e => {
|
|
||||||
dbg!(e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user