Merge branch 'gpu_drm32' into 'main'

Cleanup plane configuration and framebuffer creation in ihdgd

See merge request redox-os/base!189
This commit is contained in:
Jeremy Soller
2026-03-21 07:22:52 -06:00
8 changed files with 157 additions and 178 deletions
-2
View File
@@ -48,8 +48,6 @@ fn daemon(daemon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> ! {
display: ProducerHandle::new().ok(),
};
scheme.update_size();
register_sync_scheme(&socket, "bga", &mut scheme).expect("bgad: failed to register bga scheme");
daemon.ready();
-16
View File
@@ -13,20 +13,6 @@ pub struct BgaScheme {
pub display: Option<ProducerHandle>,
}
impl BgaScheme {
pub fn update_size(&mut self) {
if let Some(ref mut display) = self.display {
let _ = display.write_event(
orbclient::ResizeEvent {
width: self.bga.width() as u32,
height: self.bga.height() as u32,
}
.to_event(),
);
}
}
}
const SCHEME_ROOT_ID: usize = 1;
impl SchemeSync for BgaScheme {
@@ -98,8 +84,6 @@ impl SchemeSync for BgaScheme {
self.bga.set_size(width, height);
self.update_size();
Ok(buf.len())
}
@@ -292,10 +292,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
.handle_cursor(&vt_state.cursor_plane, true);
}
}
VtEventKind::Resize => {
log::warn!("driver-graphics: resize is not implemented yet")
}
}
}
}
+7 -96
View File
@@ -25,7 +25,6 @@ use self::pipe::*;
mod power;
use self::power::*;
mod scheme;
use self::scheme::*;
mod transcoder;
use self::transcoder::*;
@@ -433,40 +432,10 @@ impl Device {
for pipe in self.pipes.iter() {
for plane in pipe.planes.iter() {
if plane.ctl.readf(PLANE_CTL_ENABLE) {
let buf_cfg = plane.buf_cfg.read();
let buffer_start = buf_cfg & 0x7FF;
let buffer_end = (buf_cfg >> 16) & 0x7FF;
self.alloc_buffers
.allocate_exact_range(buffer_start..(buffer_end + 1))
.unwrap_or_else(|err| {
panic!(
"failed to allocate pre-existing buffer blocks {} to {}: {:?}",
buffer_start, buffer_end, err
);
});
plane.fetch_modeset(&mut self.alloc_buffers);
let size = plane.size.read();
let width = (size & 0xFFFF) + 1;
let height = ((size >> 16) & 0xFFFF) + 1;
let stride_16 = plane.stride.read() & 0x7FF;
//TODO: this will be wrong for tiled planes
let stride = stride_16 * 16;
let surf = plane.surf.read() & 0xFFFFF000;
//TODO: read bits per pixel
let surf_size = (stride * height * 4).next_multiple_of(4096);
self.alloc_surfaces.allocate_exact_range(surf .. (surf + surf_size)).unwrap_or_else(|err| {
panic!("failed to allocate pre-existing surface at 0x{:x} of size {}: {:?}", surf, surf_size, err);
});
self.framebuffers.push(unsafe {
DeviceFb::new(
(self.gm.virt + surf as usize) as *mut u32,
width as usize,
height as usize,
stride as usize,
false,
)
});
self.framebuffers
.push(plane.fetch_framebuffer(&self.gm, &mut self.alloc_surfaces));
}
}
}
@@ -747,73 +716,15 @@ impl Device {
// Configure and enable planes
//TODO: THIS IS HACKY
if let Some(plane) = pipe.planes.first_mut() {
//TODO: enable DBUF if more buffers needed
//TODO: more blocks would mean better power usage
// Minimum is 8 blocks for linear planes, 160 blocks is recommended for pre-OS init
let buffer_size = 160;
let buffer = self
.alloc_buffers
.allocate_range(buffer_size)
.map_err(|err| {
log::warn!(
"failed to allocate {} buffer blocks: {:?}",
buffer_size,
err
);
Error::new(EIO)
})?;
plane.buf_cfg.write(buffer.start | (buffer.end << 16));
let width = timing.horizontal_active_pixels as u32;
let height = timing.vertical_active_lines as u32;
plane.size.write((width - 1) | ((height - 1) << 16));
//TODO: documentation on this is not great
let stride_16 = (width + 15) / 16;
plane.stride.write(stride_16);
let stride = stride_16 * 16;
let fb = DeviceFb::alloc(&self.gm, &mut self.alloc_surfaces, width, height)?;
//TODO: how is memory allocated for PLANE_SURF?
let surf_size = (stride * height * 4).next_multiple_of(4096);
let surf = self
.alloc_surfaces
.allocate_range(surf_size)
.map_err(|err| {
log::warn!(
"failed to allocate surface of size {}: {:?}",
surf_size,
err
);
Error::new(EIO)
})?;
plane.surf.write(surf.start);
plane.modeset(&mut self.alloc_buffers)?;
plane.set_framebuffer(&fb);
//TODO: correct watermark calculation
plane.wm[0].write(PLANE_WM_ENABLE | (2 << PLANE_WM_LINES_SHIFT) | buffer_size);
for i in 1..plane.wm.len() {
plane.wm[i].writef(PLANE_WM_ENABLE, false);
}
plane.wm_trans.writef(PLANE_WM_ENABLE, false);
self.framebuffers.push(unsafe {
DeviceFb::new(
(self.gm.virt + surf.start as usize) as *mut u32,
width as usize,
height as usize,
stride as usize,
true,
)
});
// Disable gamma
if let Some(color_ctl) = &mut plane.color_ctl {
color_ctl.write(plane.color_ctl_gamma_disable);
}
//TODO: more PLANE_CTL bits
plane
.ctl
.write(PLANE_CTL_ENABLE | plane.ctl_source_rgb_8888);
self.framebuffers.push(fb);
}
//TODO: VGA and panel fitter steps?
+145
View File
@@ -1,5 +1,9 @@
use std::ptr;
use common::io::{Io, MmioPtr};
use range_alloc::RangeAllocator;
use syscall::error::Result;
use syscall::{Error, EIO};
use super::MmioRegion;
@@ -8,6 +12,63 @@ pub const PLANE_CTL_ENABLE: u32 = 1 << 31;
pub const PLANE_WM_ENABLE: u32 = 1 << 31;
pub const PLANE_WM_LINES_SHIFT: u32 = 14;
#[derive(Debug)]
pub struct DeviceFb {
pub onscreen: *mut [u32],
pub surf: u32,
pub width: u32,
pub height: u32,
pub stride: u32,
}
impl DeviceFb {
pub unsafe fn new(
gm: &MmioRegion,
surf: u32,
width: u32,
height: u32,
stride: u32,
clear: bool,
) -> Self {
let virt = (gm.virt + surf as usize) as *mut u32;
let onscreen = ptr::slice_from_raw_parts_mut(virt, (stride * height) as usize);
if clear {
(&mut *onscreen).fill(0);
}
Self {
onscreen,
surf,
width,
height,
stride,
}
}
pub fn alloc(
gm: &MmioRegion,
alloc_surfaces: &mut RangeAllocator<u32>,
width: u32,
height: u32,
) -> syscall::Result<Self> {
//TODO: documentation on this is not great
let stride_16 = (width + 15) / 16;
let stride = stride_16 * 16;
//TODO: how is memory allocated for PLANE_SURF?
let surf_size = (stride * height * 4).next_multiple_of(4096);
let surf = alloc_surfaces.allocate_range(surf_size).map_err(|err| {
log::warn!(
"failed to allocate surface of size {}: {:?}",
surf_size,
err
);
Error::new(EIO)
})?;
Ok(unsafe { DeviceFb::new(gm, surf.start, width, height, stride, true) })
}
}
pub struct Plane {
pub name: &'static str,
pub index: usize,
@@ -27,6 +88,90 @@ pub struct Plane {
}
impl Plane {
pub fn fetch_modeset(&self, alloc_buffers: &mut RangeAllocator<u32>) {
let buf_cfg = self.buf_cfg.read();
let buffer_start = buf_cfg & 0x7FF;
let buffer_end = (buf_cfg >> 16) & 0x7FF;
alloc_buffers
.allocate_exact_range(buffer_start..(buffer_end + 1))
.unwrap_or_else(|err| {
panic!(
"failed to allocate pre-existing buffer blocks {} to {}: {:?}",
buffer_start, buffer_end, err
);
});
}
pub fn modeset(&mut self, alloc_buffers: &mut RangeAllocator<u32>) -> syscall::Result<()> {
// FIXME handle runtime buffer reconfiguration
//TODO: enable DBUF if more buffers needed
//TODO: more blocks would mean better power usage
// Minimum is 8 blocks for linear planes, 160 blocks is recommended for pre-OS init
let buffer_size = 160;
let buffer = alloc_buffers.allocate_range(buffer_size).map_err(|err| {
log::warn!(
"failed to allocate {} buffer blocks: {:?}",
buffer_size,
err
);
Error::new(EIO)
})?;
self.buf_cfg.write(buffer.start | (buffer.end << 16));
//TODO: correct watermark calculation
self.wm[0].write(PLANE_WM_ENABLE | (2 << PLANE_WM_LINES_SHIFT) | buffer.len() as u32);
for i in 1..self.wm.len() {
self.wm[i].writef(PLANE_WM_ENABLE, false);
}
self.wm_trans.writef(PLANE_WM_ENABLE, false);
Ok(())
}
pub fn fetch_framebuffer(
&self,
gm: &MmioRegion,
alloc_surfaces: &mut RangeAllocator<u32>,
) -> DeviceFb {
let size = self.size.read();
let width = (size & 0xFFFF) + 1;
let height = ((size >> 16) & 0xFFFF) + 1;
let stride_16 = self.stride.read() & 0x7FF;
//TODO: this will be wrong for tiled planes
let stride = stride_16 * 16;
let surf = self.surf.read() & 0xFFFFF000;
//TODO: read bits per pixel
let surf_size = (stride * height * 4).next_multiple_of(4096);
alloc_surfaces
.allocate_exact_range(surf..(surf + surf_size))
.unwrap_or_else(|err| {
panic!(
"failed to allocate pre-existing surface at 0x{:x} of size {}: {:?}",
surf, surf_size, err
);
});
unsafe { DeviceFb::new(gm, surf, width, height, stride, true) }
}
pub fn set_framebuffer(&mut self, fb: &DeviceFb) {
//TODO: documentation on this is not great
let stride_16 = fb.stride / 16;
self.size.write((fb.width - 1) | ((fb.height - 1) << 16));
self.stride.write(stride_16);
self.surf.write(fb.surf);
// Disable gamma
if let Some(color_ctl) = &mut self.color_ctl {
color_ctl.write(self.color_ctl_gamma_disable);
}
//TODO: more PLANE_CTL bits
self.ctl.write(PLANE_CTL_ENABLE | self.ctl_source_rgb_8888);
}
pub fn dump(&self) {
eprint!("Plane {}", self.name);
eprint!(" buf_cfg {:08X}", self.buf_cfg.read());
+4 -31
View File
@@ -11,6 +11,7 @@ use driver_graphics::{Buffer, CursorPlane, Damage, GraphicsAdapter};
use drm_sys::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT};
use syscall::{error::EINVAL, PAGE_SIZE};
use super::pipe::DeviceFb;
use super::Device;
#[derive(Debug)]
@@ -114,9 +115,9 @@ impl GraphicsAdapter for Device {
for row in 0..framebuffer.height {
unsafe {
ptr::write_bytes(
onscreen_ptr.add(row * framebuffer.stride),
onscreen_ptr.add((row * framebuffer.stride) as usize),
0,
framebuffer.width,
framebuffer.width as usize,
);
}
}
@@ -135,34 +136,6 @@ impl GraphicsAdapter for Device {
}
}
pub struct DeviceFb {
pub onscreen: *mut [u32],
pub width: usize,
pub height: usize,
pub stride: usize,
}
impl DeviceFb {
pub unsafe fn new(
virt: *mut u32,
width: usize,
height: usize,
stride: usize,
clear: bool,
) -> Self {
let onscreen = ptr::slice_from_raw_parts_mut(virt, stride * height);
if clear {
(&mut *onscreen).fill(0);
}
Self {
onscreen,
width,
height,
stride,
}
}
}
#[derive(Debug)]
pub struct DumbFb {
width: usize,
@@ -227,7 +200,7 @@ impl DumbFb {
unsafe {
ptr::copy(
offscreen_ptr.add(row * self.width + start_x),
onscreen_ptr.add(row * framebuffer.stride + start_x),
onscreen_ptr.add(row * framebuffer.stride as usize + start_x),
w,
);
}
+1 -2
View File
@@ -165,7 +165,7 @@ impl DisplayHandle {
pub fn read_vt_event(&mut self) -> io::Result<Option<VtEvent>> {
let mut event = VtEvent {
kind: VtEventKind::Resize,
kind: VtEventKind::Activate,
vt: usize::MAX,
width: u32::MAX,
height: u32::MAX,
@@ -212,7 +212,6 @@ impl ControlHandle {
#[repr(usize)]
pub enum VtEventKind {
Activate,
Resize,
}
#[derive(Debug)]
-27
View File
@@ -443,33 +443,6 @@ impl SchemeSync for InputScheme {
}
},
EventOption::Resize(resize_event) => {
for handle in self.handles.values_mut() {
match handle {
Handle::Display {
pending,
notified,
device,
..
} => {
if self.display.as_ref() == Some(device) {
pending.push(VtEvent {
kind: VtEventKind::Resize,
vt: self.active_vt.unwrap(),
width: resize_event.width,
height: resize_event.height,
// TODO(andypython): Figure out how to get the stride.
stride: resize_event.width,
});
*notified = false;
}
}
_ => continue,
}
}
}
_ => continue,
}