Skip to main content

servo_canvas_traits/
webgl.rs

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