use std::cmp;
pub use self::attachment::AttachmentImage;
pub use self::immutable::ImmutableImage;
pub use self::layout::ImageLayout;
pub use self::storage::StorageImage;
pub use self::swapchain::SwapchainImage;
pub use self::sys::ImageCreationError;
pub use self::traits::ImageAccess;
pub use self::traits::ImageInner;
pub use self::traits::ImageViewAccess;
pub use self::usage::ImageUsage;
pub mod attachment;
pub mod immutable;
mod layout;
mod storage;
pub mod swapchain;
pub mod sys;
pub mod traits;
mod usage;
#[derive(Debug, Copy, Clone)]
pub enum MipmapsCount {
Log2,
One,
Specific(u32),
}
impl From<u32> for MipmapsCount {
#[inline]
fn from(num: u32) -> MipmapsCount {
MipmapsCount::Specific(num)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct Swizzle {
pub r: ComponentSwizzle,
pub g: ComponentSwizzle,
pub b: ComponentSwizzle,
pub a: ComponentSwizzle,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ComponentSwizzle {
Identity,
Zero,
One,
Red,
Green,
Blue,
Alpha,
}
impl Default for ComponentSwizzle {
#[inline]
fn default() -> ComponentSwizzle {
ComponentSwizzle::Identity
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Dimensions {
Dim1d { width: u32 },
Dim1dArray { width: u32, array_layers: u32 },
Dim2d { width: u32, height: u32 },
Dim2dArray {
width: u32,
height: u32,
array_layers: u32,
},
Dim3d { width: u32, height: u32, depth: u32 },
Cubemap { size: u32 },
CubemapArray { size: u32, array_layers: u32 },
}
impl Dimensions {
#[inline]
pub fn width(&self) -> u32 {
match *self {
Dimensions::Dim1d { width } => width,
Dimensions::Dim1dArray { width, .. } => width,
Dimensions::Dim2d { width, .. } => width,
Dimensions::Dim2dArray { width, .. } => width,
Dimensions::Dim3d { width, .. } => width,
Dimensions::Cubemap { size } => size,
Dimensions::CubemapArray { size, .. } => size,
}
}
#[inline]
pub fn height(&self) -> u32 {
match *self {
Dimensions::Dim1d { .. } => 1,
Dimensions::Dim1dArray { .. } => 1,
Dimensions::Dim2d { height, .. } => height,
Dimensions::Dim2dArray { height, .. } => height,
Dimensions::Dim3d { height, .. } => height,
Dimensions::Cubemap { size } => size,
Dimensions::CubemapArray { size, .. } => size,
}
}
#[inline]
pub fn width_height(&self) -> [u32; 2] {
[self.width(), self.height()]
}
#[inline]
pub fn depth(&self) -> u32 {
match *self {
Dimensions::Dim1d { .. } => 1,
Dimensions::Dim1dArray { .. } => 1,
Dimensions::Dim2d { .. } => 1,
Dimensions::Dim2dArray { .. } => 1,
Dimensions::Dim3d { depth, .. } => depth,
Dimensions::Cubemap { .. } => 1,
Dimensions::CubemapArray { .. } => 1,
}
}
#[inline]
pub fn width_height_depth(&self) -> [u32; 3] {
[self.width(), self.height(), self.depth()]
}
#[inline]
pub fn array_layers(&self) -> u32 {
match *self {
Dimensions::Dim1d { .. } => 1,
Dimensions::Dim1dArray { array_layers, .. } => array_layers,
Dimensions::Dim2d { .. } => 1,
Dimensions::Dim2dArray { array_layers, .. } => array_layers,
Dimensions::Dim3d { .. } => 1,
Dimensions::Cubemap { .. } => 1,
Dimensions::CubemapArray { array_layers, .. } => array_layers,
}
}
#[inline]
pub fn array_layers_with_cube(&self) -> u32 {
match *self {
Dimensions::Dim1d { .. } => 1,
Dimensions::Dim1dArray { array_layers, .. } => array_layers,
Dimensions::Dim2d { .. } => 1,
Dimensions::Dim2dArray { array_layers, .. } => array_layers,
Dimensions::Dim3d { .. } => 1,
Dimensions::Cubemap { .. } => 6,
Dimensions::CubemapArray { array_layers, .. } => array_layers * 6,
}
}
#[inline]
pub fn to_image_dimensions(&self) -> ImageDimensions {
match *self {
Dimensions::Dim1d { width } => {
ImageDimensions::Dim1d {
width: width,
array_layers: 1,
}
},
Dimensions::Dim1dArray {
width,
array_layers,
} => {
ImageDimensions::Dim1d {
width: width,
array_layers: array_layers,
}
},
Dimensions::Dim2d { width, height } => {
ImageDimensions::Dim2d {
width: width,
height: height,
array_layers: 1,
cubemap_compatible: false,
}
},
Dimensions::Dim2dArray {
width,
height,
array_layers,
} => {
ImageDimensions::Dim2d {
width: width,
height: height,
array_layers: array_layers,
cubemap_compatible: false,
}
},
Dimensions::Dim3d {
width,
height,
depth,
} => {
ImageDimensions::Dim3d {
width: width,
height: height,
depth: depth,
}
},
Dimensions::Cubemap { size } => {
ImageDimensions::Dim2d {
width: size,
height: size,
array_layers: 6,
cubemap_compatible: true,
}
},
Dimensions::CubemapArray { size, array_layers } => {
ImageDimensions::Dim2d {
width: size,
height: size,
array_layers: array_layers * 6,
cubemap_compatible: true,
}
},
}
}
#[inline]
pub fn to_view_type(&self) -> ViewType {
match *self {
Dimensions::Dim1d { .. } => ViewType::Dim1d,
Dimensions::Dim1dArray { .. } => ViewType::Dim1dArray,
Dimensions::Dim2d { .. } => ViewType::Dim2d,
Dimensions::Dim2dArray { .. } => ViewType::Dim2dArray,
Dimensions::Dim3d { .. } => ViewType::Dim3d,
Dimensions::Cubemap { .. } => ViewType::Cubemap,
Dimensions::CubemapArray { .. } => ViewType::CubemapArray,
}
}
#[inline]
pub fn num_texels(&self) -> u32 {
self.width() * self.height() * self.depth() * self.array_layers_with_cube()
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ViewType {
Dim1d,
Dim1dArray,
Dim2d,
Dim2dArray,
Dim3d,
Cubemap,
CubemapArray,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ImageDimensions {
Dim1d { width: u32, array_layers: u32 },
Dim2d {
width: u32,
height: u32,
array_layers: u32,
cubemap_compatible: bool,
},
Dim3d { width: u32, height: u32, depth: u32 },
}
impl ImageDimensions {
#[inline]
pub fn width(&self) -> u32 {
match *self {
ImageDimensions::Dim1d { width, .. } => width,
ImageDimensions::Dim2d { width, .. } => width,
ImageDimensions::Dim3d { width, .. } => width,
}
}
#[inline]
pub fn height(&self) -> u32 {
match *self {
ImageDimensions::Dim1d { .. } => 1,
ImageDimensions::Dim2d { height, .. } => height,
ImageDimensions::Dim3d { height, .. } => height,
}
}
#[inline]
pub fn width_height(&self) -> [u32; 2] {
[self.width(), self.height()]
}
#[inline]
pub fn depth(&self) -> u32 {
match *self {
ImageDimensions::Dim1d { .. } => 1,
ImageDimensions::Dim2d { .. } => 1,
ImageDimensions::Dim3d { depth, .. } => depth,
}
}
#[inline]
pub fn width_height_depth(&self) -> [u32; 3] {
[self.width(), self.height(), self.depth()]
}
#[inline]
pub fn array_layers(&self) -> u32 {
match *self {
ImageDimensions::Dim1d { array_layers, .. } => array_layers,
ImageDimensions::Dim2d { array_layers, .. } => array_layers,
ImageDimensions::Dim3d { .. } => 1,
}
}
#[inline]
pub fn num_texels(&self) -> u32 {
self.width() * self.height() * self.depth() * self.array_layers()
}
pub fn max_mipmaps(&self) -> u32 {
let max_dim = cmp::max(cmp::max(self.width(), self.height()), self.depth());
let num_zeroes = 32 - (max_dim - 1).leading_zeros();
num_zeroes + 1
}
pub fn mipmap_dimensions(&self, level: u32) -> Option<ImageDimensions> {
if level == 0 {
return Some(*self);
}
if level >= self.max_mipmaps() {
return None;
}
Some(match *self {
ImageDimensions::Dim1d {
width,
array_layers,
} => {
debug_assert_ne!(width, 0);
ImageDimensions::Dim1d {
array_layers: array_layers,
width: (((width - 1) >> level) + 1).next_power_of_two(),
}
},
ImageDimensions::Dim2d {
width,
height,
array_layers,
cubemap_compatible,
} => {
debug_assert_ne!(width, 0);
debug_assert_ne!(height, 0);
ImageDimensions::Dim2d {
width: (((width - 1) >> level) + 1).next_power_of_two(),
height: (((height - 1) >> level) + 1).next_power_of_two(),
array_layers: array_layers,
cubemap_compatible: cubemap_compatible,
}
},
ImageDimensions::Dim3d {
width,
height,
depth,
} => {
debug_assert_ne!(width, 0);
debug_assert_ne!(height, 0);
ImageDimensions::Dim3d {
width: (((width - 1) >> level) + 1).next_power_of_two(),
height: (((height - 1) >> level) + 1).next_power_of_two(),
depth: (((depth - 1) >> level) + 1).next_power_of_two(),
}
},
})
}
}
#[cfg(test)]
mod tests {
use image::ImageDimensions;
#[test]
fn max_mipmaps() {
let dims = ImageDimensions::Dim2d {
width: 2,
height: 1,
cubemap_compatible: false,
array_layers: 1,
};
assert_eq!(dims.max_mipmaps(), 2);
let dims = ImageDimensions::Dim2d {
width: 2,
height: 3,
cubemap_compatible: false,
array_layers: 1,
};
assert_eq!(dims.max_mipmaps(), 3);
let dims = ImageDimensions::Dim2d {
width: 512,
height: 512,
cubemap_compatible: false,
array_layers: 1,
};
assert_eq!(dims.max_mipmaps(), 10);
}
#[test]
fn mipmap_dimensions() {
let dims = ImageDimensions::Dim2d {
width: 283,
height: 175,
cubemap_compatible: false,
array_layers: 1,
};
assert_eq!(dims.mipmap_dimensions(0), Some(dims));
assert_eq!(dims.mipmap_dimensions(1),
Some(ImageDimensions::Dim2d {
width: 256,
height: 128,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(2),
Some(ImageDimensions::Dim2d {
width: 128,
height: 64,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(3),
Some(ImageDimensions::Dim2d {
width: 64,
height: 32,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(4),
Some(ImageDimensions::Dim2d {
width: 32,
height: 16,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(5),
Some(ImageDimensions::Dim2d {
width: 16,
height: 8,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(6),
Some(ImageDimensions::Dim2d {
width: 8,
height: 4,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(7),
Some(ImageDimensions::Dim2d {
width: 4,
height: 2,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(8),
Some(ImageDimensions::Dim2d {
width: 2,
height: 1,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(9),
Some(ImageDimensions::Dim2d {
width: 1,
height: 1,
cubemap_compatible: false,
array_layers: 1,
}));
assert_eq!(dims.mipmap_dimensions(10), None);
}
}