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