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