gfx_core/
format.rs

1// Copyright 2016 The Gfx-rs Developers.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Universal format specification.
16//! Applicable to textures, views, and vertex buffers.
17
18//TODO:
19//  DXT 1-5, BC7
20//  ETC2_RGB, // Use the EXT2 algorithm on 3 components.
21//  ETC2_SRGB, // Use the EXT2 algorithm on 4 components (RGBA) in the sRGB color space.
22//  ETC2_EAC_RGBA8, // Use the EXT2 EAC algorithm on 4 components.
23use memory::Pod;
24
25macro_rules! impl_channel_type {
26    { $($name:ident = $shader_type:ident [ $($imp_trait:ident),* ] ,)* } => {
27        /// Type of a surface channel. This is how we interpret the
28        /// storage allocated with `SurfaceType`.
29        #[allow(missing_docs)]
30        #[repr(u8)]
31        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
32        #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
33        pub enum ChannelType {
34            $( $name, )*
35        }
36        $(
37            #[allow(missing_docs)]
38            #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
39            #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
40            pub enum $name {}
41            impl ChannelTyped for $name {
42                type ShaderType = $shader_type;
43                fn get_channel_type() -> ChannelType {
44                    ChannelType::$name
45                }
46            }
47            $(
48                impl $imp_trait for $name {}
49            )*
50        )*
51    }
52}
53
54impl_channel_type! {
55    Int     = i32 [TextureChannel, RenderChannel],
56    Uint    = u32 [TextureChannel, RenderChannel],
57    Inorm   = f32 [TextureChannel, RenderChannel, BlendChannel],
58    Unorm   = f32 [TextureChannel, RenderChannel, BlendChannel],
59    Float   = f32 [TextureChannel, RenderChannel, BlendChannel],
60    Srgb    = f32 [TextureChannel, RenderChannel, BlendChannel],
61}
62
63macro_rules! impl_formats {
64    { $($name:ident : $container:ident < $($channel:ident),* > = $data_type:ty {$alpha_bits:expr} [ $($imp_trait:ident),* ], doc = $doc:expr ,)* } => {
65        /// Type of the allocated texture surface. It is supposed to only
66        /// carry information about the number of bits per each channel.
67        /// The actual types are up to the views to decide and interpret.
68        /// The actual components are up to the swizzle to define.
69        #[repr(u8)]
70        #[allow(missing_docs, non_camel_case_types)]
71        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
72        #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
73        pub enum SurfaceType {
74            $( #[doc = $doc] $name, )*
75        }
76        impl SurfaceType {
77            /// Return the total number of bits for this format.
78            pub fn get_total_bits(&self) -> u8 {
79                use std::mem::size_of;
80                match *self {
81                    $( SurfaceType::$name => (size_of::<$data_type>() * 8) as u8, )*
82                }
83            }
84            /// Return the number of bits allocated for alpha and stencil.
85            pub fn get_alpha_stencil_bits(&self) -> u8  {
86                match *self {
87                    $( SurfaceType::$name => $alpha_bits, )*
88                }
89            }
90        }
91        $(
92            #[allow(missing_docs, non_camel_case_types)]
93            #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
94            #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
95            #[doc = $doc]
96            pub enum $name {}
97            impl SurfaceTyped for $name {
98                type DataType = $data_type;
99                fn get_surface_type() -> SurfaceType {
100                    SurfaceType::$name
101                }
102            }
103            $(
104                impl $imp_trait for $name {}
105            )*
106            $(
107                impl Formatted for ($name, $channel) {
108                    type Surface = $name;
109                    type Channel = $channel;
110                    type View = $container< <$channel as ChannelTyped>::ShaderType >;
111                }
112            )*
113        )*
114    }
115}
116
117
118impl_formats! {
119    R4_G4           : Vec2<Unorm> = u8 {0}  [TextureSurface, RenderSurface], doc = "",
120    R4_G4_B4_A4     : Vec4<Unorm> = u16 {4} [TextureSurface, RenderSurface], doc = "",
121    R5_G5_B5_A1     : Vec4<Unorm> = u16 {1} [TextureSurface, RenderSurface], doc = "",
122    R5_G6_B5        : Vec3<Unorm> = u16 {0} [TextureSurface, RenderSurface], doc = "",
123    R8              : Vec1<Int, Uint, Inorm, Unorm> = u8 {0}
124        [BufferSurface, TextureSurface, RenderSurface], doc = "",
125    R8_G8           : Vec2<Int, Uint, Inorm, Unorm> = [u8; 2] {0}
126        [BufferSurface, TextureSurface, RenderSurface], doc = "",
127    R8_G8_B8_A8     : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 4] {8}
128        [BufferSurface, TextureSurface, RenderSurface], doc = "",
129    R10_G10_B10_A2  : Vec4<Uint, Unorm> = u32 {2}
130        [BufferSurface, TextureSurface, RenderSurface], doc = "",
131    R11_G11_B10     : Vec4<Unorm, Float> = u32 {0}
132        [BufferSurface, TextureSurface, RenderSurface], doc = "",
133    R16             : Vec1<Int, Uint, Inorm, Unorm, Float> = u16 {0}
134        [BufferSurface, TextureSurface, RenderSurface], doc = "",
135    R16_G16         : Vec2<Int, Uint, Inorm, Unorm, Float> = [u16; 2] {0}
136        [BufferSurface, TextureSurface, RenderSurface], doc = "",
137    R16_G16_B16     : Vec3<Int, Uint, Inorm, Unorm, Float> = [u16; 3] {0}
138        [BufferSurface, TextureSurface, RenderSurface], doc = "",
139    R16_G16_B16_A16 : Vec4<Int, Uint, Inorm, Unorm, Float> = [u16; 4] {16}
140        [BufferSurface, TextureSurface, RenderSurface], doc = "",
141    R32             : Vec1<Int, Uint, Float> = u32 {0}
142        [BufferSurface, TextureSurface, RenderSurface], doc = "",
143    R32_G32         : Vec2<Int, Uint, Float> = [u32; 2] {0}
144        [BufferSurface, TextureSurface, RenderSurface], doc = "",
145    R32_G32_B32     : Vec3<Int, Uint, Float> = [u32; 3] {0}
146        [BufferSurface, TextureSurface, RenderSurface], doc = "",
147    R32_G32_B32_A32 : Vec4<Int, Uint, Float> = [u32; 4] {32}
148        [BufferSurface, TextureSurface, RenderSurface], doc = "",
149    B8_G8_R8_A8     : Vec4<Unorm, Srgb> = [u8; 4] {32}
150        [BufferSurface, TextureSurface, RenderSurface], doc = "",
151    D16             : Vec1<Unorm> = F16 {0} [TextureSurface, DepthSurface], doc = "",
152    D24             : Vec1<Unorm> = f32 {8} [TextureSurface, DepthSurface], doc = "", //hacky stencil bits
153    D24_S8          : Vec1<Unorm, Uint> = u32 {8} [TextureSurface, DepthSurface, StencilSurface], doc = "",
154    D32             : Vec1<Float> = f32 {0} [TextureSurface, DepthSurface], doc = "",
155    //D32_S8          : Vec1<Unorm, Float, Uint> = (f32, u32) {32} [TextureSurface, DepthSurface, StencilSurface],
156
157    BC1_R8_G8_B8   : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 3] {0} [TextureSurface],
158        doc = "Block Compression 1 also known as DXT1, S3TC. See \
159               [S3TC wiki](https://wikipedia.org/wiki/S3_Texture_Compression).\
160               \n\nCurrently supported in the gfx_device_gl backend only.",
161    BC3_R8_G8_B8_A8 : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 4] {8} [TextureSurface],
162        doc = "Block Compression 3 also known as DXT5, S3TC. See \
163               [S3TC wiki](https://wikipedia.org/wiki/S3_Texture_Compression).\
164               \n\nCurrently supported in the gfx_device_gl backend only.",
165}
166
167
168/// Source channel in a swizzle configuration. Some may redirect onto
169/// different physical channels, some may be hardcoded to 0 or 1.
170#[allow(missing_docs)]
171#[repr(u8)]
172#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
173#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
174pub enum ChannelSource {
175    Zero,
176    One,
177    X,
178    Y,
179    Z,
180    W,
181}
182
183/// Channel swizzle configuration for the resource views.
184/// Note: It's not currently mirrored at compile-time,
185/// thus providing less safety and convenience.
186#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
187#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
188pub struct Swizzle(pub ChannelSource, pub ChannelSource, pub ChannelSource, pub ChannelSource);
189
190impl Swizzle {
191    /// Create a new swizzle where each channel is unmapped.
192    pub fn new() -> Swizzle {
193        Swizzle(ChannelSource::X, ChannelSource::Y, ChannelSource::Z, ChannelSource::W)
194    }
195}
196
197/// Complete run-time surface format.
198#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
199#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
200pub struct Format(pub SurfaceType, pub ChannelType);
201
202/// Compile-time surface type trait.
203pub trait SurfaceTyped {
204    /// The corresponding data type to be passed from CPU.
205    type DataType: Pod;
206    /// Return the run-time value of the type.
207    fn get_surface_type() -> SurfaceType;
208}
209/// An ability of a surface type to be used for vertex buffers.
210pub trait BufferSurface: SurfaceTyped {}
211/// An ability of a surface type to be used for textures.
212pub trait TextureSurface: SurfaceTyped {}
213/// An ability of a surface type to be used for render targets.
214pub trait RenderSurface: SurfaceTyped {}
215/// An ability of a surface type to be used for depth targets.
216pub trait DepthSurface: SurfaceTyped {}
217/// An ability of a surface type to be used for stencil targets.
218pub trait StencilSurface: SurfaceTyped {}
219
220/// Compile-time channel type trait.
221pub trait ChannelTyped {
222    /// Shader-visible type that corresponds to this channel.
223    /// For example, normalized integers are visible as floats.
224    type ShaderType;
225    /// Return the run-time value of the type.
226    fn get_channel_type() -> ChannelType;
227}
228/// An ability of a channel type to be used for textures.
229pub trait TextureChannel: ChannelTyped {}
230/// An ability of a channel type to be used for render targets.
231pub trait RenderChannel: ChannelTyped {}
232/// An ability of a channel type to be used for blended render targets.
233pub trait BlendChannel: RenderChannel {}
234
235/// Compile-time full format trait.
236pub trait Formatted {
237    /// Associated surface type.
238    type Surface: SurfaceTyped;
239    /// Associated channel type.
240    type Channel: ChannelTyped;
241    /// Shader view type of this format.
242    type View;
243    /// Return the run-time value of the type.
244    fn get_format() -> Format {
245        Format(
246            Self::Surface::get_surface_type(),
247            Self::Channel::get_channel_type())
248    }
249}
250/// Ability to be used for vertex buffers.
251pub trait BufferFormat: Formatted {}
252/// Ability to be used for depth targets.
253pub trait DepthFormat: Formatted {}
254/// Ability to be used for vertex buffers.
255pub trait StencilFormat: Formatted {}
256/// Ability to be used for depth+stencil targets.
257pub trait DepthStencilFormat: DepthFormat + StencilFormat {}
258/// Ability to be used for textures.
259pub trait TextureFormat: Formatted {}
260/// Ability to be used for render targets.
261pub trait RenderFormat: Formatted {}
262/// Ability to be used for blended render targets.
263pub trait BlendFormat: RenderFormat {}
264
265impl<F> BufferFormat for F where
266    F: Formatted,
267    F::Surface: BufferSurface,
268    F::Channel: ChannelTyped,
269{}
270impl<F> DepthFormat for F where
271    F: Formatted,
272    F::Surface: DepthSurface,
273    F::Channel: RenderChannel,
274{}
275impl<F> StencilFormat for F where
276    F: Formatted,
277    F::Surface: StencilSurface,
278    F::Channel: RenderChannel,
279{}
280impl<F> DepthStencilFormat for F where
281    F: DepthFormat + StencilFormat
282{}
283impl<F> TextureFormat for F where
284    F: Formatted,
285    F::Surface: TextureSurface,
286    F::Channel: TextureChannel,
287{}
288impl<F> RenderFormat for F where
289    F: Formatted,
290    F::Surface: RenderSurface,
291    F::Channel: RenderChannel,
292{}
293impl<F> BlendFormat for F where
294    F: Formatted,
295    F::Surface: RenderSurface,
296    F::Channel: BlendChannel,
297{}
298
299macro_rules! alias {
300    { $( $name:ident = $ty:ty, )* } => {
301        $(
302            #[allow(missing_docs)]
303            #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
304            #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
305            pub struct $name(pub $ty);
306            impl From<$ty> for $name {
307                fn from(v: $ty) -> $name {
308                    $name(v)
309                }
310            }
311
312            unsafe impl Pod for $name {}
313
314            impl $name {
315                /// Convert a 2-element slice.
316                pub fn cast2(v: [$ty; 2]) -> [$name; 2] {
317                    [$name(v[0]), $name(v[1])]
318                }
319                /// Convert a 3-element slice.
320                pub fn cast3(v: [$ty; 3]) -> [$name; 3] {
321                    [$name(v[0]), $name(v[1]), $name(v[2])]
322                }
323                /// Convert a 4-element slice.
324                pub fn cast4(v: [$ty; 4]) -> [$name; 4] {
325                    [$name(v[0]), $name(v[1]), $name(v[2]), $name(v[3])]
326                }
327                /// Convert a generic slice by transmutation.
328                pub fn cast_slice(slice: &[$ty]) -> &[$name] {
329                    use std::mem::transmute;
330                    unsafe { transmute(slice) }
331                }
332            }
333        )*
334    }
335}
336
337alias! {
338    U8Norm = u8,
339    I8Norm = i8,
340    U16Norm = u16,
341    I16Norm = i16,
342    F16 = u16, // half-float
343}
344
345/// Abstracted 1-element container for macro internal use
346pub type Vec1<T> = T;
347/// Abstracted 2-element container for macro internal use
348pub type Vec2<T> = [T; 2];
349/// Abstracted 3-element container for macro internal use
350pub type Vec3<T> = [T; 3];
351/// Abstracted 4-element container for macro internal use
352pub type Vec4<T> = [T; 4];
353
354/// Standard 8bits RGBA format.
355pub type Rgba8 = (R8_G8_B8_A8, Unorm);
356/// Standard 8bit gamma transforming RGB format.
357pub type Srgba8 = (R8_G8_B8_A8, Srgb);
358/// Standard HDR floating-point format with 10 bits for RGB components
359/// and 2 bits for the alpha.
360pub type Rgb10a2F = (R10_G10_B10_A2, Float);
361/// Standard 16-bit floating-point RGBA format.
362pub type Rgba16F = (R16_G16_B16_A16, Float);
363/// Standard 32-bit floating-point RGBA format.
364pub type Rgba32F = (R32_G32_B32_A32, Float);
365/// Standard 8bits BGRA format.
366pub type Bgra8 = (B8_G8_R8_A8, Unorm);
367/// Standard 24-bit depth format.
368pub type Depth = (D24, Unorm);
369/// Standard 24-bit depth format with 8-bit stencil.
370pub type DepthStencil = (D24_S8, Unorm);
371/// Standard 32-bit floating-point depth format.
372pub type Depth32F = (D32, Float);
373
374macro_rules! impl_simple_formats {
375    { $( $container:ident< $ty:ty > = $channel:ident $surface:ident, )* } => {
376        $(
377            impl Formatted for $container<$ty> {
378                type Surface = $surface;
379                type Channel = $channel;
380                type View = $container<<$channel as ChannelTyped>::ShaderType>;
381            }
382        )*
383    }
384}
385
386macro_rules! impl_formats_8bit {
387    { $( $ty:ty = $channel:ident, )* } => {
388        impl_simple_formats! {$(
389            Vec1<$ty> = $channel R8,
390            Vec2<$ty> = $channel R8_G8,
391            Vec4<$ty> = $channel R8_G8_B8_A8,
392        )*}
393    }
394}
395
396macro_rules! impl_formats_16bit {
397    { $( $ty:ty = $channel:ident, )* } => {
398        impl_simple_formats! {$(
399            Vec1<$ty> = $channel R16,
400            Vec2<$ty> = $channel R16_G16,
401            Vec3<$ty> = $channel R16_G16_B16,
402            Vec4<$ty> = $channel R16_G16_B16_A16,
403        )*}
404    }
405}
406
407macro_rules! impl_formats_32bit {
408    { $( $ty:ty = $channel:ident, )* } => {
409        impl_simple_formats! {$(
410            Vec1<$ty> = $channel R32,
411            Vec2<$ty> = $channel R32_G32,
412            Vec3<$ty> = $channel R32_G32_B32,
413            Vec4<$ty> = $channel R32_G32_B32_A32,
414        )*}
415    }
416}
417
418impl_formats_8bit! {
419    u8 = Uint,
420    i8 = Int,
421    U8Norm = Unorm,
422    I8Norm = Inorm,
423}
424
425impl_formats_16bit! {
426    u16 = Uint,
427    i16 = Int,
428    U16Norm = Unorm,
429    I16Norm = Inorm,
430    F16 = Float,
431}
432
433impl_formats_32bit! {
434    u32 = Uint,
435    i32 = Int,
436    f32 = Float,
437}