drivers/graphics/driver-graphics: Move framebuffer ioctls to a separate module

This commit is contained in:
bjorn3
2026-05-14 17:32:39 +02:00
parent 2ac2182caa
commit df845d6566
2 changed files with 209 additions and 147 deletions
@@ -0,0 +1,196 @@
use std::collections::HashMap;
use drm_fourcc::DrmFourcc;
use syscall::{Error, EINVAL};
use crate::kms::objects::{KmsFramebuffer, KmsObjectId, KmsObjects};
use crate::{Damage, DrmHandle, GraphicsAdapter, VtState};
pub(super) fn mode_get_fb<T: GraphicsAdapter>(
objects: &mut KmsObjects<T>,
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd<'_>,
) -> Result<usize, Error> {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let (bpp, depth) = match fb.pixel_format {
DrmFourcc::Xrgb8888 => (32, 24),
DrmFourcc::Argb8888 => (32, 32),
_ => todo!(),
};
handle.next_id += 1;
handle.buffers.insert(handle.next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pitch(fb.pitch);
data.set_bpp(bpp);
data.set_depth(depth);
data.set_handle(handle.next_id);
Ok(0)
}
pub(super) fn mode_add_fb<T: GraphicsAdapter>(
adapter: &mut T,
objects: &mut KmsObjects<T>,
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd<'_>,
) -> Result<usize, Error> {
let buffer = handle
.buffers
.get(&data.handle())
.ok_or(Error::new(EINVAL))?;
if data.bpp() != 32 {
return Err(Error::new(EINVAL));
}
let pixel_format = match data.depth() {
24 => DrmFourcc::Xrgb8888,
32 => DrmFourcc::Argb8888,
_ => return Err(Error::new(EINVAL)),
};
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(KmsFramebuffer {
width: data.width(),
height: data.height(),
pixel_format,
pitch: data.pitch(),
buffer: buffer.clone(),
driver_data: fb,
});
data.set_fb_id(id.0);
Ok(0)
}
pub(super) fn mode_rm_fb<T: GraphicsAdapter>(
adapter: &mut T,
objects: &mut KmsObjects<T>,
active_vt: usize,
vts: &mut HashMap<usize, VtState<T>>,
data: redox_ioctl::drm::StandinForUint<'_>,
) -> Result<usize, Error> {
let fb_id = KmsObjectId(data.inner());
objects.remove_framebuffer(fb_id)?;
// Disable planes that use this framebuffer.
for (vt, vt_data) in vts {
for (plane_idx, plane_state) in vt_data.plane_state.iter_mut().enumerate() {
if plane_state.fb_id != Some(fb_id) {
continue;
}
plane_state.fb_id = None;
if *vt != active_vt {
continue;
}
let plane = objects.planes().nth(plane_idx).unwrap();
adapter
.set_plane(
&objects,
plane,
plane_state.clone(),
Damage {
x: 0,
y: 0,
width: 0,
height: 0,
},
)
.unwrap();
}
}
Ok(0)
}
pub(super) fn mode_dirtyfb<T: GraphicsAdapter>(
adapter: &mut T,
objects: &mut KmsObjects<T>,
active_vt: usize,
handle: &mut DrmHandle<T>,
data: redox_ioctl::drm::DrmModeFbDirtyCmd<'_>,
) -> Result<usize, Error> {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let damage = data
.clips_ptr()
.iter()
.map(|rect| Damage {
x: u32::from(rect.x1),
y: u32::from(rect.y1),
width: u32::from(rect.x2 - rect.x1),
height: u32::from(rect.y2 - rect.y1),
})
.reduce(Damage::merge)
.unwrap_or(Damage {
x: 0,
y: 0,
width: fb.width,
height: fb.height,
});
if handle.vt == active_vt {
for plane in objects.planes() {
let state = plane.lock().unwrap().state.clone();
if state.fb_id == Some(KmsObjectId(data.fb_id())) {
adapter.set_plane(&objects, plane, state, damage)?;
}
}
}
Ok(0)
}
pub(super) fn mode_add_fb2<T: GraphicsAdapter>(
adapter: &mut T,
objects: &mut KmsObjects<T>,
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>,
) -> Result<usize, Error> {
// FIXME handle multi-plane framebuffers
let buffer = handle
.buffers
.get(&data.handles()[0])
.ok_or(Error::new(EINVAL))?;
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(KmsFramebuffer {
width: data.width(),
height: data.height(),
pixel_format: DrmFourcc::try_from(data.pixel_format()).map_err(|_| Error::new(EINVAL))?,
pitch: data.pitches()[0],
buffer: buffer.clone(),
driver_data: fb,
});
data.set_fb_id(id.0);
Ok(0)
}
pub(super) fn mode_get_fb2<T: GraphicsAdapter>(
objects: &mut KmsObjects<T>,
handle: &mut DrmHandle<T>,
mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>,
) -> Result<usize, Error> {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
handle.next_id += 1;
handle.buffers.insert(handle.next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pixel_format(fb.pixel_format as u32);
data.set_handles([handle.next_id, 0, 0, 0]);
data.set_pitches([fb.pitch, 0, 0, 0]);
data.set_offsets([0; 4]);
data.set_modifier([0; 4]);
Ok(0)
}
+13 -147
View File
@@ -11,10 +11,12 @@ use drm_sys::{
};
use syscall::{Error, EINVAL, ENOENT, ENXIO};
use crate::kms::objects::{self, KmsObjectId, KmsObjects, KmsRect};
use crate::kms::objects::{KmsObjectId, KmsObjects, KmsRect};
use crate::kms::properties::KmsPropertyKind;
use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, VtState, MAP_FAKE_OFFSET_MULTIPLIER};
mod framebuffer;
pub(crate) fn call_ioctl<T: GraphicsAdapter>(
adapter: &mut T,
objects: &mut KmsObjects<T>,
@@ -322,120 +324,17 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
data.set_data(&blob);
Ok(0)
}),
ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |mut data| {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let (bpp, depth) = match fb.pixel_format {
DrmFourcc::Xrgb8888 => (32, 24),
DrmFourcc::Argb8888 => (32, 32),
_ => todo!(),
};
handle.next_id += 1;
handle.buffers.insert(handle.next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pitch(fb.pitch);
data.set_bpp(bpp);
data.set_depth(depth);
data.set_handle(handle.next_id);
Ok(0)
ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |data| {
framebuffer::mode_get_fb(objects, handle, data)
}),
ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |mut data| {
let buffer = handle
.buffers
.get(&data.handle())
.ok_or(Error::new(EINVAL))?;
if data.bpp() != 32 {
return Err(Error::new(EINVAL));
}
let pixel_format = match data.depth() {
24 => DrmFourcc::Xrgb8888,
32 => DrmFourcc::Argb8888,
_ => return Err(Error::new(EINVAL)),
};
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(objects::KmsFramebuffer {
width: data.width(),
height: data.height(),
pixel_format,
pitch: data.pitch(),
buffer: buffer.clone(),
driver_data: fb,
});
data.set_fb_id(id.0);
Ok(0)
ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |data| {
framebuffer::mode_add_fb(adapter, objects, handle, data)
}),
ipc::MODE_RM_FB => ipc::StandinForUint::with(payload, |data| {
let fb_id = KmsObjectId(data.inner());
objects.remove_framebuffer(fb_id)?;
// Disable planes that use this framebuffer.
for (vt, vt_data) in vts {
for (plane_idx, plane_state) in vt_data.plane_state.iter_mut().enumerate() {
if plane_state.fb_id != Some(fb_id) {
continue;
}
plane_state.fb_id = None;
if *vt != active_vt {
continue;
}
let plane = objects.planes().nth(plane_idx).unwrap();
adapter
.set_plane(
&objects,
plane,
plane_state.clone(),
Damage {
x: 0,
y: 0,
width: 0,
height: 0,
},
)
.unwrap();
}
}
Ok(0)
framebuffer::mode_rm_fb(adapter, objects, active_vt, vts, data)
}),
ipc::MODE_DIRTYFB => ipc::DrmModeFbDirtyCmd::with(payload, |data| {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
let damage = data
.clips_ptr()
.iter()
.map(|rect| Damage {
x: u32::from(rect.x1),
y: u32::from(rect.y1),
width: u32::from(rect.x2 - rect.x1),
height: u32::from(rect.y2 - rect.y1),
})
.reduce(Damage::merge)
.unwrap_or(Damage {
x: 0,
y: 0,
width: fb.width,
height: fb.height,
});
if handle.vt == active_vt {
for plane in objects.planes() {
let state = plane.lock().unwrap().state.clone();
if state.fb_id == Some(KmsObjectId(data.fb_id())) {
adapter.set_plane(&objects, plane, state, damage)?;
}
}
}
Ok(0)
framebuffer::mode_dirtyfb(adapter, objects, active_vt, handle, data)
}),
ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| {
if data.bpp() != 32 || data.flags() != 0 {
@@ -548,29 +447,8 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
data.set_format_type_ptr(&[DrmFourcc::Argb8888 as u32]);
Ok(0)
}),
ipc::MODE_ADD_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| {
// FIXME handle multi-plane framebuffers
let buffer = handle
.buffers
.get(&data.handles()[0])
.ok_or(Error::new(EINVAL))?;
let fb = adapter.create_framebuffer(buffer);
let id = objects.add_framebuffer(objects::KmsFramebuffer {
width: data.width(),
height: data.height(),
pixel_format: DrmFourcc::try_from(data.pixel_format())
.map_err(|_| Error::new(EINVAL))?,
pitch: data.pitches()[0],
buffer: buffer.clone(),
driver_data: fb,
});
data.set_fb_id(id.0);
Ok(0)
ipc::MODE_ADD_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| {
framebuffer::mode_add_fb2(adapter, objects, handle, data)
}),
ipc::MODE_OBJ_GET_PROPERTIES => ipc::DrmModeObjGetProperties::with(payload, |mut data| {
let (props, prop_vals) =
@@ -609,20 +487,8 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
Ok(0)
}),
ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| {
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
handle.next_id += 1;
handle.buffers.insert(handle.next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pixel_format(fb.pixel_format as u32);
data.set_handles([handle.next_id, 0, 0, 0]);
data.set_pitches([fb.pitch, 0, 0, 0]);
data.set_offsets([0; 4]);
data.set_modifier([0; 4]);
Ok(0)
ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| {
framebuffer::mode_get_fb2(objects, handle, data)
}),
_ => return Err(Error::new(EINVAL)),
}