Skip to main content

servo_canvas_traits/
webgl.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::borrow::Cow;
6use std::fmt;
7use std::num::{NonZeroU32, NonZeroU64};
8use std::ops::Deref;
9
10use euclid::default::{Rect, Size2D};
11use glow::{
12    self as gl, NativeBuffer, NativeFence, NativeFramebuffer, NativeProgram, NativeQuery,
13    NativeRenderbuffer, NativeSampler, NativeShader, NativeTexture, NativeVertexArray,
14};
15use log::warn;
16use malloc_size_of_derive::MallocSizeOf;
17use pixels::{PixelFormat, SnapshotAlphaMode};
18use serde::{Deserialize, Serialize};
19/// Receiver type used in WebGLCommands.
20pub use servo_base::generic_channel::GenericReceiver;
21/// Sender type used in WebGLCommands.
22pub use servo_base::generic_channel::GenericSender;
23use servo_base::generic_channel::GenericSharedMemory;
24/// Result type for send()/recv() calls in in WebGLCommands.
25pub use servo_base::generic_channel::SendResult as WebGLSendResult;
26use servo_base::id::PainterId;
27use servo_base::{Epoch, generic_channel};
28use webrender_api::ImageKey;
29use webxr_api::{
30    ContextId as WebXRContextId, Error as WebXRError, LayerId as WebXRLayerId,
31    LayerInit as WebXRLayerInit, SubImages as WebXRSubImages,
32};
33
34/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
35pub fn webgl_channel<T>() -> Option<(GenericSender<T>, GenericReceiver<T>)>
36where
37    T: for<'de> Deserialize<'de> + Serialize,
38{
39    servo_base::generic_channel::channel()
40}
41
42/// Entry point channel type used for sending WebGLMsg messages to the WebGL renderer.
43#[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)]
44pub struct WebGLChan(pub GenericSender<WebGLMsg>);
45
46impl WebGLChan {
47    #[inline]
48    pub fn send(&self, msg: WebGLMsg) -> WebGLSendResult {
49        self.0.send(msg)
50    }
51}
52
53/// Entry point type used in a Script Pipeline to get the WebGLChan to be used in that thread.
54#[derive(Clone, Debug, Deserialize, Serialize)]
55pub struct WebGLPipeline(pub WebGLChan);
56
57impl WebGLPipeline {
58    pub fn channel(&self) -> WebGLChan {
59        self.0.clone()
60    }
61}
62
63#[derive(Clone, Debug, Deserialize, Serialize)]
64pub struct WebGLCommandBacktrace {
65    #[cfg(feature = "webgl_backtrace")]
66    pub backtrace: String,
67    #[cfg(feature = "webgl_backtrace")]
68    pub js_backtrace: Option<String>,
69}
70
71/// WebGL Threading API entry point that lives in the constellation.
72#[derive(Clone)]
73pub struct WebGLThreads(pub GenericSender<WebGLMsg>);
74
75impl WebGLThreads {
76    /// Gets the WebGLThread handle for each script pipeline.
77    pub fn pipeline(&self) -> WebGLPipeline {
78        // This mode creates a single thread, so the existing WebGLChan is just cloned.
79        WebGLPipeline(WebGLChan(self.0.clone()))
80    }
81
82    /// Sends an exit message to close the WebGLThreads and release all WebGLContexts.
83    pub fn exit(&self) {
84        if self.0.send(WebGLMsg::Exit).is_err() {
85            warn!("Could not exit WebGLThread.");
86        }
87    }
88
89    /// Sends a message to remove the resources for a `Painter` with the given [`PainterId`].
90    /// Returns `true` if clearing resources was successful and `false` otherwise.
91    pub fn clear_painter_resources(&self, painter_id: PainterId) -> bool {
92        let (webgl_exit_sender, webgl_exit_receiver) =
93            generic_channel::channel().expect("Failed to create IPC channel!");
94        self.0
95            .send(WebGLMsg::ClearPainterResources(
96                painter_id,
97                webgl_exit_sender,
98            ))
99            .is_ok_and(|_| webgl_exit_receiver.recv().is_ok())
100    }
101
102    /// Inform the WebGLThreads that WebRender has finished rendering a particular WebGL context,
103    /// and if it was marked for deletion, it can now be released.
104    pub fn finished_rendering_to_context(&self, context_id: WebGLContextId) -> WebGLSendResult {
105        self.0
106            .send(WebGLMsg::FinishedRenderingToContext(context_id))
107    }
108}
109
110/// WebGL Message API
111#[derive(Debug, Deserialize, Serialize)]
112pub enum WebGLMsg {
113    /// Creates a new WebGLContext.
114    CreateContext(
115        PainterId,
116        WebGLVersion,
117        Size2D<u32>,
118        GLContextAttributes,
119        GenericSender<Result<WebGLCreateContextResult, String>>,
120    ),
121    /// Set an [`ImageKey`] on a `WebGLContext`.
122    SetImageKey(WebGLContextId, ImageKey),
123    /// Resizes a WebGLContext.
124    ResizeContext(
125        WebGLContextId,
126        Size2D<u32>,
127        GenericSender<Result<(), String>>,
128    ),
129    /// Drops a WebGLContext.
130    RemoveContext(WebGLContextId),
131    /// Runs a WebGLCommand in a specific WebGLContext.
132    WebGLCommand(WebGLContextId, WebGLCommand, WebGLCommandBacktrace),
133    /// Runs a WebXRCommand (WebXR layers need to be created in the WebGL
134    /// thread, as they may have thread affinity).
135    WebXRCommand(WebXRCommand),
136    /// Performs a buffer swap.
137    ///
138    /// The third field contains the time (in ns) when the request
139    /// was initiated. The u64 in the second field will be the time the
140    /// request is fulfilled
141    SwapBuffers(Vec<WebGLContextId>, Option<Epoch>, u64),
142    /// Called when a [`Surface`] is returned from being used in WebRender and isn't
143    /// readily releaseable via the `SwapChain`. This can happen when the context is
144    /// released in the WebGLThread while the contents are being rendered by WebRender.
145    FinishedRenderingToContext(WebGLContextId),
146    /// Frees all resources associated with a particular `Painter`.
147    ClearPainterResources(PainterId, GenericSender<()>),
148    /// Frees all resources and closes the thread.
149    Exit,
150}
151
152#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
153pub enum GlType {
154    Gl,
155    Gles,
156}
157
158/// Contains the WebGLCommand sender and information about a WebGLContext
159#[derive(Clone, Debug, Deserialize, Serialize)]
160pub struct WebGLCreateContextResult {
161    /// Sender instance to send commands to the specific WebGLContext
162    pub sender: WebGLMsgSender,
163    /// Information about the internal GL Context.
164    pub limits: GLLimits,
165    /// The GLSL version supported by the context.
166    pub glsl_version: WebGLSLVersion,
167    /// The GL API used by the context.
168    pub api_type: GlType,
169}
170
171/// Defines the WebGL version
172#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, PartialOrd, Serialize)]
173pub enum WebGLVersion {
174    /// <https://www.khronos.org/registry/webgl/specs/1.0.2/>
175    /// Conforms closely to the OpenGL ES 2.0 API
176    WebGL1,
177    /// <https://www.khronos.org/registry/webgl/specs/latest/2.0/>
178    /// Conforms closely to the OpenGL ES 3.0 API
179    WebGL2,
180}
181
182/// Defines the GLSL version supported by the WebGL backend contexts.
183#[derive(
184    Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
185)]
186pub struct WebGLSLVersion {
187    /// Major GLSL version
188    pub major: u32,
189    /// Minor GLSL version
190    pub minor: u32,
191}
192
193/// Helper struct to send WebGLCommands to a specific WebGLContext.
194#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
195pub struct WebGLMsgSender {
196    ctx_id: WebGLContextId,
197    sender: WebGLChan,
198}
199
200impl WebGLMsgSender {
201    pub fn new(id: WebGLContextId, sender: WebGLChan) -> Self {
202        WebGLMsgSender { ctx_id: id, sender }
203    }
204
205    /// Returns the WebGLContextId associated to this sender
206    pub fn context_id(&self) -> WebGLContextId {
207        self.ctx_id
208    }
209
210    /// Send a WebGLCommand message
211    #[inline]
212    pub fn send(&self, command: WebGLCommand, backtrace: WebGLCommandBacktrace) -> WebGLSendResult {
213        self.sender
214            .send(WebGLMsg::WebGLCommand(self.ctx_id, command, backtrace))
215    }
216
217    /// Set an [`ImageKey`] on this WebGL context.
218    #[inline]
219    pub fn set_image_key(&self, image_key: ImageKey) {
220        let _ = self
221            .sender
222            .send(WebGLMsg::SetImageKey(self.ctx_id, image_key));
223    }
224
225    /// Send a resize message
226    #[inline]
227    pub fn send_resize(
228        &self,
229        size: Size2D<u32>,
230        sender: GenericSender<Result<(), String>>,
231    ) -> WebGLSendResult {
232        self.sender
233            .send(WebGLMsg::ResizeContext(self.ctx_id, size, sender))
234    }
235
236    #[inline]
237    pub fn send_remove(&self) -> WebGLSendResult {
238        self.sender.send(WebGLMsg::RemoveContext(self.ctx_id))
239    }
240}
241
242#[derive(Deserialize, Serialize)]
243pub struct TruncatedDebug<T>(T);
244
245impl<T> From<T> for TruncatedDebug<T> {
246    fn from(v: T) -> TruncatedDebug<T> {
247        TruncatedDebug(v)
248    }
249}
250
251impl<T: fmt::Debug> fmt::Debug for TruncatedDebug<T> {
252    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
253        let mut s = format!("{:?}", self.0);
254        if s.len() > 20 {
255            s.truncate(20);
256            s.push_str("...");
257        }
258        write!(f, "{}", s)
259    }
260}
261
262impl<T> Deref for TruncatedDebug<T> {
263    type Target = T;
264    fn deref(&self) -> &T {
265        &self.0
266    }
267}
268
269/// WebGL Commands for a specific WebGLContext
270#[derive(Debug, Deserialize, Serialize)]
271pub enum WebGLCommand {
272    GetContextAttributes(GenericSender<GLContextAttributes>),
273    ActiveTexture(u32),
274    BlendColor(f32, f32, f32, f32),
275    BlendEquation(u32),
276    BlendEquationSeparate(u32, u32),
277    BlendFunc(u32, u32),
278    BlendFuncSeparate(u32, u32, u32, u32),
279    AttachShader(WebGLProgramId, WebGLShaderId),
280    DetachShader(WebGLProgramId, WebGLShaderId),
281    BindAttribLocation(WebGLProgramId, u32, String),
282    BufferData(u32, GenericReceiver<GenericSharedMemory>, u32),
283    BufferSubData(u32, isize, GenericReceiver<GenericSharedMemory>),
284    GetBufferSubData(u32, usize, usize, GenericSender<GenericSharedMemory>),
285    CopyBufferSubData(u32, u32, i64, i64, i64),
286    Clear(u32),
287    ClearColor(f32, f32, f32, f32),
288    ClearDepth(f32),
289    ClearStencil(i32),
290    ColorMask(bool, bool, bool, bool),
291    CullFace(u32),
292    FrontFace(u32),
293    DepthFunc(u32),
294    DepthMask(bool),
295    DepthRange(f32, f32),
296    Enable(u32),
297    Disable(u32),
298    CompileShader(WebGLShaderId, String),
299    CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32),
300    CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32),
301    CreateBuffer(GenericSender<Option<WebGLBufferId>>),
302    CreateFramebuffer(GenericSender<Option<WebGLFramebufferId>>),
303    CreateRenderbuffer(GenericSender<Option<WebGLRenderbufferId>>),
304    CreateTexture(GenericSender<Option<WebGLTextureId>>),
305    CreateProgram(GenericSender<Option<WebGLProgramId>>),
306    CreateShader(u32, GenericSender<Option<WebGLShaderId>>),
307    DeleteBuffer(WebGLBufferId),
308    DeleteFramebuffer(WebGLFramebufferId),
309    DeleteRenderbuffer(WebGLRenderbufferId),
310    DeleteTexture(WebGLTextureId),
311    DeleteProgram(WebGLProgramId),
312    DeleteShader(WebGLShaderId),
313    BindBuffer(u32, Option<WebGLBufferId>),
314    BindFramebuffer(u32, WebGLFramebufferBindingRequest),
315    BindRenderbuffer(u32, Option<WebGLRenderbufferId>),
316    BindTexture(u32, Option<WebGLTextureId>),
317    BlitFrameBuffer(i32, i32, i32, i32, i32, i32, i32, i32, u32, u32),
318    DisableVertexAttribArray(u32),
319    EnableVertexAttribArray(u32),
320    FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>),
321    FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
322    GetExtensions(GenericSender<String>),
323    GetShaderPrecisionFormat(u32, u32, GenericSender<(i32, i32, i32)>),
324    GetFragDataLocation(WebGLProgramId, String, GenericSender<i32>),
325    GetUniformLocation(WebGLProgramId, String, GenericSender<Option<i32>>),
326    GetShaderInfoLog(WebGLShaderId, GenericSender<String>),
327    GetProgramInfoLog(WebGLProgramId, GenericSender<String>),
328    GetFramebufferAttachmentParameter(u32, u32, u32, GenericSender<i32>),
329    GetRenderbufferParameter(u32, u32, GenericSender<i32>),
330    CreateTransformFeedback(GenericSender<u32>),
331    DeleteTransformFeedback(u32),
332    IsTransformFeedback(u32, GenericSender<bool>),
333    BindTransformFeedback(u32, u32),
334    BeginTransformFeedback(u32),
335    EndTransformFeedback(),
336    PauseTransformFeedback(),
337    ResumeTransformFeedback(),
338    GetTransformFeedbackVarying(WebGLProgramId, u32, GenericSender<(i32, u32, String)>),
339    TransformFeedbackVaryings(WebGLProgramId, Vec<String>, u32),
340    PolygonOffset(f32, f32),
341    RenderbufferStorage(u32, u32, i32, i32),
342    RenderbufferStorageMultisample(u32, i32, u32, i32, i32),
343    ReadPixels(
344        Rect<u32>,
345        u32,
346        u32,
347        GenericSender<(GenericSharedMemory, SnapshotAlphaMode)>,
348    ),
349    ReadPixelsPP(Rect<i32>, u32, u32, usize),
350    SampleCoverage(f32, bool),
351    Scissor(i32, i32, u32, u32),
352    StencilFunc(u32, i32, u32),
353    StencilFuncSeparate(u32, u32, i32, u32),
354    StencilMask(u32),
355    StencilMaskSeparate(u32, u32),
356    StencilOp(u32, u32, u32),
357    StencilOpSeparate(u32, u32, u32, u32),
358    FenceSync(GenericSender<WebGLSyncId>),
359    IsSync(WebGLSyncId, GenericSender<bool>),
360    ClientWaitSync(WebGLSyncId, u32, u64, GenericSender<u32>),
361    WaitSync(WebGLSyncId, u32, i64),
362    GetSyncParameter(WebGLSyncId, u32, GenericSender<u32>),
363    DeleteSync(WebGLSyncId),
364    Hint(u32, u32),
365    LineWidth(f32),
366    PixelStorei(u32, i32),
367    LinkProgram(WebGLProgramId, GenericSender<ProgramLinkInfo>),
368    Uniform1f(i32, f32),
369    Uniform1fv(i32, Vec<f32>),
370    Uniform1i(i32, i32),
371    Uniform1ui(i32, u32),
372    Uniform1iv(i32, Vec<i32>),
373    Uniform1uiv(i32, Vec<u32>),
374    Uniform2f(i32, f32, f32),
375    Uniform2fv(i32, Vec<f32>),
376    Uniform2i(i32, i32, i32),
377    Uniform2ui(i32, u32, u32),
378    Uniform2iv(i32, Vec<i32>),
379    Uniform2uiv(i32, Vec<u32>),
380    Uniform3f(i32, f32, f32, f32),
381    Uniform3fv(i32, Vec<f32>),
382    Uniform3i(i32, i32, i32, i32),
383    Uniform3ui(i32, u32, u32, u32),
384    Uniform3iv(i32, Vec<i32>),
385    Uniform3uiv(i32, Vec<u32>),
386    Uniform4f(i32, f32, f32, f32, f32),
387    Uniform4fv(i32, Vec<f32>),
388    Uniform4i(i32, i32, i32, i32, i32),
389    Uniform4ui(i32, u32, u32, u32, u32),
390    Uniform4iv(i32, Vec<i32>),
391    Uniform4uiv(i32, Vec<u32>),
392    UniformMatrix2fv(i32, Vec<f32>),
393    UniformMatrix3fv(i32, Vec<f32>),
394    UniformMatrix4fv(i32, Vec<f32>),
395    UniformMatrix3x2fv(i32, Vec<f32>),
396    UniformMatrix4x2fv(i32, Vec<f32>),
397    UniformMatrix2x3fv(i32, Vec<f32>),
398    UniformMatrix4x3fv(i32, Vec<f32>),
399    UniformMatrix2x4fv(i32, Vec<f32>),
400    UniformMatrix3x4fv(i32, Vec<f32>),
401    UseProgram(Option<WebGLProgramId>),
402    ValidateProgram(WebGLProgramId),
403    VertexAttrib(u32, f32, f32, f32, f32),
404    VertexAttribI(u32, i32, i32, i32, i32),
405    VertexAttribU(u32, u32, u32, u32, u32),
406    VertexAttribPointer(u32, i32, u32, bool, i32, u32),
407    VertexAttribIPointer(u32, i32, u32, i32, u32),
408    VertexAttribPointer2f(u32, i32, bool, i32, u32),
409    SetViewport(i32, i32, i32, i32),
410    TexImage3D {
411        target: u32,
412        level: u32,
413        internal_format: TexFormat,
414        size: Size2D<u32>,
415        depth: u32,
416        format: TexFormat,
417        data_type: TexDataType,
418        // FIXME: This should be computed on the WebGL thread.
419        effective_data_type: u32,
420        unpacking_alignment: u32,
421        alpha_treatment: Option<AlphaTreatment>,
422        y_axis_treatment: YAxisTreatment,
423        pixel_format: Option<PixelFormat>,
424        data: TruncatedDebug<GenericSharedMemory>,
425    },
426    TexImage2D {
427        target: u32,
428        level: u32,
429        internal_format: TexFormat,
430        size: Size2D<u32>,
431        format: TexFormat,
432        data_type: TexDataType,
433        // FIXME(nox): This should be computed on the WebGL thread.
434        effective_data_type: u32,
435        unpacking_alignment: u32,
436        alpha_treatment: Option<AlphaTreatment>,
437        y_axis_treatment: YAxisTreatment,
438        pixel_format: Option<PixelFormat>,
439        data: TruncatedDebug<GenericSharedMemory>,
440    },
441    TexImage2DPBO {
442        target: u32,
443        level: u32,
444        internal_format: TexFormat,
445        size: Size2D<u32>,
446        format: TexFormat,
447        effective_data_type: u32,
448        unpacking_alignment: u32,
449        offset: i64,
450    },
451    TexSubImage2D {
452        target: u32,
453        level: u32,
454        xoffset: i32,
455        yoffset: i32,
456        size: Size2D<u32>,
457        format: TexFormat,
458        data_type: TexDataType,
459        // FIXME(nox): This should be computed on the WebGL thread.
460        effective_data_type: u32,
461        unpacking_alignment: u32,
462        alpha_treatment: Option<AlphaTreatment>,
463        y_axis_treatment: YAxisTreatment,
464        pixel_format: Option<PixelFormat>,
465        data: TruncatedDebug<GenericSharedMemory>,
466    },
467    CompressedTexImage2D {
468        target: u32,
469        level: u32,
470        internal_format: u32,
471        size: Size2D<u32>,
472        data: TruncatedDebug<GenericSharedMemory>,
473    },
474    CompressedTexSubImage2D {
475        target: u32,
476        level: i32,
477        xoffset: i32,
478        yoffset: i32,
479        size: Size2D<u32>,
480        format: u32,
481        data: TruncatedDebug<GenericSharedMemory>,
482    },
483    DrawingBufferWidth(GenericSender<i32>),
484    DrawingBufferHeight(GenericSender<i32>),
485    Finish(GenericSender<()>),
486    Flush,
487    GenerateMipmap(u32),
488    CreateVertexArray(GenericSender<Option<WebGLVertexArrayId>>),
489    DeleteVertexArray(WebGLVertexArrayId),
490    BindVertexArray(Option<WebGLVertexArrayId>),
491    GetParameterBool(ParameterBool, GenericSender<bool>),
492    GetParameterBool4(ParameterBool4, GenericSender<[bool; 4]>),
493    GetParameterInt(ParameterInt, GenericSender<i32>),
494    GetParameterUInt(ParameterUInt, GenericSender<u32>),
495    GetParameterInt2(ParameterInt2, GenericSender<[i32; 2]>),
496    GetParameterInt4(ParameterInt4, GenericSender<[i32; 4]>),
497    GetParameterFloat(ParameterFloat, GenericSender<f32>),
498    GetParameterFloat2(ParameterFloat2, GenericSender<[f32; 2]>),
499    GetParameterFloat4(ParameterFloat4, GenericSender<[f32; 4]>),
500    GetParameterString(ParameterString, GenericSender<String>),
501    GetProgramValidateStatus(WebGLProgramId, GenericSender<bool>),
502    GetProgramActiveUniforms(WebGLProgramId, GenericSender<i32>),
503    GetCurrentVertexAttrib(u32, GenericSender<[f32; 4]>),
504    GetTexParameterFloat(u32, TexParameterFloat, GenericSender<f32>),
505    GetTexParameterInt(u32, TexParameterInt, GenericSender<i32>),
506    GetTexParameterBool(u32, TexParameterBool, GenericSender<bool>),
507    GetInternalFormatIntVec(u32, u32, InternalFormatIntVec, GenericSender<Vec<i32>>),
508    TexParameteri(u32, u32, i32),
509    TexParameterf(u32, u32, f32),
510    TexStorage2D(u32, u32, TexFormat, u32, u32),
511    TexStorage3D(u32, u32, TexFormat, u32, u32, u32),
512    DrawArrays {
513        mode: u32,
514        first: i32,
515        count: i32,
516    },
517    DrawArraysInstanced {
518        mode: u32,
519        first: i32,
520        count: i32,
521        primcount: i32,
522    },
523    DrawElements {
524        mode: u32,
525        count: i32,
526        type_: u32,
527        offset: u32,
528    },
529    DrawElementsInstanced {
530        mode: u32,
531        count: i32,
532        type_: u32,
533        offset: u32,
534        primcount: i32,
535    },
536    VertexAttribDivisor {
537        index: u32,
538        divisor: u32,
539    },
540    GetUniformBool(WebGLProgramId, i32, GenericSender<bool>),
541    GetUniformBool2(WebGLProgramId, i32, GenericSender<[bool; 2]>),
542    GetUniformBool3(WebGLProgramId, i32, GenericSender<[bool; 3]>),
543    GetUniformBool4(WebGLProgramId, i32, GenericSender<[bool; 4]>),
544    GetUniformInt(WebGLProgramId, i32, GenericSender<i32>),
545    GetUniformInt2(WebGLProgramId, i32, GenericSender<[i32; 2]>),
546    GetUniformInt3(WebGLProgramId, i32, GenericSender<[i32; 3]>),
547    GetUniformInt4(WebGLProgramId, i32, GenericSender<[i32; 4]>),
548    GetUniformUint(WebGLProgramId, i32, GenericSender<u32>),
549    GetUniformUint2(WebGLProgramId, i32, GenericSender<[u32; 2]>),
550    GetUniformUint3(WebGLProgramId, i32, GenericSender<[u32; 3]>),
551    GetUniformUint4(WebGLProgramId, i32, GenericSender<[u32; 4]>),
552    GetUniformFloat(WebGLProgramId, i32, GenericSender<f32>),
553    GetUniformFloat2(WebGLProgramId, i32, GenericSender<[f32; 2]>),
554    GetUniformFloat3(WebGLProgramId, i32, GenericSender<[f32; 3]>),
555    GetUniformFloat4(WebGLProgramId, i32, GenericSender<[f32; 4]>),
556    GetUniformFloat9(WebGLProgramId, i32, GenericSender<[f32; 9]>),
557    GetUniformFloat16(WebGLProgramId, i32, GenericSender<[f32; 16]>),
558    GetUniformFloat2x3(WebGLProgramId, i32, GenericSender<[f32; 2 * 3]>),
559    GetUniformFloat2x4(WebGLProgramId, i32, GenericSender<[f32; 2 * 4]>),
560    GetUniformFloat3x2(WebGLProgramId, i32, GenericSender<[f32; 3 * 2]>),
561    GetUniformFloat3x4(WebGLProgramId, i32, GenericSender<[f32; 3 * 4]>),
562    GetUniformFloat4x2(WebGLProgramId, i32, GenericSender<[f32; 4 * 2]>),
563    GetUniformFloat4x3(WebGLProgramId, i32, GenericSender<[f32; 4 * 3]>),
564    GetUniformBlockIndex(WebGLProgramId, String, GenericSender<u32>),
565    GetUniformIndices(WebGLProgramId, Vec<String>, GenericSender<Vec<u32>>),
566    GetActiveUniforms(WebGLProgramId, Vec<u32>, u32, GenericSender<Vec<i32>>),
567    GetActiveUniformBlockName(WebGLProgramId, u32, GenericSender<String>),
568    GetActiveUniformBlockParameter(WebGLProgramId, u32, u32, GenericSender<Vec<i32>>),
569    UniformBlockBinding(WebGLProgramId, u32, u32),
570    InitializeFramebuffer {
571        color: bool,
572        depth: bool,
573        stencil: bool,
574    },
575    BeginQuery(u32, WebGLQueryId),
576    DeleteQuery(WebGLQueryId),
577    EndQuery(u32),
578    GenerateQuery(GenericSender<WebGLQueryId>),
579    GetQueryState(GenericSender<u32>, WebGLQueryId, u32),
580    GenerateSampler(GenericSender<WebGLSamplerId>),
581    DeleteSampler(WebGLSamplerId),
582    BindSampler(u32, WebGLSamplerId),
583    SetSamplerParameterFloat(WebGLSamplerId, u32, f32),
584    SetSamplerParameterInt(WebGLSamplerId, u32, i32),
585    GetSamplerParameterFloat(WebGLSamplerId, u32, GenericSender<f32>),
586    GetSamplerParameterInt(WebGLSamplerId, u32, GenericSender<i32>),
587    BindBufferBase(u32, u32, Option<WebGLBufferId>),
588    BindBufferRange(u32, u32, Option<WebGLBufferId>, i64, i64),
589    ClearBufferfv(u32, i32, Vec<f32>),
590    ClearBufferiv(u32, i32, Vec<i32>),
591    ClearBufferuiv(u32, i32, Vec<u32>),
592    ClearBufferfi(u32, i32, f32, i32),
593    InvalidateFramebuffer(u32, Vec<u32>),
594    InvalidateSubFramebuffer(u32, Vec<u32>, i32, i32, i32, i32),
595    FramebufferTextureLayer(u32, u32, Option<WebGLTextureId>, i32, i32),
596    ReadBuffer(u32),
597    DrawBuffers(Vec<u32>),
598}
599
600/// WebXR layer management
601#[derive(Debug, Deserialize, Serialize)]
602pub enum WebXRCommand {
603    CreateLayerManager(GenericSender<Result<WebXRLayerManagerId, WebXRError>>),
604    DestroyLayerManager(WebXRLayerManagerId),
605    CreateLayer(
606        WebXRLayerManagerId,
607        WebXRContextId,
608        WebXRLayerInit,
609        GenericSender<Result<WebXRLayerId, WebXRError>>,
610    ),
611    DestroyLayer(WebXRLayerManagerId, WebXRContextId, WebXRLayerId),
612    BeginFrame(
613        WebXRLayerManagerId,
614        Vec<(WebXRContextId, WebXRLayerId)>,
615        GenericSender<Result<Vec<WebXRSubImages>, WebXRError>>,
616    ),
617    EndFrame(
618        WebXRLayerManagerId,
619        Vec<(WebXRContextId, WebXRLayerId)>,
620        GenericSender<Result<(), WebXRError>>,
621    ),
622}
623
624macro_rules! nonzero_type {
625    (u32) => {
626        NonZeroU32
627    };
628    (u64) => {
629        NonZeroU64
630    };
631}
632
633macro_rules! define_resource_id {
634    ($name:ident, $type:tt) => {
635        #[derive(Clone, Copy, Eq, Hash, PartialEq)]
636        pub struct $name(nonzero_type!($type));
637
638        impl $name {
639            #[inline]
640            pub fn new(id: nonzero_type!($type)) -> Self {
641                Self(id)
642            }
643
644            #[inline]
645            pub fn maybe_new(id: $type) -> Option<Self> {
646                <nonzero_type!($type)>::new(id).map($name)
647            }
648
649            #[inline]
650            pub fn get(self) -> $type {
651                self.0.get()
652            }
653        }
654
655        impl<'de> ::serde::Deserialize<'de> for $name {
656            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
657            where
658                D: ::serde::Deserializer<'de>,
659            {
660                let id = <$type>::deserialize(deserializer)?;
661                if let Some(id) = <nonzero_type!($type)>::new(id) {
662                    Ok($name(id))
663                } else {
664                    Err(::serde::de::Error::custom("expected a non-zero value"))
665                }
666            }
667        }
668
669        impl ::serde::Serialize for $name {
670            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
671            where
672                S: ::serde::Serializer,
673            {
674                self.get().serialize(serializer)
675            }
676        }
677
678        impl ::std::fmt::Debug for $name {
679            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
680                fmt.debug_tuple(stringify!($name))
681                    .field(&self.get())
682                    .finish()
683            }
684        }
685
686        impl ::std::fmt::Display for $name {
687            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
688                write!(fmt, "{}", self.get())
689            }
690        }
691
692        impl ::malloc_size_of::MallocSizeOf for $name {
693            fn size_of(&self, _ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize {
694                0
695            }
696        }
697    };
698    ($name:ident, $type:tt, $glow:tt) => {
699        impl $name {
700            #[inline]
701            pub fn glow(self) -> $glow {
702                $glow(self.0)
703            }
704
705            #[inline]
706            pub fn from_glow(glow: $glow) -> Self {
707                Self(glow.0)
708            }
709        }
710        define_resource_id!($name, $type);
711    };
712}
713
714define_resource_id!(WebGLBufferId, u32, NativeBuffer);
715define_resource_id!(WebGLFramebufferId, u32, NativeFramebuffer);
716define_resource_id!(WebGLRenderbufferId, u32, NativeRenderbuffer);
717define_resource_id!(WebGLTextureId, u32, NativeTexture);
718define_resource_id!(WebGLProgramId, u32, NativeProgram);
719define_resource_id!(WebGLQueryId, u32, NativeQuery);
720define_resource_id!(WebGLSamplerId, u32, NativeSampler);
721define_resource_id!(WebGLShaderId, u32, NativeShader);
722define_resource_id!(WebGLSyncId, u64);
723impl WebGLSyncId {
724    #[inline]
725    pub fn glow(&self) -> NativeFence {
726        NativeFence(self.0.get() as _)
727    }
728
729    #[inline]
730    pub fn from_glow(glow: NativeFence) -> Self {
731        Self::maybe_new(glow.0 as _).expect("Glow should have valid fence")
732    }
733}
734define_resource_id!(WebGLVertexArrayId, u32, NativeVertexArray);
735define_resource_id!(WebXRLayerManagerId, u32);
736
737#[derive(
738    Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
739)]
740pub struct WebGLContextId(pub u64);
741
742impl From<WebXRContextId> for WebGLContextId {
743    fn from(id: WebXRContextId) -> Self {
744        Self(id.0)
745    }
746}
747
748impl From<WebGLContextId> for WebXRContextId {
749    fn from(id: WebGLContextId) -> Self {
750        Self(id.0)
751    }
752}
753
754#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, MallocSizeOf)]
755pub enum WebGLError {
756    InvalidEnum,
757    InvalidFramebufferOperation,
758    InvalidOperation,
759    InvalidValue,
760    OutOfMemory,
761    ContextLost,
762}
763
764#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
765pub enum WebGLFramebufferBindingRequest {
766    Explicit(WebGLFramebufferId),
767    Default,
768}
769
770pub type WebGLResult<T> = Result<T, WebGLError>;
771
772/// Information about a WebGL program linking operation.
773#[derive(Clone, Debug, Deserialize, Serialize)]
774pub struct ProgramLinkInfo {
775    /// Whether the program was linked successfully.
776    pub linked: bool,
777    /// The list of active attributes.
778    pub active_attribs: Box<[ActiveAttribInfo]>,
779    /// The list of active uniforms.
780    pub active_uniforms: Box<[ActiveUniformInfo]>,
781    /// The list of active uniform blocks.
782    pub active_uniform_blocks: Box<[ActiveUniformBlockInfo]>,
783    /// The number of varying variables
784    pub transform_feedback_length: i32,
785    /// The buffer mode used when transform feedback is active
786    pub transform_feedback_mode: i32,
787}
788
789/// Description of a single active attribute.
790#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
791pub struct ActiveAttribInfo {
792    /// The name of the attribute.
793    pub name: String,
794    /// The size of the attribute.
795    pub size: i32,
796    /// The type of the attribute.
797    pub type_: u32,
798    /// The location of the attribute.
799    pub location: Option<u32>,
800}
801
802/// Description of a single active uniform.
803#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
804pub struct ActiveUniformInfo {
805    /// The base name of the uniform.
806    pub base_name: Box<str>,
807    /// The size of the uniform, if it is an array.
808    pub size: Option<i32>,
809    /// The type of the uniform.
810    pub type_: u32,
811    /// The index of the indexed uniform buffer binding, if it is bound.
812    pub bind_index: Option<u32>,
813}
814
815impl ActiveUniformInfo {
816    pub fn name(&self) -> Cow<'_, str> {
817        if self.size.is_some() {
818            let mut name = String::from(&*self.base_name);
819            name.push_str("[0]");
820            Cow::Owned(name)
821        } else {
822            Cow::Borrowed(&self.base_name)
823        }
824    }
825}
826
827/// Description of a single uniform block.
828#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
829pub struct ActiveUniformBlockInfo {
830    /// The name of the uniform block.
831    pub name: String,
832    /// The size of the uniform block.
833    pub size: i32,
834}
835
836macro_rules! parameters {
837    ($name:ident { $(
838        $variant:ident($kind:ident { $(
839            $param:ident = gl::$value:ident,
840        )+ }),
841    )+ }) => {
842        #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
843        pub enum $name { $(
844            $variant($kind),
845        )+}
846
847        $(
848            #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
849            #[repr(u32)]
850            pub enum $kind { $(
851                $param = gl::$value,
852            )+}
853        )+
854
855        impl $name {
856            pub fn from_u32(value: u32) -> WebGLResult<Self> {
857                match value {
858                    $($(gl::$value => Ok($name::$variant($kind::$param)),)+)+
859                    _ => Err(WebGLError::InvalidEnum)
860                }
861            }
862        }
863    }
864}
865
866parameters! {
867    Parameter {
868        Bool(ParameterBool {
869            DepthWritemask = gl::DEPTH_WRITEMASK,
870            SampleCoverageInvert = gl::SAMPLE_COVERAGE_INVERT,
871            TransformFeedbackActive = gl::TRANSFORM_FEEDBACK_ACTIVE,
872            TransformFeedbackPaused = gl::TRANSFORM_FEEDBACK_PAUSED,
873            RasterizerDiscard = gl::RASTERIZER_DISCARD,
874        }),
875        Bool4(ParameterBool4 {
876            ColorWritemask = gl::COLOR_WRITEMASK,
877        }),
878        Int(ParameterInt {
879            ActiveTexture = gl::ACTIVE_TEXTURE,
880            AlphaBits = gl::ALPHA_BITS,
881            BlendDstAlpha = gl::BLEND_DST_ALPHA,
882            BlendDstRgb = gl::BLEND_DST_RGB,
883            BlendEquationAlpha = gl::BLEND_EQUATION_ALPHA,
884            BlendEquationRgb = gl::BLEND_EQUATION_RGB,
885            BlendSrcAlpha = gl::BLEND_SRC_ALPHA,
886            BlendSrcRgb = gl::BLEND_SRC_RGB,
887            BlueBits = gl::BLUE_BITS,
888            CullFaceMode = gl::CULL_FACE_MODE,
889            DepthBits = gl::DEPTH_BITS,
890            DepthFunc = gl::DEPTH_FUNC,
891            FragmentShaderDerivativeHint = gl::FRAGMENT_SHADER_DERIVATIVE_HINT,
892            FrontFace = gl::FRONT_FACE,
893            GenerateMipmapHint = gl::GENERATE_MIPMAP_HINT,
894            GreenBits = gl::GREEN_BITS,
895            RedBits = gl::RED_BITS,
896            SampleBuffers = gl::SAMPLE_BUFFERS,
897            Samples = gl::SAMPLES,
898            StencilBackFail = gl::STENCIL_BACK_FAIL,
899            StencilBackFunc = gl::STENCIL_BACK_FUNC,
900            StencilBackPassDepthFail = gl::STENCIL_BACK_PASS_DEPTH_FAIL,
901            StencilBackPassDepthPass = gl::STENCIL_BACK_PASS_DEPTH_PASS,
902            StencilBackRef = gl::STENCIL_BACK_REF,
903            StencilBits = gl::STENCIL_BITS,
904            StencilClearValue = gl::STENCIL_CLEAR_VALUE,
905            StencilFail = gl::STENCIL_FAIL,
906            StencilFunc = gl::STENCIL_FUNC,
907            StencilPassDepthFail = gl::STENCIL_PASS_DEPTH_FAIL,
908            StencilPassDepthPass = gl::STENCIL_PASS_DEPTH_PASS,
909            StencilRef = gl::STENCIL_REF,
910            SubpixelBits = gl::SUBPIXEL_BITS,
911            TransformFeedbackBinding = gl::TRANSFORM_FEEDBACK_BINDING,
912            MaxTransformFeedbackInterleavedComponents = gl::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
913            MaxTransformFeedbackSeparateAttribs = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
914            MaxTransformFeedbackSeparateComponents = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
915            TransformFeedbackBufferSize = gl::TRANSFORM_FEEDBACK_BUFFER_SIZE,
916            TransformFeedbackBufferStart = gl::TRANSFORM_FEEDBACK_BUFFER_START,
917            PackRowLength = gl::PACK_ROW_LENGTH,
918            PackSkipPixels = gl::PACK_SKIP_PIXELS,
919            PackSkipRows = gl::PACK_SKIP_ROWS,
920            UnpackImageHeight = gl::UNPACK_IMAGE_HEIGHT,
921            UnpackRowLength = gl::UNPACK_ROW_LENGTH,
922            UnpackSkipImages = gl::UNPACK_SKIP_IMAGES,
923            UnpackSkipPixels = gl::UNPACK_SKIP_PIXELS,
924            UnpackSkipRows = gl::UNPACK_SKIP_ROWS,
925        }),
926        UInt(ParameterUInt {
927            StencilBackValueMask = gl::STENCIL_BACK_VALUE_MASK,
928            StencilBackWritemask = gl::STENCIL_BACK_WRITEMASK,
929            StencilValueMask = gl::STENCIL_VALUE_MASK,
930            StencilWritemask = gl::STENCIL_WRITEMASK,
931        }),
932        Int2(ParameterInt2 {
933            MaxViewportDims = gl::MAX_VIEWPORT_DIMS,
934        }),
935        Int4(ParameterInt4 {
936            ScissorBox = gl::SCISSOR_BOX,
937            Viewport = gl::VIEWPORT,
938        }),
939        Float(ParameterFloat {
940            DepthClearValue = gl::DEPTH_CLEAR_VALUE,
941            LineWidth = gl::LINE_WIDTH,
942            MaxTextureMaxAnisotropyExt = gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT,
943            PolygonOffsetFactor = gl::POLYGON_OFFSET_FACTOR,
944            PolygonOffsetUnits = gl::POLYGON_OFFSET_UNITS,
945            SampleCoverageValue = gl::SAMPLE_COVERAGE_VALUE,
946        }),
947        Float2(ParameterFloat2 {
948            AliasedPointSizeRange = gl::ALIASED_POINT_SIZE_RANGE,
949            AliasedLineWidthRange = gl::ALIASED_LINE_WIDTH_RANGE,
950            DepthRange = gl::DEPTH_RANGE,
951        }),
952        Float4(ParameterFloat4 {
953            BlendColor = gl::BLEND_COLOR,
954            ColorClearValue = gl::COLOR_CLEAR_VALUE,
955        }),
956    }
957}
958
959#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
960pub enum ParameterString {
961    UnmaskedVendor,
962    UnmaskedRenderer,
963}
964
965parameters! {
966    TexParameter {
967        Float(TexParameterFloat {
968            TextureMaxAnisotropyExt = gl::TEXTURE_MAX_ANISOTROPY_EXT,
969            TextureMaxLod = gl::TEXTURE_MAX_LOD,
970            TextureMinLod = gl::TEXTURE_MIN_LOD,
971        }),
972        Int(TexParameterInt {
973            TextureWrapS = gl::TEXTURE_WRAP_S,
974            TextureWrapT = gl::TEXTURE_WRAP_T,
975            TextureWrapR = gl::TEXTURE_WRAP_R,
976            TextureBaseLevel = gl::TEXTURE_BASE_LEVEL,
977            TextureMinFilter = gl::TEXTURE_MIN_FILTER,
978            TextureMagFilter = gl::TEXTURE_MAG_FILTER,
979            TextureMaxLevel = gl::TEXTURE_MAX_LEVEL,
980            TextureCompareFunc = gl::TEXTURE_COMPARE_FUNC,
981            TextureCompareMode = gl::TEXTURE_COMPARE_MODE,
982            TextureImmutableLevels = gl::TEXTURE_IMMUTABLE_LEVELS,
983        }),
984        Bool(TexParameterBool {
985            TextureImmutableFormat = gl::TEXTURE_IMMUTABLE_FORMAT,
986        }),
987    }
988}
989
990impl TexParameter {
991    pub fn required_webgl_version(self) -> WebGLVersion {
992        match self {
993            Self::Float(TexParameterFloat::TextureMaxAnisotropyExt) |
994            Self::Int(TexParameterInt::TextureWrapS) |
995            Self::Int(TexParameterInt::TextureWrapT) => WebGLVersion::WebGL1,
996            _ => WebGLVersion::WebGL2,
997        }
998    }
999}
1000
1001parameters! {
1002    InternalFormatParameter {
1003        IntVec(InternalFormatIntVec {
1004            Samples = gl::SAMPLES,
1005        }),
1006    }
1007}
1008
1009#[macro_export]
1010macro_rules! gl_enums {
1011    ($(pub enum $name:ident { $($variant:ident = $mod:ident::$constant:ident,)+ })*) => {
1012        $(
1013            #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, malloc_size_of_derive::MallocSizeOf)]
1014            #[derive(PartialEq, Serialize)]
1015            #[repr(u32)]
1016            pub enum $name { $($variant = $mod::$constant,)+ }
1017
1018            impl $name {
1019                pub fn from_gl_constant(constant: u32) -> Option<Self> {
1020                    Some(match constant {
1021                        $($mod::$constant => $name::$variant, )+
1022                        _ => return None,
1023                    })
1024                }
1025
1026                #[inline]
1027                pub fn as_gl_constant(&self) -> u32 {
1028                    *self as u32
1029                }
1030            }
1031        )*
1032    }
1033}
1034
1035// TODO(sagudev): These should come from glow
1036mod gl_ext_constants {
1037    pub const COMPRESSED_RGB_ETC1_WEBGL: u32 = 0x8D64;
1038
1039    pub const ALPHA16F_ARB: u32 = 0x881C;
1040    pub const ALPHA32F_ARB: u32 = 0x8816;
1041    pub const LUMINANCE16F_ARB: u32 = 0x881E;
1042    pub const LUMINANCE32F_ARB: u32 = 0x8818;
1043    pub const LUMINANCE_ALPHA16F_ARB: u32 = 0x881F;
1044    pub const LUMINANCE_ALPHA32F_ARB: u32 = 0x8819;
1045}
1046
1047gl_enums! {
1048    pub enum TexFormat {
1049        DepthComponent = gl::DEPTH_COMPONENT,
1050        DepthStencil = gl::DEPTH_STENCIL,
1051        Alpha = gl::ALPHA,
1052        Alpha32f = gl_ext_constants::ALPHA32F_ARB,
1053        Alpha16f = gl_ext_constants::ALPHA16F_ARB,
1054        Red = gl::RED,
1055        RedInteger = gl::RED_INTEGER,
1056        RG = gl::RG,
1057        RGInteger = gl::RG_INTEGER,
1058        RGB = gl::RGB,
1059        RGBInteger = gl::RGB_INTEGER,
1060        RGBA = gl::RGBA,
1061        RGBAInteger = gl::RGBA_INTEGER,
1062        Luminance = gl::LUMINANCE,
1063        LuminanceAlpha = gl::LUMINANCE_ALPHA,
1064        Luminance32f = gl_ext_constants::LUMINANCE32F_ARB,
1065        Luminance16f = gl_ext_constants::LUMINANCE16F_ARB,
1066        LuminanceAlpha32f = gl_ext_constants::LUMINANCE_ALPHA32F_ARB,
1067        LuminanceAlpha16f = gl_ext_constants::LUMINANCE_ALPHA16F_ARB,
1068        CompressedRgbS3tcDxt1 = gl::COMPRESSED_RGB_S3TC_DXT1_EXT,
1069        CompressedRgbaS3tcDxt1 = gl::COMPRESSED_RGBA_S3TC_DXT1_EXT,
1070        CompressedRgbaS3tcDxt3 = gl::COMPRESSED_RGBA_S3TC_DXT3_EXT,
1071        CompressedRgbaS3tcDxt5 = gl::COMPRESSED_RGBA_S3TC_DXT5_EXT,
1072        CompressedRgbEtc1 = gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL,
1073        R8 = gl::R8,
1074        R8SNorm = gl::R8_SNORM,
1075        R16f = gl::R16F,
1076        R32f = gl::R32F,
1077        R8ui = gl::R8UI,
1078        R8i = gl::R8I,
1079        R16ui = gl::R16UI,
1080        R16i = gl::R16I,
1081        R32ui = gl::R32UI,
1082        R32i = gl::R32I,
1083        RG8 = gl::RG8,
1084        RG8SNorm = gl::RG8_SNORM,
1085        RG16f = gl::RG16F,
1086        RG32f = gl::RG32F,
1087        RG8ui = gl::RG8UI,
1088        RG8i = gl::RG8I,
1089        RG16ui = gl::RG16UI,
1090        RG16i = gl::RG16I,
1091        RG32ui = gl::RG32UI,
1092        RG32i = gl::RG32I,
1093        RGB8 = gl::RGB8,
1094        SRGB8 = gl::SRGB8,
1095        RGB565 = gl::RGB565,
1096        RGB8SNorm = gl::RGB8_SNORM,
1097        R11fG11fB10f = gl::R11F_G11F_B10F,
1098        RGB9E5 = gl::RGB9_E5,
1099        RGB16f = gl::RGB16F,
1100        RGB32f = gl::RGB32F,
1101        RGB8ui = gl::RGB8UI,
1102        RGB8i = gl::RGB8I,
1103        RGB16ui = gl::RGB16UI,
1104        RGB16i = gl::RGB16I,
1105        RGB32ui = gl::RGB32UI,
1106        RGB32i = gl::RGB32I,
1107        RGBA8 = gl::RGBA8,
1108        SRGB8Alpha8 = gl::SRGB8_ALPHA8,
1109        RGBA8SNorm = gl::RGBA8_SNORM,
1110        RGB5A1 = gl::RGB5_A1,
1111        RGBA4 = gl::RGBA4,
1112        RGB10A2 = gl::RGB10_A2,
1113        RGBA16f = gl::RGBA16F,
1114        RGBA32f = gl::RGBA32F,
1115        RGBA8ui = gl::RGBA8UI,
1116        RGBA8i = gl::RGBA8I,
1117        RGB10A2ui = gl::RGB10_A2UI,
1118        RGBA16ui = gl::RGBA16UI,
1119        RGBA16i = gl::RGBA16I,
1120        RGBA32i = gl::RGBA32I,
1121        RGBA32ui = gl::RGBA32UI,
1122        DepthComponent16 = gl::DEPTH_COMPONENT16,
1123        DepthComponent24 = gl::DEPTH_COMPONENT24,
1124        DepthComponent32f = gl::DEPTH_COMPONENT32F,
1125        Depth24Stencil8 = gl::DEPTH24_STENCIL8,
1126        Depth32fStencil8 = gl::DEPTH32F_STENCIL8,
1127    }
1128
1129    pub enum TexDataType {
1130        Byte = gl::BYTE,
1131        Int = gl::INT,
1132        Short = gl::SHORT,
1133        UnsignedByte = gl::UNSIGNED_BYTE,
1134        UnsignedInt = gl::UNSIGNED_INT,
1135        UnsignedInt10f11f11fRev = gl::UNSIGNED_INT_10F_11F_11F_REV,
1136        UnsignedInt2101010Rev = gl::UNSIGNED_INT_2_10_10_10_REV,
1137        UnsignedInt5999Rev = gl::UNSIGNED_INT_5_9_9_9_REV,
1138        UnsignedInt248 = gl::UNSIGNED_INT_24_8,
1139        UnsignedShort = gl::UNSIGNED_SHORT,
1140        UnsignedShort4444 = gl::UNSIGNED_SHORT_4_4_4_4,
1141        UnsignedShort5551 = gl::UNSIGNED_SHORT_5_5_5_1,
1142        UnsignedShort565 = gl::UNSIGNED_SHORT_5_6_5,
1143        Float = gl::FLOAT,
1144        HalfFloat = gl::HALF_FLOAT_OES,
1145        Float32UnsignedInt248Rev = gl::FLOAT_32_UNSIGNED_INT_24_8_REV,
1146    }
1147}
1148
1149impl TexFormat {
1150    /// Returns how many components does this format need. For example, RGBA
1151    /// needs 4 components, while RGB requires 3.
1152    pub fn components(&self) -> u32 {
1153        match self.to_unsized() {
1154            TexFormat::DepthStencil => 2,
1155            TexFormat::LuminanceAlpha => 2,
1156            TexFormat::RG | TexFormat::RGInteger => 2,
1157            TexFormat::RGB | TexFormat::RGBInteger => 3,
1158            TexFormat::RGBA | TexFormat::RGBAInteger => 4,
1159            _ => 1,
1160        }
1161    }
1162
1163    /// Returns whether this format is a known texture compression format.
1164    pub fn is_compressed(&self) -> bool {
1165        let gl_const = self.as_gl_constant();
1166        matches!(
1167            gl_const,
1168            gl::COMPRESSED_RGB_S3TC_DXT1_EXT |
1169                gl::COMPRESSED_RGBA_S3TC_DXT1_EXT |
1170                gl::COMPRESSED_RGBA_S3TC_DXT3_EXT |
1171                gl::COMPRESSED_RGBA_S3TC_DXT5_EXT |
1172                gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL
1173        )
1174    }
1175
1176    /// Returns whether this format is a known sized or unsized format.
1177    pub fn is_sized(&self) -> bool {
1178        !matches!(
1179            self,
1180            TexFormat::DepthComponent |
1181                TexFormat::DepthStencil |
1182                TexFormat::Alpha |
1183                TexFormat::Red |
1184                TexFormat::RG |
1185                TexFormat::RGB |
1186                TexFormat::RGBA |
1187                TexFormat::Luminance |
1188                TexFormat::LuminanceAlpha
1189        )
1190    }
1191
1192    pub fn to_unsized(self) -> TexFormat {
1193        match self {
1194            TexFormat::R8 => TexFormat::Red,
1195            TexFormat::R8SNorm => TexFormat::Red,
1196            TexFormat::R16f => TexFormat::Red,
1197            TexFormat::R32f => TexFormat::Red,
1198            TexFormat::R8ui => TexFormat::RedInteger,
1199            TexFormat::R8i => TexFormat::RedInteger,
1200            TexFormat::R16ui => TexFormat::RedInteger,
1201            TexFormat::R16i => TexFormat::RedInteger,
1202            TexFormat::R32ui => TexFormat::RedInteger,
1203            TexFormat::R32i => TexFormat::RedInteger,
1204            TexFormat::RG8 => TexFormat::RG,
1205            TexFormat::RG8SNorm => TexFormat::RG,
1206            TexFormat::RG16f => TexFormat::RG,
1207            TexFormat::RG32f => TexFormat::RG,
1208            TexFormat::RG8ui => TexFormat::RGInteger,
1209            TexFormat::RG8i => TexFormat::RGInteger,
1210            TexFormat::RG16ui => TexFormat::RGInteger,
1211            TexFormat::RG16i => TexFormat::RGInteger,
1212            TexFormat::RG32ui => TexFormat::RGInteger,
1213            TexFormat::RG32i => TexFormat::RGInteger,
1214            TexFormat::RGB8 => TexFormat::RGB,
1215            TexFormat::SRGB8 => TexFormat::RGB,
1216            TexFormat::RGB565 => TexFormat::RGB,
1217            TexFormat::RGB8SNorm => TexFormat::RGB,
1218            TexFormat::R11fG11fB10f => TexFormat::RGB,
1219            TexFormat::RGB9E5 => TexFormat::RGB,
1220            TexFormat::RGB16f => TexFormat::RGB,
1221            TexFormat::RGB32f => TexFormat::RGB,
1222            TexFormat::RGB8ui => TexFormat::RGBInteger,
1223            TexFormat::RGB8i => TexFormat::RGBInteger,
1224            TexFormat::RGB16ui => TexFormat::RGBInteger,
1225            TexFormat::RGB16i => TexFormat::RGBInteger,
1226            TexFormat::RGB32ui => TexFormat::RGBInteger,
1227            TexFormat::RGB32i => TexFormat::RGBInteger,
1228            TexFormat::RGBA8 => TexFormat::RGBA,
1229            TexFormat::SRGB8Alpha8 => TexFormat::RGBA,
1230            TexFormat::RGBA8SNorm => TexFormat::RGBA,
1231            TexFormat::RGB5A1 => TexFormat::RGBA,
1232            TexFormat::RGBA4 => TexFormat::RGBA,
1233            TexFormat::RGB10A2 => TexFormat::RGBA,
1234            TexFormat::RGBA16f => TexFormat::RGBA,
1235            TexFormat::RGBA32f => TexFormat::RGBA,
1236            TexFormat::RGBA8ui => TexFormat::RGBAInteger,
1237            TexFormat::RGBA8i => TexFormat::RGBAInteger,
1238            TexFormat::RGB10A2ui => TexFormat::RGBAInteger,
1239            TexFormat::RGBA16ui => TexFormat::RGBAInteger,
1240            TexFormat::RGBA16i => TexFormat::RGBAInteger,
1241            TexFormat::RGBA32i => TexFormat::RGBAInteger,
1242            TexFormat::RGBA32ui => TexFormat::RGBAInteger,
1243            TexFormat::DepthComponent16 => TexFormat::DepthComponent,
1244            TexFormat::DepthComponent24 => TexFormat::DepthComponent,
1245            TexFormat::DepthComponent32f => TexFormat::DepthComponent,
1246            TexFormat::Depth24Stencil8 => TexFormat::DepthStencil,
1247            TexFormat::Depth32fStencil8 => TexFormat::DepthStencil,
1248            TexFormat::Alpha32f => TexFormat::Alpha,
1249            TexFormat::Alpha16f => TexFormat::Alpha,
1250            TexFormat::Luminance32f => TexFormat::Luminance,
1251            TexFormat::Luminance16f => TexFormat::Luminance,
1252            TexFormat::LuminanceAlpha32f => TexFormat::LuminanceAlpha,
1253            TexFormat::LuminanceAlpha16f => TexFormat::LuminanceAlpha,
1254            _ => self,
1255        }
1256    }
1257
1258    pub fn compatible_data_types(self) -> &'static [TexDataType] {
1259        match self {
1260            TexFormat::RGB => &[
1261                TexDataType::UnsignedByte,
1262                TexDataType::UnsignedShort565,
1263                TexDataType::Float,
1264                TexDataType::HalfFloat,
1265            ][..],
1266            TexFormat::RGBA => &[
1267                TexDataType::UnsignedByte,
1268                TexDataType::UnsignedShort4444,
1269                TexDataType::UnsignedShort5551,
1270                TexDataType::Float,
1271                TexDataType::HalfFloat,
1272            ][..],
1273            TexFormat::LuminanceAlpha => &[
1274                TexDataType::UnsignedByte,
1275                TexDataType::Float,
1276                TexDataType::HalfFloat,
1277            ][..],
1278            TexFormat::Luminance => &[
1279                TexDataType::UnsignedByte,
1280                TexDataType::Float,
1281                TexDataType::HalfFloat,
1282            ][..],
1283            TexFormat::Alpha => &[
1284                TexDataType::UnsignedByte,
1285                TexDataType::Float,
1286                TexDataType::HalfFloat,
1287            ][..],
1288            TexFormat::LuminanceAlpha32f => &[TexDataType::Float][..],
1289            TexFormat::LuminanceAlpha16f => &[TexDataType::HalfFloat][..],
1290            TexFormat::Luminance32f => &[TexDataType::Float][..],
1291            TexFormat::Luminance16f => &[TexDataType::HalfFloat][..],
1292            TexFormat::Alpha32f => &[TexDataType::Float][..],
1293            TexFormat::Alpha16f => &[TexDataType::HalfFloat][..],
1294            TexFormat::R8 => &[TexDataType::UnsignedByte][..],
1295            TexFormat::R8SNorm => &[TexDataType::Byte][..],
1296            TexFormat::R16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1297            TexFormat::R32f => &[TexDataType::Float][..],
1298            TexFormat::R8ui => &[TexDataType::UnsignedByte][..],
1299            TexFormat::R8i => &[TexDataType::Byte][..],
1300            TexFormat::R16ui => &[TexDataType::UnsignedShort][..],
1301            TexFormat::R16i => &[TexDataType::Short][..],
1302            TexFormat::R32ui => &[TexDataType::UnsignedInt][..],
1303            TexFormat::R32i => &[TexDataType::Int][..],
1304            TexFormat::RG8 => &[TexDataType::UnsignedByte][..],
1305            TexFormat::RG8SNorm => &[TexDataType::Byte][..],
1306            TexFormat::RG16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1307            TexFormat::RG32f => &[TexDataType::Float][..],
1308            TexFormat::RG8ui => &[TexDataType::UnsignedByte][..],
1309            TexFormat::RG8i => &[TexDataType::Byte][..],
1310            TexFormat::RG16ui => &[TexDataType::UnsignedShort][..],
1311            TexFormat::RG16i => &[TexDataType::Short][..],
1312            TexFormat::RG32ui => &[TexDataType::UnsignedInt][..],
1313            TexFormat::RG32i => &[TexDataType::Int][..],
1314            TexFormat::RGB8 => &[TexDataType::UnsignedByte][..],
1315            TexFormat::SRGB8 => &[TexDataType::UnsignedByte][..],
1316            TexFormat::RGB565 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort565][..],
1317            TexFormat::RGB8SNorm => &[TexDataType::Byte][..],
1318            TexFormat::R11fG11fB10f => &[
1319                TexDataType::UnsignedInt10f11f11fRev,
1320                TexDataType::HalfFloat,
1321                TexDataType::Float,
1322            ][..],
1323            TexFormat::RGB9E5 => &[
1324                TexDataType::UnsignedInt5999Rev,
1325                TexDataType::HalfFloat,
1326                TexDataType::Float,
1327            ][..],
1328            TexFormat::RGB16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1329            TexFormat::RGB32f => &[TexDataType::Float][..],
1330            TexFormat::RGB8ui => &[TexDataType::UnsignedByte][..],
1331            TexFormat::RGB8i => &[TexDataType::Byte][..],
1332            TexFormat::RGB16ui => &[TexDataType::UnsignedShort][..],
1333            TexFormat::RGB16i => &[TexDataType::Short][..],
1334            TexFormat::RGB32ui => &[TexDataType::UnsignedInt][..],
1335            TexFormat::RGB32i => &[TexDataType::Int][..],
1336            TexFormat::RGBA8 => &[TexDataType::UnsignedByte][..],
1337            TexFormat::SRGB8Alpha8 => &[TexDataType::UnsignedByte][..],
1338            TexFormat::RGBA8SNorm => &[TexDataType::Byte][..],
1339            TexFormat::RGB5A1 => &[
1340                TexDataType::UnsignedByte,
1341                TexDataType::UnsignedShort5551,
1342                TexDataType::UnsignedInt2101010Rev,
1343            ][..],
1344            TexFormat::RGBA4 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort4444][..],
1345            TexFormat::RGB10A2 => &[TexDataType::UnsignedInt2101010Rev][..],
1346            TexFormat::RGBA16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1347            TexFormat::RGBA32f => &[TexDataType::Float][..],
1348            TexFormat::RGBA8ui => &[TexDataType::UnsignedByte][..],
1349            TexFormat::RGBA8i => &[TexDataType::Byte][..],
1350            TexFormat::RGB10A2ui => &[TexDataType::UnsignedInt2101010Rev][..],
1351            TexFormat::RGBA16ui => &[TexDataType::UnsignedShort][..],
1352            TexFormat::RGBA16i => &[TexDataType::Short][..],
1353            TexFormat::RGBA32i => &[TexDataType::Int][..],
1354            TexFormat::RGBA32ui => &[TexDataType::UnsignedInt][..],
1355            TexFormat::DepthComponent16 => {
1356                &[TexDataType::UnsignedShort, TexDataType::UnsignedInt][..]
1357            },
1358            TexFormat::DepthComponent24 => &[TexDataType::UnsignedInt][..],
1359            TexFormat::DepthComponent32f => &[TexDataType::Float][..],
1360            TexFormat::Depth24Stencil8 => &[TexDataType::UnsignedInt248][..],
1361            TexFormat::Depth32fStencil8 => &[TexDataType::Float32UnsignedInt248Rev][..],
1362            TexFormat::CompressedRgbS3tcDxt1 |
1363            TexFormat::CompressedRgbaS3tcDxt1 |
1364            TexFormat::CompressedRgbaS3tcDxt3 |
1365            TexFormat::CompressedRgbaS3tcDxt5 => &[TexDataType::UnsignedByte][..],
1366            _ => &[][..],
1367        }
1368    }
1369
1370    pub fn required_webgl_version(self) -> WebGLVersion {
1371        match self {
1372            TexFormat::DepthComponent |
1373            TexFormat::Alpha |
1374            TexFormat::RGB |
1375            TexFormat::RGBA |
1376            TexFormat::Luminance |
1377            TexFormat::LuminanceAlpha |
1378            TexFormat::CompressedRgbS3tcDxt1 |
1379            TexFormat::CompressedRgbaS3tcDxt1 |
1380            TexFormat::CompressedRgbaS3tcDxt3 |
1381            TexFormat::CompressedRgbaS3tcDxt5 => WebGLVersion::WebGL1,
1382            _ => WebGLVersion::WebGL2,
1383        }
1384    }
1385
1386    pub fn usable_as_internal(self) -> bool {
1387        !self.compatible_data_types().is_empty()
1388    }
1389}
1390
1391/// How a color format stores each component.
1392#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1393pub enum TexComponentType {
1394    UnsignedNormalized,
1395    SignedNormalized,
1396    Float,
1397    SignedInt,
1398    UnsignedInt,
1399}
1400
1401impl TexFormat {
1402    /// Returns the component type of a sized color format; `None` for unsized, depth, stencil
1403    /// and compressed formats.
1404    pub fn component_type(self) -> Option<TexComponentType> {
1405        use TexComponentType::*;
1406        Some(match self {
1407            TexFormat::R8 |
1408            TexFormat::RG8 |
1409            TexFormat::RGB8 |
1410            TexFormat::SRGB8 |
1411            TexFormat::RGB565 |
1412            TexFormat::RGBA8 |
1413            TexFormat::SRGB8Alpha8 |
1414            TexFormat::RGB5A1 |
1415            TexFormat::RGBA4 |
1416            TexFormat::RGB10A2 => UnsignedNormalized,
1417            TexFormat::R8SNorm |
1418            TexFormat::RG8SNorm |
1419            TexFormat::RGB8SNorm |
1420            TexFormat::RGBA8SNorm => SignedNormalized,
1421            TexFormat::R16f |
1422            TexFormat::R32f |
1423            TexFormat::RG16f |
1424            TexFormat::RG32f |
1425            TexFormat::R11fG11fB10f |
1426            TexFormat::RGB9E5 |
1427            TexFormat::RGB16f |
1428            TexFormat::RGB32f |
1429            TexFormat::RGBA16f |
1430            TexFormat::RGBA32f |
1431            TexFormat::Alpha16f |
1432            TexFormat::Alpha32f |
1433            TexFormat::Luminance16f |
1434            TexFormat::Luminance32f |
1435            TexFormat::LuminanceAlpha16f |
1436            TexFormat::LuminanceAlpha32f => Float,
1437            TexFormat::R8i |
1438            TexFormat::R16i |
1439            TexFormat::R32i |
1440            TexFormat::RG8i |
1441            TexFormat::RG16i |
1442            TexFormat::RG32i |
1443            TexFormat::RGB8i |
1444            TexFormat::RGB16i |
1445            TexFormat::RGB32i |
1446            TexFormat::RGBA8i |
1447            TexFormat::RGBA16i |
1448            TexFormat::RGBA32i => SignedInt,
1449            TexFormat::R8ui |
1450            TexFormat::R16ui |
1451            TexFormat::R32ui |
1452            TexFormat::RG8ui |
1453            TexFormat::RG16ui |
1454            TexFormat::RG32ui |
1455            TexFormat::RGB8ui |
1456            TexFormat::RGB16ui |
1457            TexFormat::RGB32ui |
1458            TexFormat::RGBA8ui |
1459            TexFormat::RGB10A2ui |
1460            TexFormat::RGBA16ui |
1461            TexFormat::RGBA32ui => UnsignedInt,
1462            _ => return None,
1463        })
1464    }
1465
1466    /// Returns the bits per red, green, blue and alpha component of a sized color format, with
1467    /// luminance counted as red; `None` for unsized, depth, stencil and compressed formats.
1468    pub fn component_sizes(self) -> Option<[u8; 4]> {
1469        Some(match self {
1470            TexFormat::R8 | TexFormat::R8SNorm | TexFormat::R8i | TexFormat::R8ui => [8, 0, 0, 0],
1471            TexFormat::R16f | TexFormat::R16i | TexFormat::R16ui | TexFormat::Luminance16f => {
1472                [16, 0, 0, 0]
1473            },
1474            TexFormat::R32f | TexFormat::R32i | TexFormat::R32ui | TexFormat::Luminance32f => {
1475                [32, 0, 0, 0]
1476            },
1477            TexFormat::Alpha16f => [0, 0, 0, 16],
1478            TexFormat::Alpha32f => [0, 0, 0, 32],
1479            TexFormat::LuminanceAlpha16f => [16, 0, 0, 16],
1480            TexFormat::LuminanceAlpha32f => [32, 0, 0, 32],
1481            TexFormat::RG8 | TexFormat::RG8SNorm | TexFormat::RG8i | TexFormat::RG8ui => {
1482                [8, 8, 0, 0]
1483            },
1484            TexFormat::RG16f | TexFormat::RG16i | TexFormat::RG16ui => [16, 16, 0, 0],
1485            TexFormat::RG32f | TexFormat::RG32i | TexFormat::RG32ui => [32, 32, 0, 0],
1486            TexFormat::RGB8 |
1487            TexFormat::SRGB8 |
1488            TexFormat::RGB8SNorm |
1489            TexFormat::RGB8i |
1490            TexFormat::RGB8ui => [8, 8, 8, 0],
1491            TexFormat::RGB565 => [5, 6, 5, 0],
1492            TexFormat::R11fG11fB10f => [11, 11, 10, 0],
1493            TexFormat::RGB9E5 => [9, 9, 9, 0],
1494            TexFormat::RGB16f | TexFormat::RGB16i | TexFormat::RGB16ui => [16, 16, 16, 0],
1495            TexFormat::RGB32f | TexFormat::RGB32i | TexFormat::RGB32ui => [32, 32, 32, 0],
1496            TexFormat::RGBA8 |
1497            TexFormat::SRGB8Alpha8 |
1498            TexFormat::RGBA8SNorm |
1499            TexFormat::RGBA8i |
1500            TexFormat::RGBA8ui => [8, 8, 8, 8],
1501            TexFormat::RGB5A1 => [5, 5, 5, 1],
1502            TexFormat::RGBA4 => [4, 4, 4, 4],
1503            TexFormat::RGB10A2 | TexFormat::RGB10A2ui => [10, 10, 10, 2],
1504            TexFormat::RGBA16f | TexFormat::RGBA16i | TexFormat::RGBA16ui => [16, 16, 16, 16],
1505            TexFormat::RGBA32f | TexFormat::RGBA32i | TexFormat::RGBA32ui => [32, 32, 32, 32],
1506            _ => return None,
1507        })
1508    }
1509
1510    pub fn is_srgb(self) -> bool {
1511        matches!(self, TexFormat::SRGB8 | TexFormat::SRGB8Alpha8)
1512    }
1513
1514    /// Returns the sized format corresponding to this unsized format and `data_type`
1515    /// (OpenGL ES 3.0.6 table 3.12); a sized format is returned unchanged.
1516    pub fn effective_internal_format(self, data_type: TexDataType) -> TexFormat {
1517        match (self, data_type) {
1518            (TexFormat::RGBA, TexDataType::UnsignedByte) => TexFormat::RGBA8,
1519            (TexFormat::RGBA, TexDataType::UnsignedShort4444) => TexFormat::RGBA4,
1520            (TexFormat::RGBA, TexDataType::UnsignedShort5551) => TexFormat::RGB5A1,
1521            (TexFormat::RGBA, TexDataType::HalfFloat) => TexFormat::RGBA16f,
1522            (TexFormat::RGBA, TexDataType::Float) => TexFormat::RGBA32f,
1523            (TexFormat::RGB, TexDataType::UnsignedByte) => TexFormat::RGB8,
1524            (TexFormat::RGB, TexDataType::UnsignedShort565) => TexFormat::RGB565,
1525            (TexFormat::RGB, TexDataType::HalfFloat) => TexFormat::RGB16f,
1526            (TexFormat::RGB, TexDataType::Float) => TexFormat::RGB32f,
1527            (TexFormat::Alpha, TexDataType::HalfFloat) => TexFormat::Alpha16f,
1528            (TexFormat::Alpha, TexDataType::Float) => TexFormat::Alpha32f,
1529            (TexFormat::Luminance, TexDataType::HalfFloat) => TexFormat::Luminance16f,
1530            (TexFormat::Luminance, TexDataType::Float) => TexFormat::Luminance32f,
1531            (TexFormat::LuminanceAlpha, TexDataType::HalfFloat) => TexFormat::LuminanceAlpha16f,
1532            (TexFormat::LuminanceAlpha, TexDataType::Float) => TexFormat::LuminanceAlpha32f,
1533            _ => self,
1534        }
1535    }
1536}
1537
1538#[derive(PartialEq)]
1539pub enum SizedDataType {
1540    Int8,
1541    Int16,
1542    Int32,
1543    Uint8,
1544    Uint16,
1545    Uint32,
1546    Float32,
1547}
1548
1549impl TexDataType {
1550    /// Parses a texture data type constant. `HalfFloat` stores WebGL 1's `HALF_FLOAT_OES`,
1551    /// while WebGL 2 uses `HALF_FLOAT` and does not define `OES_texture_half_float`.
1552    pub fn from_webgl_constant(constant: u32, version: WebGLVersion) -> Option<Self> {
1553        match (version, constant) {
1554            (WebGLVersion::WebGL2, gl::HALF_FLOAT) => Some(TexDataType::HalfFloat),
1555            (WebGLVersion::WebGL2, gl::HALF_FLOAT_OES) => None,
1556            _ => Self::from_gl_constant(constant),
1557        }
1558    }
1559
1560    /// Returns the compatible sized data type for this texture data type.
1561    pub fn sized_data_type(&self) -> SizedDataType {
1562        match self {
1563            TexDataType::Byte => SizedDataType::Int8,
1564            TexDataType::UnsignedByte => SizedDataType::Uint8,
1565            TexDataType::Short => SizedDataType::Int16,
1566            TexDataType::UnsignedShort |
1567            TexDataType::UnsignedShort4444 |
1568            TexDataType::UnsignedShort5551 |
1569            TexDataType::UnsignedShort565 => SizedDataType::Uint16,
1570            TexDataType::Int => SizedDataType::Int32,
1571            TexDataType::UnsignedInt |
1572            TexDataType::UnsignedInt10f11f11fRev |
1573            TexDataType::UnsignedInt2101010Rev |
1574            TexDataType::UnsignedInt5999Rev |
1575            TexDataType::UnsignedInt248 => SizedDataType::Uint32,
1576            TexDataType::HalfFloat => SizedDataType::Uint16,
1577            TexDataType::Float | TexDataType::Float32UnsignedInt248Rev => SizedDataType::Float32,
1578        }
1579    }
1580
1581    /// Returns the size in bytes of each element of data.
1582    pub fn element_size(&self) -> u32 {
1583        use self::*;
1584        match *self {
1585            TexDataType::Byte | TexDataType::UnsignedByte => 1,
1586            TexDataType::Short |
1587            TexDataType::UnsignedShort |
1588            TexDataType::UnsignedShort4444 |
1589            TexDataType::UnsignedShort5551 |
1590            TexDataType::UnsignedShort565 => 2,
1591            TexDataType::Int |
1592            TexDataType::UnsignedInt |
1593            TexDataType::UnsignedInt10f11f11fRev |
1594            TexDataType::UnsignedInt2101010Rev |
1595            TexDataType::UnsignedInt5999Rev => 4,
1596            TexDataType::UnsignedInt248 => 4,
1597            TexDataType::Float => 4,
1598            TexDataType::HalfFloat => 2,
1599            TexDataType::Float32UnsignedInt248Rev => 4,
1600        }
1601    }
1602
1603    /// Returns how many components a single element may hold. For example, a
1604    /// UnsignedShort4444 holds four components, each with 4 bits of data.
1605    pub fn components_per_element(&self) -> u32 {
1606        match *self {
1607            TexDataType::Byte => 1,
1608            TexDataType::UnsignedByte => 1,
1609            TexDataType::Short => 1,
1610            TexDataType::UnsignedShort => 1,
1611            TexDataType::UnsignedShort565 => 3,
1612            TexDataType::UnsignedShort5551 => 4,
1613            TexDataType::UnsignedShort4444 => 4,
1614            TexDataType::Int => 1,
1615            TexDataType::UnsignedInt => 1,
1616            TexDataType::UnsignedInt10f11f11fRev => 3,
1617            TexDataType::UnsignedInt2101010Rev => 4,
1618            TexDataType::UnsignedInt5999Rev => 4,
1619            TexDataType::UnsignedInt248 => 2,
1620            TexDataType::Float => 1,
1621            TexDataType::HalfFloat => 1,
1622            TexDataType::Float32UnsignedInt248Rev => 2,
1623        }
1624    }
1625
1626    pub fn required_webgl_version(self) -> WebGLVersion {
1627        match self {
1628            TexDataType::UnsignedByte |
1629            TexDataType::UnsignedShort4444 |
1630            TexDataType::UnsignedShort5551 |
1631            TexDataType::UnsignedShort565 |
1632            TexDataType::Float |
1633            TexDataType::HalfFloat => WebGLVersion::WebGL1,
1634            _ => WebGLVersion::WebGL2,
1635        }
1636    }
1637}
1638
1639#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
1640pub enum AlphaTreatment {
1641    Premultiply,
1642    Unmultiply,
1643}
1644
1645#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
1646pub enum YAxisTreatment {
1647    AsIs,
1648    Flipped,
1649}
1650
1651#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1652pub struct GLContextAttributes {
1653    pub alpha: bool,
1654    pub depth: bool,
1655    pub stencil: bool,
1656    pub antialias: bool,
1657    pub premultiplied_alpha: bool,
1658    pub preserve_drawing_buffer: bool,
1659}
1660
1661#[derive(Clone, Debug, Deserialize, Serialize)]
1662pub struct GLLimits {
1663    pub max_vertex_attribs: u32,
1664    pub max_tex_size: u32,
1665    pub max_3d_tex_size: u32,
1666    pub max_cube_map_tex_size: u32,
1667    pub max_combined_texture_image_units: u32,
1668    pub max_fragment_uniform_vectors: u32,
1669    pub max_renderbuffer_size: u32,
1670    pub max_texture_image_units: u32,
1671    pub max_varying_vectors: u32,
1672    pub max_vertex_texture_image_units: u32,
1673    pub max_vertex_uniform_vectors: u32,
1674    pub max_client_wait_timeout_webgl: std::time::Duration,
1675    pub max_transform_feedback_separate_attribs: u32,
1676    pub max_vertex_output_vectors: u32,
1677    pub max_fragment_input_vectors: u32,
1678    pub max_draw_buffers: u32,
1679    pub max_color_attachments: u32,
1680    pub max_uniform_buffer_bindings: u32,
1681    pub min_program_texel_offset: i32,
1682    pub max_program_texel_offset: u32,
1683    pub max_uniform_block_size: u64,
1684    pub max_combined_uniform_blocks: u32,
1685    pub max_combined_vertex_uniform_components: u64,
1686    pub max_combined_fragment_uniform_components: u64,
1687    pub max_vertex_uniform_blocks: u32,
1688    pub max_vertex_uniform_components: u32,
1689    pub max_fragment_uniform_blocks: u32,
1690    pub max_fragment_uniform_components: u32,
1691    pub max_3d_texture_size: u32,
1692    pub max_array_texture_layers: u32,
1693    pub uniform_buffer_offset_alignment: u32,
1694    pub max_element_index: u64,
1695    pub max_elements_indices: u32,
1696    pub max_elements_vertices: u32,
1697    pub max_fragment_input_components: u32,
1698    pub max_samples: u32,
1699    pub max_server_wait_timeout: std::time::Duration,
1700    pub max_texture_lod_bias: f32,
1701    pub max_varying_components: u32,
1702    pub max_vertex_output_components: u32,
1703}