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 http://mozilla.org/MPL/2.0/. */
4 
5 use euclid::Size2D;
6 use nonzero::NonZero;
7 use offscreen_gl_context::{GLContextAttributes, GLLimits};
8 use std::fmt;
9 use webrender_api::{DocumentId, ImageKey, PipelineId};
10 
11 /// Sender type used in WebGLCommands.
12 pub use ::webgl_channel::WebGLSender;
13 /// Receiver type used in WebGLCommands.
14 pub use ::webgl_channel::WebGLReceiver;
15 /// Result type for send()/recv() calls in in WebGLCommands.
16 pub use ::webgl_channel::WebGLSendResult;
17 /// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
18 pub use ::webgl_channel::webgl_channel;
19 /// Entry point type used in a Script Pipeline to get the WebGLChan to be used in that thread.
20 pub use ::webgl_channel::WebGLPipeline;
21 /// Entry point channel type used for sending WebGLMsg messages to the WebGL renderer.
22 pub use ::webgl_channel::WebGLChan;
23 
24 /// WebGL Message API
25 #[derive(Clone, Deserialize, Serialize)]
26 pub enum WebGLMsg {
27     /// Creates a new WebGLContext.
28     CreateContext(WebGLVersion, Size2D<i32>, GLContextAttributes,
29                   WebGLSender<Result<(WebGLCreateContextResult), String>>),
30     /// Resizes a WebGLContext.
31     ResizeContext(WebGLContextId, Size2D<i32>, WebGLSender<Result<(), String>>),
32     /// Drops a WebGLContext.
33     RemoveContext(WebGLContextId),
34     /// Runs a WebGLCommand in a specific WebGLContext.
35     WebGLCommand(WebGLContextId, WebGLCommand),
36     /// Runs a WebVRCommand in a specific WebGLContext.
37     WebVRCommand(WebGLContextId, WebVRCommand),
38     /// Locks a specific WebGLContext. Lock messages are used for a correct synchronization
39     /// with WebRender external image API.
40     /// WR locks a external texture when it wants to use the shared texture contents.
41     /// The WR client should not change the shared texture content until the Unlock call.
42     /// Currently OpenGL Sync Objects are used to implement the synchronization mechanism.
43     Lock(WebGLContextId, WebGLSender<(u32, Size2D<i32>, usize)>),
44     /// Unlocks a specific WebGLContext. Unlock messages are used for a correct synchronization
45     /// with WebRender external image API.
46     /// The WR unlocks a context when it finished reading the shared texture contents.
47     /// Unlock messages are always sent after a Lock message.
48     Unlock(WebGLContextId),
49     /// Creates or updates the image keys required for WebRender.
50     UpdateWebRenderImage(WebGLContextId, WebGLSender<ImageKey>),
51     /// Commands used for the DOMToTexture feature.
52     DOMToTextureCommand(DOMToTextureCommand),
53     /// Frees all resources and closes the thread.
54     Exit,
55 }
56 
57 /// Contains the WebGLCommand sender and information about a WebGLContext
58 #[derive(Clone, Deserialize, Serialize)]
59 pub struct WebGLCreateContextResult {
60     /// Sender instance to send commands to the specific WebGLContext
61     pub sender: WebGLMsgSender,
62     /// Information about the internal GL Context.
63     pub limits: GLLimits,
64     /// How the WebGLContext is shared with WebRender.
65     pub share_mode: WebGLContextShareMode,
66     /// The GLSL version supported by the context.
67     pub glsl_version: WebGLSLVersion
68 }
69 
70 #[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)]
71 pub enum WebGLContextShareMode {
72     /// Fast: a shared texture_id is used in WebRender.
73     SharedTexture,
74     /// Slow: glReadPixels is used to send pixels to WebRender each frame.
75     Readback,
76 }
77 
78 /// Defines the WebGL version
79 #[derive(Clone, Copy, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
80 pub enum WebGLVersion {
81     /// https://www.khronos.org/registry/webgl/specs/1.0.2/
82     /// Conforms closely to the OpenGL ES 2.0 API
83     WebGL1,
84     /// https://www.khronos.org/registry/webgl/specs/latest/2.0/
85     /// Conforms closely to the OpenGL ES 3.0 API
86     WebGL2,
87 }
88 
89 /// Defines the GLSL version supported by the WebGL backend contexts.
90 #[derive(Clone, Copy, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
91 pub struct WebGLSLVersion {
92     /// Major GLSL version
93     pub major: u32,
94     /// Minor GLSL version
95     pub minor: u32,
96 }
97 
98 /// Helper struct to send WebGLCommands to a specific WebGLContext.
99 #[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
100 pub struct WebGLMsgSender {
101     ctx_id: WebGLContextId,
102     #[ignore_malloc_size_of = "channels are hard"]
103     sender: WebGLChan,
104 }
105 
106 impl WebGLMsgSender {
new(id: WebGLContextId, sender: WebGLChan) -> Self107     pub fn new(id: WebGLContextId, sender: WebGLChan) -> Self {
108         WebGLMsgSender {
109             ctx_id: id,
110             sender: sender,
111         }
112     }
113 
114     /// Returns the WebGLContextId associated to this sender
context_id(&self) -> WebGLContextId115     pub fn context_id(&self) -> WebGLContextId {
116         self.ctx_id
117     }
118 
119     /// Send a WebGLCommand message
120     #[inline]
send(&self, command: WebGLCommand) -> WebGLSendResult121     pub fn send(&self, command: WebGLCommand) -> WebGLSendResult {
122         self.sender.send(WebGLMsg::WebGLCommand(self.ctx_id, command))
123     }
124 
125     /// Send a WebVRCommand message
126     #[inline]
send_vr(&self, command: WebVRCommand) -> WebGLSendResult127     pub fn send_vr(&self, command: WebVRCommand) -> WebGLSendResult {
128         self.sender.send(WebGLMsg::WebVRCommand(self.ctx_id, command))
129     }
130 
131     /// Send a resize message
132     #[inline]
send_resize(&self, size: Size2D<i32>, sender: WebGLSender<Result<(), String>>) -> WebGLSendResult133     pub fn send_resize(&self,
134                        size: Size2D<i32>,
135                        sender: WebGLSender<Result<(), String>>)
136                        -> WebGLSendResult {
137         self.sender.send(WebGLMsg::ResizeContext(self.ctx_id, size, sender))
138     }
139 
140     #[inline]
send_remove(&self) -> WebGLSendResult141     pub fn send_remove(&self) -> WebGLSendResult {
142         self.sender.send(WebGLMsg::RemoveContext(self.ctx_id))
143     }
144 
145     #[inline]
send_update_wr_image(&self, sender: WebGLSender<ImageKey>) -> WebGLSendResult146     pub fn send_update_wr_image(&self, sender: WebGLSender<ImageKey>) -> WebGLSendResult {
147         self.sender.send(WebGLMsg::UpdateWebRenderImage(self.ctx_id, sender))
148     }
149 
send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult150     pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult {
151         self.sender.send(WebGLMsg::DOMToTextureCommand(command))
152     }
153 }
154 
155 /// WebGL Commands for a specific WebGLContext
156 #[derive(Clone, Deserialize, Serialize)]
157 pub enum WebGLCommand {
158     GetContextAttributes(WebGLSender<GLContextAttributes>),
159     ActiveTexture(u32),
160     BlendColor(f32, f32, f32, f32),
161     BlendEquation(u32),
162     BlendEquationSeparate(u32, u32),
163     BlendFunc(u32, u32),
164     BlendFuncSeparate(u32, u32, u32, u32),
165     AttachShader(WebGLProgramId, WebGLShaderId),
166     DetachShader(WebGLProgramId, WebGLShaderId),
167     BindAttribLocation(WebGLProgramId, u32, String),
168     BufferData(u32, Vec<u8>, u32),
169     BufferSubData(u32, isize, Vec<u8>),
170     Clear(u32),
171     ClearColor(f32, f32, f32, f32),
172     ClearDepth(f64),
173     ClearStencil(i32),
174     ColorMask(bool, bool, bool, bool),
175     CullFace(u32),
176     FrontFace(u32),
177     DepthFunc(u32),
178     DepthMask(bool),
179     DepthRange(f64, f64),
180     Enable(u32),
181     Disable(u32),
182     CompileShader(WebGLShaderId, String),
183     CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32),
184     CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32),
185     CreateBuffer(WebGLSender<Option<WebGLBufferId>>),
186     CreateFramebuffer(WebGLSender<Option<WebGLFramebufferId>>),
187     CreateRenderbuffer(WebGLSender<Option<WebGLRenderbufferId>>),
188     CreateTexture(WebGLSender<Option<WebGLTextureId>>),
189     CreateProgram(WebGLSender<Option<WebGLProgramId>>),
190     CreateShader(u32, WebGLSender<Option<WebGLShaderId>>),
191     DeleteBuffer(WebGLBufferId),
192     DeleteFramebuffer(WebGLFramebufferId),
193     DeleteRenderbuffer(WebGLRenderbufferId),
194     DeleteTexture(WebGLTextureId),
195     DeleteProgram(WebGLProgramId),
196     DeleteShader(WebGLShaderId),
197     BindBuffer(u32, Option<WebGLBufferId>),
198     BindFramebuffer(u32, WebGLFramebufferBindingRequest),
199     BindRenderbuffer(u32, Option<WebGLRenderbufferId>),
200     BindTexture(u32, Option<WebGLTextureId>),
201     DisableVertexAttribArray(u32),
202     DrawArrays(u32, i32, i32),
203     DrawElements(u32, i32, u32, i64),
204     EnableVertexAttribArray(u32),
205     FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>),
206     FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
207     GetBufferParameter(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>),
208     GetExtensions(WebGLSender<String>),
209     GetParameter(u32, WebGLSender<WebGLResult<WebGLParameter>>),
210     GetTexParameter(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>),
211     GetProgramParameter(WebGLProgramId, u32, WebGLSender<WebGLResult<WebGLParameter>>),
212     GetShaderParameter(WebGLShaderId, u32, WebGLSender<WebGLResult<WebGLParameter>>),
213     GetShaderPrecisionFormat(u32, u32, WebGLSender<WebGLResult<(i32, i32, i32)>>),
214     GetActiveAttrib(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
215     GetActiveUniform(WebGLProgramId, u32, WebGLSender<WebGLResult<(i32, u32, String)>>),
216     GetAttribLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
217     GetUniformLocation(WebGLProgramId, String, WebGLSender<Option<i32>>),
218     GetVertexAttrib(u32, u32, WebGLSender<WebGLResult<WebGLParameter>>),
219     GetVertexAttribOffset(u32, u32, WebGLSender<WebGLResult<isize>>),
220     GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
221     GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
222     PolygonOffset(f32, f32),
223     RenderbufferStorage(u32, u32, i32, i32),
224     ReadPixels(i32, i32, i32, i32, u32, u32, WebGLSender<Vec<u8>>),
225     SampleCoverage(f32, bool),
226     Scissor(i32, i32, i32, i32),
227     StencilFunc(u32, i32, u32),
228     StencilFuncSeparate(u32, u32, i32, u32),
229     StencilMask(u32),
230     StencilMaskSeparate(u32, u32),
231     StencilOp(u32, u32, u32),
232     StencilOpSeparate(u32, u32, u32, u32),
233     Hint(u32, u32),
234     IsEnabled(u32, WebGLSender<bool>),
235     LineWidth(f32),
236     PixelStorei(u32, i32),
237     LinkProgram(WebGLProgramId),
238     Uniform1f(i32, f32),
239     Uniform1fv(i32, Vec<f32>),
240     Uniform1i(i32, i32),
241     Uniform1iv(i32, Vec<i32>),
242     Uniform2f(i32, f32, f32),
243     Uniform2fv(i32, Vec<f32>),
244     Uniform2i(i32, i32, i32),
245     Uniform2iv(i32, Vec<i32>),
246     Uniform3f(i32, f32, f32, f32),
247     Uniform3fv(i32, Vec<f32>),
248     Uniform3i(i32, i32, i32, i32),
249     Uniform3iv(i32, Vec<i32>),
250     Uniform4f(i32, f32, f32, f32, f32),
251     Uniform4fv(i32, Vec<f32>),
252     Uniform4i(i32, i32, i32, i32, i32),
253     Uniform4iv(i32, Vec<i32>),
254     UniformMatrix2fv(i32, bool, Vec<f32>),
255     UniformMatrix3fv(i32, bool, Vec<f32>),
256     UniformMatrix4fv(i32, bool, Vec<f32>),
257     UseProgram(WebGLProgramId),
258     ValidateProgram(WebGLProgramId),
259     VertexAttrib(u32, f32, f32, f32, f32),
260     VertexAttribPointer(u32, i32, u32, bool, i32, u32),
261     VertexAttribPointer2f(u32, i32, bool, i32, u32),
262     Viewport(i32, i32, i32, i32),
263     TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
264     TexParameteri(u32, u32, i32),
265     TexParameterf(u32, u32, f32),
266     TexSubImage2D(u32, i32, i32, i32, i32, i32, u32, u32, Vec<u8>),
267     DrawingBufferWidth(WebGLSender<i32>),
268     DrawingBufferHeight(WebGLSender<i32>),
269     Finish(WebGLSender<()>),
270     Flush,
271     GenerateMipmap(u32),
272     CreateVertexArray(WebGLSender<Option<WebGLVertexArrayId>>),
273     DeleteVertexArray(WebGLVertexArrayId),
274     BindVertexArray(Option<WebGLVertexArrayId>),
275 }
276 
277 macro_rules! define_resource_id_struct {
278     ($name:ident) => {
279         #[derive(Clone, Copy, Eq, Hash, PartialEq)]
280         pub struct $name(NonZero<u32>);
281 
282         impl $name {
283             #[allow(unsafe_code)]
284             #[inline]
285             pub unsafe fn new(id: u32) -> Self {
286                 $name(NonZero::new_unchecked(id))
287             }
288 
289             #[inline]
290             pub fn get(self) -> u32 {
291                 self.0.get()
292             }
293         }
294 
295     };
296 }
297 
298 macro_rules! define_resource_id {
299     ($name:ident) => {
300         define_resource_id_struct!($name);
301 
302         #[allow(unsafe_code)]
303         impl<'de> ::serde::Deserialize<'de> for $name {
304             fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
305                 where D: ::serde::Deserializer<'de>
306             {
307                 let id = try!(u32::deserialize(deserializer));
308                 if id == 0 {
309                     Err(::serde::de::Error::custom("expected a non-zero value"))
310                 } else {
311                     Ok(unsafe { $name::new(id) })
312                 }
313             }
314         }
315 
316         impl ::serde::Serialize for $name {
317             fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
318                 where S: ::serde::Serializer
319             {
320                 self.get().serialize(serializer)
321             }
322         }
323 
324         impl ::std::fmt::Debug for $name {
325             fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
326                   -> Result<(), ::std::fmt::Error> {
327                 fmt.debug_tuple(stringify!($name))
328                    .field(&self.get())
329                    .finish()
330             }
331         }
332 
333         impl ::std::fmt::Display for $name {
334             fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
335                   -> Result<(), ::std::fmt::Error> {
336                 write!(fmt, "{}", self.get())
337             }
338         }
339 
340         impl ::malloc_size_of::MallocSizeOf for $name {
341             fn size_of(&self, _ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize { 0 }
342         }
343     }
344 }
345 
346 define_resource_id!(WebGLBufferId);
347 define_resource_id!(WebGLFramebufferId);
348 define_resource_id!(WebGLRenderbufferId);
349 define_resource_id!(WebGLTextureId);
350 define_resource_id!(WebGLProgramId);
351 define_resource_id!(WebGLShaderId);
352 define_resource_id!(WebGLVertexArrayId);
353 
354 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord)]
355 #[derive(PartialEq, PartialOrd, Serialize)]
356 pub struct WebGLContextId(pub usize);
357 
358 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
359 pub enum WebGLError {
360     InvalidEnum,
361     InvalidFramebufferOperation,
362     InvalidOperation,
363     InvalidValue,
364     OutOfMemory,
365     ContextLost,
366 }
367 
368 #[derive(Clone, Debug, Deserialize, Serialize)]
369 pub enum WebGLFramebufferBindingRequest {
370     Explicit(WebGLFramebufferId),
371     Default,
372 }
373 
374 #[derive(Clone, Debug, Deserialize, Serialize)]
375 pub enum WebGLParameter {
376     Int(i32),
377     Bool(bool),
378     String(String),
379     Float(f32),
380     FloatArray(Vec<f32>),
381     Invalid,
382 }
383 
384 pub type WebGLResult<T> = Result<T, WebGLError>;
385 
386 #[derive(Clone, Debug, Deserialize, Serialize)]
387 pub enum WebGLShaderParameter {
388     Int(i32),
389     Bool(bool),
390     Invalid,
391 }
392 
393 pub type WebVRDeviceId = u32;
394 
395 // WebVR commands that must be called in the WebGL render thread.
396 #[derive(Clone, Deserialize, Serialize)]
397 pub enum WebVRCommand {
398     /// Start presenting to a VR device.
399     Create(WebVRDeviceId),
400     /// Synchronize the pose information to be used in the frame.
401     SyncPoses(WebVRDeviceId, f64, f64, WebGLSender<Result<Vec<u8>, ()>>),
402     /// Submit the frame to a VR device using the specified texture coordinates.
403     SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]),
404     /// Stop presenting to a VR device
405     Release(WebVRDeviceId)
406 }
407 
408 // Trait object that handles WebVR commands.
409 // Receives the texture id and size associated to the WebGLContext.
410 pub trait WebVRRenderHandler: Send {
handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D<i32>)>)411     fn handle(&mut self, command: WebVRCommand, texture: Option<(u32, Size2D<i32>)>);
412 }
413 
414 /// WebGL commands required to implement DOMToTexture feature.
415 #[derive(Clone, Deserialize, Serialize)]
416 pub enum DOMToTextureCommand {
417     /// Attaches a HTMLIFrameElement to a WebGLTexture.
418     Attach(WebGLContextId, WebGLTextureId, DocumentId, PipelineId, Size2D<i32>),
419     /// Releases the HTMLIFrameElement to WebGLTexture attachment.
420     Detach(WebGLTextureId),
421     /// Lock message used for a correct synchronization with WebRender GL flow.
422     Lock(PipelineId, usize, WebGLSender<Option<(u32, Size2D<i32>)>>),
423 }
424 
425 impl fmt::Debug for WebGLCommand {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result426     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
427         use self::WebGLCommand::*;
428         let name = match *self {
429             GetContextAttributes(..) => "GetContextAttributes",
430             ActiveTexture(..) => "ActiveTexture",
431             BlendColor(..) => "BlendColor",
432             BlendEquation(..) => "BlendEquation",
433             BlendEquationSeparate(..) => "BlendEquationSeparate",
434             BlendFunc(..) => "BlendFunc",
435             BlendFuncSeparate(..) => "BlendFuncSeparate",
436             AttachShader(..) => "AttachShader",
437             DetachShader(..) => "DetachShader",
438             BindAttribLocation(..) => "BindAttribLocation",
439             BufferData(..) => "BufferData",
440             BufferSubData(..) => "BufferSubData",
441             Clear(..) => "Clear",
442             ClearColor(..) => "ClearColor",
443             ClearDepth(..) => "ClearDepth",
444             ClearStencil(..) => "ClearStencil",
445             ColorMask(..) => "ColorMask",
446             CopyTexImage2D(..) => "CopyTexImage2D",
447             CopyTexSubImage2D(..) => "CopyTexSubImage2D",
448             CullFace(..) => "CullFace",
449             FrontFace(..) => "FrontFace",
450             DepthFunc(..) => "DepthFunc",
451             DepthMask(..) => "DepthMask",
452             DepthRange(..) => "DepthRange",
453             Enable(..) => "Enable",
454             Disable(..) => "Disable",
455             CompileShader(..) => "CompileShader",
456             CreateBuffer(..) => "CreateBuffer",
457             CreateFramebuffer(..) => "CreateFramebuffer",
458             CreateRenderbuffer(..) => "CreateRenderbuffer",
459             CreateTexture(..) => "CreateTexture",
460             CreateProgram(..) => "CreateProgram",
461             CreateShader(..) => "CreateShader",
462             DeleteBuffer(..) => "DeleteBuffer",
463             DeleteFramebuffer(..) => "DeleteFramebuffer",
464             DeleteRenderbuffer(..) => "DeleteRenderBuffer",
465             DeleteTexture(..) => "DeleteTexture",
466             DeleteProgram(..) => "DeleteProgram",
467             DeleteShader(..) => "DeleteShader",
468             BindBuffer(..) => "BindBuffer",
469             BindFramebuffer(..) => "BindFramebuffer",
470             BindRenderbuffer(..) => "BindRenderbuffer",
471             BindTexture(..) => "BindTexture",
472             DisableVertexAttribArray(..) => "DisableVertexAttribArray",
473             DrawArrays(..) => "DrawArrays",
474             DrawElements(..) => "DrawElements",
475             EnableVertexAttribArray(..) => "EnableVertexAttribArray",
476             FramebufferRenderbuffer(..) => "FramebufferRenderbuffer",
477             FramebufferTexture2D(..) => "FramebufferTexture2D",
478             GetBufferParameter(..) => "GetBufferParameter",
479             GetExtensions(..) => "GetExtensions",
480             GetParameter(..) => "GetParameter",
481             GetTexParameter(..) => "GetTexParameter",
482             GetProgramParameter(..) => "GetProgramParameter",
483             GetShaderParameter(..) => "GetShaderParameter",
484             GetShaderPrecisionFormat(..) => "GetShaderPrecisionFormat",
485             GetActiveAttrib(..) => "GetActiveAttrib",
486             GetActiveUniform(..) => "GetActiveUniform",
487             GetAttribLocation(..) => "GetAttribLocation",
488             GetUniformLocation(..) => "GetUniformLocation",
489             GetShaderInfoLog(..) => "GetShaderInfoLog",
490             GetProgramInfoLog(..) => "GetProgramInfoLog",
491             GetVertexAttrib(..) => "GetVertexAttrib",
492             GetVertexAttribOffset(..) => "GetVertexAttribOffset",
493             PolygonOffset(..) => "PolygonOffset",
494             ReadPixels(..) => "ReadPixels",
495             RenderbufferStorage(..) => "RenderbufferStorage",
496             SampleCoverage(..) => "SampleCoverage",
497             Scissor(..) => "Scissor",
498             StencilFunc(..) => "StencilFunc",
499             StencilFuncSeparate(..) => "StencilFuncSeparate",
500             StencilMask(..) => "StencilMask",
501             StencilMaskSeparate(..) => "StencilMaskSeparate",
502             StencilOp(..) => "StencilOp",
503             StencilOpSeparate(..) => "StencilOpSeparate",
504             Hint(..) => "Hint",
505             IsEnabled(..) => "IsEnabled",
506             LineWidth(..) => "LineWidth",
507             PixelStorei(..) => "PixelStorei",
508             LinkProgram(..) => "LinkProgram",
509             Uniform1f(..) => "Uniform1f",
510             Uniform1fv(..) => "Uniform1fv",
511             Uniform1i(..) => "Uniform1i",
512             Uniform1iv(..) => "Uniform1iv",
513             Uniform2f(..) => "Uniform2f",
514             Uniform2fv(..) => "Uniform2fv",
515             Uniform2i(..) => "Uniform2i",
516             Uniform2iv(..) => "Uniform2iv",
517             Uniform3f(..) => "Uniform3f",
518             Uniform3fv(..) => "Uniform3fv",
519             Uniform3i(..) => "Uniform3i",
520             Uniform3iv(..) => "Uniform3iv",
521             Uniform4f(..) => "Uniform4f",
522             Uniform4fv(..) => "Uniform4fv",
523             Uniform4i(..) => "Uniform4i",
524             Uniform4iv(..) => "Uniform4iv",
525             UniformMatrix2fv(..) => "UniformMatrix2fv",
526             UniformMatrix3fv(..) => "UniformMatrix3fv",
527             UniformMatrix4fv(..) => "UniformMatrix4fv",
528             UseProgram(..) => "UseProgram",
529             ValidateProgram(..) => "ValidateProgram",
530             VertexAttrib(..) => "VertexAttrib",
531             VertexAttribPointer2f(..) => "VertexAttribPointer2f",
532             VertexAttribPointer(..) => "VertexAttribPointer",
533             Viewport(..) => "Viewport",
534             TexImage2D(..) => "TexImage2D",
535             TexParameteri(..) => "TexParameteri",
536             TexParameterf(..) => "TexParameterf",
537             TexSubImage2D(..) => "TexSubImage2D",
538             DrawingBufferWidth(..) => "DrawingBufferWidth",
539             DrawingBufferHeight(..) => "DrawingBufferHeight",
540             Finish(..) => "Finish",
541             Flush => "Flush",
542             GenerateMipmap(..) => "GenerateMipmap",
543             CreateVertexArray(..) => "CreateVertexArray",
544             DeleteVertexArray(..) => "DeleteVertexArray",
545             BindVertexArray(..) => "BindVertexArray"
546         };
547 
548         write!(f, "CanvasWebGLMsg::{}(..)", name)
549     }
550 }
551