wgpu_hal/gles/
conv.rs

1impl super::AdapterShared {
2    pub(super) fn describe_texture_format(
3        &self,
4        texture_format: wgt::TextureFormat,
5    ) -> super::TextureFormatDesc {
6        use wgt::TextureFormat as Tf;
7        use wgt::{AstcBlock, AstcChannel};
8
9        let (internal, external, data_type) = match texture_format {
10            Tf::R8Unorm => (glow::R8, glow::RED, glow::UNSIGNED_BYTE),
11            Tf::R8Snorm => (glow::R8_SNORM, glow::RED, glow::BYTE),
12            Tf::R8Uint => (glow::R8UI, glow::RED_INTEGER, glow::UNSIGNED_BYTE),
13            Tf::R8Sint => (glow::R8I, glow::RED_INTEGER, glow::BYTE),
14            Tf::R16Uint => (glow::R16UI, glow::RED_INTEGER, glow::UNSIGNED_SHORT),
15            Tf::R16Sint => (glow::R16I, glow::RED_INTEGER, glow::SHORT),
16            Tf::R16Unorm => (glow::R16, glow::RED, glow::UNSIGNED_SHORT),
17            Tf::R16Snorm => (glow::R16_SNORM, glow::RED, glow::SHORT),
18            Tf::R16Float => (glow::R16F, glow::RED, glow::HALF_FLOAT),
19            Tf::Rg8Unorm => (glow::RG8, glow::RG, glow::UNSIGNED_BYTE),
20            Tf::Rg8Snorm => (glow::RG8_SNORM, glow::RG, glow::BYTE),
21            Tf::Rg8Uint => (glow::RG8UI, glow::RG_INTEGER, glow::UNSIGNED_BYTE),
22            Tf::Rg8Sint => (glow::RG8I, glow::RG_INTEGER, glow::BYTE),
23            Tf::R32Uint => (glow::R32UI, glow::RED_INTEGER, glow::UNSIGNED_INT),
24            Tf::R32Sint => (glow::R32I, glow::RED_INTEGER, glow::INT),
25            Tf::R32Float => (glow::R32F, glow::RED, glow::FLOAT),
26            Tf::Rg16Uint => (glow::RG16UI, glow::RG_INTEGER, glow::UNSIGNED_SHORT),
27            Tf::Rg16Sint => (glow::RG16I, glow::RG_INTEGER, glow::SHORT),
28            Tf::Rg16Unorm => (glow::RG16, glow::RG, glow::UNSIGNED_SHORT),
29            Tf::Rg16Snorm => (glow::RG16_SNORM, glow::RG, glow::SHORT),
30            Tf::Rg16Float => (glow::RG16F, glow::RG, glow::HALF_FLOAT),
31            Tf::Rgba8Unorm => (glow::RGBA8, glow::RGBA, glow::UNSIGNED_BYTE),
32            Tf::Rgba8UnormSrgb => (glow::SRGB8_ALPHA8, glow::RGBA, glow::UNSIGNED_BYTE),
33            Tf::Bgra8UnormSrgb => (glow::SRGB8_ALPHA8, glow::BGRA, glow::UNSIGNED_BYTE), //TODO?
34            Tf::Rgba8Snorm => (glow::RGBA8_SNORM, glow::RGBA, glow::BYTE),
35            Tf::Bgra8Unorm => (glow::RGBA8, glow::BGRA, glow::UNSIGNED_BYTE), //TODO?
36            Tf::Rgba8Uint => (glow::RGBA8UI, glow::RGBA_INTEGER, glow::UNSIGNED_BYTE),
37            Tf::Rgba8Sint => (glow::RGBA8I, glow::RGBA_INTEGER, glow::BYTE),
38            Tf::Rgb10a2Uint => (
39                glow::RGB10_A2UI,
40                glow::RGBA_INTEGER,
41                glow::UNSIGNED_INT_2_10_10_10_REV,
42            ),
43            Tf::Rgb10a2Unorm => (
44                glow::RGB10_A2,
45                glow::RGBA,
46                glow::UNSIGNED_INT_2_10_10_10_REV,
47            ),
48            Tf::Rg11b10Ufloat => (
49                glow::R11F_G11F_B10F,
50                glow::RGB,
51                glow::UNSIGNED_INT_10F_11F_11F_REV,
52            ),
53            Tf::R64Uint => (glow::RG32UI, glow::RED_INTEGER, glow::UNSIGNED_INT),
54            Tf::Rg32Uint => (glow::RG32UI, glow::RG_INTEGER, glow::UNSIGNED_INT),
55            Tf::Rg32Sint => (glow::RG32I, glow::RG_INTEGER, glow::INT),
56            Tf::Rg32Float => (glow::RG32F, glow::RG, glow::FLOAT),
57            Tf::Rgba16Uint => (glow::RGBA16UI, glow::RGBA_INTEGER, glow::UNSIGNED_SHORT),
58            Tf::Rgba16Sint => (glow::RGBA16I, glow::RGBA_INTEGER, glow::SHORT),
59            Tf::Rgba16Unorm => (glow::RGBA16, glow::RGBA, glow::UNSIGNED_SHORT),
60            Tf::Rgba16Snorm => (glow::RGBA16_SNORM, glow::RGBA, glow::SHORT),
61            Tf::Rgba16Float => (glow::RGBA16F, glow::RGBA, glow::HALF_FLOAT),
62            Tf::Rgba32Uint => (glow::RGBA32UI, glow::RGBA_INTEGER, glow::UNSIGNED_INT),
63            Tf::Rgba32Sint => (glow::RGBA32I, glow::RGBA_INTEGER, glow::INT),
64            Tf::Rgba32Float => (glow::RGBA32F, glow::RGBA, glow::FLOAT),
65            Tf::Stencil8 => (
66                glow::STENCIL_INDEX8,
67                glow::STENCIL_INDEX,
68                glow::UNSIGNED_BYTE,
69            ),
70            Tf::Depth16Unorm => (
71                glow::DEPTH_COMPONENT16,
72                glow::DEPTH_COMPONENT,
73                glow::UNSIGNED_SHORT,
74            ),
75            Tf::Depth32Float => (glow::DEPTH_COMPONENT32F, glow::DEPTH_COMPONENT, glow::FLOAT),
76            Tf::Depth32FloatStencil8 => (
77                glow::DEPTH32F_STENCIL8,
78                glow::DEPTH_STENCIL,
79                glow::FLOAT_32_UNSIGNED_INT_24_8_REV,
80            ),
81            Tf::Depth24Plus => (
82                glow::DEPTH_COMPONENT24,
83                glow::DEPTH_COMPONENT,
84                glow::UNSIGNED_INT,
85            ),
86            Tf::Depth24PlusStencil8 => (
87                glow::DEPTH24_STENCIL8,
88                glow::DEPTH_STENCIL,
89                glow::UNSIGNED_INT_24_8,
90            ),
91            Tf::NV12 => unreachable!(),
92            Tf::P010 => unreachable!(),
93            Tf::Rgb9e5Ufloat => (glow::RGB9_E5, glow::RGB, glow::UNSIGNED_INT_5_9_9_9_REV),
94            Tf::Bc1RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT1_EXT, glow::RGBA, 0),
95            Tf::Bc1RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, glow::RGBA, 0),
96            Tf::Bc2RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT3_EXT, glow::RGBA, 0),
97            Tf::Bc2RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, glow::RGBA, 0),
98            Tf::Bc3RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT5_EXT, glow::RGBA, 0),
99            Tf::Bc3RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, glow::RGBA, 0),
100            Tf::Bc4RUnorm => (glow::COMPRESSED_RED_RGTC1, glow::RED, 0),
101            Tf::Bc4RSnorm => (glow::COMPRESSED_SIGNED_RED_RGTC1, glow::RED, 0),
102            Tf::Bc5RgUnorm => (glow::COMPRESSED_RG_RGTC2, glow::RG, 0),
103            Tf::Bc5RgSnorm => (glow::COMPRESSED_SIGNED_RG_RGTC2, glow::RG, 0),
104            Tf::Bc6hRgbUfloat => (glow::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, glow::RGB, 0),
105            Tf::Bc6hRgbFloat => (glow::COMPRESSED_RGB_BPTC_SIGNED_FLOAT, glow::RGB, 0),
106            Tf::Bc7RgbaUnorm => (glow::COMPRESSED_RGBA_BPTC_UNORM, glow::RGBA, 0),
107            Tf::Bc7RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, glow::RGBA, 0),
108            Tf::Etc2Rgb8Unorm => (glow::COMPRESSED_RGB8_ETC2, glow::RGB, 0),
109            Tf::Etc2Rgb8UnormSrgb => (glow::COMPRESSED_SRGB8_ETC2, glow::RGB, 0),
110            Tf::Etc2Rgb8A1Unorm => (
111                glow::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
112                glow::RGBA,
113                0,
114            ),
115            Tf::Etc2Rgb8A1UnormSrgb => (
116                glow::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
117                glow::RGBA,
118                0,
119            ),
120            Tf::Etc2Rgba8Unorm => (glow::COMPRESSED_RGBA8_ETC2_EAC, glow::RGBA, 0),
121            Tf::Etc2Rgba8UnormSrgb => (glow::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, glow::RGBA, 0),
122            Tf::EacR11Unorm => (glow::COMPRESSED_R11_EAC, glow::RED, 0),
123            Tf::EacR11Snorm => (glow::COMPRESSED_SIGNED_R11_EAC, glow::RED, 0),
124            Tf::EacRg11Unorm => (glow::COMPRESSED_RG11_EAC, glow::RG, 0),
125            Tf::EacRg11Snorm => (glow::COMPRESSED_SIGNED_RG11_EAC, glow::RG, 0),
126            Tf::Astc { block, channel } => match channel {
127                AstcChannel::Unorm | AstcChannel::Hdr => match block {
128                    AstcBlock::B4x4 => (glow::COMPRESSED_RGBA_ASTC_4x4_KHR, glow::RGBA, 0),
129                    AstcBlock::B5x4 => (glow::COMPRESSED_RGBA_ASTC_5x4_KHR, glow::RGBA, 0),
130                    AstcBlock::B5x5 => (glow::COMPRESSED_RGBA_ASTC_5x5_KHR, glow::RGBA, 0),
131                    AstcBlock::B6x5 => (glow::COMPRESSED_RGBA_ASTC_6x5_KHR, glow::RGBA, 0),
132                    AstcBlock::B6x6 => (glow::COMPRESSED_RGBA_ASTC_6x6_KHR, glow::RGBA, 0),
133                    AstcBlock::B8x5 => (glow::COMPRESSED_RGBA_ASTC_8x5_KHR, glow::RGBA, 0),
134                    AstcBlock::B8x6 => (glow::COMPRESSED_RGBA_ASTC_8x6_KHR, glow::RGBA, 0),
135                    AstcBlock::B8x8 => (glow::COMPRESSED_RGBA_ASTC_8x8_KHR, glow::RGBA, 0),
136                    AstcBlock::B10x5 => (glow::COMPRESSED_RGBA_ASTC_10x5_KHR, glow::RGBA, 0),
137                    AstcBlock::B10x6 => (glow::COMPRESSED_RGBA_ASTC_10x6_KHR, glow::RGBA, 0),
138                    AstcBlock::B10x8 => (glow::COMPRESSED_RGBA_ASTC_10x8_KHR, glow::RGBA, 0),
139                    AstcBlock::B10x10 => (glow::COMPRESSED_RGBA_ASTC_10x10_KHR, glow::RGBA, 0),
140                    AstcBlock::B12x10 => (glow::COMPRESSED_RGBA_ASTC_12x10_KHR, glow::RGBA, 0),
141                    AstcBlock::B12x12 => (glow::COMPRESSED_RGBA_ASTC_12x12_KHR, glow::RGBA, 0),
142                },
143                AstcChannel::UnormSrgb => match block {
144                    AstcBlock::B4x4 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, glow::RGBA, 0),
145                    AstcBlock::B5x4 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, glow::RGBA, 0),
146                    AstcBlock::B5x5 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, glow::RGBA, 0),
147                    AstcBlock::B6x5 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, glow::RGBA, 0),
148                    AstcBlock::B6x6 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, glow::RGBA, 0),
149                    AstcBlock::B8x5 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, glow::RGBA, 0),
150                    AstcBlock::B8x6 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, glow::RGBA, 0),
151                    AstcBlock::B8x8 => (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, glow::RGBA, 0),
152                    AstcBlock::B10x5 => {
153                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, glow::RGBA, 0)
154                    }
155                    AstcBlock::B10x6 => {
156                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, glow::RGBA, 0)
157                    }
158                    AstcBlock::B10x8 => {
159                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, glow::RGBA, 0)
160                    }
161                    AstcBlock::B10x10 => {
162                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, glow::RGBA, 0)
163                    }
164                    AstcBlock::B12x10 => {
165                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, glow::RGBA, 0)
166                    }
167                    AstcBlock::B12x12 => {
168                        (glow::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, glow::RGBA, 0)
169                    }
170                },
171            },
172        };
173
174        super::TextureFormatDesc {
175            internal,
176            external,
177            data_type,
178        }
179    }
180}
181
182pub(super) fn describe_vertex_format(vertex_format: wgt::VertexFormat) -> super::VertexFormatDesc {
183    use super::VertexAttribKind as Vak;
184    use wgt::VertexFormat as Vf;
185
186    let (element_count, element_format, attrib_kind) = match vertex_format {
187        Vf::Unorm8 => (1, glow::UNSIGNED_BYTE, Vak::Float),
188        Vf::Snorm8 => (1, glow::BYTE, Vak::Float),
189        Vf::Uint8 => (1, glow::UNSIGNED_BYTE, Vak::Integer),
190        Vf::Sint8 => (1, glow::BYTE, Vak::Integer),
191        Vf::Unorm8x2 => (2, glow::UNSIGNED_BYTE, Vak::Float),
192        Vf::Snorm8x2 => (2, glow::BYTE, Vak::Float),
193        Vf::Uint8x2 => (2, glow::UNSIGNED_BYTE, Vak::Integer),
194        Vf::Sint8x2 => (2, glow::BYTE, Vak::Integer),
195        Vf::Unorm8x4 => (4, glow::UNSIGNED_BYTE, Vak::Float),
196        Vf::Snorm8x4 => (4, glow::BYTE, Vak::Float),
197        Vf::Uint8x4 => (4, glow::UNSIGNED_BYTE, Vak::Integer),
198        Vf::Sint8x4 => (4, glow::BYTE, Vak::Integer),
199        Vf::Unorm16 => (1, glow::UNSIGNED_SHORT, Vak::Float),
200        Vf::Snorm16 => (1, glow::SHORT, Vak::Float),
201        Vf::Uint16 => (1, glow::UNSIGNED_SHORT, Vak::Integer),
202        Vf::Sint16 => (1, glow::SHORT, Vak::Integer),
203        Vf::Float16 => (1, glow::HALF_FLOAT, Vak::Float),
204        Vf::Unorm16x2 => (2, glow::UNSIGNED_SHORT, Vak::Float),
205        Vf::Snorm16x2 => (2, glow::SHORT, Vak::Float),
206        Vf::Uint16x2 => (2, glow::UNSIGNED_SHORT, Vak::Integer),
207        Vf::Sint16x2 => (2, glow::SHORT, Vak::Integer),
208        Vf::Float16x2 => (2, glow::HALF_FLOAT, Vak::Float),
209        Vf::Unorm16x4 => (4, glow::UNSIGNED_SHORT, Vak::Float),
210        Vf::Snorm16x4 => (4, glow::SHORT, Vak::Float),
211        Vf::Uint16x4 => (4, glow::UNSIGNED_SHORT, Vak::Integer),
212        Vf::Sint16x4 => (4, glow::SHORT, Vak::Integer),
213        Vf::Float16x4 => (4, glow::HALF_FLOAT, Vak::Float),
214        Vf::Uint32 => (1, glow::UNSIGNED_INT, Vak::Integer),
215        Vf::Sint32 => (1, glow::INT, Vak::Integer),
216        Vf::Float32 => (1, glow::FLOAT, Vak::Float),
217        Vf::Uint32x2 => (2, glow::UNSIGNED_INT, Vak::Integer),
218        Vf::Sint32x2 => (2, glow::INT, Vak::Integer),
219        Vf::Float32x2 => (2, glow::FLOAT, Vak::Float),
220        Vf::Uint32x3 => (3, glow::UNSIGNED_INT, Vak::Integer),
221        Vf::Sint32x3 => (3, glow::INT, Vak::Integer),
222        Vf::Float32x3 => (3, glow::FLOAT, Vak::Float),
223        Vf::Uint32x4 => (4, glow::UNSIGNED_INT, Vak::Integer),
224        Vf::Sint32x4 => (4, glow::INT, Vak::Integer),
225        Vf::Float32x4 => (4, glow::FLOAT, Vak::Float),
226        Vf::Unorm10_10_10_2 => (4, glow::UNSIGNED_INT_10_10_10_2, Vak::Float),
227        Vf::Unorm8x4Bgra => (glow::BGRA as i32, glow::UNSIGNED_BYTE, Vak::Float),
228        Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(),
229    };
230
231    super::VertexFormatDesc {
232        element_count,
233        element_format,
234        attrib_kind,
235    }
236}
237
238pub fn map_filter_modes(
239    min: wgt::FilterMode,
240    mag: wgt::FilterMode,
241    mip: wgt::FilterMode,
242) -> (u32, u32) {
243    use wgt::FilterMode as Fm;
244
245    let mag_filter = match mag {
246        Fm::Nearest => glow::NEAREST,
247        Fm::Linear => glow::LINEAR,
248    };
249
250    let min_filter = match (min, mip) {
251        (Fm::Nearest, Fm::Nearest) => glow::NEAREST_MIPMAP_NEAREST,
252        (Fm::Nearest, Fm::Linear) => glow::NEAREST_MIPMAP_LINEAR,
253        (Fm::Linear, Fm::Nearest) => glow::LINEAR_MIPMAP_NEAREST,
254        (Fm::Linear, Fm::Linear) => glow::LINEAR_MIPMAP_LINEAR,
255    };
256
257    (min_filter, mag_filter)
258}
259
260pub fn map_address_mode(mode: wgt::AddressMode) -> u32 {
261    match mode {
262        wgt::AddressMode::Repeat => glow::REPEAT,
263        wgt::AddressMode::MirrorRepeat => glow::MIRRORED_REPEAT,
264        wgt::AddressMode::ClampToEdge => glow::CLAMP_TO_EDGE,
265        wgt::AddressMode::ClampToBorder => glow::CLAMP_TO_BORDER,
266        //wgt::AddressMode::MirrorClamp => glow::MIRROR_CLAMP_TO_EDGE,
267    }
268}
269
270pub fn map_compare_func(fun: wgt::CompareFunction) -> u32 {
271    use wgt::CompareFunction as Cf;
272    match fun {
273        Cf::Never => glow::NEVER,
274        Cf::Less => glow::LESS,
275        Cf::LessEqual => glow::LEQUAL,
276        Cf::Equal => glow::EQUAL,
277        Cf::GreaterEqual => glow::GEQUAL,
278        Cf::Greater => glow::GREATER,
279        Cf::NotEqual => glow::NOTEQUAL,
280        Cf::Always => glow::ALWAYS,
281    }
282}
283
284pub fn map_primitive_topology(topology: wgt::PrimitiveTopology) -> u32 {
285    use wgt::PrimitiveTopology as Pt;
286    match topology {
287        Pt::PointList => glow::POINTS,
288        Pt::LineList => glow::LINES,
289        Pt::LineStrip => glow::LINE_STRIP,
290        Pt::TriangleList => glow::TRIANGLES,
291        Pt::TriangleStrip => glow::TRIANGLE_STRIP,
292    }
293}
294
295pub(super) fn map_primitive_state(state: &wgt::PrimitiveState) -> super::PrimitiveState {
296    super::PrimitiveState {
297        //Note: we are flipping the front face, so that
298        // the Y-flip in the generated GLSL keeps the same visibility.
299        // See `naga::back::glsl::WriterFlags::ADJUST_COORDINATE_SPACE`.
300        front_face: match state.front_face {
301            wgt::FrontFace::Cw => glow::CCW,
302            wgt::FrontFace::Ccw => glow::CW,
303        },
304        cull_face: match state.cull_mode {
305            Some(wgt::Face::Front) => glow::FRONT,
306            Some(wgt::Face::Back) => glow::BACK,
307            None => 0,
308        },
309        unclipped_depth: state.unclipped_depth,
310        polygon_mode: match state.polygon_mode {
311            wgt::PolygonMode::Fill => glow::FILL,
312            wgt::PolygonMode::Line => glow::LINE,
313            wgt::PolygonMode::Point => glow::POINT,
314        },
315    }
316}
317
318pub fn _map_view_dimension(dim: wgt::TextureViewDimension) -> u32 {
319    use wgt::TextureViewDimension as Tvd;
320    match dim {
321        Tvd::D1 | Tvd::D2 => glow::TEXTURE_2D,
322        Tvd::D2Array => glow::TEXTURE_2D_ARRAY,
323        Tvd::Cube => glow::TEXTURE_CUBE_MAP,
324        Tvd::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
325        Tvd::D3 => glow::TEXTURE_3D,
326    }
327}
328
329fn map_stencil_op(operation: wgt::StencilOperation) -> u32 {
330    use wgt::StencilOperation as So;
331    match operation {
332        So::Keep => glow::KEEP,
333        So::Zero => glow::ZERO,
334        So::Replace => glow::REPLACE,
335        So::Invert => glow::INVERT,
336        So::IncrementClamp => glow::INCR,
337        So::DecrementClamp => glow::DECR,
338        So::IncrementWrap => glow::INCR_WRAP,
339        So::DecrementWrap => glow::DECR_WRAP,
340    }
341}
342
343fn map_stencil_ops(face: &wgt::StencilFaceState) -> super::StencilOps {
344    super::StencilOps {
345        pass: map_stencil_op(face.pass_op),
346        fail: map_stencil_op(face.fail_op),
347        depth_fail: map_stencil_op(face.depth_fail_op),
348    }
349}
350
351pub(super) fn map_stencil(state: &wgt::StencilState) -> super::StencilState {
352    super::StencilState {
353        front: super::StencilSide {
354            function: map_compare_func(state.front.compare),
355            mask_read: state.read_mask,
356            mask_write: state.write_mask,
357            reference: 0,
358            ops: map_stencil_ops(&state.front),
359        },
360        back: super::StencilSide {
361            function: map_compare_func(state.back.compare),
362            mask_read: state.read_mask,
363            mask_write: state.write_mask,
364            reference: 0,
365            ops: map_stencil_ops(&state.back),
366        },
367    }
368}
369
370fn map_blend_factor(factor: wgt::BlendFactor) -> u32 {
371    use wgt::BlendFactor as Bf;
372    match factor {
373        Bf::Zero => glow::ZERO,
374        Bf::One => glow::ONE,
375        Bf::Src => glow::SRC_COLOR,
376        Bf::OneMinusSrc => glow::ONE_MINUS_SRC_COLOR,
377        Bf::Dst => glow::DST_COLOR,
378        Bf::OneMinusDst => glow::ONE_MINUS_DST_COLOR,
379        Bf::SrcAlpha => glow::SRC_ALPHA,
380        Bf::OneMinusSrcAlpha => glow::ONE_MINUS_SRC_ALPHA,
381        Bf::DstAlpha => glow::DST_ALPHA,
382        Bf::OneMinusDstAlpha => glow::ONE_MINUS_DST_ALPHA,
383        Bf::Constant => glow::CONSTANT_COLOR,
384        Bf::OneMinusConstant => glow::ONE_MINUS_CONSTANT_COLOR,
385        Bf::SrcAlphaSaturated => glow::SRC_ALPHA_SATURATE,
386        Bf::Src1 => glow::SRC1_COLOR,
387        Bf::OneMinusSrc1 => glow::ONE_MINUS_SRC1_COLOR,
388        Bf::Src1Alpha => glow::SRC1_ALPHA,
389        Bf::OneMinusSrc1Alpha => glow::ONE_MINUS_SRC1_ALPHA,
390    }
391}
392
393fn map_blend_component(component: &wgt::BlendComponent) -> super::BlendComponent {
394    super::BlendComponent {
395        src: map_blend_factor(component.src_factor),
396        dst: map_blend_factor(component.dst_factor),
397        equation: match component.operation {
398            wgt::BlendOperation::Add => glow::FUNC_ADD,
399            wgt::BlendOperation::Subtract => glow::FUNC_SUBTRACT,
400            wgt::BlendOperation::ReverseSubtract => glow::FUNC_REVERSE_SUBTRACT,
401            wgt::BlendOperation::Min => glow::MIN,
402            wgt::BlendOperation::Max => glow::MAX,
403        },
404    }
405}
406
407pub(super) fn map_blend(blend: &wgt::BlendState) -> super::BlendDesc {
408    super::BlendDesc {
409        color: map_blend_component(&blend.color),
410        alpha: map_blend_component(&blend.alpha),
411    }
412}
413
414pub(super) fn map_storage_access(access: wgt::StorageTextureAccess) -> u32 {
415    match access {
416        wgt::StorageTextureAccess::ReadOnly => glow::READ_ONLY,
417        wgt::StorageTextureAccess::WriteOnly => glow::WRITE_ONLY,
418        wgt::StorageTextureAccess::ReadWrite => glow::READ_WRITE,
419        wgt::StorageTextureAccess::Atomic => glow::READ_WRITE,
420    }
421}
422
423pub(super) fn is_layered_target(target: u32) -> bool {
424    match target {
425        glow::TEXTURE_2D | glow::TEXTURE_CUBE_MAP => false,
426        glow::TEXTURE_2D_ARRAY | glow::TEXTURE_CUBE_MAP_ARRAY | glow::TEXTURE_3D => true,
427        _ => unreachable!(),
428    }
429}