Skip to content

Commit 0dfb42c

Browse files
mtjhrcslp
authored andcommitted
Introduce APIs for hooking up display implementations
Introduce krun_set_display for specifying the amount of displays and their resoultion. Introduce the the krun_set_display_backend for specifying the display backend as a vtable and a bitmask of features. This also introduces a new header libkrun_display.h and a krun_display rust crate which serves as a bidirectional bindings for the C display API. Signed-off-by: Matej Hrica <[email protected]>
1 parent b5bc35f commit 0dfb42c

File tree

24 files changed

+1295
-38
lines changed

24 files changed

+1295
-38
lines changed

Cargo.lock

Lines changed: 41 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = ["src/libkrun"]
3+
exclude = ["examples/gtk_display"]
34
resolver = "2"
45

56
[profile.dev]

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
LIBRARY_HEADER = include/libkrun.h
2+
LIBRARY_HEADER_DISPLAY = include/libkrun_display.h
23

34
ABI_VERSION=1
45
FULL_VERSION=1.14.0
@@ -145,6 +146,7 @@ install: libkrun.pc
145146
install -d $(DESTDIR)$(PREFIX)/$(LIBDIR_$(OS))/pkgconfig
146147
install -d $(DESTDIR)$(PREFIX)/include
147148
install -m 644 $(LIBRARY_HEADER) $(DESTDIR)$(PREFIX)/include
149+
install -m 644 $(LIBRARY_HEADER_DISPLAY) $(DESTDIR)$(PREFIX)/include
148150
install -m 644 libkrun.pc $(DESTDIR)$(PREFIX)/$(LIBDIR_$(OS))/pkgconfig
149151
install -m 755 $(LIBRARY_RELEASE_$(OS)) $(DESTDIR)$(PREFIX)/$(LIBDIR_$(OS))/
150152
cd $(DESTDIR)$(PREFIX)/$(LIBDIR_$(OS))/ ; ln -sf $(KRUN_BINARY_$(OS)) $(KRUN_SONAME_$(OS)) ; ln -sf $(KRUN_SONAME_$(OS)) $(KRUN_BASE_$(OS))

