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