aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared/canvas/webgl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared/canvas/webgl.rs')
-rw-r--r--components/shared/canvas/webgl.rs1431
1 files changed, 1431 insertions, 0 deletions
diff --git a/components/shared/canvas/webgl.rs b/components/shared/canvas/webgl.rs
new file mode 100644
index 00000000000..2a2e0f0c3b3
--- /dev/null
+++ b/components/shared/canvas/webgl.rs
@@ -0,0 +1,1431 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use std::borrow::Cow;
+use std::fmt;
+use std::num::{NonZeroU32, NonZeroU64};
+use std::ops::Deref;
+
+use euclid::default::{Rect, Size2D};
+use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender, IpcSharedMemory};
+use malloc_size_of_derive::MallocSizeOf;
+use pixels::PixelFormat;
+use serde::{Deserialize, Serialize};
+use sparkle::gl;
+use webrender_api::ImageKey;
+use webxr_api::{
+ ContextId as WebXRContextId, Error as WebXRError, LayerId as WebXRLayerId,
+ LayerInit as WebXRLayerInit, SubImages as WebXRSubImages,
+};
+
+/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
+pub use crate::webgl_channel::webgl_channel;
+/// Entry point channel type used for sending WebGLMsg messages to the WebGL renderer.
+pub use crate::webgl_channel::WebGLChan;
+/// Entry point type used in a Script Pipeline to get the WebGLChan to be used in that thread.
+pub use crate::webgl_channel::WebGLPipeline;
+/// Receiver type used in WebGLCommands.
+pub use crate::webgl_channel::WebGLReceiver;
+/// Result type for send()/recv() calls in in WebGLCommands.
+pub use crate::webgl_channel::WebGLSendResult;
+/// Sender type used in WebGLCommands.
+pub use crate::webgl_channel::WebGLSender;
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct WebGLCommandBacktrace {
+ #[cfg(feature = "webgl_backtrace")]
+ pub backtrace: String,
+ #[cfg(feature = "webgl_backtrace")]
+ pub js_backtrace: Option<String>,
+}
+
+/// WebGL Threading API entry point that lives in the constellation.
+pub struct WebGLThreads(pub WebGLSender<WebGLMsg>);
+
+impl WebGLThreads {
+ /// Gets the WebGLThread handle for each script pipeline.
+ pub fn pipeline(&self) -> WebGLPipeline {
+ // This mode creates a single thread, so the existing WebGLChan is just cloned.
+ WebGLPipeline(WebGLChan(self.0.clone()))
+ }
+
+ /// Sends a exit message to close the WebGLThreads and release all WebGLContexts.
+ pub fn exit(&self) -> Result<(), &'static str> {
+ self.0
+ .send(WebGLMsg::Exit)
+ .map_err(|_| "Failed to send Exit message")
+ }
+}
+
+/// WebGL Message API
+#[derive(Debug, Deserialize, Serialize)]
+pub enum WebGLMsg {
+ /// Creates a new WebGLContext.
+ CreateContext(
+ WebGLVersion,
+ Size2D<u32>,
+ GLContextAttributes,
+ WebGLSender<Result<WebGLCreateContextResult, String>>,
+ ),
+ /// Resizes a WebGLContext.
+ ResizeContext(WebGLContextId, Size2D<u32>, WebGLSender<Result<(), String>>),
+ /// Drops a WebGLContext.
+ RemoveContext(WebGLContextId),
+ /// Runs a WebGLCommand in a specific WebGLContext.
+ WebGLCommand(WebGLContextId, WebGLCommand, WebGLCommandBacktrace),
+ /// Runs a WebXRCommand (WebXR layers need to be created in the WebGL
+ /// thread, as they may have thread affinity).
+ WebXRCommand(WebXRCommand),
+ /// Performs a buffer swap.
+ ///
+ /// The third field contains the time (in ns) when the request
+ /// was initiated. The u64 in the second field will be the time the
+ /// request is fulfilled
+ SwapBuffers(Vec<WebGLContextId>, WebGLSender<u64>, u64),
+ /// Frees all resources and closes the thread.
+ Exit,
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub enum GlType {
+ Gl,
+ Gles,
+}
+
+/// Contains the WebGLCommand sender and information about a WebGLContext
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct WebGLCreateContextResult {
+ /// Sender instance to send commands to the specific WebGLContext
+ pub sender: WebGLMsgSender,
+ /// Information about the internal GL Context.
+ pub limits: GLLimits,
+ /// The GLSL version supported by the context.
+ pub glsl_version: WebGLSLVersion,
+ /// The GL API used by the context.
+ pub api_type: GlType,
+ /// The WebRender image key.
+ pub image_key: ImageKey,
+}
+
+/// Defines the WebGL version
+#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, PartialOrd, Serialize)]
+pub enum WebGLVersion {
+ /// https://www.khronos.org/registry/webgl/specs/1.0.2/
+ /// Conforms closely to the OpenGL ES 2.0 API
+ WebGL1,
+ /// https://www.khronos.org/registry/webgl/specs/latest/2.0/
+ /// Conforms closely to the OpenGL ES 3.0 API
+ WebGL2,
+}
+
+/// Defines the GLSL version supported by the WebGL backend contexts.
+#[derive(
+ Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
+)]
+pub struct WebGLSLVersion {
+ /// Major GLSL version
+ pub major: u32,
+ /// Minor GLSL version
+ pub minor: u32,
+}
+
+/// Helper struct to send WebGLCommands to a specific WebGLContext.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct WebGLMsgSender {
+ ctx_id: WebGLContextId,
+ #[ignore_malloc_size_of = "channels are hard"]
+ sender: WebGLChan,
+}
+
+impl WebGLMsgSender {
+ pub fn new(id: WebGLContextId, sender: WebGLChan) -> Self {
+ WebGLMsgSender {
+ ctx_id: id,
+ sender: sender,
+ }
+ }
+
+ /// Returns the WebGLContextId associated to this sender
+ pub fn context_id(&self) -> WebGLContextId {
+ self.ctx_id
+ }
+
+ /// Send a WebGLCommand message
+ #[inline]
+ pub fn send(&self, command: WebGLCommand, backtrace: WebGLCommandBacktrace) -> WebGLSendResult {
+ self.sender
+ .send(WebGLMsg::WebGLCommand(self.ctx_id, command, backtrace))
+ }
+
+ /// Send a resize message
+ #[inline]
+ pub fn send_resize(
+ &self,
+ size: Size2D<u32>,
+ sender: WebGLSender<Result<(), String>>,
+ ) -> WebGLSendResult {
+ self.sender
+ .send(WebGLMsg::ResizeContext(self.ctx_id, size, sender))
+ }
+
+ #[inline]
+ pub fn send_remove(&self) -> WebGLSendResult {
+ self.sender.send(WebGLMsg::RemoveContext(self.ctx_id))
+ }
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct TruncatedDebug<T>(T);
+
+impl<T> From<T> for TruncatedDebug<T> {
+ fn from(v: T) -> TruncatedDebug<T> {
+ TruncatedDebug(v)
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for TruncatedDebug<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut s = format!("{:?}", self.0);
+ if s.len() > 20 {
+ s.truncate(20);
+ s.push_str("...");
+ }
+ write!(f, "{}", s)
+ }
+}
+
+impl<T> Deref for TruncatedDebug<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ &self.0
+ }
+}
+
+/// WebGL Commands for a specific WebGLContext
+#[derive(Debug, Deserialize, Serialize)]
+pub enum WebGLCommand {
+ GetContextAttributes(WebGLSender<GLContextAttributes>),
+ ActiveTexture(u32),
+ BlendColor(f32, f32, f32, f32),
+ BlendEquation(u32),
+ BlendEquationSeparate(u32, u32),
+ BlendFunc(u32, u32),
+ BlendFuncSeparate(u32, u32, u32, u32),
+ AttachShader(WebGLProgramId, WebGLShaderId),
+ DetachShader(WebGLProgramId, WebGLShaderId),
+ BindAttribLocation(WebGLProgramId, u32, String),
+ BufferData(u32, IpcBytesReceiver, u32),
+ BufferSubData(u32, isize, IpcBytesReceiver),
+ GetBufferSubData(u32, usize, usize, IpcBytesSender),
+ CopyBufferSubData(u32, u32, i64, i64, i64),
+ Clear(u32),
+ ClearColor(f32, f32, f32, f32),
+ ClearDepth(f32),
+ ClearStencil(i32),
+ ColorMask(bool, bool, bool, bool),
+ CullFace(u32),
+ FrontFace(u32),
+ DepthFunc(u32),
+ DepthMask(bool),
+ DepthRange(f32, f32),
+ Enable(u32),
+ Disable(u32),
+ CompileShader(WebGLShaderId, String),
+ CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32),
+ CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32),
+ CreateBuffer(WebGLSender<Option<WebGLBufferId>>),
+ CreateFramebuffer(WebGLSender<Option<WebGLFramebufferId>>),
+ CreateRenderbuffer(WebGLSender<Option<WebGLRenderbufferId>>),
+ CreateTexture(WebGLSender<Option<WebGLTextureId>>),
+ CreateProgram(WebGLSender<Option<WebGLProgramId>>),
+ CreateShader(u32, WebGLSender<Option<WebGLShaderId>>),
+ DeleteBuffer(WebGLBufferId),
+ DeleteFramebuffer(WebGLFramebufferId),
+ DeleteRenderbuffer(WebGLRenderbufferId),
+ DeleteTexture(WebGLTextureId),
+ DeleteProgram(WebGLProgramId),
+ DeleteShader(WebGLShaderId),
+ BindBuffer(u32, Option<WebGLBufferId>),
+ BindFramebuffer(u32, WebGLFramebufferBindingRequest),
+ BindRenderbuffer(u32, Option<WebGLRenderbufferId>),
+ BindTexture(u32, Option<WebGLTextureId>),
+ DisableVertexAttribArray(u32),
+ EnableVertexAttribArray(u32),
+ FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>),
+ FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
+ GetExtensions(WebGLSender<String>),
+ GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>),
+ GetFragDataLocation(WebGLProgramId, String, WebGLSender<i32>),
+ GetUniformLocation(WebGLProgramId, String, WebGLSender<i32>),
+ GetShaderInfoLog(WebGLShaderId, WebGLSender<String>),
+ GetProgramInfoLog(WebGLProgramId, WebGLSender<String>),
+ GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender<i32>),
+ GetRenderbufferParameter(u32, u32, WebGLSender<i32>),
+ CreateTransformFeedback(WebGLSender<u32>),
+ DeleteTransformFeedback(u32),
+ IsTransformFeedback(u32, WebGLSender<bool>),
+ BindTransformFeedback(u32, u32),
+ BeginTransformFeedback(u32),
+ EndTransformFeedback(),
+ PauseTransformFeedback(),
+ ResumeTransformFeedback(),
+ GetTransformFeedbackVarying(WebGLProgramId, u32, WebGLSender<(i32, u32, String)>),
+ TransformFeedbackVaryings(WebGLProgramId, Vec<String>, u32),
+ PolygonOffset(f32, f32),
+ RenderbufferStorage(u32, u32, i32, i32),
+ RenderbufferStorageMultisample(u32, i32, u32, i32, i32),
+ ReadPixels(Rect<u32>, u32, u32, IpcBytesSender),
+ ReadPixelsPP(Rect<i32>, u32, u32, usize),
+ SampleCoverage(f32, bool),
+ Scissor(i32, i32, u32, u32),
+ StencilFunc(u32, i32, u32),
+ StencilFuncSeparate(u32, u32, i32, u32),
+ StencilMask(u32),
+ StencilMaskSeparate(u32, u32),
+ StencilOp(u32, u32, u32),
+ StencilOpSeparate(u32, u32, u32, u32),
+ FenceSync(WebGLSender<WebGLSyncId>),
+ IsSync(WebGLSyncId, WebGLSender<bool>),
+ ClientWaitSync(WebGLSyncId, u32, u64, WebGLSender<u32>),
+ WaitSync(WebGLSyncId, u32, i64),
+ GetSyncParameter(WebGLSyncId, u32, WebGLSender<u32>),
+ DeleteSync(WebGLSyncId),
+ Hint(u32, u32),
+ LineWidth(f32),
+ PixelStorei(u32, i32),
+ LinkProgram(WebGLProgramId, WebGLSender<ProgramLinkInfo>),
+ Uniform1f(i32, f32),
+ Uniform1fv(i32, Vec<f32>),
+ Uniform1i(i32, i32),
+ Uniform1ui(i32, u32),
+ Uniform1iv(i32, Vec<i32>),
+ Uniform1uiv(i32, Vec<u32>),
+ Uniform2f(i32, f32, f32),
+ Uniform2fv(i32, Vec<f32>),
+ Uniform2i(i32, i32, i32),
+ Uniform2ui(i32, u32, u32),
+ Uniform2iv(i32, Vec<i32>),
+ Uniform2uiv(i32, Vec<u32>),
+ Uniform3f(i32, f32, f32, f32),
+ Uniform3fv(i32, Vec<f32>),
+ Uniform3i(i32, i32, i32, i32),
+ Uniform3ui(i32, u32, u32, u32),
+ Uniform3iv(i32, Vec<i32>),
+ Uniform3uiv(i32, Vec<u32>),
+ Uniform4f(i32, f32, f32, f32, f32),
+ Uniform4fv(i32, Vec<f32>),
+ Uniform4i(i32, i32, i32, i32, i32),
+ Uniform4ui(i32, u32, u32, u32, u32),
+ Uniform4iv(i32, Vec<i32>),
+ Uniform4uiv(i32, Vec<u32>),
+ UniformMatrix2fv(i32, Vec<f32>),
+ UniformMatrix3fv(i32, Vec<f32>),
+ UniformMatrix4fv(i32, Vec<f32>),
+ UniformMatrix3x2fv(i32, Vec<f32>),
+ UniformMatrix4x2fv(i32, Vec<f32>),
+ UniformMatrix2x3fv(i32, Vec<f32>),
+ UniformMatrix4x3fv(i32, Vec<f32>),
+ UniformMatrix2x4fv(i32, Vec<f32>),
+ UniformMatrix3x4fv(i32, Vec<f32>),
+ UseProgram(Option<WebGLProgramId>),
+ ValidateProgram(WebGLProgramId),
+ VertexAttrib(u32, f32, f32, f32, f32),
+ VertexAttribI(u32, i32, i32, i32, i32),
+ VertexAttribU(u32, u32, u32, u32, u32),
+ VertexAttribPointer(u32, i32, u32, bool, i32, u32),
+ VertexAttribPointer2f(u32, i32, bool, i32, u32),
+ SetViewport(i32, i32, i32, i32),
+ TexImage2D {
+ target: u32,
+ level: u32,
+ internal_format: TexFormat,
+ size: Size2D<u32>,
+ format: TexFormat,
+ data_type: TexDataType,
+ // FIXME(nox): This should be computed on the WebGL thread.
+ effective_data_type: u32,
+ unpacking_alignment: u32,
+ alpha_treatment: Option<AlphaTreatment>,
+ y_axis_treatment: YAxisTreatment,
+ pixel_format: Option<PixelFormat>,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
+ TexImage2DPBO {
+ target: u32,
+ level: u32,
+ internal_format: TexFormat,
+ size: Size2D<u32>,
+ format: TexFormat,
+ effective_data_type: u32,
+ unpacking_alignment: u32,
+ offset: i64,
+ },
+ TexSubImage2D {
+ target: u32,
+ level: u32,
+ xoffset: i32,
+ yoffset: i32,
+ size: Size2D<u32>,
+ format: TexFormat,
+ data_type: TexDataType,
+ // FIXME(nox): This should be computed on the WebGL thread.
+ effective_data_type: u32,
+ unpacking_alignment: u32,
+ alpha_treatment: Option<AlphaTreatment>,
+ y_axis_treatment: YAxisTreatment,
+ pixel_format: Option<PixelFormat>,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
+ CompressedTexImage2D {
+ target: u32,
+ level: u32,
+ internal_format: u32,
+ size: Size2D<u32>,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
+ CompressedTexSubImage2D {
+ target: u32,
+ level: i32,
+ xoffset: i32,
+ yoffset: i32,
+ size: Size2D<u32>,
+ format: u32,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
+ DrawingBufferWidth(WebGLSender<i32>),
+ DrawingBufferHeight(WebGLSender<i32>),
+ Finish(WebGLSender<()>),
+ Flush,
+ GenerateMipmap(u32),
+ CreateVertexArray(WebGLSender<Option<WebGLVertexArrayId>>),
+ DeleteVertexArray(WebGLVertexArrayId),
+ BindVertexArray(Option<WebGLVertexArrayId>),
+ GetParameterBool(ParameterBool, WebGLSender<bool>),
+ GetParameterBool4(ParameterBool4, WebGLSender<[bool; 4]>),
+ GetParameterInt(ParameterInt, WebGLSender<i32>),
+ GetParameterInt2(ParameterInt2, WebGLSender<[i32; 2]>),
+ GetParameterInt4(ParameterInt4, WebGLSender<[i32; 4]>),
+ GetParameterFloat(ParameterFloat, WebGLSender<f32>),
+ GetParameterFloat2(ParameterFloat2, WebGLSender<[f32; 2]>),
+ GetParameterFloat4(ParameterFloat4, WebGLSender<[f32; 4]>),
+ GetProgramValidateStatus(WebGLProgramId, WebGLSender<bool>),
+ GetProgramActiveUniforms(WebGLProgramId, WebGLSender<i32>),
+ GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>),
+ GetTexParameterFloat(u32, TexParameterFloat, WebGLSender<f32>),
+ GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
+ GetTexParameterBool(u32, TexParameterBool, WebGLSender<bool>),
+ GetInternalFormatIntVec(u32, u32, InternalFormatIntVec, WebGLSender<Vec<i32>>),
+ TexParameteri(u32, u32, i32),
+ TexParameterf(u32, u32, f32),
+ TexStorage2D(u32, u32, TexFormat, u32, u32),
+ TexStorage3D(u32, u32, TexFormat, u32, u32, u32),
+ DrawArrays {
+ mode: u32,
+ first: i32,
+ count: i32,
+ },
+ DrawArraysInstanced {
+ mode: u32,
+ first: i32,
+ count: i32,
+ primcount: i32,
+ },
+ DrawElements {
+ mode: u32,
+ count: i32,
+ type_: u32,
+ offset: u32,
+ },
+ DrawElementsInstanced {
+ mode: u32,
+ count: i32,
+ type_: u32,
+ offset: u32,
+ primcount: i32,
+ },
+ VertexAttribDivisor {
+ index: u32,
+ divisor: u32,
+ },
+ GetUniformBool(WebGLProgramId, i32, WebGLSender<bool>),
+ GetUniformBool2(WebGLProgramId, i32, WebGLSender<[bool; 2]>),
+ GetUniformBool3(WebGLProgramId, i32, WebGLSender<[bool; 3]>),
+ GetUniformBool4(WebGLProgramId, i32, WebGLSender<[bool; 4]>),
+ GetUniformInt(WebGLProgramId, i32, WebGLSender<i32>),
+ GetUniformInt2(WebGLProgramId, i32, WebGLSender<[i32; 2]>),
+ GetUniformInt3(WebGLProgramId, i32, WebGLSender<[i32; 3]>),
+ GetUniformInt4(WebGLProgramId, i32, WebGLSender<[i32; 4]>),
+ GetUniformUint(WebGLProgramId, i32, WebGLSender<u32>),
+ GetUniformUint2(WebGLProgramId, i32, WebGLSender<[u32; 2]>),
+ GetUniformUint3(WebGLProgramId, i32, WebGLSender<[u32; 3]>),
+ GetUniformUint4(WebGLProgramId, i32, WebGLSender<[u32; 4]>),
+ GetUniformFloat(WebGLProgramId, i32, WebGLSender<f32>),
+ GetUniformFloat2(WebGLProgramId, i32, WebGLSender<[f32; 2]>),
+ GetUniformFloat3(WebGLProgramId, i32, WebGLSender<[f32; 3]>),
+ GetUniformFloat4(WebGLProgramId, i32, WebGLSender<[f32; 4]>),
+ GetUniformFloat9(WebGLProgramId, i32, WebGLSender<[f32; 9]>),
+ GetUniformFloat16(WebGLProgramId, i32, WebGLSender<[f32; 16]>),
+ GetUniformFloat2x3(WebGLProgramId, i32, WebGLSender<[f32; 2 * 3]>),
+ GetUniformFloat2x4(WebGLProgramId, i32, WebGLSender<[f32; 2 * 4]>),
+ GetUniformFloat3x2(WebGLProgramId, i32, WebGLSender<[f32; 3 * 2]>),
+ GetUniformFloat3x4(WebGLProgramId, i32, WebGLSender<[f32; 3 * 4]>),
+ GetUniformFloat4x2(WebGLProgramId, i32, WebGLSender<[f32; 4 * 2]>),
+ GetUniformFloat4x3(WebGLProgramId, i32, WebGLSender<[f32; 4 * 3]>),
+ GetUniformBlockIndex(WebGLProgramId, String, WebGLSender<u32>),
+ GetUniformIndices(WebGLProgramId, Vec<String>, WebGLSender<Vec<u32>>),
+ GetActiveUniforms(WebGLProgramId, Vec<u32>, u32, WebGLSender<Vec<i32>>),
+ GetActiveUniformBlockName(WebGLProgramId, u32, WebGLSender<String>),
+ GetActiveUniformBlockParameter(WebGLProgramId, u32, u32, WebGLSender<Vec<i32>>),
+ UniformBlockBinding(WebGLProgramId, u32, u32),
+ InitializeFramebuffer {
+ color: bool,
+ depth: bool,
+ stencil: bool,
+ },
+ BeginQuery(u32, WebGLQueryId),
+ DeleteQuery(WebGLQueryId),
+ EndQuery(u32),
+ GenerateQuery(WebGLSender<WebGLQueryId>),
+ GetQueryState(WebGLSender<u32>, WebGLQueryId, u32),
+ GenerateSampler(WebGLSender<WebGLSamplerId>),
+ DeleteSampler(WebGLSamplerId),
+ BindSampler(u32, WebGLSamplerId),
+ SetSamplerParameterFloat(WebGLSamplerId, u32, f32),
+ SetSamplerParameterInt(WebGLSamplerId, u32, i32),
+ GetSamplerParameterFloat(WebGLSamplerId, u32, WebGLSender<f32>),
+ GetSamplerParameterInt(WebGLSamplerId, u32, WebGLSender<i32>),
+ BindBufferBase(u32, u32, Option<WebGLBufferId>),
+ BindBufferRange(u32, u32, Option<WebGLBufferId>, i64, i64),
+ ClearBufferfv(u32, i32, Vec<f32>),
+ ClearBufferiv(u32, i32, Vec<i32>),
+ ClearBufferuiv(u32, i32, Vec<u32>),
+ ClearBufferfi(u32, i32, f32, i32),
+ InvalidateFramebuffer(u32, Vec<u32>),
+ InvalidateSubFramebuffer(u32, Vec<u32>, i32, i32, i32, i32),
+ FramebufferTextureLayer(u32, u32, Option<WebGLTextureId>, i32, i32),
+ ReadBuffer(u32),
+ DrawBuffers(Vec<u32>),
+}
+
+/// WebXR layer management
+#[derive(Debug, Deserialize, Serialize)]
+pub enum WebXRCommand {
+ CreateLayerManager(WebGLSender<Result<WebXRLayerManagerId, WebXRError>>),
+ DestroyLayerManager(WebXRLayerManagerId),
+ CreateLayer(
+ WebXRLayerManagerId,
+ WebXRContextId,
+ WebXRLayerInit,
+ WebGLSender<Result<WebXRLayerId, WebXRError>>,
+ ),
+ DestroyLayer(WebXRLayerManagerId, WebXRContextId, WebXRLayerId),
+ BeginFrame(
+ WebXRLayerManagerId,
+ Vec<(WebXRContextId, WebXRLayerId)>,
+ WebGLSender<Result<Vec<WebXRSubImages>, WebXRError>>,
+ ),
+ EndFrame(
+ WebXRLayerManagerId,
+ Vec<(WebXRContextId, WebXRLayerId)>,
+ WebGLSender<Result<(), WebXRError>>,
+ ),
+}
+
+macro_rules! nonzero_type {
+ (u32) => {
+ NonZeroU32
+ };
+ (u64) => {
+ NonZeroU64
+ };
+}
+
+macro_rules! define_resource_id {
+ ($name:ident, $type:tt) => {
+ #[derive(Clone, Copy, Eq, Hash, PartialEq)]
+ pub struct $name(nonzero_type!($type));
+
+ impl $name {
+ #[allow(unsafe_code)]
+ #[inline]
+ pub unsafe fn new(id: $type) -> Self {
+ $name(<nonzero_type!($type)>::new_unchecked(id))
+ }
+
+ #[inline]
+ pub fn maybe_new(id: $type) -> Option<Self> {
+ <nonzero_type!($type)>::new(id).map($name)
+ }
+
+ #[inline]
+ pub fn get(self) -> $type {
+ self.0.get()
+ }
+ }
+
+ #[allow(unsafe_code)]
+ impl<'de> ::serde::Deserialize<'de> for $name {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: ::serde::Deserializer<'de>,
+ {
+ let id = <$type>::deserialize(deserializer)?;
+ if id == 0 {
+ Err(::serde::de::Error::custom("expected a non-zero value"))
+ } else {
+ Ok(unsafe { $name::new(id) })
+ }
+ }
+ }
+
+ impl ::serde::Serialize for $name {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: ::serde::Serializer,
+ {
+ self.get().serialize(serializer)
+ }
+ }
+
+ impl ::std::fmt::Debug for $name {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ fmt.debug_tuple(stringify!($name))
+ .field(&self.get())
+ .finish()
+ }
+ }
+
+ impl ::std::fmt::Display for $name {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ write!(fmt, "{}", self.get())
+ }
+ }
+
+ impl ::malloc_size_of::MallocSizeOf for $name {
+ fn size_of(&self, _ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize {
+ 0
+ }
+ }
+ };
+}
+
+define_resource_id!(WebGLBufferId, u32);
+define_resource_id!(WebGLFramebufferId, u32);
+define_resource_id!(WebGLRenderbufferId, u32);
+define_resource_id!(WebGLTextureId, u32);
+define_resource_id!(WebGLProgramId, u32);
+define_resource_id!(WebGLQueryId, u32);
+define_resource_id!(WebGLSamplerId, u32);
+define_resource_id!(WebGLShaderId, u32);
+define_resource_id!(WebGLSyncId, u64);
+define_resource_id!(WebGLVertexArrayId, u32);
+define_resource_id!(WebXRLayerManagerId, u32);
+
+#[derive(
+ Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
+)]
+pub struct WebGLContextId(pub u64);
+
+impl From<WebXRContextId> for WebGLContextId {
+ fn from(id: WebXRContextId) -> Self {
+ Self(id.0)
+ }
+}
+
+impl From<WebGLContextId> for WebXRContextId {
+ fn from(id: WebGLContextId) -> Self {
+ Self(id.0)
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
+pub enum WebGLError {
+ InvalidEnum,
+ InvalidFramebufferOperation,
+ InvalidOperation,
+ InvalidValue,
+ OutOfMemory,
+ ContextLost,
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
+pub enum WebGLFramebufferBindingRequest {
+ Explicit(WebGLFramebufferId),
+ Default,
+}
+
+pub type WebGLResult<T> = Result<T, WebGLError>;
+
+/// Information about a WebGL program linking operation.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct ProgramLinkInfo {
+ /// Whether the program was linked successfully.
+ pub linked: bool,
+ /// The list of active attributes.
+ pub active_attribs: Box<[ActiveAttribInfo]>,
+ /// The list of active uniforms.
+ pub active_uniforms: Box<[ActiveUniformInfo]>,
+ /// The list of active uniform blocks.
+ pub active_uniform_blocks: Box<[ActiveUniformBlockInfo]>,
+ /// The number of varying variables
+ pub transform_feedback_length: i32,
+ /// The buffer mode used when transform feedback is active
+ pub transform_feedback_mode: i32,
+}
+
+/// Description of a single active attribute.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct ActiveAttribInfo {
+ /// The name of the attribute.
+ pub name: String,
+ /// The size of the attribute.
+ pub size: i32,
+ /// The type of the attribute.
+ pub type_: u32,
+ /// The location of the attribute.
+ pub location: i32,
+}
+
+/// Description of a single active uniform.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct ActiveUniformInfo {
+ /// The base name of the uniform.
+ pub base_name: Box<str>,
+ /// The size of the uniform, if it is an array.
+ pub size: Option<i32>,
+ /// The type of the uniform.
+ pub type_: u32,
+ /// The index of the indexed uniform buffer binding, if it is bound.
+ pub bind_index: Option<u32>,
+}
+
+impl ActiveUniformInfo {
+ pub fn name(&self) -> Cow<str> {
+ if self.size.is_some() {
+ let mut name = String::from(&*self.base_name);
+ name.push_str("[0]");
+ Cow::Owned(name)
+ } else {
+ Cow::Borrowed(&self.base_name)
+ }
+ }
+}
+
+/// Description of a single uniform block.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub struct ActiveUniformBlockInfo {
+ /// The name of the uniform block.
+ pub name: String,
+ /// The size of the uniform block.
+ pub size: i32,
+}
+
+macro_rules! parameters {
+ ($name:ident { $(
+ $variant:ident($kind:ident { $(
+ $param:ident = gl::$value:ident,
+ )+ }),
+ )+ }) => {
+ #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+ pub enum $name { $(
+ $variant($kind),
+ )+}
+
+ $(
+ #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+ #[repr(u32)]
+ pub enum $kind { $(
+ $param = gl::$value,
+ )+}
+ )+
+
+ impl $name {
+ pub fn from_u32(value: u32) -> WebGLResult<Self> {
+ match value {
+ $($(gl::$value => Ok($name::$variant($kind::$param)),)+)+
+ _ => Err(WebGLError::InvalidEnum)
+ }
+ }
+ }
+ }
+}
+
+parameters! {
+ Parameter {
+ Bool(ParameterBool {
+ DepthWritemask = gl::DEPTH_WRITEMASK,
+ SampleCoverageInvert = gl::SAMPLE_COVERAGE_INVERT,
+ TransformFeedbackActive = gl::TRANSFORM_FEEDBACK_ACTIVE,
+ TransformFeedbackPaused = gl::TRANSFORM_FEEDBACK_PAUSED,
+ RasterizerDiscard = gl::RASTERIZER_DISCARD,
+ }),
+ Bool4(ParameterBool4 {
+ ColorWritemask = gl::COLOR_WRITEMASK,
+ }),
+ Int(ParameterInt {
+ ActiveTexture = gl::ACTIVE_TEXTURE,
+ AlphaBits = gl::ALPHA_BITS,
+ BlendDstAlpha = gl::BLEND_DST_ALPHA,
+ BlendDstRgb = gl::BLEND_DST_RGB,
+ BlendEquationAlpha = gl::BLEND_EQUATION_ALPHA,
+ BlendEquationRgb = gl::BLEND_EQUATION_RGB,
+ BlendSrcAlpha = gl::BLEND_SRC_ALPHA,
+ BlendSrcRgb = gl::BLEND_SRC_RGB,
+ BlueBits = gl::BLUE_BITS,
+ CullFaceMode = gl::CULL_FACE_MODE,
+ DepthBits = gl::DEPTH_BITS,
+ DepthFunc = gl::DEPTH_FUNC,
+ FragmentShaderDerivativeHint = gl::FRAGMENT_SHADER_DERIVATIVE_HINT,
+ FrontFace = gl::FRONT_FACE,
+ GenerateMipmapHint = gl::GENERATE_MIPMAP_HINT,
+ GreenBits = gl::GREEN_BITS,
+ RedBits = gl::RED_BITS,
+ SampleBuffers = gl::SAMPLE_BUFFERS,
+ Samples = gl::SAMPLES,
+ StencilBackFail = gl::STENCIL_BACK_FAIL,
+ StencilBackFunc = gl::STENCIL_BACK_FUNC,
+ StencilBackPassDepthFail = gl::STENCIL_BACK_PASS_DEPTH_FAIL,
+ StencilBackPassDepthPass = gl::STENCIL_BACK_PASS_DEPTH_PASS,
+ StencilBackRef = gl::STENCIL_BACK_REF,
+ StencilBackValueMask = gl::STENCIL_BACK_VALUE_MASK,
+ StencilBackWritemask = gl::STENCIL_BACK_WRITEMASK,
+ StencilBits = gl::STENCIL_BITS,
+ StencilClearValue = gl::STENCIL_CLEAR_VALUE,
+ StencilFail = gl::STENCIL_FAIL,
+ StencilFunc = gl::STENCIL_FUNC,
+ StencilPassDepthFail = gl::STENCIL_PASS_DEPTH_FAIL,
+ StencilPassDepthPass = gl::STENCIL_PASS_DEPTH_PASS,
+ StencilRef = gl::STENCIL_REF,
+ StencilValueMask = gl::STENCIL_VALUE_MASK,
+ StencilWritemask = gl::STENCIL_WRITEMASK,
+ SubpixelBits = gl::SUBPIXEL_BITS,
+ TransformFeedbackBinding = gl::TRANSFORM_FEEDBACK_BINDING,
+ MaxTransformFeedbackInterleavedComponents = gl::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
+ MaxTransformFeedbackSeparateAttribs = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
+ MaxTransformFeedbackSeparateComponents = gl::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS,
+ TransformFeedbackBufferSize = gl::TRANSFORM_FEEDBACK_BUFFER_SIZE,
+ TransformFeedbackBufferStart = gl::TRANSFORM_FEEDBACK_BUFFER_START,
+ PackRowLength = gl::PACK_ROW_LENGTH,
+ PackSkipPixels = gl::PACK_SKIP_PIXELS,
+ PackSkipRows = gl::PACK_SKIP_ROWS,
+ UnpackImageHeight = gl::UNPACK_IMAGE_HEIGHT,
+ UnpackRowLength = gl::UNPACK_ROW_LENGTH,
+ UnpackSkipImages = gl::UNPACK_SKIP_IMAGES,
+ UnpackSkipPixels = gl::UNPACK_SKIP_PIXELS,
+ UnpackSkipRows = gl::UNPACK_SKIP_ROWS,
+ }),
+ Int2(ParameterInt2 {
+ MaxViewportDims = gl::MAX_VIEWPORT_DIMS,
+ }),
+ Int4(ParameterInt4 {
+ ScissorBox = gl::SCISSOR_BOX,
+ Viewport = gl::VIEWPORT,
+ }),
+ Float(ParameterFloat {
+ DepthClearValue = gl::DEPTH_CLEAR_VALUE,
+ LineWidth = gl::LINE_WIDTH,
+ MaxTextureMaxAnisotropyExt = gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT,
+ PolygonOffsetFactor = gl::POLYGON_OFFSET_FACTOR,
+ PolygonOffsetUnits = gl::POLYGON_OFFSET_UNITS,
+ SampleCoverageValue = gl::SAMPLE_COVERAGE_VALUE,
+ }),
+ Float2(ParameterFloat2 {
+ AliasedPointSizeRange = gl::ALIASED_POINT_SIZE_RANGE,
+ AliasedLineWidthRange = gl::ALIASED_LINE_WIDTH_RANGE,
+ DepthRange = gl::DEPTH_RANGE,
+ }),
+ Float4(ParameterFloat4 {
+ BlendColor = gl::BLEND_COLOR,
+ ColorClearValue = gl::COLOR_CLEAR_VALUE,
+ }),
+ }
+}
+
+parameters! {
+ TexParameter {
+ Float(TexParameterFloat {
+ TextureMaxAnisotropyExt = gl::TEXTURE_MAX_ANISOTROPY_EXT,
+ TextureMaxLod = gl::TEXTURE_MAX_LOD,
+ TextureMinLod = gl::TEXTURE_MIN_LOD,
+ }),
+ Int(TexParameterInt {
+ TextureWrapS = gl::TEXTURE_WRAP_S,
+ TextureWrapT = gl::TEXTURE_WRAP_T,
+ TextureWrapR = gl::TEXTURE_WRAP_R,
+ TextureBaseLevel = gl::TEXTURE_BASE_LEVEL,
+ TextureMinFilter = gl::TEXTURE_MIN_FILTER,
+ TextureMagFilter = gl::TEXTURE_MAG_FILTER,
+ TextureMaxLevel = gl::TEXTURE_MAX_LEVEL,
+ TextureCompareFunc = gl::TEXTURE_COMPARE_FUNC,
+ TextureCompareMode = gl::TEXTURE_COMPARE_MODE,
+ TextureImmutableLevels = gl::TEXTURE_IMMUTABLE_LEVELS,
+ }),
+ Bool(TexParameterBool {
+ TextureImmutableFormat = gl::TEXTURE_IMMUTABLE_FORMAT,
+ }),
+ }
+}
+
+impl TexParameter {
+ pub fn required_webgl_version(self) -> WebGLVersion {
+ match self {
+ Self::Float(TexParameterFloat::TextureMaxAnisotropyExt) |
+ Self::Int(TexParameterInt::TextureWrapS) |
+ Self::Int(TexParameterInt::TextureWrapT) => WebGLVersion::WebGL1,
+ _ => WebGLVersion::WebGL2,
+ }
+ }
+}
+
+parameters! {
+ InternalFormatParameter {
+ IntVec(InternalFormatIntVec {
+ Samples = gl::SAMPLES,
+ }),
+ }
+}
+
+#[macro_export]
+macro_rules! gl_enums {
+ ($(pub enum $name:ident { $($variant:ident = $mod:ident::$constant:ident,)+ })*) => {
+ $(
+ #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, malloc_size_of_derive::MallocSizeOf)]
+ #[derive(PartialEq, Serialize)]
+ #[repr(u32)]
+ pub enum $name { $($variant = $mod::$constant,)+ }
+
+ impl $name {
+ pub fn from_gl_constant(constant: u32) -> Option<Self> {
+ Some(match constant {
+ $($mod::$constant => $name::$variant, )+
+ _ => return None,
+ })
+ }
+
+ #[inline]
+ pub fn as_gl_constant(&self) -> u32 {
+ *self as u32
+ }
+ }
+ )*
+ }
+}
+
+// FIXME: These should come from sparkle
+mod gl_ext_constants {
+ use sparkle::gl::types::GLenum;
+
+ pub const COMPRESSED_RGB_S3TC_DXT1_EXT: GLenum = 0x83F0;
+ pub const COMPRESSED_RGBA_S3TC_DXT1_EXT: GLenum = 0x83F1;
+ pub const COMPRESSED_RGBA_S3TC_DXT3_EXT: GLenum = 0x83F2;
+ pub const COMPRESSED_RGBA_S3TC_DXT5_EXT: GLenum = 0x83F3;
+ pub const COMPRESSED_RGB_ETC1_WEBGL: GLenum = 0x8D64;
+
+ pub static COMPRESSIONS: &'static [GLenum] = &[
+ COMPRESSED_RGB_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ COMPRESSED_RGB_ETC1_WEBGL,
+ ];
+
+ pub const ALPHA16F_ARB: u32 = 0x881C;
+ pub const ALPHA32F_ARB: u32 = 0x8816;
+ pub const LUMINANCE16F_ARB: u32 = 0x881E;
+ pub const LUMINANCE32F_ARB: u32 = 0x8818;
+ pub const LUMINANCE_ALPHA16F_ARB: u32 = 0x881F;
+ pub const LUMINANCE_ALPHA32F_ARB: u32 = 0x8819;
+}
+
+gl_enums! {
+ pub enum TexFormat {
+ DepthComponent = gl::DEPTH_COMPONENT,
+ DepthStencil = gl::DEPTH_STENCIL,
+ Alpha = gl::ALPHA,
+ Alpha32f = gl_ext_constants::ALPHA32F_ARB,
+ Alpha16f = gl_ext_constants::ALPHA16F_ARB,
+ Red = gl::RED,
+ RedInteger = gl::RED_INTEGER,
+ RG = gl::RG,
+ RGInteger = gl::RG_INTEGER,
+ RGB = gl::RGB,
+ RGBInteger = gl::RGB_INTEGER,
+ RGBA = gl::RGBA,
+ RGBAInteger = gl::RGBA_INTEGER,
+ Luminance = gl::LUMINANCE,
+ LuminanceAlpha = gl::LUMINANCE_ALPHA,
+ Luminance32f = gl_ext_constants::LUMINANCE32F_ARB,
+ Luminance16f = gl_ext_constants::LUMINANCE16F_ARB,
+ LuminanceAlpha32f = gl_ext_constants::LUMINANCE_ALPHA32F_ARB,
+ LuminanceAlpha16f = gl_ext_constants::LUMINANCE_ALPHA16F_ARB,
+ CompressedRgbS3tcDxt1 = gl_ext_constants::COMPRESSED_RGB_S3TC_DXT1_EXT,
+ CompressedRgbaS3tcDxt1 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ CompressedRgbaS3tcDxt3 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ CompressedRgbaS3tcDxt5 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ CompressedRgbEtc1 = gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL,
+ R8 = gl::R8,
+ R8SNorm = gl::R8_SNORM,
+ R16f = gl::R16F,
+ R32f = gl::R32F,
+ R8ui = gl::R8UI,
+ R8i = gl::R8I,
+ R16ui = gl::R16UI,
+ R16i = gl::R16I,
+ R32ui = gl::R32UI,
+ R32i = gl::R32I,
+ RG8 = gl::RG8,
+ RG8SNorm = gl::RG8_SNORM,
+ RG16f = gl::RG16F,
+ RG32f = gl::RG32F,
+ RG8ui = gl::RG8UI,
+ RG8i = gl::RG8I,
+ RG16ui = gl::RG16UI,
+ RG16i = gl::RG16I,
+ RG32ui = gl::RG32UI,
+ RG32i = gl::RG32I,
+ RGB8 = gl::RGB8,
+ SRGB8 = gl::SRGB8,
+ RGB565 = gl::RGB565,
+ RGB8SNorm = gl::RGB8_SNORM,
+ R11fG11fB10f = gl::R11F_G11F_B10F,
+ RGB9E5 = gl::RGB9_E5,
+ RGB16f = gl::RGB16F,
+ RGB32f = gl::RGB32F,
+ RGB8ui = gl::RGB8UI,
+ RGB8i = gl::RGB8I,
+ RGB16ui = gl::RGB16UI,
+ RGB16i = gl::RGB16I,
+ RGB32ui = gl::RGB32UI,
+ RGB32i = gl::RGB32I,
+ RGBA8 = gl::RGBA8,
+ SRGB8Alpha8 = gl::SRGB8_ALPHA8,
+ RGBA8SNorm = gl::RGBA8_SNORM,
+ RGB5A1 = gl::RGB5_A1,
+ RGBA4 = gl::RGBA4,
+ RGB10A2 = gl::RGB10_A2,
+ RGBA16f = gl::RGBA16F,
+ RGBA32f = gl::RGBA32F,
+ RGBA8ui = gl::RGBA8UI,
+ RGBA8i = gl::RGBA8I,
+ RGB10A2ui = gl::RGB10_A2UI,
+ RGBA16ui = gl::RGBA16UI,
+ RGBA16i = gl::RGBA16I,
+ RGBA32i = gl::RGBA32I,
+ RGBA32ui = gl::RGBA32UI,
+ DepthComponent16 = gl::DEPTH_COMPONENT16,
+ DepthComponent24 = gl::DEPTH_COMPONENT24,
+ DepthComponent32f = gl::DEPTH_COMPONENT32F,
+ Depth24Stencil8 = gl::DEPTH24_STENCIL8,
+ Depth32fStencil8 = gl::DEPTH32F_STENCIL8,
+ }
+
+ pub enum TexDataType {
+ Byte = gl::BYTE,
+ Int = gl::INT,
+ Short = gl::SHORT,
+ UnsignedByte = gl::UNSIGNED_BYTE,
+ UnsignedInt = gl::UNSIGNED_INT,
+ UnsignedInt10f11f11fRev = gl::UNSIGNED_INT_10F_11F_11F_REV,
+ UnsignedInt2101010Rev = gl::UNSIGNED_INT_2_10_10_10_REV,
+ UnsignedInt5999Rev = gl::UNSIGNED_INT_5_9_9_9_REV,
+ UnsignedInt248 = gl::UNSIGNED_INT_24_8,
+ UnsignedShort = gl::UNSIGNED_SHORT,
+ UnsignedShort4444 = gl::UNSIGNED_SHORT_4_4_4_4,
+ UnsignedShort5551 = gl::UNSIGNED_SHORT_5_5_5_1,
+ UnsignedShort565 = gl::UNSIGNED_SHORT_5_6_5,
+ Float = gl::FLOAT,
+ HalfFloat = gl::HALF_FLOAT_OES,
+ Float32UnsignedInt248Rev = gl::FLOAT_32_UNSIGNED_INT_24_8_REV,
+ }
+}
+
+impl TexFormat {
+ /// Returns how many components does this format need. For example, RGBA
+ /// needs 4 components, while RGB requires 3.
+ pub fn components(&self) -> u32 {
+ match self.to_unsized() {
+ TexFormat::DepthStencil => 2,
+ TexFormat::LuminanceAlpha => 2,
+ TexFormat::RG | TexFormat::RGInteger => 2,
+ TexFormat::RGB | TexFormat::RGBInteger => 3,
+ TexFormat::RGBA | TexFormat::RGBAInteger => 4,
+ _ => 1,
+ }
+ }
+
+ /// Returns whether this format is a known texture compression format.
+ pub fn is_compressed(&self) -> bool {
+ gl_ext_constants::COMPRESSIONS.contains(&self.as_gl_constant())
+ }
+
+ /// Returns whether this format is a known sized or unsized format.
+ pub fn is_sized(&self) -> bool {
+ match self {
+ TexFormat::DepthComponent |
+ TexFormat::DepthStencil |
+ TexFormat::Alpha |
+ TexFormat::Red |
+ TexFormat::RG |
+ TexFormat::RGB |
+ TexFormat::RGBA |
+ TexFormat::Luminance |
+ TexFormat::LuminanceAlpha => false,
+ _ => true,
+ }
+ }
+
+ pub fn to_unsized(self) -> TexFormat {
+ match self {
+ TexFormat::R8 => TexFormat::Red,
+ TexFormat::R8SNorm => TexFormat::Red,
+ TexFormat::R16f => TexFormat::Red,
+ TexFormat::R32f => TexFormat::Red,
+ TexFormat::R8ui => TexFormat::RedInteger,
+ TexFormat::R8i => TexFormat::RedInteger,
+ TexFormat::R16ui => TexFormat::RedInteger,
+ TexFormat::R16i => TexFormat::RedInteger,
+ TexFormat::R32ui => TexFormat::RedInteger,
+ TexFormat::R32i => TexFormat::RedInteger,
+ TexFormat::RG8 => TexFormat::RG,
+ TexFormat::RG8SNorm => TexFormat::RG,
+ TexFormat::RG16f => TexFormat::RG,
+ TexFormat::RG32f => TexFormat::RG,
+ TexFormat::RG8ui => TexFormat::RGInteger,
+ TexFormat::RG8i => TexFormat::RGInteger,
+ TexFormat::RG16ui => TexFormat::RGInteger,
+ TexFormat::RG16i => TexFormat::RGInteger,
+ TexFormat::RG32ui => TexFormat::RGInteger,
+ TexFormat::RG32i => TexFormat::RGInteger,
+ TexFormat::RGB8 => TexFormat::RGB,
+ TexFormat::SRGB8 => TexFormat::RGB,
+ TexFormat::RGB565 => TexFormat::RGB,
+ TexFormat::RGB8SNorm => TexFormat::RGB,
+ TexFormat::R11fG11fB10f => TexFormat::RGB,
+ TexFormat::RGB9E5 => TexFormat::RGB,
+ TexFormat::RGB16f => TexFormat::RGB,
+ TexFormat::RGB32f => TexFormat::RGB,
+ TexFormat::RGB8ui => TexFormat::RGBInteger,
+ TexFormat::RGB8i => TexFormat::RGBInteger,
+ TexFormat::RGB16ui => TexFormat::RGBInteger,
+ TexFormat::RGB16i => TexFormat::RGBInteger,
+ TexFormat::RGB32ui => TexFormat::RGBInteger,
+ TexFormat::RGB32i => TexFormat::RGBInteger,
+ TexFormat::RGBA8 => TexFormat::RGBA,
+ TexFormat::SRGB8Alpha8 => TexFormat::RGBA,
+ TexFormat::RGBA8SNorm => TexFormat::RGBA,
+ TexFormat::RGB5A1 => TexFormat::RGBA,
+ TexFormat::RGBA4 => TexFormat::RGBA,
+ TexFormat::RGB10A2 => TexFormat::RGBA,
+ TexFormat::RGBA16f => TexFormat::RGBA,
+ TexFormat::RGBA32f => TexFormat::RGBA,
+ TexFormat::RGBA8ui => TexFormat::RGBAInteger,
+ TexFormat::RGBA8i => TexFormat::RGBAInteger,
+ TexFormat::RGB10A2ui => TexFormat::RGBAInteger,
+ TexFormat::RGBA16ui => TexFormat::RGBAInteger,
+ TexFormat::RGBA16i => TexFormat::RGBAInteger,
+ TexFormat::RGBA32i => TexFormat::RGBAInteger,
+ TexFormat::RGBA32ui => TexFormat::RGBAInteger,
+ TexFormat::DepthComponent16 => TexFormat::DepthComponent,
+ TexFormat::DepthComponent24 => TexFormat::DepthComponent,
+ TexFormat::DepthComponent32f => TexFormat::DepthComponent,
+ TexFormat::Depth24Stencil8 => TexFormat::DepthStencil,
+ TexFormat::Depth32fStencil8 => TexFormat::DepthStencil,
+ TexFormat::Alpha32f => TexFormat::Alpha,
+ TexFormat::Alpha16f => TexFormat::Alpha,
+ TexFormat::Luminance32f => TexFormat::Luminance,
+ TexFormat::Luminance16f => TexFormat::Luminance,
+ TexFormat::LuminanceAlpha32f => TexFormat::LuminanceAlpha,
+ TexFormat::LuminanceAlpha16f => TexFormat::LuminanceAlpha,
+ _ => self,
+ }
+ }
+
+ pub fn compatible_data_types(self) -> &'static [TexDataType] {
+ match self {
+ TexFormat::RGB => &[
+ TexDataType::UnsignedByte,
+ TexDataType::UnsignedShort565,
+ TexDataType::Float,
+ TexDataType::HalfFloat,
+ ][..],
+ TexFormat::RGBA => &[
+ TexDataType::UnsignedByte,
+ TexDataType::UnsignedShort4444,
+ TexDataType::UnsignedShort5551,
+ TexDataType::Float,
+ TexDataType::HalfFloat,
+ ][..],
+ TexFormat::LuminanceAlpha => &[
+ TexDataType::UnsignedByte,
+ TexDataType::Float,
+ TexDataType::HalfFloat,
+ ][..],
+ TexFormat::Luminance => &[
+ TexDataType::UnsignedByte,
+ TexDataType::Float,
+ TexDataType::HalfFloat,
+ ][..],
+ TexFormat::Alpha => &[
+ TexDataType::UnsignedByte,
+ TexDataType::Float,
+ TexDataType::HalfFloat,
+ ][..],
+ TexFormat::LuminanceAlpha32f => &[TexDataType::Float][..],
+ TexFormat::LuminanceAlpha16f => &[TexDataType::HalfFloat][..],
+ TexFormat::Luminance32f => &[TexDataType::Float][..],
+ TexFormat::Luminance16f => &[TexDataType::HalfFloat][..],
+ TexFormat::Alpha32f => &[TexDataType::Float][..],
+ TexFormat::Alpha16f => &[TexDataType::HalfFloat][..],
+ TexFormat::R8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::R8SNorm => &[TexDataType::Byte][..],
+ TexFormat::R16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
+ TexFormat::R32f => &[TexDataType::Float][..],
+ TexFormat::R8ui => &[TexDataType::UnsignedByte][..],
+ TexFormat::R8i => &[TexDataType::Byte][..],
+ TexFormat::R16ui => &[TexDataType::UnsignedShort][..],
+ TexFormat::R16i => &[TexDataType::Short][..],
+ TexFormat::R32ui => &[TexDataType::UnsignedInt][..],
+ TexFormat::R32i => &[TexDataType::Int][..],
+ TexFormat::RG8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::RG8SNorm => &[TexDataType::Byte][..],
+ TexFormat::RG16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
+ TexFormat::RG32f => &[TexDataType::Float][..],
+ TexFormat::RG8ui => &[TexDataType::UnsignedByte][..],
+ TexFormat::RG8i => &[TexDataType::Byte][..],
+ TexFormat::RG16ui => &[TexDataType::UnsignedShort][..],
+ TexFormat::RG16i => &[TexDataType::Short][..],
+ TexFormat::RG32ui => &[TexDataType::UnsignedInt][..],
+ TexFormat::RG32i => &[TexDataType::Int][..],
+ TexFormat::RGB8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::SRGB8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::RGB565 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort565][..],
+ TexFormat::RGB8SNorm => &[TexDataType::Byte][..],
+ TexFormat::R11fG11fB10f => &[
+ TexDataType::UnsignedInt10f11f11fRev,
+ TexDataType::HalfFloat,
+ TexDataType::Float,
+ ][..],
+ TexFormat::RGB9E5 => &[
+ TexDataType::UnsignedInt5999Rev,
+ TexDataType::HalfFloat,
+ TexDataType::Float,
+ ][..],
+ TexFormat::RGB16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
+ TexFormat::RGB32f => &[TexDataType::Float][..],
+ TexFormat::RGB8ui => &[TexDataType::UnsignedByte][..],
+ TexFormat::RGB8i => &[TexDataType::Byte][..],
+ TexFormat::RGB16ui => &[TexDataType::UnsignedShort][..],
+ TexFormat::RGB16i => &[TexDataType::Short][..],
+ TexFormat::RGB32ui => &[TexDataType::UnsignedInt][..],
+ TexFormat::RGB32i => &[TexDataType::Int][..],
+ TexFormat::RGBA8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::SRGB8Alpha8 => &[TexDataType::UnsignedByte][..],
+ TexFormat::RGBA8SNorm => &[TexDataType::Byte][..],
+ TexFormat::RGB5A1 => &[
+ TexDataType::UnsignedByte,
+ TexDataType::UnsignedShort5551,
+ TexDataType::UnsignedInt2101010Rev,
+ ][..],
+ TexFormat::RGBA4 => &[TexDataType::UnsignedByte, TexDataType::UnsignedShort4444][..],
+ TexFormat::RGB10A2 => &[TexDataType::UnsignedInt2101010Rev][..],
+ TexFormat::RGBA16f => &[TexDataType::HalfFloat, TexDataType::Float][..],
+ TexFormat::RGBA32f => &[TexDataType::Float][..],
+ TexFormat::RGBA8ui => &[TexDataType::UnsignedByte][..],
+ TexFormat::RGBA8i => &[TexDataType::Byte][..],
+ TexFormat::RGB10A2ui => &[TexDataType::UnsignedInt2101010Rev][..],
+ TexFormat::RGBA16ui => &[TexDataType::UnsignedShort][..],
+ TexFormat::RGBA16i => &[TexDataType::Short][..],
+ TexFormat::RGBA32i => &[TexDataType::Int][..],
+ TexFormat::RGBA32ui => &[TexDataType::UnsignedInt][..],
+ TexFormat::DepthComponent16 => {
+ &[TexDataType::UnsignedShort, TexDataType::UnsignedInt][..]
+ },
+ TexFormat::DepthComponent24 => &[TexDataType::UnsignedInt][..],
+ TexFormat::DepthComponent32f => &[TexDataType::Float][..],
+ TexFormat::Depth24Stencil8 => &[TexDataType::UnsignedInt248][..],
+ TexFormat::Depth32fStencil8 => &[TexDataType::Float32UnsignedInt248Rev][..],
+ TexFormat::CompressedRgbS3tcDxt1 |
+ TexFormat::CompressedRgbaS3tcDxt1 |
+ TexFormat::CompressedRgbaS3tcDxt3 |
+ TexFormat::CompressedRgbaS3tcDxt5 => &[TexDataType::UnsignedByte][..],
+ _ => &[][..],
+ }
+ }
+
+ pub fn required_webgl_version(self) -> WebGLVersion {
+ match self {
+ TexFormat::DepthComponent |
+ TexFormat::Alpha |
+ TexFormat::RGB |
+ TexFormat::RGBA |
+ TexFormat::Luminance |
+ TexFormat::LuminanceAlpha |
+ TexFormat::CompressedRgbS3tcDxt1 |
+ TexFormat::CompressedRgbaS3tcDxt1 |
+ TexFormat::CompressedRgbaS3tcDxt3 |
+ TexFormat::CompressedRgbaS3tcDxt5 => WebGLVersion::WebGL1,
+ _ => WebGLVersion::WebGL2,
+ }
+ }
+
+ pub fn usable_as_internal(self) -> bool {
+ !self.compatible_data_types().is_empty()
+ }
+}
+
+#[derive(PartialEq)]
+pub enum SizedDataType {
+ Int8,
+ Int16,
+ Int32,
+ Uint8,
+ Uint16,
+ Uint32,
+ Float32,
+}
+
+impl TexDataType {
+ /// Returns the compatible sized data type for this texture data type.
+ pub fn sized_data_type(&self) -> SizedDataType {
+ match self {
+ TexDataType::Byte => SizedDataType::Int8,
+ TexDataType::UnsignedByte => SizedDataType::Uint8,
+ TexDataType::Short => SizedDataType::Int16,
+ TexDataType::UnsignedShort |
+ TexDataType::UnsignedShort4444 |
+ TexDataType::UnsignedShort5551 |
+ TexDataType::UnsignedShort565 => SizedDataType::Uint16,
+ TexDataType::Int => SizedDataType::Int32,
+ TexDataType::UnsignedInt |
+ TexDataType::UnsignedInt10f11f11fRev |
+ TexDataType::UnsignedInt2101010Rev |
+ TexDataType::UnsignedInt5999Rev |
+ TexDataType::UnsignedInt248 => SizedDataType::Uint32,
+ TexDataType::HalfFloat => SizedDataType::Uint16,
+ TexDataType::Float | TexDataType::Float32UnsignedInt248Rev => SizedDataType::Float32,
+ }
+ }
+
+ /// Returns the size in bytes of each element of data.
+ pub fn element_size(&self) -> u32 {
+ use self::*;
+ match *self {
+ TexDataType::Byte | TexDataType::UnsignedByte => 1,
+ TexDataType::Short |
+ TexDataType::UnsignedShort |
+ TexDataType::UnsignedShort4444 |
+ TexDataType::UnsignedShort5551 |
+ TexDataType::UnsignedShort565 => 2,
+ TexDataType::Int |
+ TexDataType::UnsignedInt |
+ TexDataType::UnsignedInt10f11f11fRev |
+ TexDataType::UnsignedInt2101010Rev |
+ TexDataType::UnsignedInt5999Rev => 4,
+ TexDataType::UnsignedInt248 => 4,
+ TexDataType::Float => 4,
+ TexDataType::HalfFloat => 2,
+ TexDataType::Float32UnsignedInt248Rev => 4,
+ }
+ }
+
+ /// Returns how many components a single element may hold. For example, a
+ /// UnsignedShort4444 holds four components, each with 4 bits of data.
+ pub fn components_per_element(&self) -> u32 {
+ match *self {
+ TexDataType::Byte => 1,
+ TexDataType::UnsignedByte => 1,
+ TexDataType::Short => 1,
+ TexDataType::UnsignedShort => 1,
+ TexDataType::UnsignedShort565 => 3,
+ TexDataType::UnsignedShort5551 => 4,
+ TexDataType::UnsignedShort4444 => 4,
+ TexDataType::Int => 1,
+ TexDataType::UnsignedInt => 1,
+ TexDataType::UnsignedInt10f11f11fRev => 3,
+ TexDataType::UnsignedInt2101010Rev => 4,
+ TexDataType::UnsignedInt5999Rev => 4,
+ TexDataType::UnsignedInt248 => 2,
+ TexDataType::Float => 1,
+ TexDataType::HalfFloat => 1,
+ TexDataType::Float32UnsignedInt248Rev => 2,
+ }
+ }
+
+ pub fn required_webgl_version(self) -> WebGLVersion {
+ match self {
+ TexDataType::UnsignedByte |
+ TexDataType::UnsignedShort4444 |
+ TexDataType::UnsignedShort5551 |
+ TexDataType::UnsignedShort565 |
+ TexDataType::Float |
+ TexDataType::HalfFloat => WebGLVersion::WebGL1,
+ _ => WebGLVersion::WebGL2,
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+pub enum AlphaTreatment {
+ Premultiply,
+ Unmultiply,
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+pub enum YAxisTreatment {
+ AsIs,
+ Flipped,
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
+pub struct GLContextAttributes {
+ pub alpha: bool,
+ pub depth: bool,
+ pub stencil: bool,
+ pub antialias: bool,
+ pub premultiplied_alpha: bool,
+ pub preserve_drawing_buffer: bool,
+}
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct GLLimits {
+ pub max_vertex_attribs: u32,
+ pub max_tex_size: u32,
+ pub max_cube_map_tex_size: u32,
+ pub max_combined_texture_image_units: u32,
+ pub max_fragment_uniform_vectors: u32,
+ pub max_renderbuffer_size: u32,
+ pub max_texture_image_units: u32,
+ pub max_varying_vectors: u32,
+ pub max_vertex_texture_image_units: u32,
+ pub max_vertex_uniform_vectors: u32,
+ pub max_client_wait_timeout_webgl: std::time::Duration,
+ pub max_transform_feedback_separate_attribs: u32,
+ pub max_vertex_output_vectors: u32,
+ pub max_fragment_input_vectors: u32,
+ pub max_draw_buffers: u32,
+ pub max_color_attachments: u32,
+ pub max_uniform_buffer_bindings: u32,
+ pub min_program_texel_offset: i32,
+ pub max_program_texel_offset: u32,
+ pub max_uniform_block_size: u64,
+ pub max_combined_uniform_blocks: u32,
+ pub max_combined_vertex_uniform_components: u64,
+ pub max_combined_fragment_uniform_components: u64,
+ pub max_vertex_uniform_blocks: u32,
+ pub max_vertex_uniform_components: u32,
+ pub max_fragment_uniform_blocks: u32,
+ pub max_fragment_uniform_components: u32,
+ pub max_3d_texture_size: u32,
+ pub max_array_texture_layers: u32,
+ pub uniform_buffer_offset_alignment: u32,
+ pub max_element_index: u64,
+ pub max_elements_indices: u32,
+ pub max_elements_vertices: u32,
+ pub max_fragment_input_components: u32,
+ pub max_samples: u32,
+ pub max_server_wait_timeout: std::time::Duration,
+ pub max_texture_lod_bias: f32,
+ pub max_varying_components: u32,
+ pub max_vertex_output_components: u32,
+}