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}