use skia_rs_core::{AlphaType, ColorType};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TextureFormat {
Rgba8Unorm,
Rgba8UnormSrgb,
Bgra8Unorm,
Bgra8UnormSrgb,
R8Unorm,
Rg8Unorm,
Rgba16Float,
Rgba32Float,
Depth24Stencil8,
Depth32Float,
}
impl TextureFormat {
pub fn bytes_per_pixel(&self) -> u32 {
match self {
Self::R8Unorm => 1,
Self::Rg8Unorm => 2,
Self::Rgba8Unorm | Self::Rgba8UnormSrgb | Self::Bgra8Unorm | Self::Bgra8UnormSrgb => 4,
Self::Rgba16Float => 8,
Self::Rgba32Float => 16,
Self::Depth24Stencil8 | Self::Depth32Float => 4,
}
}
pub fn from_color_type(color_type: ColorType) -> Option<Self> {
match color_type {
ColorType::Rgba8888 => Some(Self::Rgba8Unorm),
ColorType::Bgra8888 => Some(Self::Bgra8Unorm),
ColorType::Alpha8 => Some(Self::R8Unorm),
ColorType::Gray8 => Some(Self::R8Unorm),
ColorType::RgbaF16 => Some(Self::Rgba16Float),
ColorType::RgbaF32 => Some(Self::Rgba32Float),
_ => None,
}
}
pub fn is_depth(&self) -> bool {
matches!(self, Self::Depth24Stencil8 | Self::Depth32Float)
}
pub fn is_srgb(&self) -> bool {
matches!(self, Self::Rgba8UnormSrgb | Self::Bgra8UnormSrgb)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct TextureUsage(u32);
impl TextureUsage {
pub const NONE: Self = Self(0);
pub const COPY_SRC: Self = Self(1 << 0);
pub const COPY_DST: Self = Self(1 << 1);
pub const SAMPLED: Self = Self(1 << 2);
pub const STORAGE: Self = Self(1 << 3);
pub const RENDER_TARGET: Self = Self(1 << 4);
pub fn contains(&self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
pub fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl std::ops::BitOr for TextureUsage {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
#[derive(Debug, Clone)]
pub struct TextureDescriptor {
pub width: u32,
pub height: u32,
pub depth_or_layers: u32,
pub mip_level_count: u32,
pub sample_count: u32,
pub format: TextureFormat,
pub usage: TextureUsage,
pub label: Option<String>,
}
impl TextureDescriptor {
pub fn new_2d(width: u32, height: u32, format: TextureFormat, usage: TextureUsage) -> Self {
Self {
width,
height,
depth_or_layers: 1,
mip_level_count: 1,
sample_count: 1,
format,
usage,
label: None,
}
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn with_mip_levels(mut self, count: u32) -> Self {
self.mip_level_count = count;
self
}
}
#[derive(Debug)]
pub struct BackendTexture {
pub width: u32,
pub height: u32,
pub format: TextureFormat,
pub handle: u64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_texture_format_bytes() {
assert_eq!(TextureFormat::Rgba8Unorm.bytes_per_pixel(), 4);
assert_eq!(TextureFormat::R8Unorm.bytes_per_pixel(), 1);
assert_eq!(TextureFormat::Rgba16Float.bytes_per_pixel(), 8);
}
#[test]
fn test_texture_usage() {
let usage = TextureUsage::SAMPLED | TextureUsage::RENDER_TARGET;
assert!(usage.contains(TextureUsage::SAMPLED));
assert!(usage.contains(TextureUsage::RENDER_TARGET));
assert!(!usage.contains(TextureUsage::STORAGE));
}
}