/* 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, } /// WebGL Threading API entry point that lives in the constellation. pub struct WebGLThreads(pub WebGLSender); 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, GLContextAttributes, WebGLSender>, ), /// Resizes a WebGLContext. ResizeContext(WebGLContextId, Size2D, WebGLSender>), /// 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, WebGLSender, 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 { /// /// Conforms closely to the OpenGL ES 2.0 API WebGL1, /// /// 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, sender: WebGLSender>, ) -> 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); impl From for TruncatedDebug { fn from(v: T) -> TruncatedDebug { TruncatedDebug(v) } } impl fmt::Debug for TruncatedDebug { 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 Deref for TruncatedDebug { type Target = T; fn deref(&self) -> &T { &self.0 } } /// WebGL Commands for a specific WebGLContext #[derive(Debug, Deserialize, Serialize)] pub enum WebGLCommand { GetContextAttributes(WebGLSender), 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>), CreateFramebuffer(WebGLSender>), CreateRenderbuffer(WebGLSender>), CreateTexture(WebGLSender>), CreateProgram(WebGLSender>), CreateShader(u32, WebGLSender>), DeleteBuffer(WebGLBufferId), DeleteFramebuffer(WebGLFramebufferId), DeleteRenderbuffer(WebGLRenderbufferId), DeleteTexture(WebGLTextureId), DeleteProgram(WebGLProgramId), DeleteShader(WebGLShaderId), BindBuffer(u32, Option), BindFramebuffer(u32, WebGLFramebufferBindingRequest), BindRenderbuffer(u32, Option), BindTexture(u32, Option), DisableVertexAttribArray(u32), EnableVertexAttribArray(u32), FramebufferRenderbuffer(u32, u32, u32, Option), FramebufferTexture2D(u32, u32, u32, Option, i32), GetExtensions(WebGLSender), GetShaderPrecisionFormat(u32, u32, WebGLSender<(i32, i32, i32)>), GetFragDataLocation(WebGLProgramId, String, WebGLSender), GetUniformLocation(WebGLProgramId, String, WebGLSender), GetShaderInfoLog(WebGLShaderId, WebGLSender), GetProgramInfoLog(WebGLProgramId, WebGLSender), GetFramebufferAttachmentParameter(u32, u32, u32, WebGLSender), GetRenderbufferParameter(u32, u32, WebGLSender), CreateTransformFeedback(WebGLSender), DeleteTransformFeedback(u32), IsTransformFeedback(u32, WebGLSender), BindTransformFeedback(u32, u32), BeginTransformFeedback(u32), EndTransformFeedback(), PauseTransformFeedback(), ResumeTransformFeedback(), GetTransformFeedbackVarying(WebGLProgramId, u32, WebGLSender<(i32, u32, String)>), TransformFeedbackVaryings(WebGLProgramId, Vec, u32), PolygonOffset(f32, f32), RenderbufferStorage(u32, u32, i32, i32), RenderbufferStorageMultisample(u32, i32, u32, i32, i32), ReadPixels(Rect, u32, u32, IpcBytesSender), ReadPixelsPP(Rect, 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), IsSync(WebGLSyncId, WebGLSender), ClientWaitSync(WebGLSyncId, u32, u64, WebGLSender), WaitSync(WebGLSyncId, u32, i64), GetSyncParameter(WebGLSyncId, u32, WebGLSender), DeleteSync(WebGLSyncId), Hint(u32, u32), LineWidth(f32), PixelStorei(u32, i32), LinkProgram(WebGLProgramId, WebGLSender), Uniform1f(i32, f32), Uniform1fv(i32, Vec), Uniform1i(i32, i32), Uniform1ui(i32, u32), Uniform1iv(i32, Vec), Uniform1uiv(i32, Vec), Uniform2f(i32, f32, f32), Uniform2fv(i32, Vec), Uniform2i(i32, i32, i32), Uniform2ui(i32, u32, u32), Uniform2iv(i32, Vec), Uniform2uiv(i32, Vec), Uniform3f(i32, f32, f32, f32), Uniform3fv(i32, Vec), Uniform3i(i32, i32, i32, i32), Uniform3ui(i32, u32, u32, u32), Uniform3iv(i32, Vec), Uniform3uiv(i32, Vec), Uniform4f(i32, f32, f32, f32, f32), Uniform4fv(i32, Vec), Uniform4i(i32, i32, i32, i32, i32), Uniform4ui(i32, u32, u32, u32, u32), Uniform4iv(i32, Vec), Uniform4uiv(i32, Vec), UniformMatrix2fv(i32, Vec), UniformMatrix3fv(i32, Vec), UniformMatrix4fv(i32, Vec), UniformMatrix3x2fv(i32, Vec), UniformMatrix4x2fv(i32, Vec), UniformMatrix2x3fv(i32, Vec), UniformMatrix4x3fv(i32, Vec), UniformMatrix2x4fv(i32, Vec), UniformMatrix3x4fv(i32, Vec), UseProgram(Option), 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, 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, y_axis_treatment: YAxisTreatment, pixel_format: Option, data: TruncatedDebug, }, TexImage2DPBO { target: u32, level: u32, internal_format: TexFormat, size: Size2D, format: TexFormat, effective_data_type: u32, unpacking_alignment: u32, offset: i64, }, TexSubImage2D { target: u32, level: u32, xoffset: i32, yoffset: i32, size: Size2D, 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, y_axis_treatment: YAxisTreatment, pixel_format: Option, data: TruncatedDebug, }, CompressedTexImage2D { target: u32, level: u32, internal_format: u32, size: Size2D, data: TruncatedDebug, }, CompressedTexSubImage2D { target: u32, level: i32, xoffset: i32, yoffset: i32, size: Size2D, format: u32, data: TruncatedDebug, }, DrawingBufferWidth(WebGLSender), DrawingBufferHeight(WebGLSender), Finish(WebGLSender<()>), Flush, GenerateMipmap(u32), CreateVertexArray(WebGLSender>), DeleteVertexArray(WebGLVertexArrayId), BindVertexArray(Option), GetParameterBool(ParameterBool, WebGLSender), GetParameterBool4(ParameterBool4, WebGLSender<[bool; 4]>), GetParameterInt(ParameterInt, WebGLSender), GetParameterInt2(ParameterInt2, WebGLSender<[i32; 2]>), GetParameterInt4(ParameterInt4, WebGLSender<[i32; 4]>), GetParameterFloat(ParameterFloat, WebGLSender), GetParameterFloat2(ParameterFloat2, WebGLSender<[f32; 2]>), GetParameterFloat4(ParameterFloat4, WebGLSender<[f32; 4]>), GetProgramValidateStatus(WebGLProgramId, WebGLSender), GetProgramActiveUniforms(WebGLProgramId, WebGLSender), GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>), GetTexParameterFloat(u32, TexParameterFloat, WebGLSender), GetTexParameterInt(u32, TexParameterInt, WebGLSender), GetTexParameterBool(u32, TexParameterBool, WebGLSender), GetInternalFormatIntVec(u32, u32, InternalFormatIntVec, WebGLSender>), 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), GetUniformBool2(WebGLProgramId, i32, WebGLSender<[bool; 2]>), GetUniformBool3(WebGLProgramId, i32, WebGLSender<[bool; 3]>), GetUniformBool4(WebGLProgramId, i32, WebGLSender<[bool; 4]>), GetUniformInt(WebGLProgramId, i32, WebGLSender), GetUniformInt2(WebGLProgramId, i32, WebGLSender<[i32; 2]>), GetUniformInt3(WebGLProgramId, i32, WebGLSender<[i32; 3]>), GetUniformInt4(WebGLProgramId, i32, WebGLSender<[i32; 4]>), GetUniformUint(WebGLProgramId, i32, WebGLSender), GetUniformUint2(WebGLProgramId, i32, WebGLSender<[u32; 2]>), GetUniformUint3(WebGLProgramId, i32, WebGLSender<[u32; 3]>), GetUniformUint4(WebGLProgramId, i32, WebGLSender<[u32; 4]>), GetUniformFloat(WebGLProgramId, i32, WebGLSender), 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), GetUniformIndices(WebGLProgramId, Vec, WebGLSender>), GetActiveUniforms(WebGLProgramId, Vec, u32, WebGLSender>), GetActiveUniformBlockName(WebGLProgramId, u32, WebGLSender), GetActiveUniformBlockParameter(WebGLProgramId, u32, u32, WebGLSender>), UniformBlockBinding(WebGLProgramId, u32, u32), InitializeFramebuffer { color: bool, depth: bool, stencil: bool, }, BeginQuery(u32, WebGLQueryId), DeleteQuery(WebGLQueryId), EndQuery(u32), GenerateQuery(WebGLSender), GetQueryState(WebGLSender, WebGLQueryId, u32), GenerateSampler(WebGLSender), DeleteSampler(WebGLSamplerId), BindSampler(u32, WebGLSamplerId), SetSamplerParameterFloat(WebGLSamplerId, u32, f32), SetSamplerParameterInt(WebGLSamplerId, u32, i32), GetSamplerParameterFloat(WebGLSamplerId, u32, WebGLSender), GetSamplerParameterInt(WebGLSamplerId, u32, WebGLSender), BindBufferBase(u32, u32, Option), BindBufferRange(u32, u32, Option, i64, i64), ClearBufferfv(u32, i32, Vec), ClearBufferiv(u32, i32, Vec), ClearBufferuiv(u32, i32, Vec), ClearBufferfi(u32, i32, f32, i32), InvalidateFramebuffer(u32, Vec), InvalidateSubFramebuffer(u32, Vec, i32, i32, i32, i32), FramebufferTextureLayer(u32, u32, Option, i32, i32), ReadBuffer(u32), DrawBuffers(Vec), } /// WebXR layer management #[derive(Debug, Deserialize, Serialize)] pub enum WebXRCommand { CreateLayerManager(WebGLSender>), DestroyLayerManager(WebXRLayerManagerId), CreateLayer( WebXRLayerManagerId, WebXRContextId, WebXRLayerInit, WebGLSender>, ), DestroyLayer(WebXRLayerManagerId, WebXRContextId, WebXRLayerId), BeginFrame( WebXRLayerManagerId, Vec<(WebXRContextId, WebXRLayerId)>, WebGLSender, WebXRError>>, ), EndFrame( WebXRLayerManagerId, Vec<(WebXRContextId, WebXRLayerId)>, WebGLSender>, ), } 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(::new_unchecked(id)) } #[inline] pub fn maybe_new(id: $type) -> Option { ::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(deserializer: D) -> Result 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(&self, serializer: S) -> Result 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 for WebGLContextId { fn from(id: WebXRContextId) -> Self { Self(id.0) } } impl From 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 = Result; /// 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, /// The size of the uniform, if it is an array. pub size: Option, /// The type of the uniform. pub type_: u32, /// The index of the indexed uniform buffer binding, if it is bound. pub bind_index: Option, } impl ActiveUniformInfo { pub fn name(&self) -> Cow { 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 { 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 { 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, }