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