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