use crate::format::{Extent2D, Fourcc, Modifier, PixelFormat};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct TextureUsage {
pub sampled: bool,
pub render_target: bool,
pub transfer: bool,
pub scanout: bool,
}
impl TextureUsage {
pub const fn sampled() -> Self {
Self {
sampled: true,
render_target: false,
transfer: true,
scanout: false,
}
}
pub const fn offscreen() -> Self {
Self {
sampled: true,
render_target: true,
transfer: true,
scanout: false,
}
}
}
#[cfg(unix)]
#[derive(Debug)]
pub struct DmaBufPlane {
pub fd: std::os::fd::OwnedFd,
pub offset: u32,
pub stride: u32,
}
#[cfg(unix)]
#[derive(Debug)]
pub struct ExternalImageDesc {
pub planes: Vec<DmaBufPlane>,
pub fourcc: Fourcc,
pub modifier: Modifier,
}
#[derive(Debug)]
pub struct TextureDescriptor {
pub extent: Extent2D,
pub format: PixelFormat,
pub usage: TextureUsage,
pub sample_count: u32,
pub mip_levels: u32,
#[cfg(unix)]
pub external: Option<ExternalImageDesc>,
}
pub fn mip_levels_for(extent: Extent2D) -> u32 {
let longest = extent.width.max(extent.height).max(1);
longest.ilog2() + 1
}
impl TextureDescriptor {
pub fn offscreen(extent: Extent2D, format: PixelFormat) -> Self {
Self {
extent,
format,
usage: TextureUsage::offscreen(),
sample_count: 1,
mip_levels: 1,
#[cfg(unix)]
external: None,
}
}
pub fn sampled(extent: Extent2D, format: PixelFormat) -> Self {
Self {
extent,
format,
usage: TextureUsage::sampled(),
sample_count: 1,
mip_levels: 1,
#[cfg(unix)]
external: None,
}
}
pub fn mipmapped(extent: Extent2D, format: PixelFormat) -> Self {
Self {
mip_levels: mip_levels_for(extent),
..Self::offscreen(extent, format)
}
}
pub fn is_mipmapped(&self) -> bool {
self.mip_levels > 1
}
pub fn is_external(&self) -> bool {
#[cfg(unix)]
{
self.external.is_some()
}
#[cfg(not(unix))]
{
false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct BufferUsage {
pub vertex: bool,
pub index: bool,
pub uniform: bool,
pub transfer: bool,
}
#[derive(Debug, Clone)]
pub struct BufferDescriptor {
pub size: u64,
pub usage: BufferUsage,
pub host_visible: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn offscreen_targets_are_not_external() {
let desc = TextureDescriptor::offscreen(Extent2D::new(1920, 1080), PixelFormat::Rgba8Unorm);
assert!(!desc.is_external());
assert_eq!(desc.sample_count, 1);
assert!(desc.usage.render_target);
assert!(desc.usage.transfer);
assert!(desc.usage.sampled);
assert!(!desc.usage.scanout);
}
#[test]
fn scanout_usage_is_distinct_from_render_target_usage() {
let usage = TextureUsage {
scanout: true,
..TextureUsage::offscreen()
};
assert!(usage.scanout);
assert!(usage.render_target);
assert!(!TextureUsage::offscreen().scanout);
}
}