include/libkrun.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern "C" {
66
#endif
77

88
#include <inttypes.h>
9+
#include <stddef.h>
910
#include <stdbool.h>
1011
#include <unistd.h>
1112

@@ -488,6 +489,103 @@ int32_t krun_set_gpu_options2(uint32_t ctx_id,
488489
uint32_t virgl_flags,
489490
uint64_t shm_size);
490491

492+
/* Maximum number of displays. Same as VIRTIO_GPU_MAX_SCANOUTS defined in the virtio-gpu spec */
493+
#define KRUN_MAX_DISPLAYS 16
494+
495+
/**
496+
* Configure a display output for the VM.
497+
*
498+
* Note that to have display output a display backend must also be set (see krun_set_display_backend).
499+
*
500+
* Arguments:
501+
* "ctx_id" - the configuration context ID.
502+
* "width" - the width of the window/display
503+
* "height" - the height of the window/display
504+
*
505+
* Returns:
506+
* The id of the display (0 to KRUN_MAX_DISPLAYS - 1) on success or a negative error number on failure.
507+
*/
508+
int32_t krun_add_display(uint32_t ctx_id, uint32_t width, uint32_t height);
509+
510+
/**
511+
* Configure refresh rate for a display
512+
*
513+
*
514+
* Arguments:
515+
* "ctx_id" - the configuration context ID.
516+
* "display_id" - the ID of the display (range: 0 to KRUN_MAX_DISPLAYS - 1)
517+
* "refresh_rate" - refresh rate (in Hz)
518+
*
519+
* Returns:
520+
* Zero on success or a negative error number on failure.
521+
*/
522+
int32_t krun_display_set_refresh_rate(uint32_t ctx_id, uint32_t display_id, uint32_t refresh_rate);
523+
524+
525+
/**
526+
* Configure physical size of the display reported to the guest
527+
*
528+
* This overrides the DPI set by krun_set_display_dpi()
529+
*
530+
* Arguments:
531+
* "ctx_id" - the configuration context ID.
532+
* "display_id" - the ID of the display (range: 0 to KRUN_MAX_DISPLAYS - 1)
533+
* "width_mm" - width of the display in millimeters
534+
* "height_mm" - height of the display in millimeters
535+
*
536+
* Returns:
537+
* Zero on success or a negative error number on failure.
538+
*/
539+
int32_t krun_display_set_physical_size(uint32_t ctx_id, uint32_t display_id, uint16_t width_mm, uint16_t height_mm);
540+
541+
542+
/**
543+
* Configure DPI of the display reported to the guest
544+
*
545+
* This overrides the physical size of the display set by krun_set_display_physical_size()
546+
*
547+
* Arguments:
548+
* "ctx_id" - the configuration context ID.
549+
* "display_id" - the ID of the display (range: 0 to KRUN_MAX_DISPLAYS - 1)
550+
* "dpi" - DPI (PPI) dots/pixels per inch of the display
551+
*
552+
* Returns:
553+
* Zero on success or a negative error number on failure.
554+
*/
555+
int32_t krun_display_set_dpi(uint32_t ctx_id, uint32_t display_id, uint32_t dpi);
556+
557+
/**
558+
* Configure a custom EDID blob for a display
559+
*
560+
* This replaces the generated EDID with a custom one. Configuring an EDID blob makes all display parameters except
561+
* width and height ignored.
562+
*
563+
* Note that libkrun doesn't do any checks if the EDID matches the width/height specified in krun_add_display().
564+
*
565+
* Arguments:
566+
* "ctx_id" - the configuration context ID.
567+
* "display_id" - the ID of the display (range: 0 to KRUN_MAX_DISPLAYS - 1)
568+
* "edid_blob" - the EDID blob
569+
* "blob_size" - the size of the blob in bytes
570+
*
571+
* Returns:
572+
* Zero on success or a negative error number on failure.
573+
*/
574+
int32_t krun_display_set_edid(uint32_t ctx_id, uint32_t display_id, const uint8_t* edid_blob, size_t blob_size);
575+
576+
/**
577+
* Configures a krun_display_backend struct to be used for display output. (see libkrun_display.h)
578+
*
579+
* Arguments:
580+
* "ctx_id" - the configuration context ID
581+
* "display_backend" - Pointer to a krun_display_backend struct
582+
* "backend_size" - sizeof() the krun_display_backend struct
583+
*
584+
* Returns:
585+
* Zero on success or a negative error number (errno) on failure.
586+
*/
587+
int32_t krun_set_display_backend(uint32_t ctx_id, const void *display_backend, size_t backend_size);
588+
491589
/**
492590
* Enables or disables a virtio-snd device.
493591
*

include/libkrun_display.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../src/krun_display/libkrun_display.h

src/arch_gen/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
#[allow(deref_nullptr)]
54
#[allow(clippy::all)]
65
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
76
pub mod x86;

src/devices/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tdx = ["blk", "tee"]
1111
net = []
1212
blk = []
1313
efi = ["blk", "net"]
14-
gpu = ["rutabaga_gfx", "thiserror", "zerocopy", "zerocopy-derive"]
14+
gpu = ["rutabaga_gfx", "thiserror", "zerocopy", "zerocopy-derive", "krun_display"]
1515
snd = ["pw", "thiserror"]
1616
virgl_resource_map2 = []
1717
nitro = []
@@ -31,6 +31,7 @@ virtio-bindings = "0.2.0"
3131
vm-memory = { version = ">=0.13", features = ["backend-mmap"] }
3232
zerocopy = { version = "0.6.3", optional = true }
3333
zerocopy-derive = { version = "0.6.3", optional = true }
34+
krun_display = { path = "../krun_display", optional = true, features = ["bindgen_clang_runtime"] }
3435

3536
arch = { path = "../arch" }
3637
utils = { path = "../utils" }

src/devices/src/virtio/gpu/device.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use super::defs;
1313
use super::defs::uapi;
1414
use super::defs::uapi::virtio_gpu_config;
1515
use super::worker::Worker;
16+
use crate::virtio::display::DisplayInfo;
1617
use crate::virtio::InterruptTransport;
18+
use krun_display::DisplayBackend;
1719
#[cfg(target_os = "macos")]
1820
use utils::worker_message::WorkerMessage;
1921

@@ -44,12 +46,16 @@ pub struct Gpu {
4446
#[cfg(target_os = "macos")]
4547
map_sender: Sender<WorkerMessage>,
4648
export_table: Option<ExportTable>,
49+
displays: Box<[DisplayInfo]>,
50+
display_backend: DisplayBackend<'static>,
4751
}
4852

4953
impl Gpu {
5054
pub(crate) fn with_queues(
5155
queues: Vec<VirtQueue>,
5256
virgl_flags: u32,
57+
displays: Box<[DisplayInfo]>,
58+
display_backend: DisplayBackend<'static>,
5359
#[cfg(target_os = "macos")] map_sender: Sender<WorkerMessage>,
5460
) -> super::Result<Gpu> {
5561
let mut queue_events = Vec::new();
@@ -76,11 +82,15 @@ impl Gpu {
7682
#[cfg(target_os = "macos")]
7783
map_sender,
7884
export_table: None,
85+
displays,
86+
display_backend,
7987
})
8088
}
8189

8290
pub fn new(
8391
virgl_flags: u32,
92+
displays: Box<[DisplayInfo]>,
93+
display_backend: DisplayBackend<'static>,
8494
#[cfg(target_os = "macos")] map_sender: Sender<WorkerMessage>,
8595
) -> super::Result<Gpu> {
8696
let queues: Vec<VirtQueue> = defs::QUEUE_SIZES
@@ -90,6 +100,8 @@ impl Gpu {
90100
Self::with_queues(
91101
queues,
92102
virgl_flags,
103+
displays,
104+
display_backend,
93105
#[cfg(target_os = "macos")]
94106
map_sender,
95107
)
@@ -201,7 +213,7 @@ impl VirtioDevice for Gpu {
201213
let config = virtio_gpu_config {
202214
events_read: 0,
203215
events_clear: 0,
204-
num_scanouts: 0,
216+
num_scanouts: self.displays.len() as u32,
205217
num_capsets: 5,
206218
};
207219

@@ -255,6 +267,8 @@ impl VirtioDevice for Gpu {
255267
#[cfg(target_os = "macos")]
256268
self.map_sender.clone(),
257269
self.export_table.take(),
270+
self.displays.clone(),
271+
self.display_backend,
258272
);
259273
worker.run();
260274

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use krun_display::{
2+
DisplayBackendBasicFramebuffer, DisplayBackendError, DisplayBackendNew, Rect, ResourceFormat,
3+
};
4+
use virtio_bindings::virtio_gpu::VIRTIO_GPU_MAX_SCANOUTS;
5+
6+
#[derive(Clone, Debug)]
7+
pub struct DisplayInfo {
8+
pub width: u32,
9+
pub height: u32,
10+
}
11+
12+
pub const MAX_DISPLAYS: usize = VIRTIO_GPU_MAX_SCANOUTS as usize;
13+
14+
pub type DisplayInfoList = [Option<DisplayInfo>; MAX_DISPLAYS];
15+
16+
impl DisplayInfo {
17+
pub fn new(width: u32, height: u32) -> Self {
18+
DisplayInfo { width, height }
19+
}
20+
}
21+
22+
pub struct NoopDisplayBackend;
23+
24+
impl DisplayBackendNew<()> for NoopDisplayBackend {
25+
fn new(_userdata: Option<&()>) -> Self {
26+
Self
27+
}
28+
}
29+
30+
impl DisplayBackendBasicFramebuffer for NoopDisplayBackend {
31+
fn configure_scanout(
32+
&mut self,
33+
_scanout_id: u32,
34+
_display_width: u32,
35+
_display_height: u32,
36+
_width: u32,
37+
_height: u32,
38+
_format: ResourceFormat,
39+
) -> Result<(), DisplayBackendError> {
40+
Err(DisplayBackendError::InvalidScanoutId)
41+
}
42+
43+
fn disable_scanout(&mut self, _scanout_id: u32) -> Result<(), DisplayBackendError> {
44+
Err(DisplayBackendError::InvalidScanoutId)
45+
}
46+
47+
fn alloc_frame(&mut self, _scanout_id: u32) -> Result<(u32, &mut [u8]), DisplayBackendError> {
48+
Err(DisplayBackendError::InvalidScanoutId)
49+
}
50+
51+
fn present_frame(
52+
&mut self,
53+
_scanout_id: u32,
54+
_frame_id: u32,
55+
_rect: Option<&Rect>,
56+
) -> Result<(), DisplayBackendError> {
57+
Err(DisplayBackendError::InvalidScanoutId)
58+
}
59+
}

src/devices/src/virtio/gpu/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod device;
2+
pub mod display;
23
mod event_handler;
34
mod protocol;
45
mod virtio_gpu;

0 commit comments

Comments
 (0)