diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/macros.rs | 11 | ||||
-rw-r--r-- | components/script/dom/mod.rs | 1 | ||||
-rw-r--r-- | components/script/dom/webgl2renderingcontext.rs | 101 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 12 | ||||
-rw-r--r-- | components/script/dom/webglsampler.rs | 187 | ||||
-rw-r--r-- | components/script/dom/webidls/WebGL2RenderingContext.webidl | 4 | ||||
-rw-r--r-- | components/script/dom/webidls/WebGLSampler.webidl | 11 |
8 files changed, 315 insertions, 15 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index bf65eb1e87d..5fbc9629f68 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -47,7 +47,7 @@ use canvas_traits::canvas::{ use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; use canvas_traits::webgl::WebGLVertexArrayId; use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat}; -use canvas_traits::webgl::{GLFormats, GLLimits, WebGLQueryId}; +use canvas_traits::webgl::{GLFormats, GLLimits, WebGLQueryId, WebGLSamplerId}; use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextShareMode, WebGLError}; use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId}; use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender}; @@ -481,6 +481,7 @@ unsafe_no_jsmanaged_fields!(WebGLPipeline); unsafe_no_jsmanaged_fields!(WebGLProgramId); unsafe_no_jsmanaged_fields!(WebGLQueryId); unsafe_no_jsmanaged_fields!(WebGLRenderbufferId); +unsafe_no_jsmanaged_fields!(WebGLSamplerId); unsafe_no_jsmanaged_fields!(WebGLShaderId); unsafe_no_jsmanaged_fields!(WebGLSyncId); unsafe_no_jsmanaged_fields!(WebGLTextureId); diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 021527a286a..755624a8855 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -660,3 +660,14 @@ macro_rules! impl_rare_data ( } ); ); + +#[macro_export] +macro_rules! optional_root_object_to_js_or_null { + ($cx: expr, $binding:expr) => {{ + rooted!(in($cx) let mut rval = NullValue()); + if let Some(object) = $binding { + object.to_jsval($cx, rval.handle_mut()); + } + rval.get() + }}; +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 598832403e0..639c3444b29 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -525,6 +525,7 @@ pub mod webglprogram; pub mod webglquery; pub mod webglrenderbuffer; pub mod webglrenderingcontext; +pub mod webglsampler; pub mod webglshader; pub mod webglshaderprecisionformat; pub mod webglsync; diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index ec959177d32..63cfd0bc530 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -11,6 +11,7 @@ use crate::dom::bindings::codegen::UnionTypes::ArrayBufferViewOrArrayBuffer; use crate::dom::bindings::codegen::UnionTypes::Float32ArrayOrUnrestrictedFloatSequence; use crate::dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; use crate::dom::bindings::codegen::UnionTypes::Int32ArrayOrLongSequence; +use crate::dom::bindings::conversions::ToJSValConvertible; use crate::dom::bindings::error::{ErrorResult, Fallible}; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom}; @@ -26,6 +27,7 @@ use crate::dom::webglrenderbuffer::WebGLRenderbuffer; use crate::dom::webglrenderingcontext::{ LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext, }; +use crate::dom::webglsampler::{WebGLSampler, WebGLSamplerValue}; use crate::dom::webglshader::WebGLShader; use crate::dom::webglshaderprecisionformat::WebGLShaderPrecisionFormat; use crate::dom::webglsync::WebGLSync; @@ -39,7 +41,7 @@ use canvas_traits::webgl::{webgl_channel, GLContextAttributes, WebGLCommand, Web use dom_struct::dom_struct; use euclid::default::Size2D; use js::jsapi::JSObject; -use js::jsval::{BooleanValue, Int32Value, JSVal, NullValue, UInt32Value}; +use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value}; use js::rust::CustomAutoRooterGuard; use js::typedarray::ArrayBufferView; use script_layout_interface::HTMLCanvasDataSource; @@ -51,6 +53,7 @@ pub struct WebGL2RenderingContext { base: Dom<WebGLRenderingContext>, occlusion_query: MutNullableDom<WebGLQuery>, primitives_query: MutNullableDom<WebGLQuery>, + samplers: Box<[MutNullableDom<WebGLSampler>]>, } impl WebGL2RenderingContext { @@ -61,11 +64,18 @@ impl WebGL2RenderingContext { attrs: GLContextAttributes, ) -> Option<WebGL2RenderingContext> { let base = WebGLRenderingContext::new(window, canvas, WebGLVersion::WebGL2, size, attrs)?; + + let samplers = (0..base.limits().max_combined_texture_image_units) + .map(|_| Default::default()) + .collect::<Vec<_>>() + .into(); + Some(WebGL2RenderingContext { reflector_: Reflector::new(), base: Dom::from_ref(&*base), occlusion_query: MutNullableDom::new(None), primitives_query: MutNullableDom::new(None), + samplers: samplers, }) } @@ -130,6 +140,12 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { constants::MAX_CLIENT_WAIT_TIMEOUT_WEBGL => { Int32Value(self.base.limits().max_client_wait_timeout_webgl.as_nanos() as i32) }, + constants::SAMPLER_BINDING => unsafe { + let idx = (self.base.textures().active_unit_enum() - constants::TEXTURE0) as usize; + assert!(idx < self.samplers.len()); + let sampler = self.samplers[idx].get(); + optional_root_object_to_js_or_null!(*cx, sampler) + }, _ => self.base.GetParameter(cx, parameter), } } @@ -1099,6 +1115,32 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { } } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn CreateSampler(&self) -> Option<DomRoot<WebGLSampler>> { + Some(WebGLSampler::new(&self.base)) + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn DeleteSampler(&self, sampler: Option<&WebGLSampler>) { + if let Some(sampler) = sampler { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return); + for slot in self.samplers.iter() { + if slot.get().map_or(false, |s| sampler == &*s) { + slot.set(None); + } + } + sampler.delete(false); + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn IsSampler(&self, sampler: Option<&WebGLSampler>) -> bool { + match sampler { + Some(sampler) => self.base.validate_ownership(sampler).is_ok() && sampler.is_valid(), + None => false, + } + } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12 #[cfg_attr(rustfmt, rustfmt_skip)] fn BeginQuery(&self, target: u32, query: &WebGLQuery) { @@ -1321,6 +1363,63 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { sync.delete(false); } } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn BindSampler(&self, unit: u32, sampler: Option<&WebGLSampler>) { + if let Some(sampler) = sampler { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return); + + if unit as usize >= self.samplers.len() { + self.base.webgl_error(InvalidValue); + return; + } + + let result = sampler.bind(&self.base, unit); + match result { + Ok(_) => self.samplers[unit as usize].set(Some(sampler)), + Err(error) => self.base.webgl_error(error), + } + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn SamplerParameteri(&self, sampler: &WebGLSampler, pname: u32, param: i32) { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return); + let param = WebGLSamplerValue::GLenum(param as u32); + let result = sampler.set_parameter(&self.base, pname, param); + if let Err(error) = result { + self.base.webgl_error(error); + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn SamplerParameterf(&self, sampler: &WebGLSampler, pname: u32, param: f32) { + handle_potential_webgl_error!(self.base, self.base.validate_ownership(sampler), return); + let param = WebGLSamplerValue::Float(param); + let result = sampler.set_parameter(&self.base, pname, param); + if let Err(error) = result { + self.base.webgl_error(error); + } + } + + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.13 + fn GetSamplerParameter(&self, _cx: JSContext, sampler: &WebGLSampler, pname: u32) -> JSVal { + handle_potential_webgl_error!( + self.base, + self.base.validate_ownership(sampler), + return NullValue() + ); + match sampler.get_parameter(&self.base, pname) { + Ok(value) => match value { + WebGLSamplerValue::GLenum(value) => UInt32Value(value), + WebGLSamplerValue::Float(value) => DoubleValue(value as f64), + }, + Err(error) => { + self.base.webgl_error(error); + NullValue() + }, + } + } } impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingContext> { diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index d6d46eee0ef..06141d5b5e7 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -104,16 +104,6 @@ macro_rules! handle_object_deletion { }; } -macro_rules! optional_root_object_to_js_or_null { - ($cx: expr, $binding:expr) => {{ - rooted!(in($cx) let mut rval = NullValue()); - if let Some(object) = $binding { - object.to_jsval($cx, rval.handle_mut()); - } - rval.get() - }}; -} - fn has_invalid_blend_constants(arg1: u32, arg2: u32) -> bool { match (arg1, arg2) { (constants::CONSTANT_COLOR, constants::CONSTANT_ALPHA) => true, @@ -4267,7 +4257,7 @@ impl Textures { } } - fn active_unit_enum(&self) -> u32 { + pub fn active_unit_enum(&self) -> u32 { self.active_unit.get() + constants::TEXTURE0 } diff --git a/components/script/dom/webglsampler.rs b/components/script/dom/webglsampler.rs new file mode 100644 index 00000000000..4689677c9bd --- /dev/null +++ b/components/script/dom/webglsampler.rs @@ -0,0 +1,187 @@ +/* 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 crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; +use crate::dom::bindings::codegen::Bindings::WebGLSamplerBinding; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::DomRoot; +use crate::dom::webglobject::WebGLObject; +use crate::dom::webglrenderingcontext::WebGLRenderingContext; +use canvas_traits::webgl::WebGLError::*; +use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLSamplerId}; +use dom_struct::dom_struct; +use std::cell::Cell; + +#[dom_struct] +pub struct WebGLSampler { + webgl_object: WebGLObject, + gl_id: WebGLSamplerId, + marked_for_deletion: Cell<bool>, +} + +#[derive(Clone, Copy)] +pub enum WebGLSamplerValue { + Float(f32), + GLenum(u32), +} + +fn validate_params(pname: u32, value: WebGLSamplerValue) -> bool { + match value { + WebGLSamplerValue::GLenum(value) => { + let allowed_values = match pname { + constants::TEXTURE_MIN_FILTER => &[ + constants::NEAREST, + constants::LINEAR, + constants::NEAREST_MIPMAP_NEAREST, + constants::LINEAR_MIPMAP_NEAREST, + constants::NEAREST_MIPMAP_LINEAR, + constants::LINEAR_MIPMAP_LINEAR, + ][..], + constants::TEXTURE_MAG_FILTER => &[constants::NEAREST, constants::LINEAR][..], + constants::TEXTURE_WRAP_R | + constants::TEXTURE_WRAP_S | + constants::TEXTURE_WRAP_T => &[ + constants::CLAMP_TO_EDGE, + constants::MIRRORED_REPEAT, + constants::REPEAT, + ][..], + constants::TEXTURE_COMPARE_MODE => { + &[constants::NONE, constants::COMPARE_REF_TO_TEXTURE][..] + }, + constants::TEXTURE_COMPARE_FUNC => &[ + constants::LEQUAL, + constants::GEQUAL, + constants::LESS, + constants::GREATER, + constants::EQUAL, + constants::NOTEQUAL, + constants::ALWAYS, + constants::NEVER, + ][..], + _ => &[][..], + }; + allowed_values.contains(&value) + }, + WebGLSamplerValue::Float(_) => match pname { + constants::TEXTURE_MIN_LOD | constants::TEXTURE_MAX_LOD => true, + _ => false, + }, + } +} + +impl WebGLSampler { + fn new_inherited(context: &WebGLRenderingContext, id: WebGLSamplerId) -> Self { + Self { + webgl_object: WebGLObject::new_inherited(context), + gl_id: id, + marked_for_deletion: Cell::new(false), + } + } + + pub fn new(context: &WebGLRenderingContext) -> DomRoot<Self> { + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GenerateSampler(sender)); + let id = receiver.recv().unwrap(); + + reflect_dom_object( + Box::new(Self::new_inherited(context, id)), + &*context.global(), + WebGLSamplerBinding::Wrap, + ) + } + + pub fn delete(&self, fallible: bool) { + if !self.marked_for_deletion.get() { + self.marked_for_deletion.set(true); + + let command = WebGLCommand::DeleteSampler(self.gl_id); + let context = self.upcast::<WebGLObject>().context(); + if fallible { + context.send_command_ignored(command); + } else { + context.send_command(command); + } + } + } + + pub fn is_valid(&self) -> bool { + !self.marked_for_deletion.get() + } + + pub fn bind( + &self, + context: &WebGLRenderingContext, + unit: u32, + ) -> Result<(), canvas_traits::webgl::WebGLError> { + if !self.is_valid() { + return Err(InvalidOperation); + } + context.send_command(WebGLCommand::BindSampler(unit, self.gl_id)); + Ok(()) + } + + pub fn set_parameter( + &self, + context: &WebGLRenderingContext, + pname: u32, + value: WebGLSamplerValue, + ) -> Result<(), canvas_traits::webgl::WebGLError> { + if !self.is_valid() { + return Err(InvalidOperation); + } + if !validate_params(pname, value) { + return Err(InvalidEnum); + } + let command = match value { + WebGLSamplerValue::GLenum(value) => { + WebGLCommand::SetSamplerParameterInt(self.gl_id, pname, value as i32) + }, + WebGLSamplerValue::Float(value) => { + WebGLCommand::SetSamplerParameterFloat(self.gl_id, pname, value) + }, + }; + context.send_command(command); + Ok(()) + } + + pub fn get_parameter( + &self, + context: &WebGLRenderingContext, + pname: u32, + ) -> Result<WebGLSamplerValue, canvas_traits::webgl::WebGLError> { + if !self.is_valid() { + return Err(InvalidOperation); + } + match pname { + constants::TEXTURE_MIN_FILTER | + constants::TEXTURE_MAG_FILTER | + constants::TEXTURE_WRAP_R | + constants::TEXTURE_WRAP_S | + constants::TEXTURE_WRAP_T | + constants::TEXTURE_COMPARE_FUNC | + constants::TEXTURE_COMPARE_MODE => { + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GetSamplerParameterInt( + self.gl_id, pname, sender, + )); + Ok(WebGLSamplerValue::GLenum(receiver.recv().unwrap() as u32)) + }, + constants::TEXTURE_MIN_LOD | constants::TEXTURE_MAX_LOD => { + let (sender, receiver) = webgl_channel().unwrap(); + context.send_command(WebGLCommand::GetSamplerParameterFloat( + self.gl_id, pname, sender, + )); + Ok(WebGLSamplerValue::Float(receiver.recv().unwrap())) + }, + _ => Err(InvalidEnum), + } + } +} + +impl Drop for WebGLSampler { + fn drop(&mut self) { + self.delete(true); + } +} diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl index 9162b71a230..edc26bb4ef6 100644 --- a/components/script/dom/webidls/WebGL2RenderingContext.webidl +++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl @@ -530,13 +530,13 @@ interface mixin WebGL2RenderingContextBase any getQueryParameter(WebGLQuery query, GLenum pname); /* Sampler Objects */ - /*WebGLSampler? createSampler(); + WebGLSampler? createSampler(); void deleteSampler(WebGLSampler? sampler); [WebGLHandlesContextLoss] GLboolean isSampler(WebGLSampler? sampler); void bindSampler(GLuint unit, WebGLSampler? sampler); void samplerParameteri(WebGLSampler sampler, GLenum pname, GLint param); void samplerParameterf(WebGLSampler sampler, GLenum pname, GLfloat param); - any getSamplerParameter(WebGLSampler sampler, GLenum pname);*/ + any getSamplerParameter(WebGLSampler sampler, GLenum pname); /* Sync objects */ WebGLSync? fenceSync(GLenum condition, GLbitfield flags); diff --git a/components/script/dom/webidls/WebGLSampler.webidl b/components/script/dom/webidls/WebGLSampler.webidl new file mode 100644 index 00000000000..90c66b65a1d --- /dev/null +++ b/components/script/dom/webidls/WebGLSampler.webidl @@ -0,0 +1,11 @@ +/* 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/. */ +// +// WebGL IDL definitions scraped from the Khronos specification: +// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.8 +// + +[Exposed=Window, Pref="dom.webgl2.enabled"] +interface WebGLSampler : WebGLObject { +}; |