vhost_user: Add GpuBackend::update_scanout
Add a method and related struct to send VHOST_USER_GPU_UPDATE. The data part of the message is not part of the struct like sugested by the spec but a separate argument to update_scanout. This is necessary because of limitations of having an unsized array inside of struct in Rust. But this aproach seems preferable anyway, because it allows the consumer of the crate to store the array in a diferent location than the struct. Signed-off-by: Dorinda Bassey <dbassey@redhat.com> Signed-off-by: Matej Hrica <mhrica@redhat.com>
This commit is contained in:
parent
d35c657c05
commit
e385837436
2 changed files with 82 additions and 0 deletions
|
|
@ -63,6 +63,23 @@ impl BackendInternal {
|
|||
Ok(hdr)
|
||||
}
|
||||
|
||||
fn send_message_with_payload<T: ByteValued>(
|
||||
&mut self,
|
||||
request: GpuBackendReq,
|
||||
body: &T,
|
||||
data: &[u8],
|
||||
fds: Option<&[RawFd]>,
|
||||
) -> io::Result<VhostUserGpuMsgHeader<GpuBackendReq>> {
|
||||
self.check_state()?;
|
||||
|
||||
let len = mem::size_of::<T>() + data.len();
|
||||
let hdr = VhostUserGpuMsgHeader::new(request, 0, len as u32);
|
||||
self.sock
|
||||
.send_message_with_payload(&hdr, body, data, fds)
|
||||
.map_err(io_err_convert_fn("send_message_with_payload"))?;
|
||||
Ok(hdr)
|
||||
}
|
||||
|
||||
// Note that there is no VHOST_USER_PROTOCOL_F_REPLY_ACK for this protocol, some messages always
|
||||
// expect a reply/ack and others don't expect a reply/ack at all.
|
||||
fn recv_reply<V: ByteValued + Sized + Default + VhostUserMsgValidator>(
|
||||
|
|
@ -132,6 +149,16 @@ impl GpuBackend {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Sends the VHOST_USER_GPU_UPDATE message to the frontend. Doesn't wait for a reply.
|
||||
/// Updates the scanout content. The data payload contains the graphical bits.
|
||||
/// The display should be flushed and presented.
|
||||
pub fn update_scanout(&self, update: &VhostUserGpuUpdate, data: &[u8]) -> io::Result<()> {
|
||||
let mut node = self.node();
|
||||
|
||||
node.send_message_with_payload(GpuBackendReq::UPDATE, update, data, None)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a new instance from a `UnixStream` object.
|
||||
pub fn from_stream(sock: UnixStream) -> Self {
|
||||
Self::new(Endpoint::<VhostUserGpuMsgHeader<GpuBackendReq>>::from_stream(sock))
|
||||
|
|
@ -274,4 +301,38 @@ mod tests {
|
|||
|
||||
sender_thread.join().expect("Failed to send!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_scanout() {
|
||||
let (mut frontend, backend) = frontend_backend_pair();
|
||||
|
||||
let request = VhostUserGpuUpdate {
|
||||
scanout_id: 1,
|
||||
x: 30,
|
||||
y: 40,
|
||||
width: 10,
|
||||
height: 10,
|
||||
};
|
||||
let payload = [1u8; 4 * 10 * 10];
|
||||
|
||||
let sender_thread = thread::spawn(move || {
|
||||
let _: () = backend.update_scanout(&request, &payload).unwrap();
|
||||
});
|
||||
|
||||
let mut recv_buf = [0u8; 4096];
|
||||
let (hdr, req_body, recv_buf_len, fds) = frontend
|
||||
.recv_payload_into_buf::<VhostUserGpuUpdate>(&mut recv_buf)
|
||||
.unwrap();
|
||||
assert!(fds.is_none());
|
||||
assert_hdr(
|
||||
&hdr,
|
||||
GpuBackendReq::UPDATE,
|
||||
size_of_val(&request) + payload.len(),
|
||||
);
|
||||
assert_eq!(req_body, request);
|
||||
|
||||
assert_eq!(&payload[..], &recv_buf[..recv_buf_len]);
|
||||
|
||||
sender_thread.join().expect("Failed to send!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,6 +262,27 @@ unsafe impl ByteValued for VhostUserGpuEdidRequest {}
|
|||
|
||||
impl VhostUserMsgValidator for VhostUserGpuEdidRequest {}
|
||||
|
||||
/// The VhostUserGpuUpdate from the vhost-user-gpu specification.
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct VhostUserGpuUpdate {
|
||||
/// The id of the scanout that is being updated
|
||||
pub scanout_id: u32,
|
||||
/// The x coordinate of the region to update
|
||||
pub x: u32,
|
||||
/// The y coordinate of the region to update
|
||||
pub y: u32,
|
||||
/// The width of the region to update
|
||||
pub width: u32,
|
||||
/// The height of the region to update
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
// SAFETY: Safe because all fields are POD.
|
||||
unsafe impl ByteValued for VhostUserGpuUpdate {}
|
||||
|
||||
impl VhostUserMsgValidator for VhostUserGpuUpdate {}
|
||||
|
||||
/// The virtio_gpu_resp_edid struct from the virtio specification.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[repr(C)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue