Skip to main content

servo_canvas_traits/
webgl.rs

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