Merge branch 'gpu_drm17' into 'main'

drivers/graphics: Unify buffer types between regular and cursor planes

See merge request redox-os/base!160
This commit is contained in:
Jeremy Soller
2026-03-13 14:09:35 -06:00
6 changed files with 193 additions and 244 deletions
+61 -76
View File
@@ -39,8 +39,7 @@ pub struct StandardProperties {
pub trait GraphicsAdapter: Sized + Debug {
type Connector: Debug + 'static;
type Framebuffer: Framebuffer;
type Cursor: CursorFramebuffer;
type Buffer: Buffer;
fn name(&self) -> &'static [u8];
fn desc(&self) -> &'static [u8];
@@ -63,23 +62,27 @@ pub trait GraphicsAdapter: Sized + Debug {
fn display_count(&self) -> usize;
fn display_size(&self, display_id: usize) -> (u32, u32);
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer;
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8;
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer;
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8;
fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage);
fn update_plane(
&mut self,
display_id: usize,
framebuffer: Option<&Self::Buffer>,
damage: Damage,
);
fn supports_hw_cursor(&self) -> bool;
fn create_cursor_framebuffer(&mut self) -> Self::Cursor;
fn map_cursor_framebuffer(&mut self, cursor: &Self::Cursor) -> *mut u8;
fn handle_cursor(&mut self, cursor: &CursorPlane<Self::Cursor>, dirty_fb: bool);
fn hw_cursor_size(&self) -> Option<(u32, u32)>;
fn handle_cursor(&mut self, cursor: Option<&CursorPlane<Self::Buffer>>, dirty_fb: bool);
}
pub trait Framebuffer {
pub trait Buffer {
fn width(&self) -> u32;
fn height(&self) -> u32;
}
pub struct CursorPlane<C: CursorFramebuffer> {
#[derive(Debug)]
pub struct CursorPlane<C: Buffer> {
pub x: i32,
pub y: i32,
pub hot_x: i32,
@@ -87,8 +90,6 @@ pub struct CursorPlane<C: CursorFramebuffer> {
pub framebuffer: C,
}
pub trait CursorFramebuffer {}
pub struct GraphicsScheme<T: GraphicsAdapter> {
inner: GraphicsSchemeInner<T>,
inputd_handle: DisplayHandle,
@@ -217,15 +218,22 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
);
for (display_id, fb) in vt_state.display_fbs.iter().enumerate() {
GraphicsSchemeInner::update_whole_screen(
&mut self.inner.adapter,
self.inner.adapter.update_plane(
display_id,
fb,
fb.as_deref(),
Damage {
x: 0,
y: 0,
width: fb.as_deref().map_or(0, |fb| fb.width()),
height: fb.as_deref().map_or(0, |fb| fb.height()),
},
);
}
if let Some(cursor_plane) = &vt_state.cursor_plane {
self.inner.adapter.handle_cursor(cursor_plane, true);
if self.inner.adapter.hw_cursor_size().is_some() {
self.inner
.adapter
.handle_cursor(vt_state.cursor_plane.as_ref(), true);
}
}
@@ -291,8 +299,8 @@ struct GraphicsSchemeInner<T: GraphicsAdapter> {
}
struct VtState<T: GraphicsAdapter> {
display_fbs: Vec<Arc<T::Framebuffer>>,
cursor_plane: Option<CursorPlane<T::Cursor>>,
display_fbs: Vec<Option<Arc<T::Buffer>>>,
cursor_plane: Option<CursorPlane<T::Buffer>>,
}
enum Handle<T: GraphicsAdapter> {
@@ -304,7 +312,7 @@ enum Handle<T: GraphicsAdapter> {
V2 {
vt: usize,
next_id: u32,
fbs: HashMap<u32, Arc<T::Framebuffer>>,
fbs: HashMap<u32, Arc<T::Buffer>>,
},
SchemeRoot,
}
@@ -315,41 +323,12 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
vts: &'a mut HashMap<usize, VtState<T>>,
vt: usize,
) -> &'a mut VtState<T> {
vts.entry(vt).or_insert_with(|| {
let mut display_fbs = vec![];
for display_id in 0..adapter.display_count() {
let (width, height) = adapter.display_size(display_id);
display_fbs.push(Arc::new(adapter.create_dumb_framebuffer(width, height)));
}
let cursor_plane = adapter.supports_hw_cursor().then(|| CursorPlane {
x: 0,
y: 0,
hot_x: 0,
hot_y: 0,
framebuffer: adapter.create_cursor_framebuffer(),
});
VtState {
display_fbs,
cursor_plane,
}
vts.entry(vt).or_insert_with(|| VtState {
display_fbs: vec![None; adapter.display_count()],
cursor_plane: None,
})
}
fn update_whole_screen(adapter: &mut T, screen: usize, framebuffer: &T::Framebuffer) {
adapter.update_plane(
screen,
framebuffer,
Damage {
x: 0,
y: 0,
width: framebuffer.width(),
height: framebuffer.height(),
},
);
}
fn handle_cursor_update(
&mut self,
vt: usize,
@@ -357,11 +336,18 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
) -> Result<()> {
let vt_state = self.vts.get_mut(&vt).unwrap();
let Some(cursor_plane) = &mut vt_state.cursor_plane else {
// Hardware cursor not supported
let Some((width, height)) = self.adapter.hw_cursor_size() else {
return Err(Error::new(EINVAL));
};
let cursor_plane = vt_state.cursor_plane.get_or_insert_with(|| CursorPlane {
x: 0,
y: 0,
hot_x: 0,
hot_y: 0,
framebuffer: self.adapter.create_dumb_buffer(width, height),
});
cursor_plane.x = cursor_damage.x;
cursor_plane.y = cursor_damage.y;
@@ -370,7 +356,7 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
return Ok(());
}
self.adapter.handle_cursor(cursor_plane, false);
self.adapter.handle_cursor(Some(cursor_plane), false);
} else {
cursor_plane.hot_x = cursor_damage.hot_x;
cursor_plane.hot_y = cursor_damage.hot_y;
@@ -378,9 +364,7 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
let w: i32 = cursor_damage.width;
let h: i32 = cursor_damage.height;
let cursor_image = cursor_damage.cursor_img_bytes;
let cursor_ptr = self
.adapter
.map_cursor_framebuffer(&cursor_plane.framebuffer);
let cursor_ptr = self.adapter.map_dumb_buffer(&cursor_plane.framebuffer);
//Clear previous image from backing storage
unsafe {
@@ -405,7 +389,7 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
return Ok(());
}
self.adapter.handle_cursor(cursor_plane, true);
self.adapter.handle_cursor(Some(cursor_plane), true);
}
return Ok(());
@@ -483,13 +467,8 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result<usize> {
let path = match self.handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::V1Screen { vt, screen } => {
let framebuffer = &self.vts[vt].display_fbs[*screen];
format!(
"{}:{vt}.{screen}/{}/{}",
self.scheme_name,
framebuffer.width(),
framebuffer.height()
)
let (width, height) = self.adapter.display_size(*screen);
format!("{}:{vt}.{screen}/{width}/{height}", self.scheme_name)
}
Handle::V2 {
vt,
@@ -629,7 +608,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
}
let connector = self
.objects
.get_connector_mut(DrmObjectId(data.connector_id()))?;
.get_connector(DrmObjectId(data.connector_id()))?;
data.set_connection(connector.connection as u32);
data.set_modes_ptr(&connector.modes);
data.set_mm_width(connector.mm_width);
@@ -753,9 +732,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
return Err(Error::new(EINVAL));
}
let fb = self
.adapter
.create_dumb_framebuffer(data.width(), data.height());
let fb = self.adapter.create_dumb_buffer(data.width(), data.height());
*next_id += 1;
fbs.insert(*next_id, Arc::new(fb));
@@ -856,15 +833,23 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
return Err(Error::new(EINVAL));
}
let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) else {
let framebuffer = if payload.fb_id == 0 {
None
} else if let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) {
Some(framebuffer)
} else {
return Err(Error::new(EINVAL));
};
self.vts.get_mut(vt).unwrap().display_fbs[display_id] = framebuffer.clone();
self.vts.get_mut(vt).unwrap().display_fbs[display_id] =
framebuffer.map(Arc::clone);
if *vt == self.active_vt {
self.adapter
.update_plane(display_id, framebuffer, payload.damage);
self.adapter.update_plane(
display_id,
framebuffer.map(|fb| &**fb),
payload.damage,
);
}
Ok(size_of::<ipc::UpdatePlane>())
@@ -910,7 +895,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
),
Handle::V1Screen { .. } | Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)),
};
let ptr = T::map_dumb_framebuffer(&mut self.adapter, framebuffer);
let ptr = T::map_dumb_buffer(&mut self.adapter, framebuffer);
Ok(unsafe { ptr.add(offset as usize) } as usize)
}
}
@@ -66,9 +66,16 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
}
pub fn add_connector(&mut self, driver_data: T::Connector) -> DrmObjectId {
let encoder_id = self.add(DrmEncoder {
crtc_id: DrmObjectId::INVALID,
possible_crtcs: 0,
possible_clones: 0,
});
self.encoders.push(encoder_id);
let connector_id = self.add(DrmConnector {
modes: vec![],
encoder_id: DrmObjectId::INVALID,
encoder_id,
connector_type: 0,
connector_type_id: 0,
connection: DrmConnectorStatus::Unknown,
@@ -79,15 +86,6 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
});
self.connectors.push(connector_id);
let encoder_id = self.add(DrmEncoder {
crtc_id: DrmObjectId::INVALID,
possible_crtcs: 0,
possible_clones: 0,
});
self.encoders.push(encoder_id);
self.get_connector_mut(connector_id).unwrap().encoder_id = encoder_id;
connector_id
}
@@ -121,10 +119,6 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
pub fn get_encoder(&self, id: DrmObjectId) -> Result<&DrmEncoder> {
self.get(id)
}
pub fn get_encoder_mut(&mut self, id: DrmObjectId) -> Result<&mut DrmEncoder> {
self.get_mut(id)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+24 -25
View File
@@ -6,8 +6,7 @@ use std::ptr::{self, NonNull};
use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects};
use driver_graphics::{
modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter,
StandardProperties,
modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties,
};
use drm_sys::DRM_MODE_DPMS_ON;
use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
@@ -21,16 +20,10 @@ pub struct Connector {
framebuffer_id: usize,
}
//TODO: use hardware cursor
pub enum Cursor {}
impl CursorFramebuffer for Cursor {}
impl GraphicsAdapter for Device {
type Connector = Connector;
type Framebuffer = DumbFb;
type Cursor = Cursor;
type Buffer = DumbFb;
fn name(&self) -> &'static [u8] {
b"ihdgd"
@@ -94,31 +87,37 @@ impl GraphicsAdapter for Device {
)
}
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer {
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
DumbFb::new(width as usize, height as usize)
}
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 {
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) {
framebuffer.sync(&mut self.framebuffers[display_id], damage)
fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) {
let framebuffer = &mut self.framebuffers[display_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
}
}
}
}
fn supports_hw_cursor(&self) -> bool {
false
fn hw_cursor_size(&self) -> Option<(u32, u32)> {
None
}
fn create_cursor_framebuffer(&mut self) -> Self::Cursor {
unimplemented!("ihdgd does not support this function");
}
fn map_cursor_framebuffer(&mut self, _cursor: &Self::Cursor) -> *mut u8 {
unimplemented!("ihdgd does not support this function");
}
fn handle_cursor(&mut self, _cursor: &CursorPlane<Self::Cursor>, _dirty_fb: bool) {
fn handle_cursor(&mut self, _cursor: Option<&CursorPlane<Self::Buffer>>, _dirty_fb: bool) {
unimplemented!("ihdgd does not support this function");
}
}
@@ -185,7 +184,7 @@ impl Drop for DumbFb {
}
}
impl Framebuffer for DumbFb {
impl Buffer for DumbFb {
fn width(&self) -> u32 {
self.width as u32
}
+24 -24
View File
@@ -4,8 +4,7 @@ use std::ptr::{self, NonNull};
use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects};
use driver_graphics::{
modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter,
StandardProperties,
modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties,
};
use drm_sys::DRM_MODE_DPMS_ON;
use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
@@ -23,15 +22,10 @@ pub struct Connector {
height: u32,
}
pub enum VesadCursor {}
impl CursorFramebuffer for VesadCursor {}
impl GraphicsAdapter for FbAdapter {
type Connector = Connector;
type Framebuffer = GraphicScreen;
type Cursor = VesadCursor;
type Buffer = GraphicScreen;
fn name(&self) -> &'static [u8] {
b"vesad"
@@ -94,31 +88,37 @@ impl GraphicsAdapter for FbAdapter {
)
}
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer {
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
GraphicScreen::new(width as usize, height as usize)
}
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 {
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) {
framebuffer.sync(&mut self.framebuffers[display_id], damage)
fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) {
let framebuffer = &mut self.framebuffers[display_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
} else {
let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
0,
framebuffer.width,
);
}
}
}
}
fn supports_hw_cursor(&self) -> bool {
false
fn hw_cursor_size(&self) -> Option<(u32, u32)> {
None
}
fn create_cursor_framebuffer(&mut self) -> VesadCursor {
unimplemented!("Vesad does not support this function");
}
fn map_cursor_framebuffer(&mut self, _cursor: &Self::Cursor) -> *mut u8 {
unimplemented!("Vesad does not support this function");
}
fn handle_cursor(&mut self, _cursor: &CursorPlane<VesadCursor>, _dirty_fb: bool) {
fn handle_cursor(&mut self, _cursor: Option<&CursorPlane<Self::Buffer>>, _dirty_fb: bool) {
unimplemented!("Vesad does not support this function");
}
}
@@ -216,7 +216,7 @@ impl Drop for GraphicScreen {
}
}
impl Framebuffer for GraphicScreen {
impl Buffer for GraphicScreen {
fn width(&self) -> u32 {
self.width as u32
}
+2
View File
@@ -207,6 +207,8 @@ static RESOURCE_ALLOC: AtomicU32 = AtomicU32::new(1); // XXX: 0 is reserved for
pub struct ResourceId(u32);
impl ResourceId {
const NONE: ResourceId = ResourceId(0);
fn alloc() -> Self {
ResourceId(RESOURCE_ALLOC.fetch_add(1, Ordering::SeqCst))
}
+74 -105
View File
@@ -4,8 +4,8 @@ use std::sync::Arc;
use common::{dma::Dma, sgl};
use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects};
use driver_graphics::{
modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter,
GraphicsScheme, StandardProperties,
modeinfo_for_size, Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme,
StandardProperties,
};
use drm_sys::{
DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON, DRM_MODE_TYPE_PREFERRED,
@@ -44,7 +44,7 @@ pub struct VirtGpuFramebuffer<'a> {
height: u32,
}
impl Framebuffer for VirtGpuFramebuffer<'_> {
impl DrmBuffer for VirtGpuFramebuffer<'_> {
fn width(&self) -> u32 {
self.width
}
@@ -70,13 +70,6 @@ impl Drop for VirtGpuFramebuffer<'_> {
}
}
pub struct VirtGpuCursor {
resource_id: ResourceId,
sgl: sgl::Sgl,
}
impl CursorFramebuffer for VirtGpuCursor {}
#[derive(Debug, Clone)]
pub struct Display {
enabled: bool,
@@ -93,6 +86,7 @@ pub struct VirtGpuAdapter<'a> {
transport: Arc<dyn Transport>,
has_edid: bool,
displays: Vec<Display>,
hidden_cursor: Option<Arc<VirtGpuFramebuffer<'a>>>,
}
impl<'a> fmt::Debug for VirtGpuAdapter<'a> {
@@ -200,11 +194,18 @@ impl VirtGpuAdapter<'_> {
Ok(response)
}
fn update_cursor(&mut self, cursor: &VirtGpuCursor, x: i32, y: i32, hot_x: i32, hot_y: i32) {
fn update_cursor(
&mut self,
cursor: &VirtGpuFramebuffer,
x: i32,
y: i32,
hot_x: i32,
hot_y: i32,
) {
//Transfering cursor resource to host
futures::executor::block_on(async {
let transfer_request = Dma::new(XferToHost2d::new(
cursor.resource_id,
cursor.id,
GpuRect {
x: 0,
y: 0,
@@ -219,14 +220,7 @@ impl VirtGpuAdapter<'_> {
});
//Update the cursor position
let request = Dma::new(UpdateCursor::update_cursor(
x,
y,
hot_x,
hot_y,
cursor.resource_id,
))
.unwrap();
let request = Dma::new(UpdateCursor::update_cursor(x, y, hot_x, hot_y, cursor.id)).unwrap();
futures::executor::block_on(async {
let command = ChainBuilder::new().chain(Buffer::new(&request)).build();
self.cursor_queue.send(command).await;
@@ -241,13 +235,30 @@ impl VirtGpuAdapter<'_> {
self.cursor_queue.send(command).await;
});
}
fn disable_cursor(&mut self) {
if self.hidden_cursor.is_none() {
let (width, height) = self.hw_cursor_size().unwrap();
let cursor = self.create_dumb_buffer(width, height);
unsafe {
core::ptr::write_bytes(
cursor.sgl.as_ptr() as *mut u8,
0,
(width * height * 4) as usize,
);
}
self.hidden_cursor = Some(Arc::new(cursor));
}
let hidden_cursor = self.hidden_cursor.as_ref().unwrap().clone();
self.update_cursor(&hidden_cursor, 0, 0, 0, 0);
}
}
impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
type Connector = VirtGpuConnector;
type Framebuffer = VirtGpuFramebuffer<'a>;
type Cursor = VirtGpuCursor;
type Buffer = VirtGpuFramebuffer<'a>;
fn name(&self) -> &'static [u8] {
b"virtio-gpud"
@@ -278,8 +289,8 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
fn get_cap(&self, cap: u32) -> syscall::Result<u64> {
match cap {
DRM_CAP_DUMB_BUFFER => Ok(1),
DRM_CAP_CURSOR_WIDTH => Ok(32),
DRM_CAP_CURSOR_HEIGHT => Ok(32),
DRM_CAP_CURSOR_WIDTH => Ok(64),
DRM_CAP_CURSOR_HEIGHT => Ok(64),
_ => Err(syscall::Error::new(EINVAL)),
}
}
@@ -367,7 +378,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
)
}
fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer {
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
futures::executor::block_on(async {
let bpp = 32;
let fb_size = width as usize * height as usize * bpp / 8;
@@ -426,12 +437,30 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
})
}
fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 {
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 {
framebuffer.sgl.as_ptr()
}
fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) {
fn update_plane(
&mut self,
display_id: usize,
framebuffer: Option<&Self::Buffer>,
damage: Damage,
) {
futures::executor::block_on(async {
let Some(framebuffer) = framebuffer else {
let scanout_request = Dma::new(SetScanout::new(
display_id as u32,
ResourceId::NONE,
GpuRect::new(0, 0, 0, 0),
))
.unwrap();
let header = self.send_request(scanout_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
self.displays[display_id].active_resource = None;
return;
};
let req = Dma::new(XferToHost2d::new(
framebuffer.id,
GpuRect {
@@ -468,88 +497,27 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
});
}
fn supports_hw_cursor(&self) -> bool {
true
fn hw_cursor_size(&self) -> Option<(u32, u32)> {
Some((64, 64))
}
fn create_cursor_framebuffer(&mut self) -> VirtGpuCursor {
//Creating a new resource for the cursor
let fb_size = 64 * 64 * 4;
let sgl = sgl::Sgl::new(fb_size).unwrap();
let res_id = ResourceId::alloc();
futures::executor::block_on(async {
unsafe {
core::ptr::write_bytes(sgl.as_ptr() as *mut u8, 0, fb_size);
fn handle_cursor(&mut self, cursor: Option<&CursorPlane<Self::Buffer>>, dirty_fb: bool) {
if let Some(cursor) = cursor {
if dirty_fb {
self.update_cursor(
&cursor.framebuffer,
cursor.x,
cursor.y,
cursor.hot_x,
cursor.hot_y,
);
} else {
self.move_cursor(cursor.x, cursor.y);
}
let resource_request =
Dma::new(ResourceCreate2d::new(res_id, ResourceFormat::Bgrx, 64, 64)).unwrap();
let header = self.send_request_fenced(resource_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
//Attaching cursor resource as backing storage
let mut mem_entries =
unsafe { Dma::zeroed_slice(sgl.chunks().len()).unwrap().assume_init() };
for (entry, chunk) in mem_entries.iter_mut().zip(sgl.chunks().iter()) {
*entry = MemEntry {
address: chunk.phys as u64,
length: chunk.length.next_multiple_of(PAGE_SIZE) as u32,
padding: 0,
};
}
let attach_request =
Dma::new(AttachBacking::new(res_id, mem_entries.len() as u32)).unwrap();
let mut header = Dma::new(ControlHeader::default()).unwrap();
header.flags |= VIRTIO_GPU_FLAG_FENCE;
let command = ChainBuilder::new()
.chain(Buffer::new(&attach_request))
.chain(Buffer::new_unsized(&mem_entries))
.chain(Buffer::new(&header).flags(DescriptorFlags::WRITE_ONLY))
.build();
self.control_queue.send(command).await;
assert_eq!(header.ty, CommandTy::RespOkNodata);
//Transfering cursor resource to host
let transfer_request = Dma::new(XferToHost2d::new(
res_id,
GpuRect {
x: 0,
y: 0,
width: 64,
height: 64,
},
0,
))
.unwrap();
let header = self.send_request_fenced(transfer_request).await.unwrap();
assert_eq!(header.ty, CommandTy::RespOkNodata);
});
VirtGpuCursor {
resource_id: res_id,
sgl,
}
}
fn map_cursor_framebuffer(&mut self, cursor: &Self::Cursor) -> *mut u8 {
cursor.sgl.as_ptr()
}
fn handle_cursor(&mut self, cursor: &CursorPlane<VirtGpuCursor>, dirty_fb: bool) {
if dirty_fb {
self.update_cursor(
&cursor.framebuffer,
cursor.x,
cursor.y,
cursor.hot_x,
cursor.hot_y,
);
} else {
self.move_cursor(cursor.x, cursor.y);
if dirty_fb {
self.disable_cursor();
}
}
}
}
@@ -571,6 +539,7 @@ impl<'a> GpuScheme {
transport,
has_edid,
displays: vec![],
hidden_cursor: None,
};
Ok(GraphicsScheme::new(