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    GetParameterUInt(ParameterUInt, GenericSender<u32>),
494    GetParameterInt2(ParameterInt2, GenericSender<[i32; 2]>),
495    GetParameterInt4(ParameterInt4, GenericSender<[i32; 4]>),
496    GetParameterFloat(ParameterFloat, GenericSender<f32>),
497    GetParameterFloat2(ParameterFloat2, GenericSender<[f32; 2]>),
498    GetParameterFloat4(ParameterFloat4, GenericSender<[f32; 4]>),
499    GetProgramValidateStatus(WebGLProgramId, GenericSender<bool>),
500    GetProgramActiveUniforms(WebGLProgramId, GenericSender<i32>),
501    GetCurrentVertexAttrib(u32, GenericSender<[f32; 4]>),
502    GetTexParameterFloat(u32, TexParameterFloat, GenericSender<f32>),
503    GetTexParameterInt(u32, TexParameterInt, GenericSender<i32>),
504    GetTexParameterBool(u32, TexParameterBool, GenericSender<bool>),
505    GetInternalFormatIntVec(u32, u32, InternalFormatIntVec, GenericSender<Vec<i32>>),
506    TexParameteri(u32, u32, i32),
507    TexParameterf(u32, u32, f32),
508    TexStorage2D(u32, u32, TexFormat, u32, u32),
509    TexStorage3D(u32, u32, TexFormat, u32, u32, u32),
510    DrawArrays {
511        mode: u32,
512        first: i32,
513        count: i32,
514    },
515    DrawArraysInstanced {
516        mode: u32,
517        first: i32,
518        count: i32,
519        primcount: i32,
520    },
521    DrawElements {
522        mode: u32,
523        count: i32,
524        type_: u32,
525        offset: u32,
526    },
527    DrawElementsInstanced {
528        mode: u32,
529        count: i32,
530        type_: u32,
531        offset: u32,
532        primcount: i32,
533    },
534    VertexAttribDivisor {
535        index: u32,
536        divisor: u32,
537    },
538    GetUniformBool(WebGLProgramId, i32, GenericSender<bool>),
539    GetUniformBool2(WebGLProgramId, i32, GenericSender<[bool; 2]>),
540    GetUniformBool3(WebGLProgramId, i32, GenericSender<[bool; 3]>),
541    GetUniformBool4(WebGLProgramId, i32, GenericSender<[bool; 4]>),
542    GetUniformInt(WebGLProgramId, i32, GenericSender<i32>),
543    GetUniformInt2(WebGLProgramId, i32, GenericSender<[i32; 2]>),
544    GetUniformInt3(WebGLProgramId, i32, GenericSender<[i32; 3]>),
545    GetUniformInt4(WebGLProgramId, i32, GenericSender<[i32; 4]>),
546    GetUniformUint(WebGLProgramId, i32, GenericSender<u32>),
547    GetUniformUint2(WebGLProgramId, i32, GenericSender<[u32; 2]>),
548    GetUniformUint3(WebGLProgramId, i32, GenericSender<[u32; 3]>),
549    GetUniformUint4(WebGLProgramId, i32, GenericSender<[u32; 4]>),
550    GetUniformFloat(WebGLProgramId, i32, GenericSender<f32>),
551    GetUniformFloat2(WebGLProgramId, i32, GenericSender<[f32; 2]>),
552    GetUniformFloat3(WebGLProgramId, i32, GenericSender<[f32; 3]>),
553    GetUniformFloat4(WebGLProgramId, i32, GenericSender<[f32; 4]>),
554    GetUniformFloat9(WebGLProgramId, i32, GenericSender<[f32; 9]>),
555    GetUniformFloat16(WebGLProgramId, i32, GenericSender<[f32; 16]>),
556    GetUniformFloat2x3(WebGLProgramId, i32, GenericSender<[f32; 2 * 3]>),
557    GetUniformFloat2x4(WebGLProgramId, i32, GenericSender<[f32; 2 * 4]>),
558    GetUniformFloat3x2(WebGLProgramId, i32, GenericSender<[f32; 3 * 2]>),
559    GetUniformFloat3x4(WebGLProgramId, i32, GenericSender<[f32; 3 * 4]>),
560    GetUniformFloat4x2(WebGLProgramId, i32, GenericSender<[f32; 4 * 2]>),
561    GetUniformFloat4x3(WebGLProgramId, i32, GenericSender<[f32; 4 * 3]>),
562    GetUniformBlockIndex(WebGLProgramId, String, GenericSender<u32>),
563    GetUniformIndices(WebGLProgramId, Vec<String>, GenericSender<Vec<u32>>),
564    GetActiveUniforms(WebGLProgramId, Vec<u32>, u32, GenericSender<Vec<i32>>),
565    GetActiveUniformBlockName(WebGLProgramId, u32, GenericSender<String>),
566    GetActiveUniformBlockParameter(WebGLProgramId, u32, u32, GenericSender<Vec<i32>>),
567    UniformBlockBinding(WebGLProgramId, u32, u32),
568    InitializeFramebuffer {
569        color: bool,
570        depth: bool,
571        stencil: bool,
572    },
573    BeginQuery(u32, WebGLQueryId),
574    DeleteQuery(WebGLQueryId),
575    EndQuery(u32),
576    GenerateQuery(GenericSender<WebGLQueryId>),
577    GetQueryState(GenericSender<u32>, WebGLQueryId, u32),
578    GenerateSampler(GenericSender<WebGLSamplerId>),
579    DeleteSampler(WebGLSamplerId),
580    BindSampler(u32, WebGLSamplerId),
581    SetSamplerParameterFloat(WebGLSamplerId, u32, f32),
582    SetSamplerParameterInt(WebGLSamplerId, u32, i32),
583    GetSamplerParameterFloat(WebGLSamplerId, u32, GenericSender<f32>),
584    GetSamplerParameterInt(WebGLSamplerId, u32, GenericSender<i32>),
585    BindBufferBase(u32, u32, Option<WebGLBufferId>),
586    BindBufferRange(u32, u32, Option<WebGLBufferId>, i64, i64),
587    ClearBufferfv(u32, i32, Vec<f32>),
588    ClearBufferiv(u32, i32, Vec<i32>),
589    ClearBufferuiv(u32, i32, Vec<u32>),
590    ClearBufferfi(u32, i32, f32, i32),
591    InvalidateFramebuffer(u32, Vec<u32>),
592    InvalidateSubFramebuffer(u32, Vec<u32>, i32, i32, i32, i32),
593    FramebufferTextureLayer(u32, u32, Option<WebGLTextureId>, i32, i32),
594    ReadBuffer(u32),
595    DrawBuffers(Vec<u32>),
596}
597
598/// WebXR layer management
599#[derive(Debug, Deserialize, Serialize)]
600pub enum WebXRCommand {
601    CreateLayerManager(GenericSender<Result<WebXRLayerManagerId, WebXRError>>),
602    DestroyLayerManager(WebXRLayerManagerId),
603    CreateLayer(
604        WebXRLayerManagerId,
605        WebXRContextId,
606        WebXRLayerInit,
607        GenericSender<Result<WebXRLayerId, WebXRError>>,
608    ),
609    DestroyLayer(WebXRLayerManagerId, WebXRContextId, WebXRLayerId),
610    BeginFrame(
611        WebXRLayerManagerId,
612        Vec<(WebXRContextId, WebXRLayerId)>,
613        GenericSender<Result<Vec<WebXRSubImages>, WebXRError>>,
614    ),
615    EndFrame(
616        WebXRLayerManagerId,
617        Vec<(WebXRContextId, WebXRLayerId)>,
618        GenericSender<Result<(), WebXRError>>,
619    ),
620}
621
622macro_rules! nonzero_type {
623    (u32) => {
624        NonZeroU32
625    };
626    (u64) => {
627        NonZeroU64
628    };
629}
630
631macro_rules! define_resource_id {
632    ($name:ident, $type:tt) => {
633        #[derive(Clone, Copy, Eq, Hash, PartialEq)]
634        pub struct $name(nonzero_type!($type));
635
636        impl $name {
637            #[inline]
638            pub fn new(id: nonzero_type!($type)) -> Self {
639                Self(id)
640            }
641
642            #[inline]
643            pub fn maybe_new(id: $type) -> Option<Self> {
644                <nonzero_type!($type)>::new(id).map($name)
645            }
646
647            #[inline]
648            pub fn get(self) -> $type {
649                self.0.get()
650            }
651        }
652
653        impl<'de> ::serde::Deserialize<'de> for $name {
654            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
655            where
656                D: ::serde::Deserializer<'de>,
657            {
658                let id = <$type>::deserialize(deserializer)?;
659                if let Some(id) = <nonzero_type!($type)>::new(id) {
660                    Ok($name(id))
661                } else {
662                    Err(::serde::de::Error::custom("expected a non-zero value"))
663                }
664            }
665        }
666
667        impl ::serde::Serialize for $name {
668            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
669            where
670                S: ::serde::Serializer,
671            {
672                self.get().serialize(serializer)
673            }
674        }
675
676        impl ::std::fmt::Debug for $name {
677            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
678                fmt.debug_tuple(stringify!($name))
679                    .field(&self.get())
680                    .finish()
681            }
682        }
683
684        impl ::std::fmt::Display for $name {
685            fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
686                write!(fmt, "{}", self.get())
687            }
688        }
689
690        impl ::malloc_size_of::MallocSizeOf for $name {
691            fn size_of(&self, _ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize {
692                0
693            }
694        }
695    };
696    ($name:ident, $type:tt, $glow:tt) => {
697        impl $name {
698            #[inline]
699            pub fn glow(self) -> $glow {
700                $glow(self.0)
701            }
702
703            #[inline]
704            pub fn from_glow(glow: $glow) -> Self {
705                Self(glow.0)
706            }
707        }
708        define_resource_id!($name, $type);
709    };
710}
711
712define_resource_id!(WebGLBufferId, u32, NativeBuffer);
713define_resource_id!(WebGLFramebufferId, u32, NativeFramebuffer);
714define_resource_id!(WebGLRenderbufferId, u32, NativeRenderbuffer);
715define_resource_id!(WebGLTextureId, u32, NativeTexture);
716define_resource_id!(WebGLProgramId, u32, NativeProgram);
717define_resource_id!(WebGLQueryId, u32, NativeQuery);
718define_resource_id!(WebGLSamplerId, u32, NativeSampler);
719define_resource_id!(WebGLShaderId, u32, NativeShader);
720define_resource_id!(WebGLSyncId, u64);
721impl WebGLSyncId {
722    #[inline]
723    pub fn glow(&self) -> NativeFence {
724        NativeFence(self.0.get() as _)
725    }
726
727    #[inline]
728    pub fn from_glow(glow: NativeFence) -> Self {
729        Self::maybe_new(glow.0 as _).expect("Glow should have valid fence")
730    }
731}
732define_resource_id!(WebGLVertexArrayId, u32, NativeVertexArray);
733define_resource_id!(WebXRLayerManagerId, u32);
734
735#[derive(
736    Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
737)]
738pub struct WebGLContextId(pub u64);
739
740impl From<WebXRContextId> for WebGLContextId {
741    fn from(id: WebXRContextId) -> Self {
742        Self(id.0)
743    }
744}
745
746impl From<WebGLContextId> for WebXRContextId {
747    fn from(id: WebGLContextId) -> Self {
748        Self(id.0)
749    }
750}
751
752#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, MallocSizeOf)]
753pub enum WebGLError {
754    InvalidEnum,
755    InvalidFramebufferOperation,
756    InvalidOperation,
757    InvalidValue,
758    OutOfMemory,
759    ContextLost,
760}
761
762#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
763pub enum WebGLFramebufferBindingRequest {
764    Explicit(WebGLFramebufferId),
765    Default,
766}
767
768pub type WebGLResult<T> = Result<T, WebGLError>;
769
770/// Information about a WebGL program linking operation.
771#[derive(Clone, Debug, Deserialize, Serialize)]
772pub struct ProgramLinkInfo {
773    /// Whether the program was linked successfully.
774    pub linked: bool,
775    /// The list of active attributes.
776    pub active_attribs: Box<[ActiveAttribInfo]>,
777    /// The list of active uniforms.
778    pub active_uniforms: Box<[ActiveUniformInfo]>,
779    /// The list of active uniform blocks.
780    pub active_uniform_blocks: Box<[ActiveUniformBlockInfo]>,
781    /// The number of varying variables
782    pub transform_feedback_length: i32,
783    /// The buffer mode used when transform feedback is active
784    pub transform_feedback_mode: i32,
785}
786
787/// Description of a single active attribute.
788#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
789pub struct ActiveAttribInfo {
790    /// The name of the attribute.
791    pub name: String,
792    /// The size of the attribute.
793    pub size: i32,
794    /// The type of the attribute.
795    pub type_: u32,
796    /// The location of the attribute.
797    pub location: Option<u32>,
798}
799
800/// Description of a single active uniform.
801#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
802pub struct ActiveUniformInfo {
803    /// The base name of the uniform.
804    pub base_name: Box<str>,
805    /// The size of the uniform, if it is an array.
806    pub size: Option<i32>,
807    /// The type of the uniform.
808    pub type_: u32,
809    /// The index of the indexed uniform buffer binding, if it is bound.
810    pub bind_index: Option<u32>,
811}
812
813impl ActiveUniformInfo {
814    pub fn name(&self) -> Cow<'_, str> {
815        if self.size.is_some() {
816            let mut name = String::from(&*self.base_name);
817            name.push_str("[0]");
818            Cow::Owned(name)
819        } else {
820            Cow::Borrowed(&self.base_name)
821        }
822    }
823}
824
825/// Description of a single uniform block.
826#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
827pub struct ActiveUniformBlockInfo {
828    /// The name of the uniform block.
829    pub name: String,
830    /// The size of the uniform block.
831    pub size: i32,
832}
833
834macro_rules! parameters {
835    ($name:ident { $(
836        $variant:ident($kind:ident { $(
837            $param:ident = gl::$value:ident,
838        )+ }),
839    )+ }) => {
840        #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
841        pub enum $name { $(
842            $variant($kind),
843        )+}
844
845        $(
846            #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
847            #[repr(u32)]
848            pub enum $kind { $(
849                $param = gl::$value,
850            )+}
851        )+
852
853        impl $name {
854            pub fn from_u32(value: u32) -> WebGLResult<Self> {
855                match value {
856                    $($(gl::$value => Ok($name::$variant($kind::$param)),)+)+
857                    _ => Err(WebGLError::InvalidEnum)
858                }
859            }
860        }
861    }
862}
863
864parameters! {
865    Parameter {
866        Bool(ParameterBool {
867            DepthWritemask = gl::DEPTH_WRITEMASK,
868            SampleCoverageInvert = gl::SAMPLE_COVERAGE_INVERT,
869            TransformFeedbackActive = gl::TRANSFORM_FEEDBACK_ACTIVE,
870            TransformFeedbackPaused = gl::TRANSFORM_FEEDBACK_PAUSED,
871            RasterizerDiscard = gl::RASTERIZER_DISCARD,
872        }),
873        Bool4(ParameterBool4 {
874            ColorWritemask = gl::COLOR_WRITEMASK,
875        }),
876        Int(ParameterInt {
877            ActiveTexture = gl::ACTIVE_TEXTURE,
878            AlphaBits = gl::ALPHA_BITS,
879            BlendDstAlpha = gl::BLEND_DST_ALPHA,
880            BlendDstRgb = gl::BLEND_DST_RGB,
881            BlendEquationAlpha = gl::BLEND_EQUATION_ALPHA,
882            BlendEquationRgb = gl::BLEND_EQUATION_RGB,
883            BlendSrcAlpha = gl::BLEND_SRC_ALPHA,
884            BlendSrcRgb = gl::BLEND_SRC_RGB,
885            BlueBits = gl::BLUE_BITS,
886            CullFaceMode = gl::CULL_FACE_MODE,
887            DepthBits = gl::DEPTH_BITS,
888            DepthFunc = gl::DEPTH_FUNC,
889            FragmentShaderDerivativeHint = gl::FRAGMENT_SHADER_DERIVATIVE_HINT,
890            FrontFace = gl::FRONT_FACE,
891            GenerateMipmapHint = gl::GENERATE_MIPMAP_HINT,
892            GreenBits = gl::GREEN_BITS,
893            RedBits = gl::RED_BITS,
894            SampleBuffers = gl::SAMPLE_BUFFERS,
895            Samples = gl::SAMPLES,
896            StencilBackFail = gl::STENCIL_BACK_FAIL,
897            StencilBackFunc = gl::STENCIL_BACK_FUNC,
898            StencilBackPassDepthFail = gl::STENCIL_BACK_PASS_DEPTH_FAIL,
899            StencilBackPassDepthPass = gl::STENCIL_BACK_PASS_DEPTH_PASS,
900            StencilBackRef = gl::STENCIL_BACK_REF,
901            StencilBits = gl::STENCIL_BITS,
902            StencilClearValue = gl::STENCIL_CLEAR_VALUE,
903            StencilFail = gl::STENCIL_FAIL,
904            StencilFunc = gl::STENCIL_FUNC,
905            StencilPassDepthFail = gl::STENCIL_PASS_DEPTH_FAIL,
906            StencilPassDepthPass = gl::STENCIL_PASS_DEPTH_PASS,
907            StencilRef = gl::STENCIL_REF,
908            SubpixelBits = gl::SUBPIXEL_BITS,
909            TransformFeedbackBinding = gl::TRANSFORM_FEEDBACK_BINDING,
910            MaxTransformFeedbackInterleavedComponents = gl::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
911            MaxTransformFeedbackSeparateAttribs = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
912            MaxTransformFeedbackSeparateComponents = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
913            TransformFeedbackBufferSize = gl::TRANSFORM_FEEDBACK_BUFFER_SIZE,
914            TransformFeedbackBufferStart = gl::TRANSFORM_FEEDBACK_BUFFER_START,
915            PackRowLength = gl::PACK_ROW_LENGTH,
916            PackSkipPixels = gl::PACK_SKIP_PIXELS,
917            PackSkipRows = gl::PACK_SKIP_ROWS,
918            UnpackImageHeight = gl::UNPACK_IMAGE_HEIGHT,
919            UnpackRowLength = gl::UNPACK_ROW_LENGTH,
920            UnpackSkipImages = gl::UNPACK_SKIP_IMAGES,
921            UnpackSkipPixels = gl::UNPACK_SKIP_PIXELS,
922            UnpackSkipRows = gl::UNPACK_SKIP_ROWS,
923        }),
924        UInt(ParameterUInt {
925            StencilBackValueMask = gl::STENCIL_BACK_VALUE_MASK,
926            StencilBackWritemask = gl::STENCIL_BACK_WRITEMASK,
927            StencilValueMask = gl::STENCIL_VALUE_MASK,
928            StencilWritemask = gl::STENCIL_WRITEMASK,
929        }),
930        Int2(ParameterInt2 {
931            MaxViewportDims = gl::MAX_VIEWPORT_DIMS,
932        }),
933        Int4(ParameterInt4 {
934            ScissorBox = gl::SCISSOR_BOX,
935            Viewport = gl::VIEWPORT,
936        }),
937        Float(ParameterFloat {
938            DepthClearValue = gl::DEPTH_CLEAR_VALUE,
939            LineWidth = gl::LINE_WIDTH,
940            MaxTextureMaxAnisotropyExt = gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT,
941            PolygonOffsetFactor = gl::POLYGON_OFFSET_FACTOR,
942            PolygonOffsetUnits = gl::POLYGON_OFFSET_UNITS,
943            SampleCoverageValue = gl::SAMPLE_COVERAGE_VALUE,
944        }),
945        Float2(ParameterFloat2 {
946            AliasedPointSizeRange = gl::ALIASED_POINT_SIZE_RANGE,
947            AliasedLineWidthRange = gl::ALIASED_LINE_WIDTH_RANGE,
948            DepthRange = gl::DEPTH_RANGE,
949        }),
950        Float4(ParameterFloat4 {
951            BlendColor = gl::BLEND_COLOR,
952            ColorClearValue = gl::COLOR_CLEAR_VALUE,
953        }),
954    }
955}
956
957parameters! {
958    TexParameter {
959        Float(TexParameterFloat {
960            TextureMaxAnisotropyExt = gl::TEXTURE_MAX_ANISOTROPY_EXT,
961            TextureMaxLod = gl::TEXTURE_MAX_LOD,
962            TextureMinLod = gl::TEXTURE_MIN_LOD,
963        }),
964        Int(TexParameterInt {
965            TextureWrapS = gl::TEXTURE_WRAP_S,
966            TextureWrapT = gl::TEXTURE_WRAP_T,
967            TextureWrapR = gl::TEXTURE_WRAP_R,
968            TextureBaseLevel = gl::TEXTURE_BASE_LEVEL,
969            TextureMinFilter = gl::TEXTURE_MIN_FILTER,
970            TextureMagFilter = gl::TEXTURE_MAG_FILTER,
971            TextureMaxLevel = gl::TEXTURE_MAX_LEVEL,
972            TextureCompareFunc = gl::TEXTURE_COMPARE_FUNC,
973            TextureCompareMode = gl::TEXTURE_COMPARE_MODE,
974            TextureImmutableLevels = gl::TEXTURE_IMMUTABLE_LEVELS,
975        }),
976        Bool(TexParameterBool {
977            TextureImmutableFormat = gl::TEXTURE_IMMUTABLE_FORMAT,
978        }),
979    }
980}
981
982impl TexParameter {
983    pub fn required_webgl_version(self) -> WebGLVersion {
984        match self {
985            Self::Float(TexParameterFloat::TextureMaxAnisotropyExt) |
986            Self::Int(TexParameterInt::TextureWrapS) |
987            Self::Int(TexParameterInt::TextureWrapT) => WebGLVersion::WebGL1,
988            _ => WebGLVersion::WebGL2,
989        }
990    }
991}
992
993parameters! {
994    InternalFormatParameter {
995        IntVec(InternalFormatIntVec {
996            Samples = gl::SAMPLES,
997        }),
998    }
999}
1000
1001#[macro_export]
1002macro_rules! gl_enums {
1003    ($(pub enum $name:ident { $($variant:ident = $mod:ident::$constant:ident,)+ })*) => {
1004        $(
1005            #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, malloc_size_of_derive::MallocSizeOf)]
1006            #[derive(PartialEq, Serialize)]
1007            #[repr(u32)]
1008            pub enum $name { $($variant = $mod::$constant,)+ }
1009
1010            impl $name {
1011                pub fn from_gl_constant(constant: u32) -> Option<Self> {
1012                    Some(match constant {
1013                        $($mod::$constant => $name::$variant, )+
1014                        _ => return None,
1015                    })
1016                }
1017
1018                #[inline]
1019                pub fn as_gl_constant(&self) -> u32 {
1020                    *self as u32
1021                }
1022            }
1023        )*
1024    }
1025}
1026
1027// TODO(sagudev): These should come from glow
1028mod gl_ext_constants {
1029    pub const COMPRESSED_RGB_ETC1_WEBGL: u32 = 0x8D64;
1030
1031    pub const ALPHA16F_ARB: u32 = 0x881C;
1032    pub const ALPHA32F_ARB: u32 = 0x8816;
1033    pub const LUMINANCE16F_ARB: u32 = 0x881E;
1034    pub const LUMINANCE32F_ARB: u32 = 0x8818;
1035    pub const LUMINANCE_ALPHA16F_ARB: u32 = 0x881F;
1036    pub const LUMINANCE_ALPHA32F_ARB: u32 = 0x8819;
1037}
1038
1039gl_enums! {
1040    pub enum TexFormat {
1041        DepthComponent = gl::DEPTH_COMPONENT,
1042        DepthStencil = gl::DEPTH_STENCIL,
1043        Alpha = gl::ALPHA,
1044        Alpha32f = gl_ext_constants::ALPHA32F_ARB,
1045        Alpha16f = gl_ext_constants::ALPHA16F_ARB,
1046        Red = gl::RED,
1047        RedInteger = gl::RED_INTEGER,
1048        RG = gl::RG,
1049        RGInteger = gl::RG_INTEGER,
1050        RGB = gl::RGB,
1051        RGBInteger = gl::RGB_INTEGER,
1052        RGBA = gl::RGBA,
1053        RGBAInteger = gl::RGBA_INTEGER,
1054        Luminance = gl::LUMINANCE,
1055        LuminanceAlpha = gl::LUMINANCE_ALPHA,
1056        Luminance32f = gl_ext_constants::LUMINANCE32F_ARB,
1057        Luminance16f = gl_ext_constants::LUMINANCE16F_ARB,
1058        LuminanceAlpha32f = gl_ext_constants::LUMINANCE_ALPHA32F_ARB,
1059        LuminanceAlpha16f = gl_ext_constants::LUMINANCE_ALPHA16F_ARB,
1060        CompressedRgbS3tcDxt1 = gl::COMPRESSED_RGB_S3TC_DXT1_EXT,
1061        CompressedRgbaS3tcDxt1 = gl::COMPRESSED_RGBA_S3TC_DXT1_EXT,
1062        CompressedRgbaS3tcDxt3 = gl::COMPRESSED_RGBA_S3TC_DXT3_EXT,
1063        CompressedRgbaS3tcDxt5 = gl::COMPRESSED_RGBA_S3TC_DXT5_EXT,
1064        CompressedRgbEtc1 = gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL,
1065        R8 = gl::R8,
1066        R8SNorm = gl::R8_SNORM,
1067        R16f = gl::R16F,
1068        R32f = gl::R32F,
1069        R8ui = gl::R8UI,
1070        R8i = gl::R8I,
1071        R16ui = gl::R16UI,
1072        R16i = gl::R16I,
1073        R32ui = gl::R32UI,
1074        R32i = gl::R32I,
1075        RG8 = gl::RG8,
1076        RG8SNorm = gl::RG8_SNORM,
1077        RG16f = gl::RG16F,
1078        RG32f = gl::RG32F,
1079        RG8ui = gl::RG8UI,
1080        RG8i = gl::RG8I,
1081        RG16ui = gl::RG16UI,
1082        RG16i = gl::RG16I,
1083        RG32ui = gl::RG32UI,
1084        RG32i = gl::RG32I,
1085        RGB8 = gl::RGB8,
1086        SRGB8 = gl::SRGB8,
1087        RGB565 = gl::RGB565,
1088        RGB8SNorm = gl::RGB8_SNORM,
1089        R11fG11fB10f = gl::R11F_G11F_B10F,
1090        RGB9E5 = gl::RGB9_E5,
1091        RGB16f = gl::RGB16F,
1092        RGB32f = gl::RGB32F,
1093        RGB8ui = gl::RGB8UI,
1094        RGB8i = gl::RGB8I,
1095        RGB16ui = gl::RGB16UI,
1096        RGB16i = gl::RGB16I,
1097        RGB32ui = gl::RGB32UI,
1098        RGB32i = gl::RGB32I,
1099        RGBA8 = gl::RGBA8,
1100        SRGB8Alpha8 = gl::SRGB8_ALPHA8,
1101        RGBA8SNorm = gl::RGBA8_SNORM,
1102        RGB5A1 = gl::RGB5_A1,
1103        RGBA4 = gl::RGBA4,
1104        RGB10A2 = gl::RGB10_A2,
1105        RGBA16f = gl::RGBA16F,
1106        RGBA32f = gl::RGBA32F,
1107        RGBA8ui = gl::RGBA8UI,
1108        RGBA8i = gl::RGBA8I,
1109        RGB10A2ui = gl::RGB10_A2UI,
1110        RGBA16ui = gl::RGBA16UI,
1111        RGBA16i = gl::RGBA16I,
1112        RGBA32i = gl::RGBA32I,
1113        RGBA32ui = gl::RGBA32UI,
1114        DepthComponent16 = gl::DEPTH_COMPONENT16,
1115        DepthComponent24 = gl::DEPTH_COMPONENT24,
1116        DepthComponent32f = gl::DEPTH_COMPONENT32F,
1117        Depth24Stencil8 = gl::DEPTH24_STENCIL8,
1118        Depth32fStencil8 = gl::DEPTH32F_STENCIL8,
1119    }
1120
1121    pub enum TexDataType {
1122        Byte = gl::BYTE,
1123        Int = gl::INT,
1124        Short = gl::SHORT,
1125        UnsignedByte = gl::UNSIGNED_BYTE,
1126        UnsignedInt = gl::UNSIGNED_INT,
1127        UnsignedInt10f11f11fRev = gl::UNSIGNED_INT_10F_11F_11F_REV,
1128        UnsignedInt2101010Rev = gl::UNSIGNED_INT_2_10_10_10_REV,
1129        UnsignedInt5999Rev = gl::UNSIGNED_INT_5_9_9_9_REV,
1130        UnsignedInt248 = gl::UNSIGNED_INT_24_8,
1131        UnsignedShort = gl::UNSIGNED_SHORT,
1132        UnsignedShort4444 = gl::UNSIGNED_SHORT_4_4_4_4,
1133        UnsignedShort5551 = gl::UNSIGNED_SHORT_5_5_5_1,
1134        UnsignedShort565 = gl::UNSIGNED_SHORT_5_6_5,
1135        Float = gl::FLOAT,
1136        HalfFloat = gl::HALF_FLOAT_OES,
1137        Float32UnsignedInt248Rev = gl::FLOAT_32_UNSIGNED_INT_24_8_REV,
1138    }
1139}
1140
1141impl TexFormat {
1142    /// Returns how many components does this format need. For example, RGBA
1143    /// needs 4 components, while RGB requires 3.
1144    pub fn components(&self) -> u32 {
1145        match self.to_unsized() {
1146            TexFormat::DepthStencil => 2,
1147            TexFormat::LuminanceAlpha => 2,
1148            TexFormat::RG | TexFormat::RGInteger => 2,
1149            TexFormat::RGB | TexFormat::RGBInteger => 3,
1150            TexFormat::RGBA | TexFormat::RGBAInteger => 4,
1151            _ => 1,
1152        }
1153    }
1154
1155    /// Returns whether this format is a known texture compression format.
1156    pub fn is_compressed(&self) -> bool {
1157        let gl_const = self.as_gl_constant();
1158        matches!(
1159            gl_const,
1160            gl::COMPRESSED_RGB_S3TC_DXT1_EXT |
1161                gl::COMPRESSED_RGBA_S3TC_DXT1_EXT |
1162                gl::COMPRESSED_RGBA_S3TC_DXT3_EXT |
1163                gl::COMPRESSED_RGBA_S3TC_DXT5_EXT |
1164                gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL
1165        )
1166    }
1167
1168    /// Returns whether this format is a known sized or unsized format.
1169    pub fn is_sized(&self) -> bool {
1170        !matches!(
1171            self,
1172            TexFormat::DepthComponent |
1173                TexFormat::DepthStencil |
1174                TexFormat::Alpha |
1175                TexFormat::Red |
1176                TexFormat::RG |
1177                TexFormat::RGB |
1178                TexFormat::RGBA |
1179                TexFormat::Luminance |
1180                TexFormat::LuminanceAlpha
1181        )
1182    }
1183
1184    pub fn to_unsized(self) -> TexFormat {
1185        match self {
1186            TexFormat::R8 => TexFormat::Red,
1187            TexFormat::R8SNorm => TexFormat::Red,
1188            TexFormat::R16f => TexFormat::Red,
1189            TexFormat::R32f => TexFormat::Red,
1190            TexFormat::R8ui => TexFormat::RedInteger,
1191            TexFormat::R8i => TexFormat::RedInteger,
1192            TexFormat::R16ui => TexFormat::RedInteger,
1193            TexFormat::R16i => TexFormat::RedInteger,
1194            TexFormat::R32ui => TexFormat::RedInteger,
1195            TexFormat::R32i => TexFormat::RedInteger,
1196            TexFormat::RG8 => TexFormat::RG,
1197            TexFormat::RG8SNorm => TexFormat::RG,
1198            TexFormat::RG16f => TexFormat::RG,
1199            TexFormat::RG32f => TexFormat::RG,
1200            TexFormat::RG8ui => TexFormat::RGInteger,
1201            TexFormat::RG8i => TexFormat::RGInteger,
1202            TexFormat::RG16ui => TexFormat::RGInteger,
1203            TexFormat::RG16i => TexFormat::RGInteger,
1204            TexFormat::RG32ui => TexFormat::RGInteger,
1205            TexFormat::RG32i => TexFormat::RGInteger,
1206            TexFormat::RGB8 => TexFormat::RGB,
1207            TexFormat::SRGB8 => TexFormat::RGB,
1208            TexFormat::RGB565 => TexFormat::RGB,
1209            TexFormat::RGB8SNorm => TexFormat::RGB,
1210            TexFormat::R11fG11fB10f => TexFormat::RGB,
1211            TexFormat::RGB9E5 => TexFormat::RGB,
1212            TexFormat::RGB16f => TexFormat::RGB,
1213            TexFormat::RGB32f => TexFormat::RGB,
1214            TexFormat::RGB8ui => TexFormat::RGBInteger,
1215            TexFormat::RGB8i => TexFormat::RGBInteger,
1216            TexFormat::RGB16ui => TexFormat::RGBInteger,
1217            TexFormat::RGB16i => TexFormat::RGBInteger,
1218            TexFormat::RGB32ui => TexFormat::RGBInteger,
1219            TexFormat::RGB32i => TexFormat::RGBInteger,
1220            TexFormat::RGBA8 => TexFormat::RGBA,
1221            TexFormat::SRGB8Alpha8 => TexFormat::RGBA,
1222            TexFormat::RGBA8SNorm => TexFormat::RGBA,
1223            TexFormat::RGB5A1 => TexFormat::RGBA,
1224            TexFormat::RGBA4 => TexFormat::RGBA,
1225            TexFormat::RGB10A2 => TexFormat::RGBA,
1226            TexFormat::RGBA16f => TexFormat::RGBA,
1227            TexFormat::RGBA32f => TexFormat::RGBA,
1228            TexFormat::RGBA8ui => TexFormat::RGBAInteger,
1229            TexFormat::RGBA8i => TexFormat::RGBAInteger,
1230            TexFormat::RGB10A2ui => TexFormat::RGBAInteger,
1231            TexFormat::RGBA16ui => TexFormat::RGBAInteger,
1232            TexFormat::RGBA16i => TexFormat::RGBAInteger,
1233            TexFormat::RGBA32i => TexFormat::RGBAInteger,
1234            TexFormat::RGBA32ui => TexFormat::RGBAInteger,
1235            TexFormat::DepthComponent16 => TexFormat::DepthComponent,
1236            TexFormat::DepthComponent24 => TexFormat::DepthComponent,
1237            TexFormat::DepthComponent32f => TexFormat::DepthComponent,
1238            TexFormat::Depth24Stencil8 => TexFormat::DepthStencil,
1239            TexFormat::Depth32fStencil8 => TexFormat::DepthStencil,
1240            TexFormat::Alpha32f => TexFormat::Alpha,
1241            TexFormat::Alpha16f => TexFormat::Alpha,
1242            TexFormat::Luminance32f => TexFormat::Luminance,
1243            TexFormat::Luminance16f => TexFormat::Luminance,
1244            TexFormat::LuminanceAlpha32f => TexFormat::LuminanceAlpha,
1245            TexFormat::LuminanceAlpha16f => TexFormat::LuminanceAlpha,
1246            _ => self,
1247        }
1248    }
1249
1250    pub fn compatible_data_types(self) -> &'static [TexDataType] {
1251        match self {
1252            TexFormat::RGB => &[
1253                TexDataType::UnsignedByte,
1254                TexDataType::UnsignedShort565,
1255                TexDataType::Float,
1256                TexDataType::HalfFloat,
1257            ][..],
1258            TexFormat::RGBA => &[
1259                TexDataType::UnsignedByte,
1260                TexDataType::UnsignedShort4444,
1261                TexDataType::UnsignedShort5551,
1262                TexDataType::Float,
1263                TexDataType::HalfFloat,
1264            ][..],
1265            TexFormat::LuminanceAlpha => &[
1266                TexDataType::UnsignedByte,
1267                TexDataType::Float,
1268                TexDataType::HalfFloat,
1269            ][..],
1270            TexFormat::Luminance => &[
1271                TexDataType::UnsignedByte,
1272                TexDataType::Float,
1273                TexDataType::HalfFloat,
1274            ][..],
1275            TexFormat::Alpha => &[
1276                TexDataType::UnsignedByte,
1277                TexDataType::Float,
1278                TexDataType::HalfFloat,
1279            ][..],
1280            TexFormat::LuminanceAlpha32f => &[TexDataType::Float][..],
1281            TexFormat::LuminanceAlpha16f => &[TexDataType::HalfFloat][..],
1282            TexFormat::Luminance32f => &[TexDataType::Float][..],
1283            TexFormat::Luminance16f => &[TexDataType::HalfFloat][..],
1284            TexFormat::Alpha32f => &[TexDataType::Float][..],
1285            TexFormat::Alpha16f => &[TexDataType::HalfFloat][..],
1286            TexFormat::R8 => &[TexDataType::UnsignedByte][..],
1287            TexFormat::R8SNorm => &[TexDataType::Byte][..],
1288            TexFormat::R16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1289            TexFormat::R32f => &[TexDataType::Float][..],
1290            TexFormat::R8ui => &[TexDataType::UnsignedByte][..],
1291            TexFormat::R8i => &[TexDataType::Byte][..],
1292            TexFormat::R16ui => &[TexDataType::UnsignedShort][..],
1293            TexFormat::R16i => &[TexDataType::Short][..],
1294            TexFormat::R32ui => &[TexDataType::UnsignedInt][..],
1295            TexFormat::R32i => &[TexDataType::Int][..],
1296            TexFormat::RG8 => &[TexDataType::UnsignedByte][..],
1297            TexFormat::RG8SNorm => &[TexDataType::Byte][..],
1298            TexFormat::RG16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1299            TexFormat::RG32f => &[TexDataType::Float][..],
1300            TexFormat::RG8ui => &[TexDataType::UnsignedByte][..],
1301            TexFormat::RG8i => &[TexDataType::Byte][..],
1302            TexFormat::RG16ui => &[TexDataType::UnsignedShort][..],
1303            TexFormat::RG16i => &[TexDataType::Short][..],
1304            TexFormat::RG32ui => &[TexDataType::UnsignedInt][..],
1305            TexFormat::RG32i => &[TexDataType::Int][..],
1306            TexFormat::RGB8 => &[TexDataType::UnsignedByte][..],
1307            TexFormat::SRGB8 => &[TexDataType::UnsignedByte][..],
1308            TexFormat::RGB565 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort565][..],
1309            TexFormat::RGB8SNorm => &[TexDataType::Byte][..],
1310            TexFormat::R11fG11fB10f => &[
1311                TexDataType::UnsignedInt10f11f11fRev,
1312                TexDataType::HalfFloat,
1313                TexDataType::Float,
1314            ][..],
1315            TexFormat::RGB9E5 => &[
1316                TexDataType::UnsignedInt5999Rev,
1317                TexDataType::HalfFloat,
1318                TexDataType::Float,
1319            ][..],
1320            TexFormat::RGB16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1321            TexFormat::RGB32f => &[TexDataType::Float][..],
1322            TexFormat::RGB8ui => &[TexDataType::UnsignedByte][..],
1323            TexFormat::RGB8i => &[TexDataType::Byte][..],
1324            TexFormat::RGB16ui => &[TexDataType::UnsignedShort][..],
1325            TexFormat::RGB16i => &[TexDataType::Short][..],
1326            TexFormat::RGB32ui => &[TexDataType::UnsignedInt][..],
1327            TexFormat::RGB32i => &[TexDataType::Int][..],
1328            TexFormat::RGBA8 => &[TexDataType::UnsignedByte][..],
1329            TexFormat::SRGB8Alpha8 => &[TexDataType::UnsignedByte][..],
1330            TexFormat::RGBA8SNorm => &[TexDataType::Byte][..],
1331            TexFormat::RGB5A1 => &[
1332                TexDataType::UnsignedByte,
1333                TexDataType::UnsignedShort5551,
1334                TexDataType::UnsignedInt2101010Rev,
1335            ][..],
1336            TexFormat::RGBA4 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort4444][..],
1337            TexFormat::RGB10A2 => &[TexDataType::UnsignedInt2101010Rev][..],
1338            TexFormat::RGBA16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
1339            TexFormat::RGBA32f => &[TexDataType::Float][..],
1340            TexFormat::RGBA8ui => &[TexDataType::UnsignedByte][..],
1341            TexFormat::RGBA8i => &[TexDataType::Byte][..],
1342            TexFormat::RGB10A2ui => &[TexDataType::UnsignedInt2101010Rev][..],
1343            TexFormat::RGBA16ui => &[TexDataType::UnsignedShort][..],
1344            TexFormat::RGBA16i => &[TexDataType::Short][..],
1345            TexFormat::RGBA32i => &[TexDataType::Int][..],
1346            TexFormat::RGBA32ui => &[TexDataType::UnsignedInt][..],
1347            TexFormat::DepthComponent16 => {
1348                &[TexDataType::UnsignedShort, TexDataType::UnsignedInt][..]
1349            },
1350            TexFormat::DepthComponent24 => &[TexDataType::UnsignedInt][..],
1351            TexFormat::DepthComponent32f => &[TexDataType::Float][..],
1352            TexFormat::Depth24Stencil8 => &[TexDataType::UnsignedInt248][..],
1353            TexFormat::Depth32fStencil8 => &[TexDataType::Float32UnsignedInt248Rev][..],
1354            TexFormat::CompressedRgbS3tcDxt1 |
1355            TexFormat::CompressedRgbaS3tcDxt1 |
1356            TexFormat::CompressedRgbaS3tcDxt3 |
1357            TexFormat::CompressedRgbaS3tcDxt5 => &[TexDataType::UnsignedByte][..],
1358            _ => &[][..],
1359        }
1360    }
1361
1362    pub fn required_webgl_version(self) -> WebGLVersion {
1363        match self {
1364            TexFormat::DepthComponent |
1365            TexFormat::Alpha |
1366            TexFormat::RGB |
1367            TexFormat::RGBA |
1368            TexFormat::Luminance |
1369            TexFormat::LuminanceAlpha |
1370            TexFormat::CompressedRgbS3tcDxt1 |
1371            TexFormat::CompressedRgbaS3tcDxt1 |
1372            TexFormat::CompressedRgbaS3tcDxt3 |
1373            TexFormat::CompressedRgbaS3tcDxt5 => WebGLVersion::WebGL1,
1374            _ => WebGLVersion::WebGL2,
1375        }
1376    }
1377
1378    pub fn usable_as_internal(self) -> bool {
1379        !self.compatible_data_types().is_empty()
1380    }
1381}
1382
1383#[derive(PartialEq)]
1384pub enum SizedDataType {
1385    Int8,
1386    Int16,
1387    Int32,
1388    Uint8,
1389    Uint16,
1390    Uint32,
1391    Float32,
1392}
1393
1394impl TexDataType {
1395    /// Parses a texture data type constant. `HalfFloat` stores WebGL 1's `HALF_FLOAT_OES`,
1396    /// while WebGL 2 uses `HALF_FLOAT` and does not define `OES_texture_half_float`.
1397    pub fn from_webgl_constant(constant: u32, version: WebGLVersion) -> Option<Self> {
1398        match (version, constant) {
1399            (WebGLVersion::WebGL2, gl::HALF_FLOAT) => Some(TexDataType::HalfFloat),
1400            (WebGLVersion::WebGL2, gl::HALF_FLOAT_OES) => None,
1401            _ => Self::from_gl_constant(constant),
1402        }
1403    }
1404
1405    /// Returns the compatible sized data type for this texture data type.
1406    pub fn sized_data_type(&self) -> SizedDataType {
1407        match self {
1408            TexDataType::Byte => SizedDataType::Int8,
1409            TexDataType::UnsignedByte => SizedDataType::Uint8,
1410            TexDataType::Short => SizedDataType::Int16,
1411            TexDataType::UnsignedShort |
1412            TexDataType::UnsignedShort4444 |
1413            TexDataType::UnsignedShort5551 |
1414            TexDataType::UnsignedShort565 => SizedDataType::Uint16,
1415            TexDataType::Int => SizedDataType::Int32,
1416            TexDataType::UnsignedInt |
1417            TexDataType::UnsignedInt10f11f11fRev |
1418            TexDataType::UnsignedInt2101010Rev |
1419            TexDataType::UnsignedInt5999Rev |
1420            TexDataType::UnsignedInt248 => SizedDataType::Uint32,
1421            TexDataType::HalfFloat => SizedDataType::Uint16,
1422            TexDataType::Float | TexDataType::Float32UnsignedInt248Rev => SizedDataType::Float32,
1423        }
1424    }
1425
1426    /// Returns the size in bytes of each element of data.
1427    pub fn element_size(&self) -> u32 {
1428        use self::*;
1429        match *self {
1430            TexDataType::Byte | TexDataType::UnsignedByte => 1,
1431            TexDataType::Short |
1432            TexDataType::UnsignedShort |
1433            TexDataType::UnsignedShort4444 |
1434            TexDataType::UnsignedShort5551 |
1435            TexDataType::UnsignedShort565 => 2,
1436            TexDataType::Int |
1437            TexDataType::UnsignedInt |
1438            TexDataType::UnsignedInt10f11f11fRev |
1439            TexDataType::UnsignedInt2101010Rev |
1440            TexDataType::UnsignedInt5999Rev => 4,
1441            TexDataType::UnsignedInt248 => 4,
1442            TexDataType::Float => 4,
1443            TexDataType::HalfFloat => 2,
1444            TexDataType::Float32UnsignedInt248Rev => 4,
1445        }
1446    }
1447
1448    /// Returns how many components a single element may hold. For example, a
1449    /// UnsignedShort4444 holds four components, each with 4 bits of data.
1450    pub fn components_per_element(&self) -> u32 {
1451        match *self {
1452            TexDataType::Byte => 1,
1453            TexDataType::UnsignedByte => 1,
1454            TexDataType::Short => 1,
1455            TexDataType::UnsignedShort => 1,
1456            TexDataType::UnsignedShort565 => 3,
1457            TexDataType::UnsignedShort5551 => 4,
1458            TexDataType::UnsignedShort4444 => 4,
1459            TexDataType::Int => 1,
1460            TexDataType::UnsignedInt => 1,
1461            TexDataType::UnsignedInt10f11f11fRev => 3,
1462            TexDataType::UnsignedInt2101010Rev => 4,
1463            TexDataType::UnsignedInt5999Rev => 4,
1464            TexDataType::UnsignedInt248 => 2,
1465            TexDataType::Float => 1,
1466            TexDataType::HalfFloat => 1,
1467            TexDataType::Float32UnsignedInt248Rev => 2,
1468        }
1469    }
1470
1471    pub fn required_webgl_version(self) -> WebGLVersion {
1472        match self {
1473            TexDataType::UnsignedByte |
1474            TexDataType::UnsignedShort4444 |
1475            TexDataType::UnsignedShort5551 |
1476            TexDataType::UnsignedShort565 |
1477            TexDataType::Float |
1478            TexDataType::HalfFloat => WebGLVersion::WebGL1,
1479            _ => WebGLVersion::WebGL2,
1480        }
1481    }
1482}
1483
1484#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
1485pub enum AlphaTreatment {
1486    Premultiply,
1487    Unmultiply,
1488}
1489
1490#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
1491pub enum YAxisTreatment {
1492    AsIs,
1493    Flipped,
1494}
1495
1496#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1497pub struct GLContextAttributes {
1498    pub alpha: bool,
1499    pub depth: bool,
1500    pub stencil: bool,
1501    pub antialias: bool,
1502    pub premultiplied_alpha: bool,
1503    pub preserve_drawing_buffer: bool,
1504}
1505
1506#[derive(Clone, Debug, Deserialize, Serialize)]
1507pub struct GLLimits {
1508    pub max_vertex_attribs: u32,
1509    pub max_tex_size: u32,
1510    pub max_3d_tex_size: u32,
1511    pub max_cube_map_tex_size: u32,
1512    pub max_combined_texture_image_units: u32,
1513    pub max_fragment_uniform_vectors: u32,
1514    pub max_renderbuffer_size: u32,
1515    pub max_texture_image_units: u32,
1516    pub max_varying_vectors: u32,
1517    pub max_vertex_texture_image_units: u32,
1518    pub max_vertex_uniform_vectors: u32,
1519    pub max_client_wait_timeout_webgl: std::time::Duration,
1520    pub max_transform_feedback_separate_attribs: u32,
1521    pub max_vertex_output_vectors: u32,
1522    pub max_fragment_input_vectors: u32,
1523    pub max_draw_buffers: u32,
1524    pub max_color_attachments: u32,
1525    pub max_uniform_buffer_bindings: u32,
1526    pub min_program_texel_offset: i32,
1527    pub max_program_texel_offset: u32,
1528    pub max_uniform_block_size: u64,
1529    pub max_combined_uniform_blocks: u32,
1530    pub max_combined_vertex_uniform_components: u64,
1531    pub max_combined_fragment_uniform_components: u64,
1532    pub max_vertex_uniform_blocks: u32,
1533    pub max_vertex_uniform_components: u32,
1534    pub max_fragment_uniform_blocks: u32,
1535    pub max_fragment_uniform_components: u32,
1536    pub max_3d_texture_size: u32,
1537    pub max_array_texture_layers: u32,
1538    pub uniform_buffer_offset_alignment: u32,
1539    pub max_element_index: u64,
1540    pub max_elements_indices: u32,
1541    pub max_elements_vertices: u32,
1542    pub max_fragment_input_components: u32,
1543    pub max_samples: u32,
1544    pub max_server_wait_timeout: std::time::Duration,
1545    pub max_texture_lod_bias: f32,
1546    pub max_varying_components: u32,
1547    pub max_vertex_output_components: u32,
1548}