canvas_traits/
webgl.rs

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