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