use core::fmt;
use std::{mem::MaybeUninit, os::fd::RawFd};
use crate::{check, PixelFormat, Result};
use super::{ExportSurfaceFlags, Surface, SurfaceAttribMemoryType};
#[repr(C)]
pub struct PrimeSurfaceDescriptor {
fourcc: PixelFormat,
width: u32,
height: u32,
num_objects: u32,
objects: [PrimeObject; 4],
num_layers: u32,
layers: [PrimeLayer; 4],
}
impl fmt::Debug for PrimeSurfaceDescriptor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PrimeSurfaceDescriptor")
.field("fourcc", &self.fourcc)
.field("width", &self.width)
.field("height", &self.height)
.field("objects", &self.objects())
.field("layers", &self.layers())
.finish()
}
}
impl PrimeSurfaceDescriptor {
#[inline]
pub fn fourcc(&self) -> PixelFormat {
self.fourcc
}
#[inline]
pub fn width(&self) -> u32 {
self.width
}
#[inline]
pub fn height(&self) -> u32 {
self.height
}
#[inline]
pub fn objects(&self) -> &[PrimeObject] {
&self.objects[..self.num_objects as usize]
}
pub fn object(&self, index: u32) -> &PrimeObject {
assert!(index < self.num_objects && index < 4);
&self.objects[index as usize]
}
#[inline]
pub fn layers(&self) -> &[PrimeLayer] {
&self.layers[..self.num_layers as usize]
}
}
#[derive(Debug)]
#[repr(C)]
pub struct PrimeObject {
fd: RawFd,
size: u32,
drm_format_modifier: u64,
}
impl PrimeObject {
#[inline]
pub fn fd(&self) -> RawFd {
self.fd
}
#[inline]
pub fn size(&self) -> u32 {
self.size
}
#[inline]
pub fn drm_format_modifier(&self) -> u64 {
self.drm_format_modifier
}
}
#[repr(C)]
pub struct PrimeLayer {
drm_format: PixelFormat,
num_planes: u32,
object_index: [u32; 4],
offset: [u32; 4],
pitch: [u32; 4],
}
impl fmt::Debug for PrimeLayer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct PlanesDebug<'a>(&'a PrimeLayer, u32);
impl<'a> fmt::Debug for PlanesDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
for i in 0..self.1 {
list.entry(&self.0.plane(i));
}
list.finish()
}
}
f.debug_struct("PrimeLayer")
.field("drm_format", &self.drm_format)
.field("planes", &PlanesDebug(self, self.num_planes))
.finish()
}
}
impl PrimeLayer {
#[inline]
pub fn drm_format(&self) -> PixelFormat {
self.drm_format
}
#[inline]
pub fn num_planes(&self) -> u32 {
self.num_planes
}
pub fn plane(&self, index: u32) -> PrimePlane {
assert!(index < self.num_planes && index < 4);
PrimePlane {
object_index: self.object_index[index as usize],
offset: self.offset[index as usize],
pitch: self.pitch[index as usize],
}
}
pub fn planes(&self) -> impl Iterator<Item = PrimePlane> + '_ {
(0..self.num_planes).map(|i| self.plane(i))
}
}
#[derive(Debug)]
pub struct PrimePlane {
object_index: u32,
offset: u32,
pitch: u32,
}
impl PrimePlane {
#[inline]
pub fn object_index(&self) -> u32 {
self.object_index
}
#[inline]
pub fn offset(&self) -> u32 {
self.offset
}
#[inline]
pub fn pitch(&self) -> u32 {
self.pitch
}
}
impl Surface {
pub fn export_prime(&mut self, flags: ExportSurfaceFlags) -> Result<PrimeSurfaceDescriptor> {
unsafe {
let mut descriptor: MaybeUninit<PrimeSurfaceDescriptor> = MaybeUninit::uninit();
check(
"vaExportSurfaceHandle",
self.d.libva.vaExportSurfaceHandle(
self.d.raw,
self.id,
SurfaceAttribMemoryType::DRM_PRIME_2,
flags,
descriptor.as_mut_ptr().cast(),
),
)?;
Ok(descriptor.assume_init())
}
}
}