drivers/graphics: Add framebuffer indirection to the DRM interface

This matches the Linux DRM interface. With this I believe the only
divergence from the Linux DRM interface that would be a breaking change
to the in-tree users of the graphics api to change to the proper
interface is the use of the UPDATE_PLANE ioctl in the place of proper
modesetting interface. It should be possible to support this in
parallel to UPDATE_PLANE, so updating Orbital to the DRM interface
should now be possible. Orbital can be updated to the proper modesetting
interface once it is implemented.
This commit is contained in:
bjorn3
2026-03-11 22:49:19 +01:00
parent 9795abb0ea
commit 511c6080ca
4 changed files with 27 additions and 19 deletions
+11 -7
View File
@@ -6,27 +6,31 @@ use std::{cmp, io, mem, ptr};
use drm::buffer::{Buffer, DrmFourcc};
use drm::control::dumbbuffer::{DumbBuffer, DumbMapping};
use drm::control::Device;
use drm::control::{framebuffer, Device};
use graphics_ipc::v1::Damage;
use graphics_ipc::v2::V2GraphicsHandle;
use orbclient::FONT;
pub struct V2DisplayMap {
pub display_handle: V2GraphicsHandle,
pub fb: DumbBuffer,
pub fb: framebuffer::Handle,
pub buffer: DumbBuffer,
mapping: DumbMapping<'static>,
}
impl V2DisplayMap {
pub fn new(display_handle: V2GraphicsHandle, width: u32, height: u32) -> io::Result<Self> {
let mut fb = display_handle.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)?;
let mut buffer =
display_handle.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)?;
let fb = display_handle.add_framebuffer(&buffer, 24, 32)?;
let map = display_handle.map_dumb_buffer(&mut fb)?;
let map = display_handle.map_dumb_buffer(&mut buffer)?;
let map = unsafe { mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(map) };
Ok(Self {
display_handle,
fb,
buffer,
mapping: map,
})
}
@@ -37,8 +41,8 @@ impl V2DisplayMap {
self.mapping.as_mut_ptr() as *mut u32,
self.mapping.len() / 4,
),
width: self.fb.size().0 as usize,
height: self.fb.size().1 as usize,
width: self.buffer.size().0 as usize,
height: self.buffer.size().1 as usize,
}
}
}
@@ -324,7 +328,7 @@ impl TextScreen {
}
}
let old_fb = mem::replace(&mut map.fb, new_fb);
let old_fb = mem::replace(&mut map.buffer, new_fb);
map.mapping = new_mapping;
let _ = map.display_handle.destroy_dumb_buffer(old_fb);
@@ -810,6 +810,10 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
data.set_handle(fb_handle_id(i));
Ok(0)
}),
ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |mut data| {
data.set_fb_id(fb_handle_id(id_index(data.handle())));
Ok(0)
}),
ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| {
if data.bpp() != 32 {
return Err(Error::new(EINVAL));
+7 -7
View File
@@ -122,7 +122,7 @@ impl FbbootlogScheme {
self.is_scrollback = true;
self.scrollback_offset = cmp::min(
self.scrollback_offset,
buffer_len - map.fb.size().1 as usize / 16 + spare_lines,
buffer_len - map.buffer.size().1 as usize / 16 + spare_lines,
);
let mut i = self.scrollback_offset;
self.text_screen
@@ -135,9 +135,9 @@ impl FbbootlogScheme {
.write(map, &self.text_buffer.lines[i][..], &mut VecDeque::new());
i += 1;
let yd = (damage.y + damage.height) as usize;
if i == buffer_len || yd + spare_lines * 16 > map.fb.size().1 as usize {
if i == buffer_len || yd + spare_lines * 16 > map.buffer.size().1 as usize {
// render until end of screen
damage.height = map.fb.size().1 - damage.y;
damage.height = map.buffer.size().1 - damage.y;
total_damage = total_damage.merge(damage);
self.is_scrollback = i < buffer_len;
break;
@@ -146,7 +146,7 @@ impl FbbootlogScheme {
}
}
map.display_handle
.update_plane(0, u32::from(map.fb.handle()), total_damage)
.update_plane(0, u32::from(map.buffer.handle()), total_damage)
.unwrap();
}
@@ -157,11 +157,11 @@ impl FbbootlogScheme {
Ok((width, height)) => (width.into(), height.into()),
Err(err) => {
eprintln!("fbbootlogd: failed to get display size: {}", err);
map.fb.size()
map.buffer.size()
}
};
if (width, height) != map.fb.size() {
if (width, height) != map.buffer.size() {
match text_screen.resize(map, width, height) {
Ok(()) => eprintln!("fbbootlogd: mapped display"),
Err(err) => {
@@ -248,7 +248,7 @@ impl SchemeSync for FbbootlogScheme {
if let Some(map) = &self.display_map {
map.display_handle
.update_plane(0, u32::from(map.fb.handle()), damage)
.update_plane(0, u32::from(map.buffer.handle()), damage)
.unwrap();
}
}
+5 -5
View File
@@ -45,8 +45,8 @@ impl Display {
Ok(map) => {
log::debug!(
"fbcond: Mapped new display with size {}x{}",
map.fb.size().0,
map.fb.size().1,
map.buffer.size().0,
map.buffer.size().1,
);
self.map = Some(map)
}
@@ -64,11 +64,11 @@ impl Display {
Ok((width, height)) => (width.into(), height.into()),
Err(err) => {
log::error!("fbcond: failed to get display size: {}", err);
map.fb.size()
map.buffer.size()
}
};
if (width, height) != map.fb.size() {
if (width, height) != map.buffer.size() {
match text_screen.resize(map, width, height) {
Ok(()) => eprintln!("fbcond: mapped display"),
Err(err) => {
@@ -82,7 +82,7 @@ impl Display {
pub fn sync_rect(&mut self, damage: Damage) {
if let Some(map) = &self.map {
map.display_handle
.update_plane(0, u32::from(map.fb.handle()), damage)
.update_plane(0, u32::from(map.buffer.handle()), damage)
.unwrap();
}
}