Skip to main content

wgpu_types/texture/
external_texture.rs

1#[cfg(any(feature = "serde", test))]
2use serde::{Deserialize, Serialize};
3
4#[cfg(doc)]
5use crate::TextureFormat;
6
7pub use nt::ExternalTextureTransferFunction;
8
9/// Format of an `ExternalTexture`. This indicates the number of underlying
10/// planes used by the `ExternalTexture` as well as each plane's format.
11#[repr(C)]
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub enum ExternalTextureFormat {
15    /// Single [`TextureFormat::Rgba8Unorm`] or [`TextureFormat::Bgra8Unorm`] format plane.
16    Rgba,
17    /// [`TextureFormat::R8Unorm`] Y plane, and [`TextureFormat::Rg8Unorm`]
18    /// interleaved CbCr plane.
19    Nv12,
20    /// Separate [`TextureFormat::R8Unorm`] Y, Cb, and Cr planes.
21    Yu12,
22}
23
24/// Describes an [`ExternalTexture`](../wgpu/struct.ExternalTexture.html).
25///
26/// Note that [`width`] and [`height`] are the values that should be returned by
27/// size queries in shader code; they do not necessarily match the dimensions of
28/// the underlying plane texture(s). As a special case, if `(width, height)` is
29/// `(0, 0)`, the actual size of the first underlying plane should be used instead.
30///
31/// The size given by [`width`] and [`height`] must be consistent with
32/// [`sample_transform`]: they should be the size in texels of the rectangle
33/// covered by the square (0,0)..(1,1) after [`sample_transform`] has been applied
34/// to it.
35///
36/// [`width`]: Self::width
37/// [`height`]: Self::height
38/// [`sample_transform`]: Self::sample_transform
39///
40/// Corresponds to [WebGPU `GPUExternalTextureDescriptor`](
41/// https://gpuweb.github.io/gpuweb/#dictdef-gpuexternaltexturedescriptor).
42#[repr(C)]
43#[derive(Clone, Debug, PartialEq)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45pub struct ExternalTextureDescriptor<L> {
46    /// Debug label of the external texture. This will show up in graphics
47    /// debuggers for easy identification.
48    pub label: L,
49
50    /// Width of the external texture.
51    pub width: u32,
52
53    /// Height of the external texture.
54    pub height: u32,
55
56    /// Format of the external texture.
57    pub format: ExternalTextureFormat,
58
59    /// 4x4 column-major matrix with which to convert sampled YCbCr values
60    /// to RGBA.
61    /// This is ignored when `format` is [`ExternalTextureFormat::Rgba`].
62    pub yuv_conversion_matrix: [f32; 16],
63
64    /// 3x3 column-major matrix to transform linear RGB values in the source
65    /// color space to linear RGB values in the destination color space. In
66    /// combination with [`Self::src_transfer_function`] and
67    /// [`Self::dst_transfer_function`] this can be used to ensure that
68    /// [`ImageSample`] and [`ImageLoad`] operations return values in the
69    /// desired destination color space rather than the source color space of
70    /// the underlying planes.
71    ///
72    /// [`ImageSample`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageSample
73    /// [`ImageLoad`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageLoad
74    pub gamut_conversion_matrix: [f32; 9],
75
76    /// Transfer function for the source color space. The *inverse* of this
77    /// will be applied to decode non-linear RGB to linear RGB in the source
78    /// color space.
79    pub src_transfer_function: ExternalTextureTransferFunction,
80
81    /// Transfer function for the destination color space. This will be applied
82    /// to encode linear RGB to non-linear RGB in the destination color space.
83    pub dst_transfer_function: ExternalTextureTransferFunction,
84
85    /// Transform to apply to [`ImageSample`] coordinates.
86    ///
87    /// This is a 3x2 column-major matrix representing an affine transform from
88    /// normalized texture coordinates to the normalized coordinates that should
89    /// be sampled from the external texture's underlying plane(s).
90    ///
91    /// This transform may scale, translate, flip, and rotate in 90-degree
92    /// increments, but the result of transforming the rectangle (0,0)..(1,1)
93    /// must be an axis-aligned rectangle that falls within the bounds of
94    /// (0,0)..(1,1).
95    ///
96    /// [`ImageSample`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageSample
97    pub sample_transform: [f32; 6],
98
99    /// Transform to apply to [`ImageLoad`] coordinates.
100    ///
101    /// This is a 3x2 column-major matrix representing an affine transform from
102    /// non-normalized texel coordinates to the non-normalized coordinates of
103    /// the texel that should be loaded from the external texture's underlying
104    /// plane 0. For planes 1 and 2, if present, plane 0's coordinates are
105    /// scaled according to the textures' relative sizes.
106    ///
107    /// This transform may scale, translate, flip, and rotate in 90-degree
108    /// increments, but the result of transforming the rectangle (0,0)..([`width`],
109    /// [`height`]) must be an axis-aligned rectangle that falls within the bounds
110    /// of (0,0)..([`width`], [`height`]).
111    ///
112    /// [`ImageLoad`]: https://docs.rs/naga/latest/naga/ir/enum.Expression.html#variant.ImageLoad
113    /// [`width`]: Self::width
114    /// [`height`]: Self::height
115    pub load_transform: [f32; 6],
116}
117
118impl<L> ExternalTextureDescriptor<L> {
119    /// Takes a closure and maps the label of the external texture descriptor into another.
120    #[must_use]
121    pub fn map_label<'a, K>(
122        &'a self,
123        fun: impl FnOnce(&'a L) -> K,
124    ) -> ExternalTextureDescriptor<K> {
125        ExternalTextureDescriptor {
126            label: fun(&self.label),
127            width: self.width,
128            height: self.height,
129            format: self.format,
130            yuv_conversion_matrix: self.yuv_conversion_matrix,
131            sample_transform: self.sample_transform,
132            load_transform: self.load_transform,
133            gamut_conversion_matrix: self.gamut_conversion_matrix,
134            src_transfer_function: self.src_transfer_function,
135            dst_transfer_function: self.dst_transfer_function,
136        }
137    }
138
139    /// The number of underlying planes used by the external texture.
140    pub fn num_planes(&self) -> usize {
141        match self.format {
142            ExternalTextureFormat::Rgba => 1,
143            ExternalTextureFormat::Nv12 => 2,
144            ExternalTextureFormat::Yu12 => 3,
145        }
146    }
147}