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