canvas_traits/
webgl.rs

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