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:
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user