metal: use IN_FORMATS plane property
This commit is contained in:
parent
d022d96fbf
commit
e0ed29038e
9 changed files with 183 additions and 87 deletions
|
|
@ -35,8 +35,11 @@ use crate::{
|
|||
utils::{buf::Buf, errorfmt::ErrorFmt, stack::Stack, syncqueue::SyncQueue, vec_ext::VecExt},
|
||||
video::{
|
||||
dmabuf::DmaBuf,
|
||||
drm::sys::{get_version, DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH},
|
||||
INVALID_MODIFIER,
|
||||
drm::sys::{
|
||||
drm_format_modifier, drm_format_modifier_blob, get_version, DRM_CAP_CURSOR_HEIGHT,
|
||||
DRM_CAP_CURSOR_WIDTH, FORMAT_BLOB_CURRENT,
|
||||
},
|
||||
Modifier, INVALID_MODIFIER,
|
||||
},
|
||||
};
|
||||
pub use sys::{
|
||||
|
|
@ -106,6 +109,8 @@ pub enum DrmError {
|
|||
InvalidRead,
|
||||
#[error("Could not determine the drm version")]
|
||||
Version(#[source] OsError),
|
||||
#[error("Format of IN_FORMATS property is invalid")]
|
||||
InFormats,
|
||||
}
|
||||
|
||||
fn render_node_name(fd: c::c_int) -> Result<Ustring, DrmError> {
|
||||
|
|
@ -174,6 +179,11 @@ impl Drm {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct InFormat {
|
||||
pub format: u32,
|
||||
pub modifiers: Vec<Modifier>,
|
||||
}
|
||||
|
||||
pub struct DrmMaster {
|
||||
drm: Drm,
|
||||
u32_bufs: Stack<Vec<u32>>,
|
||||
|
|
@ -373,6 +383,64 @@ impl DrmMaster {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_in_formats(&self, property: u32) -> Result<Vec<InFormat>, DrmError> {
|
||||
let blob = self.getblob_vec::<u8>(DrmBlob(property))?;
|
||||
let header: drm_format_modifier_blob = match uapi::pod_read_init(blob.as_bytes()) {
|
||||
Ok(h) => h,
|
||||
Err(_) => {
|
||||
log::error!("Header of IN_FORMATS blob doesn't fit in the blob");
|
||||
return Err(DrmError::InFormats);
|
||||
}
|
||||
};
|
||||
if header.version != FORMAT_BLOB_CURRENT {
|
||||
log::error!(
|
||||
"Header of IN_FORMATS has an invalid version: {}",
|
||||
header.version
|
||||
);
|
||||
return Err(DrmError::InFormats);
|
||||
}
|
||||
let formats_start = header.formats_offset as usize;
|
||||
let formats_end = formats_start
|
||||
.wrapping_add((header.count_formats as usize).wrapping_mul(mem::size_of::<u32>()));
|
||||
let modifiers_start = header.modifiers_offset as usize;
|
||||
let modifiers_end = modifiers_start.wrapping_add(
|
||||
(header.count_modifiers as usize).wrapping_mul(mem::size_of::<drm_format_modifier>()),
|
||||
);
|
||||
if blob.len() < formats_end || formats_end < formats_start {
|
||||
log::error!("Formats of IN_FORMATS blob don't fit in the blob");
|
||||
return Err(DrmError::InFormats);
|
||||
}
|
||||
if blob.len() < modifiers_end || modifiers_end < modifiers_start {
|
||||
log::error!("Formats of IN_FORMATS blob don't fit in the blob");
|
||||
return Err(DrmError::InFormats);
|
||||
}
|
||||
let mut formats: Vec<_> = uapi::pod_iter::<u32, _>(&blob[formats_start..formats_end])
|
||||
.unwrap()
|
||||
.map(|f| InFormat {
|
||||
format: f,
|
||||
modifiers: vec![],
|
||||
})
|
||||
.collect();
|
||||
let modifiers =
|
||||
uapi::pod_iter::<drm_format_modifier, _>(&blob[modifiers_start..modifiers_end])
|
||||
.unwrap();
|
||||
for modifier in modifiers {
|
||||
let offset = modifier.offset as usize;
|
||||
let mut indices = modifier.formats;
|
||||
while indices != 0 {
|
||||
let idx = indices.trailing_zeros();
|
||||
indices &= !(1 << idx);
|
||||
let idx = idx as usize + offset;
|
||||
if idx >= formats.len() {
|
||||
log::error!("Modifier offset is out of bounds");
|
||||
return Err(DrmError::InFormats);
|
||||
}
|
||||
formats[idx].modifiers.push(modifier.modifier);
|
||||
}
|
||||
}
|
||||
Ok(formats)
|
||||
}
|
||||
|
||||
#[allow(clippy::await_holding_refcell_ref)]
|
||||
pub async fn event(&self) -> Result<Option<DrmEvent>, DrmError> {
|
||||
if self.events.is_empty() {
|
||||
|
|
|
|||
|
|
@ -1132,3 +1132,27 @@ pub fn get_version(fd: c::c_int) -> Result<DrmVersion, OsError> {
|
|||
desc: desc.into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub const FORMAT_BLOB_CURRENT: u32 = 1;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct drm_format_modifier_blob {
|
||||
pub version: u32,
|
||||
pub flags: u32,
|
||||
pub count_formats: u32,
|
||||
pub formats_offset: u32,
|
||||
pub count_modifiers: u32,
|
||||
pub modifiers_offset: u32,
|
||||
}
|
||||
|
||||
unsafe impl Pod for drm_format_modifier_blob {}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct drm_format_modifier {
|
||||
pub formats: u64,
|
||||
pub offset: u32,
|
||||
pub pad: u32,
|
||||
pub modifier: u64,
|
||||
}
|
||||
|
||||
unsafe impl Pod for drm_format_modifier {}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
use {
|
||||
crate::{
|
||||
format::formats,
|
||||
format::{formats, Format},
|
||||
utils::oserror::OsError,
|
||||
video::{
|
||||
dmabuf::{DmaBuf, DmaBufPlane, PlaneVec},
|
||||
drm::{Drm, DrmError},
|
||||
ModifiedFormat, INVALID_MODIFIER,
|
||||
Modifier,
|
||||
},
|
||||
},
|
||||
std::{
|
||||
|
|
@ -27,7 +27,7 @@ pub enum GbmError {
|
|||
#[error("Cloud not create a gbm device")]
|
||||
CreateDevice,
|
||||
#[error("Cloud not create a gbm buffer")]
|
||||
CreateBo,
|
||||
CreateBo(#[source] OsError),
|
||||
#[error("gbm buffer has an unknown format")]
|
||||
UnknownFormat,
|
||||
#[error("Could not retrieve a drm-buf fd")]
|
||||
|
|
@ -199,26 +199,27 @@ impl GbmDevice {
|
|||
&self,
|
||||
width: i32,
|
||||
height: i32,
|
||||
format: &ModifiedFormat,
|
||||
format: &Format,
|
||||
modifiers: &[Modifier],
|
||||
usage: u32,
|
||||
) -> Result<GbmBo, GbmError> {
|
||||
unsafe {
|
||||
let (modifiers, n_modifiers) = if format.modifier == INVALID_MODIFIER {
|
||||
let (modifiers, n_modifiers) = if modifiers.is_empty() {
|
||||
(ptr::null(), 0)
|
||||
} else {
|
||||
(&format.modifier as _, 1)
|
||||
(modifiers.as_ptr() as _, modifiers.len() as _)
|
||||
};
|
||||
let bo = gbm_bo_create_with_modifiers2(
|
||||
self.dev,
|
||||
width as _,
|
||||
height as _,
|
||||
format.format.drm,
|
||||
format.drm,
|
||||
modifiers,
|
||||
n_modifiers,
|
||||
usage,
|
||||
);
|
||||
if bo.is_null() {
|
||||
return Err(GbmError::CreateBo);
|
||||
return Err(GbmError::CreateBo(OsError::default()));
|
||||
}
|
||||
let bo = BoHolder { bo };
|
||||
let dma = export_bo(bo.bo)?;
|
||||
|
|
@ -250,7 +251,7 @@ impl GbmDevice {
|
|||
usage,
|
||||
);
|
||||
if bo.is_null() {
|
||||
return Err(GbmError::CreateBo);
|
||||
return Err(GbmError::CreateBo(OsError::default()));
|
||||
}
|
||||
let bo = BoHolder { bo };
|
||||
Ok(GbmBo {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue