Merge branch 'gpu_drm44' into 'main'
drivers/graphics/driver-graphics: Implement DRM_IOCTL_MODE_CLOSEFB See merge request redox-os/base!292
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
name = "driver-graphics"
|
||||
description = "Shared video and graphics code library"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
drm-fourcc.workspace = true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use drm_sys::{DRM_MODE_CURSOR_BO, DRM_MODE_CURSOR_MOVE};
|
||||
use syscall::{Error, ENOENT, ENXIO};
|
||||
use syscall::{ENOENT, ENXIO, Error};
|
||||
|
||||
use crate::{DrmHandle, GraphicsAdapter, VtState};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use drm_fourcc::DrmFourcc;
|
||||
use syscall::{Error, EINVAL};
|
||||
use syscall::{EINVAL, Error};
|
||||
|
||||
use crate::kms::objects::{KmsFramebuffer, KmsObjectId, KmsObjects};
|
||||
use crate::{Damage, DrmHandle, GraphicsAdapter, VtState};
|
||||
@@ -11,7 +12,7 @@ pub(super) fn mode_get_fb<T: GraphicsAdapter>(
|
||||
handle: &mut DrmHandle<T>,
|
||||
mut data: redox_ioctl::drm::DrmModeFbCmd<'_>,
|
||||
) -> Result<usize, Error> {
|
||||
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
|
||||
let fb = objects.get_framebuffer_maybe_closed(KmsObjectId(data.fb_id()))?;
|
||||
|
||||
let (bpp, depth) = match fb.pixel_format {
|
||||
DrmFourcc::Xrgb8888 => (32, 24),
|
||||
@@ -54,6 +55,7 @@ pub(super) fn mode_add_fb<T: GraphicsAdapter>(
|
||||
let fb = adapter.create_framebuffer(buffer);
|
||||
|
||||
let id = objects.add_framebuffer(KmsFramebuffer {
|
||||
closed: AtomicBool::new(false),
|
||||
width: data.width(),
|
||||
height: data.height(),
|
||||
pixel_format,
|
||||
@@ -162,6 +164,7 @@ pub(super) fn mode_add_fb2<T: GraphicsAdapter>(
|
||||
let fb = adapter.create_framebuffer(buffer);
|
||||
|
||||
let id = objects.add_framebuffer(KmsFramebuffer {
|
||||
closed: AtomicBool::new(false),
|
||||
width: data.width(),
|
||||
height: data.height(),
|
||||
pixel_format: DrmFourcc::try_from(data.pixel_format()).map_err(|_| Error::new(EINVAL))?,
|
||||
@@ -180,7 +183,7 @@ pub(super) fn mode_get_fb2<T: GraphicsAdapter>(
|
||||
handle: &mut DrmHandle<T>,
|
||||
mut data: redox_ioctl::drm::DrmModeFbCmd2<'_>,
|
||||
) -> Result<usize, Error> {
|
||||
let fb = objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
|
||||
let fb = objects.get_framebuffer_maybe_closed(KmsObjectId(data.fb_id()))?;
|
||||
|
||||
handle.next_id += 1;
|
||||
handle.buffers.insert(handle.next_id, fb.buffer.clone());
|
||||
@@ -194,3 +197,19 @@ pub(super) fn mode_get_fb2<T: GraphicsAdapter>(
|
||||
data.set_modifier([0; 4]);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub(super) fn mode_close_fb<T: GraphicsAdapter>(
|
||||
objects: &mut KmsObjects<T>,
|
||||
vts: &mut HashMap<usize, VtState<T>>,
|
||||
data: redox_ioctl::drm::DrmModeClosefb<'_>,
|
||||
) -> Result<usize, Error> {
|
||||
let fb_id = KmsObjectId(data.fb_id());
|
||||
let fb = objects.get_framebuffer(fb_id)?;
|
||||
fb.closed.store(true, Ordering::SeqCst);
|
||||
|
||||
if !VtState::fb_has_any_use(vts, fb_id) {
|
||||
objects.remove_framebuffer(fb_id).unwrap();
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use drm_fourcc::DrmFourcc;
|
||||
use syscall::{Error, EINVAL, ENOENT};
|
||||
use syscall::{EINVAL, ENOENT, Error};
|
||||
|
||||
use crate::kms::objects::{KmsObjectId, KmsObjects, KmsRect};
|
||||
use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, VtState, MAP_FAKE_OFFSET_MULTIPLIER};
|
||||
use crate::{Buffer, Damage, DrmHandle, GraphicsAdapter, MAP_FAKE_OFFSET_MULTIPLIER, VtState};
|
||||
|
||||
mod cursor;
|
||||
mod framebuffer;
|
||||
@@ -144,7 +144,9 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
.map(|&id| KmsObjectId(id))
|
||||
.collect();
|
||||
let fb_id = if data.fb_id() != 0 {
|
||||
Some(KmsObjectId(data.fb_id()))
|
||||
let fb_id = KmsObjectId(data.fb_id());
|
||||
objects.get_framebuffer(fb_id)?;
|
||||
Some(fb_id)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -159,6 +161,7 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
let mut new_crtc_state = crtc.lock().unwrap().state.clone();
|
||||
new_crtc_state.mode = mode;
|
||||
let mut new_plane_state = plane.lock().unwrap().state.clone();
|
||||
let old_fb_id = new_plane_state.fb_id;
|
||||
new_plane_state.fb_id = fb_id;
|
||||
new_plane_state.crtc_id = Some(crtc_id);
|
||||
if handle.vt == active_vt {
|
||||
@@ -189,6 +192,13 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
new_crtc_state;
|
||||
vts.get_mut(&handle.vt).unwrap().plane_state
|
||||
[plane.lock().unwrap().plane_index as usize] = new_plane_state;
|
||||
|
||||
if let Some(old_fb_id) = old_fb_id {
|
||||
if !VtState::fb_has_any_use(vts, old_fb_id) {
|
||||
objects.remove_framebuffer_if_closed(old_fb_id);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_CURSOR => ipc::DrmModeCursor::with(payload, |data| {
|
||||
@@ -305,11 +315,14 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
plane.state.clone()
|
||||
};
|
||||
let fb_id = if data.fb_id() != 0 {
|
||||
KmsObjectId(data.fb_id())
|
||||
let fb_id = KmsObjectId(data.fb_id());
|
||||
objects.get_framebuffer(fb_id)?;
|
||||
Some(fb_id)
|
||||
} else {
|
||||
KmsObjectId::INVALID
|
||||
None
|
||||
};
|
||||
new_state.fb_id = Some(fb_id);
|
||||
let old_fb_id = new_state.fb_id;
|
||||
new_state.fb_id = fb_id;
|
||||
new_state.crtc_id = Some(crtc_id);
|
||||
new_state.src_rect = KmsRect {
|
||||
x: data.src_x(),
|
||||
@@ -339,6 +352,13 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
}
|
||||
vts.get_mut(&handle.vt).unwrap().plane_state
|
||||
[plane.lock().unwrap().plane_index as usize] = new_state;
|
||||
|
||||
if let Some(old_fb_id) = old_fb_id {
|
||||
if !VtState::fb_has_any_use(vts, old_fb_id) {
|
||||
objects.remove_framebuffer_if_closed(old_fb_id);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}),
|
||||
ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| {
|
||||
@@ -365,6 +385,9 @@ pub(crate) fn call_ioctl<T: GraphicsAdapter>(
|
||||
ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |data| {
|
||||
framebuffer::mode_get_fb2(objects, handle, data)
|
||||
}),
|
||||
ipc::MODE_CLOSE_FB => ipc::DrmModeClosefb::with(payload, |data| {
|
||||
framebuffer::mode_close_fb(objects, vts, data)
|
||||
}),
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use drm_sys::{
|
||||
drm_mode_property_enum, DRM_MODE_PROP_ATOMIC, DRM_MODE_PROP_BITMASK, DRM_MODE_PROP_BLOB,
|
||||
DRM_MODE_PROP_ENUM, DRM_MODE_PROP_IMMUTABLE, DRM_MODE_PROP_OBJECT, DRM_MODE_PROP_RANGE,
|
||||
DRM_MODE_PROP_SIGNED_RANGE,
|
||||
DRM_MODE_PROP_ATOMIC, DRM_MODE_PROP_BITMASK, DRM_MODE_PROP_BLOB, DRM_MODE_PROP_ENUM,
|
||||
DRM_MODE_PROP_IMMUTABLE, DRM_MODE_PROP_OBJECT, DRM_MODE_PROP_RANGE, DRM_MODE_PROP_SIGNED_RANGE,
|
||||
drm_mode_property_enum,
|
||||
};
|
||||
use syscall::Error;
|
||||
|
||||
use crate::GraphicsAdapter;
|
||||
use crate::kms::objects::{KmsObjectId, KmsObjects};
|
||||
use crate::kms::properties::KmsPropertyKind;
|
||||
use crate::GraphicsAdapter;
|
||||
|
||||
pub(super) fn mode_get_property<T: GraphicsAdapter>(
|
||||
objects: &mut KmsObjects<T>,
|
||||
|
||||
@@ -3,14 +3,14 @@ use std::fmt::Debug;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON,
|
||||
DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND, DRM_MODE_TYPE_PREFERRED,
|
||||
DRM_MODE_CONNECTOR_Unknown, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY,
|
||||
DRM_MODE_DPMS_SUSPEND, DRM_MODE_TYPE_PREFERRED, drm_mode_modeinfo,
|
||||
};
|
||||
use syscall::Result;
|
||||
|
||||
use crate::kms::objects::{KmsObjectId, KmsObjects};
|
||||
use crate::kms::properties::{define_object_props, KmsPropertyData, CRTC_ID, DPMS, EDID, TILE};
|
||||
use crate::GraphicsAdapter;
|
||||
use crate::kms::objects::{KmsObjectId, KmsObjects};
|
||||
use crate::kms::properties::{CRTC_ID, DPMS, EDID, KmsPropertyData, TILE, define_object_props};
|
||||
|
||||
impl<T: GraphicsAdapter> KmsObjects<T> {
|
||||
pub fn add_connector(
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use drm_fourcc::DrmFourcc;
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC,
|
||||
DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_FB, DRM_MODE_OBJECT_PLANE, DRM_MODE_OBJECT_PROPERTY,
|
||||
DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY,
|
||||
DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_ENCODER,
|
||||
DRM_MODE_OBJECT_FB, DRM_MODE_OBJECT_PLANE, DRM_MODE_OBJECT_PROPERTY, DRM_PLANE_TYPE_CURSOR,
|
||||
DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY, drm_mode_modeinfo,
|
||||
};
|
||||
use syscall::{Error, Result, ENOENT};
|
||||
use syscall::{ENOENT, Error, Result};
|
||||
|
||||
use crate::GraphicsAdapter;
|
||||
use crate::kms::connector::{KmsConnector, KmsEncoder};
|
||||
use crate::kms::properties::{
|
||||
define_object_props, init_standard_props, type_, KmsBlob, KmsProperty, KmsPropertyData, ACTIVE,
|
||||
CRTC_H, CRTC_ID, CRTC_W, CRTC_X, CRTC_Y, FB_ID, SRC_H, SRC_W, SRC_X, SRC_Y,
|
||||
ACTIVE, CRTC_H, CRTC_ID, CRTC_W, CRTC_X, CRTC_Y, FB_ID, KmsBlob, KmsProperty, KmsPropertyData,
|
||||
SRC_H, SRC_W, SRC_X, SRC_Y, define_object_props, init_standard_props, type_,
|
||||
};
|
||||
use crate::GraphicsAdapter;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KmsObjects<T: GraphicsAdapter> {
|
||||
@@ -192,12 +193,31 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
|
||||
self.remove::<KmsFramebuffer<T>>(id)
|
||||
}
|
||||
|
||||
pub fn remove_framebuffer_if_closed(&mut self, id: KmsObjectId) {
|
||||
if self
|
||||
.get_framebuffer_maybe_closed(id)
|
||||
.unwrap()
|
||||
.closed
|
||||
.load(Ordering::SeqCst)
|
||||
{
|
||||
self.remove::<KmsFramebuffer<T>>(id).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fb_ids(&self) -> &[KmsObjectId] {
|
||||
&self.framebuffers
|
||||
}
|
||||
|
||||
pub fn get_framebuffer(&self, id: KmsObjectId) -> Result<&KmsFramebuffer<T>> {
|
||||
self.get(id)
|
||||
let fb = self.get::<KmsFramebuffer<T>>(id)?;
|
||||
if fb.closed.load(Ordering::SeqCst) {
|
||||
return Err(Error::new(ENOENT));
|
||||
}
|
||||
Ok(fb)
|
||||
}
|
||||
|
||||
pub fn get_framebuffer_maybe_closed(&self, id: KmsObjectId) -> Result<&KmsFramebuffer<T>> {
|
||||
self.get::<KmsFramebuffer<T>>(id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,6 +415,15 @@ pub struct KmsRect<T> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KmsFramebuffer<T: GraphicsAdapter> {
|
||||
/// Was this framebuffer closed using the CLOSEFB ioctl or implicitly
|
||||
/// created by the CURSOR or CURSOR2 ioctls or similar?
|
||||
///
|
||||
/// A closed framebuffer will be destroyed as soon as the last plane that
|
||||
/// uses it switches to a different framebuffer. In the mean time the GETFB
|
||||
/// and GETFB2 ioctls still function on it, but anything else will result
|
||||
/// in ENOENT, including another CLOSEFB call.
|
||||
pub closed: AtomicBool,
|
||||
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub pixel_format: DrmFourcc,
|
||||
|
||||
@@ -7,10 +7,10 @@ use drm_sys::{
|
||||
DRM_MODE_OBJECT_CRTC, DRM_MODE_OBJECT_FB, DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY,
|
||||
DRM_PLANE_TYPE_PRIMARY, DRM_PROP_NAME_LEN,
|
||||
};
|
||||
use syscall::{Error, Result, ENOENT};
|
||||
use syscall::{ENOENT, Error, Result};
|
||||
|
||||
use crate::kms::objects::{KmsObject, KmsObjectId, KmsObjects};
|
||||
use crate::GraphicsAdapter;
|
||||
use crate::kms::objects::{KmsObject, KmsObjectId, KmsObjects};
|
||||
|
||||
impl<T: GraphicsAdapter> KmsObjects<T> {
|
||||
pub fn add_property(
|
||||
|
||||
@@ -10,11 +10,11 @@ use std::sync::{Arc, Mutex};
|
||||
|
||||
use inputd::{DisplayHandle, VtEventKind};
|
||||
use libredox::Fd;
|
||||
use redox_scheme::scheme::{register_scheme_inner, SchemeState, SchemeSync};
|
||||
use redox_scheme::scheme::{SchemeState, SchemeSync, register_scheme_inner};
|
||||
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
|
||||
use scheme_utils::{FpathWriter, HandleMap};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP};
|
||||
use syscall::{EACCES, EAGAIN, EINVAL, ENOENT, EOPNOTSUPP, Error, MapFlags, Result};
|
||||
|
||||
use crate::kms::connector::{KmsConnectorDriver, KmsConnectorState};
|
||||
use crate::kms::objects::{
|
||||
@@ -284,6 +284,21 @@ struct VtState<T: GraphicsAdapter> {
|
||||
cursor_plane: Option<CursorPlane<T::Buffer>>,
|
||||
}
|
||||
|
||||
impl<T: GraphicsAdapter> VtState<T> {
|
||||
fn fb_has_any_use(vts: &HashMap<usize, Self>, fb_id: KmsObjectId) -> bool {
|
||||
let mut has_any_use = false;
|
||||
for vt_data in vts.values() {
|
||||
for plane_state in vt_data.plane_state.iter() {
|
||||
if plane_state.fb_id == Some(fb_id) {
|
||||
has_any_use = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
has_any_use
|
||||
}
|
||||
}
|
||||
|
||||
enum Handle<T: GraphicsAdapter> {
|
||||
V2(DrmHandle<T>),
|
||||
SchemeRoot,
|
||||
@@ -377,7 +392,7 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
|
||||
|
||||
let fb = plane_state.fb_id.map(|fb_id| {
|
||||
self.objects
|
||||
.get_framebuffer(fb_id)
|
||||
.get_framebuffer_maybe_closed(fb_id)
|
||||
.expect("removed framebuffers should be unset")
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use driver_graphics::kms::objects::{KmsFramebuffer, KmsObjects};
|
||||
use drm_fourcc::DrmFourcc;
|
||||
use pcid_interface::{PciFunction, PciFunctionHandle};
|
||||
use range_alloc::RangeAllocator;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::{collections::VecDeque, fmt, mem, sync::Arc};
|
||||
use syscall::error::{Error, Result, EIO, ENODEV, ERANGE};
|
||||
|
||||
@@ -776,6 +777,7 @@ impl Device {
|
||||
GpuBuffer::alloc_dumb(&self.gm, &mut self.ggtt, width, height)?;
|
||||
|
||||
let fb = KmsFramebuffer {
|
||||
closed: AtomicBool::new(true),
|
||||
width,
|
||||
height,
|
||||
pixel_format: DrmFourcc::Argb8888,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::io::{Io, MmioPtr};
|
||||
@@ -93,6 +94,7 @@ impl Plane {
|
||||
let buffer = unsafe { GpuBuffer::new(gm, surf, stride * height, true) };
|
||||
|
||||
KmsFramebuffer {
|
||||
closed: AtomicBool::new(true),
|
||||
width,
|
||||
height,
|
||||
pixel_format: DrmFourcc::Argb8888,
|
||||
|
||||
@@ -121,7 +121,7 @@ impl GraphicsAdapter for Device {
|
||||
|
||||
let buffer = new_plane_state
|
||||
.fb_id
|
||||
.map(|fb_id| objects.get_framebuffer(fb_id))
|
||||
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
|
||||
.transpose()?;
|
||||
|
||||
plane.state = new_plane_state;
|
||||
|
||||
@@ -130,7 +130,7 @@ impl GraphicsAdapter for FbAdapter {
|
||||
|
||||
let buffer = new_plane_state
|
||||
.fb_id
|
||||
.map(|fb_id| objects.get_framebuffer(fb_id))
|
||||
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
|
||||
.transpose()?;
|
||||
|
||||
plane.state = new_plane_state;
|
||||
|
||||
@@ -452,7 +452,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
|
||||
let framebuffer = new_plane_state
|
||||
.fb_id
|
||||
.map(|fb_id| objects.get_framebuffer(fb_id))
|
||||
.map(|fb_id| objects.get_framebuffer_maybe_closed(fb_id))
|
||||
.transpose()?;
|
||||
|
||||
plane.state = new_plane_state;
|
||||
|
||||
Reference in New Issue
Block a user