diff options
Diffstat (limited to 'components/script/dom/webglrenderingcontext.rs')
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 582 |
1 files changed, 255 insertions, 327 deletions
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 8d3801c36e3..204426f8063 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -14,8 +14,9 @@ use dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2Rende use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; +use dom::bindings::codegen::UnionTypes::ArrayBufferOrArrayBufferView; use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; -use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, ToJSValConvertible}; +use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; @@ -46,10 +47,10 @@ use dom_struct::dom_struct; use euclid::Size2D; use fnv::FnvHashMap; use half::f16; -use js::conversions::ConversionBehavior; use js::jsapi::{JSContext, JSObject, Type}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue}; -use js::typedarray::{TypedArray, TypedArrayElement, Float32, Int32}; +use js::rust::CustomAutoRooterGuard; +use js::typedarray::{ArrayBufferView, Float32Array, Int32Array}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageResponse; use offscreen_gl_context::{GLContextAttributes, GLLimits}; @@ -824,15 +825,13 @@ impl WebGLRenderingContext { } // TODO(emilio): Move this logic to a validator. - #[allow(unsafe_code)] - unsafe fn validate_tex_image_2d_data(&self, - width: u32, - height: u32, - format: TexFormat, - data_type: TexDataType, - unpacking_alignment: u32, - data: *mut JSObject, - cx: *mut JSContext) + fn validate_tex_image_2d_data(&self, + width: u32, + height: u32, + format: TexFormat, + data_type: TexDataType, + unpacking_alignment: u32, + data: &Option<ArrayBufferView>) -> Result<u32, ()> { let element_size = data_type.element_size(); let components_per_element = data_type.components_per_element(); @@ -845,21 +844,16 @@ impl WebGLRenderingContext { // or UNSIGNED_SHORT_5_5_5_1, a Uint16Array must be supplied. // or FLOAT, a Float32Array must be supplied. // If the types do not match, an INVALID_OPERATION error is generated. - typedarray!(in(cx) let typedarray_u8: Uint8Array = data); - typedarray!(in(cx) let typedarray_u16: Uint16Array = data); - typedarray!(in(cx) let typedarray_f32: Float32Array = data); - let received_size = if data.is_null() { - element_size - } else { - if typedarray_u16.is_ok() { - 2 - } else if typedarray_u8.is_ok() { - 1 - } else if typedarray_f32.is_ok() { - 4 - } else { - self.webgl_error(InvalidOperation); - return Err(()); + let received_size = match *data { + None => element_size, + Some(ref buffer) => match buffer.get_array_type() { + Type::Uint8 => 1, + Type::Uint16 => 2, + Type::Float32 => 4, + _ => { + self.webgl_error(InvalidOperation); + return Err(()); + } } }; @@ -1198,45 +1192,13 @@ impl Drop for WebGLRenderingContext { } } -// FIXME: After [1] lands and the relevant Servo and codegen PR too, we should -// convert all our raw JSObject pointers to proper types. -// -// [1]: https://github.com/servo/rust-mozjs/pull/304 -#[allow(unsafe_code)] -unsafe fn typed_array_or_sequence_to_vec<T>(cx: *mut JSContext, - sequence_or_abv: *mut JSObject, - config: <T::Element as FromJSValConvertible>::Config) - -> Result<Vec<T::Element>, Error> - where T: TypedArrayElement, - T::Element: FromJSValConvertible + Clone, - <T::Element as FromJSValConvertible>::Config: Clone, -{ - // TODO(servo/rust-mozjs#330): replace this with a macro that supports generic types. - let typed_array: Option<TypedArray<T, *mut JSObject>> = - TypedArray::from(sequence_or_abv).ok(); - if let Some(mut typed_array) = typed_array { - return Ok(typed_array.as_slice().to_vec()); - } - assert!(!sequence_or_abv.is_null()); - rooted!(in(cx) let mut val = UndefinedValue()); - sequence_or_abv.to_jsval(cx, val.handle_mut()); - - match Vec::<T::Element>::from_jsval(cx, val.handle(), config) { - Ok(ConversionResult::Success(v)) => Ok(v), - Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())), - // FIXME: What to do here? Generated code only aborts the execution of - // the script. - Err(err) => panic!("unexpected conversion error: {:?}", err), - } -} - #[allow(unsafe_code)] unsafe fn fallible_array_buffer_view_to_vec(cx: *mut JSContext, abv: *mut JSObject) -> Result<Vec<u8>, Error> { assert!(!abv.is_null()); typedarray!(in(cx) let array_buffer_view: ArrayBufferView = abv); match array_buffer_view { - Ok(mut v) => Ok(v.as_slice().to_vec()), + Ok(mut v) => Ok(v.to_vec()), Err(_) => Err(Error::Type("Not an ArrayBufferView".to_owned())), } } @@ -1680,7 +1642,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { typedarray!(in(cx) let array_buffer: ArrayBuffer = data); let data_vec = match array_buffer { - Ok(mut data) => data.as_slice().to_vec(), + Ok(mut data) => data.to_vec(), Err(_) => fallible_array_buffer_view_to_vec(cx, data)?, }; @@ -1739,64 +1701,53 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { Ok(()) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 - unsafe fn BufferSubData(&self, cx: *mut JSContext, target: u32, offset: i64, data: *mut JSObject) -> Fallible<()> { - if data.is_null() { - return Ok(self.webgl_error(InvalidValue)); - } - - typedarray!(in(cx) let array_buffer: ArrayBuffer = data); - let data_vec = match array_buffer { - Ok(mut data) => data.as_slice().to_vec(), - Err(_) => fallible_array_buffer_view_to_vec(cx, data)?, + fn BufferSubData(&self, target: u32, offset: i64, data: Option<ArrayBufferOrArrayBufferView>) { + let data_vec = match data { + // Typed array is rooted, so we can safely temporarily retrieve its slice + Some(ArrayBufferOrArrayBufferView::ArrayBuffer(mut inner)) => inner.to_vec(), + Some(ArrayBufferOrArrayBufferView::ArrayBufferView(mut inner)) => inner.to_vec(), + // Spec: If data is null then an INVALID_VALUE error is generated. + None => return self.webgl_error(InvalidValue), }; let bound_buffer = match target { constants::ARRAY_BUFFER => self.bound_buffer_array.get(), constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(), - _ => return Ok(self.webgl_error(InvalidEnum)), + _ => return self.webgl_error(InvalidEnum), }; let bound_buffer = match bound_buffer { Some(bound_buffer) => bound_buffer, - None => return Ok(self.webgl_error(InvalidOperation)), + None => return self.webgl_error(InvalidOperation), }; if offset < 0 { - return Ok(self.webgl_error(InvalidValue)); + return self.webgl_error(InvalidValue); } if (offset as usize) + data_vec.len() > bound_buffer.capacity() { - return Ok(self.webgl_error(InvalidValue)); + return self.webgl_error(InvalidValue); } self.send_command(WebGLCommand::BufferSubData(target, offset as isize, data_vec)); - - Ok(()) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 - unsafe fn CompressedTexImage2D(&self, cx: *mut JSContext, _target: u32, _level: i32, _internal_format: u32, - _width: i32, _height: i32, _border: i32, pixels: *mut JSObject) -> Fallible<()> { - let _data = fallible_array_buffer_view_to_vec(cx, pixels)?; + fn CompressedTexImage2D(&self, _target: u32, _level: i32, _internal_format: u32, + _width: i32, _height: i32, _border: i32, + _data: CustomAutoRooterGuard<ArrayBufferView>) { // FIXME: No compressed texture format is currently supported, so error out as per // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT self.webgl_error(InvalidEnum); - Ok(()) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 - unsafe fn CompressedTexSubImage2D(&self, cx: *mut JSContext, _target: u32, _level: i32, - _xoffset: i32, _yoffset: i32, _width: i32, _height: i32, - _format: u32, pixels: *mut JSObject) -> Fallible<()> { - let _data = fallible_array_buffer_view_to_vec(cx, pixels)?; + fn CompressedTexSubImage2D(&self, _target: u32, _level: i32, _xoffset: i32, + _yoffset: i32, _width: i32, _height: i32, _format: u32, + _data: CustomAutoRooterGuard<ArrayBufferView>) { // FIXME: No compressed texture format is currently supported, so error out as per // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT self.webgl_error(InvalidEnum); - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 @@ -2642,27 +2593,25 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.send_command(WebGLCommand::PolygonOffset(factor, units)) } - #[allow(unsafe_code)] // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.12 - unsafe fn ReadPixels(&self, cx: *mut JSContext, x: i32, y: i32, width: i32, height: i32, - format: u32, pixel_type: u32, pixels: *mut JSObject) -> Fallible<()> { - if pixels.is_null() { - return Ok(self.webgl_error(InvalidValue)); - } - - typedarray!(in(cx) let mut pixels_data: ArrayBufferView = pixels); - let (array_type, data) = match { pixels_data.as_mut() } { - Ok(data) => (data.get_array_type(), data.as_mut_slice()), - Err(_) => return Err(Error::Type("Not an ArrayBufferView".to_owned())), + #[allow(unsafe_code)] + fn ReadPixels(&self, x: i32, y: i32, width: i32, height: i32, format: u32, pixel_type: u32, + mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>) { + let (array_type, data) = match *pixels { + // Spec: If data is null then an INVALID_VALUE error is generated. + None => return self.webgl_error(InvalidValue), + // The typed array is rooted and we should have a unique reference to it, + // so retrieving its mutable slice is safe here + Some(ref mut data) => (data.get_array_type(), unsafe { data.as_mut_slice() }), }; if !self.validate_framebuffer_complete() { - return Ok(()); + return; } match array_type { Type::Uint8 => (), - _ => return Ok(self.webgl_error(InvalidOperation)), + _ => return self.webgl_error(InvalidOperation), } // From the WebGL specification, 5.14.12 Reading back pixels @@ -2683,7 +2632,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // always report RGBA/UNSIGNED_BYTE as our only supported // format. if format != constants::RGBA || pixel_type != constants::UNSIGNED_BYTE { - return Ok(self.webgl_error(InvalidOperation)); + return self.webgl_error(InvalidOperation); } let cpp = 4; @@ -2693,12 +2642,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // INVALID_OPERATION error is generated." let stride = match width.checked_mul(cpp) { Some(stride) => stride, - _ => return Ok(self.webgl_error(InvalidOperation)), + _ => return self.webgl_error(InvalidOperation), }; match height.checked_mul(stride) { Some(size) if size <= data.len() as i32 => {} - _ => return Ok(self.webgl_error(InvalidOperation)), + _ => return self.webgl_error(InvalidOperation), } // "For any pixel lying outside the frame buffer, the @@ -2724,7 +2673,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } if width < 0 || height < 0 { - return Ok(self.webgl_error(InvalidValue)); + return self.webgl_error(InvalidValue); } match self.get_current_framebuffer_size() { @@ -2736,7 +2685,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { height = fb_height - y; } } - _ => return Ok(self.webgl_error(InvalidOperation)), + _ => return self.webgl_error(InvalidOperation), }; let (sender, receiver) = webgl_channel().unwrap(); @@ -2750,8 +2699,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { result[(i * width * cpp + j) as usize]; } } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 @@ -2854,279 +2801,269 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform1f(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, val: f32) { - if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &[val]) { - self.send_command(WebGLCommand::Uniform1f(uniform.unwrap().id(), val)) + if self.validate_uniform_parameters(location, UniformSetterType::Float, &[val]) { + self.send_command(WebGLCommand::Uniform1f(location.unwrap().id(), val)) } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform1i(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, val: i32) { - if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &[val]) { - self.send_command(WebGLCommand::Uniform1i(uniform.unwrap().id(), val)) + if self.validate_uniform_parameters(location, UniformSetterType::Int, &[val]) { + self.send_command(WebGLCommand::Uniform1i(location.unwrap().id(), val)) } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform1iv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Int32>(cx, data, ConversionBehavior::Default)?; + fn Uniform1iv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Int32Array>) { + self.Uniform1iv_(location, v.to_vec()); + } - if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &data_vec) { - self.send_command(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec)) + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform1iv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<i32>) { + if self.validate_uniform_parameters(location, UniformSetterType::Int, &v) { + self.send_command(WebGLCommand::Uniform1iv(location.unwrap().id(), v)) } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform1fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; + fn Uniform1fv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.Uniform1fv_(location, v.to_vec()); + } - if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &data_vec) { - self.send_command(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec)); + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform1fv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::Float, &v) { + self.send_command(WebGLCommand::Uniform1fv(location.unwrap().id(), v)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform2f(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: f32, y: f32) { - if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, &[x, y]) { - self.send_command(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y)); + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec2, &[x, y]) { + self.send_command(WebGLCommand::Uniform2f(location.unwrap().id(), x, y)); } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform2fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - - if self.validate_uniform_parameters(uniform, + fn Uniform2fv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.Uniform2fv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform2fv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec2, - &data_vec) { - self.send_command(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec)); + &v) { + self.send_command(WebGLCommand::Uniform2fv(location.unwrap().id(), v)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform2i(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: i32, y: i32) { - if self.validate_uniform_parameters(uniform, + if self.validate_uniform_parameters(location, UniformSetterType::IntVec2, &[x, y]) { - self.send_command(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y)); + self.send_command(WebGLCommand::Uniform2i(location.unwrap().id(), x, y)); } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform2iv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Int32>(cx, data, ConversionBehavior::Default)?; - - if self.validate_uniform_parameters(uniform, + fn Uniform2iv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Int32Array>) { + self.Uniform2iv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform2iv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<i32>) { + if self.validate_uniform_parameters(location, UniformSetterType::IntVec2, - &data_vec) { - self.send_command(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec)); + &v) { + self.send_command(WebGLCommand::Uniform2iv(location.unwrap().id(), v)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform3f(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: f32, y: f32, z: f32) { - if self.validate_uniform_parameters(uniform, + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec3, &[x, y, z]) { - self.send_command(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z)); + self.send_command(WebGLCommand::Uniform3f(location.unwrap().id(), x, y, z)); } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform3fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - - if self.validate_uniform_parameters(uniform, + fn Uniform3fv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.Uniform3fv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform3fv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec3, - &data_vec) { - self.send_command(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec)) + &v) { + self.send_command(WebGLCommand::Uniform3fv(location.unwrap().id(), v)) } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform3i(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: i32, y: i32, z: i32) { - if self.validate_uniform_parameters(uniform, + if self.validate_uniform_parameters(location, UniformSetterType::IntVec3, &[x, y, z]) { - self.send_command(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z)) + self.send_command(WebGLCommand::Uniform3i(location.unwrap().id(), x, y, z)) } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform3iv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Int32>(cx, data, ConversionBehavior::Default)?; - - if self.validate_uniform_parameters(uniform, + fn Uniform3iv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Int32Array>) { + self.Uniform3iv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform3iv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<i32>) { + if self.validate_uniform_parameters(location, UniformSetterType::IntVec3, - &data_vec) { - self.send_command(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec)) + &v) { + self.send_command(WebGLCommand::Uniform3iv(location.unwrap().id(), v)) } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform4i(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: i32, y: i32, z: i32, w: i32) { - if self.validate_uniform_parameters(uniform, + if self.validate_uniform_parameters(location, UniformSetterType::IntVec4, &[x, y, z, w]) { - self.send_command(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w)) + self.send_command(WebGLCommand::Uniform4i(location.unwrap().id(), x, y, z, w)) } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform4iv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Int32>(cx, data, ConversionBehavior::Default)?; - - if self.validate_uniform_parameters(uniform, + fn Uniform4iv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Int32Array>) { + self.Uniform4iv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform4iv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<i32>) { + if self.validate_uniform_parameters(location, UniformSetterType::IntVec4, - &data_vec) { - self.send_command(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec)) + &v) { + self.send_command(WebGLCommand::Uniform4iv(location.unwrap().id(), v)) } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn Uniform4f(&self, - uniform: Option<&WebGLUniformLocation>, + location: Option<&WebGLUniformLocation>, x: f32, y: f32, z: f32, w: f32) { - if self.validate_uniform_parameters(uniform, + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec4, &[x, y, z, w]) { - self.send_command(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w)) + self.send_command(WebGLCommand::Uniform4f(location.unwrap().id(), x, y, z, w)) } } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn Uniform4fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - - if self.validate_uniform_parameters(uniform, + fn Uniform4fv(&self, + location: Option<&WebGLUniformLocation>, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.Uniform4fv_(location, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn Uniform4fv_(&self, location: Option<&WebGLUniformLocation>, v: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatVec4, - &data_vec) { - self.send_command(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec)) + &v) { + self.send_command(WebGLCommand::Uniform4fv(location.unwrap().id(), v)) } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn UniformMatrix2fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, + fn UniformMatrix2fv(&self, + location: Option<&WebGLUniformLocation>, transpose: bool, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if self.validate_uniform_parameters(uniform, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.UniformMatrix2fv_(location, transpose, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn UniformMatrix2fv_(&self, + location: Option<&WebGLUniformLocation>, + transpose: bool, + value: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatMat2, - &data_vec) { - self.send_command(WebGLCommand::UniformMatrix2fv(uniform.unwrap().id(), transpose, data_vec)); + &value) { + self.send_command(WebGLCommand::UniformMatrix2fv(location.unwrap().id(), transpose, value)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn UniformMatrix3fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, + fn UniformMatrix3fv(&self, + location: Option<&WebGLUniformLocation>, transpose: bool, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if self.validate_uniform_parameters(uniform, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.UniformMatrix3fv_(location, transpose, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn UniformMatrix3fv_(&self, + location: Option<&WebGLUniformLocation>, + transpose: bool, + value: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatMat3, - &data_vec) { - self.send_command(WebGLCommand::UniformMatrix3fv(uniform.unwrap().id(), transpose, data_vec)); + &value) { + self.send_command(WebGLCommand::UniformMatrix3fv(location.unwrap().id(), transpose, value)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn UniformMatrix4fv(&self, - cx: *mut JSContext, - uniform: Option<&WebGLUniformLocation>, + fn UniformMatrix4fv(&self, + location: Option<&WebGLUniformLocation>, transpose: bool, - data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if self.validate_uniform_parameters(uniform, + mut v: CustomAutoRooterGuard<Float32Array>) { + self.UniformMatrix4fv_(location, transpose, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn UniformMatrix4fv_(&self, + location: Option<&WebGLUniformLocation>, + transpose: bool, + value: Vec<f32>) { + if self.validate_uniform_parameters(location, UniformSetterType::FloatMat4, - &data_vec) { - self.send_command(WebGLCommand::UniformMatrix4fv(uniform.unwrap().id(), transpose, data_vec)); + &value) { + self.send_command(WebGLCommand::UniformMatrix4fv(location.unwrap().id(), transpose, value)); } - - Ok(()) } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -3152,15 +3089,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn VertexAttrib1fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if data_vec.len() < 1 { - return Ok(self.webgl_error(InvalidOperation)); + fn VertexAttrib1fv(&self, indx: u32, mut v: CustomAutoRooterGuard<Float32Array>) { + self.VertexAttrib1fv_(indx, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn VertexAttrib1fv_(&self, indx: u32, values: Vec<f32>) { + if values.len() < 1 { + return self.webgl_error(InvalidOperation); } - self.vertex_attrib(indx, data_vec[0], 0f32, 0f32, 1f32); - Ok(()) + + self.vertex_attrib(indx, values[0], 0f32, 0f32, 1f32); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -3169,15 +3108,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn VertexAttrib2fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if data_vec.len() < 2 { - return Ok(self.webgl_error(InvalidOperation)); + fn VertexAttrib2fv(&self, indx: u32, mut v: CustomAutoRooterGuard<Float32Array>) { + self.VertexAttrib2fv_(indx, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn VertexAttrib2fv_(&self, indx: u32, values: Vec<f32>) { + if values.len() < 2 { + return self.webgl_error(InvalidOperation); } - self.vertex_attrib(indx, data_vec[0], data_vec[1], 0f32, 1f32); - Ok(()) + + self.vertex_attrib(indx, values[0], values[1], 0f32, 1f32); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -3186,15 +3127,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn VertexAttrib3fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if data_vec.len() < 3 { - return Ok(self.webgl_error(InvalidOperation)); + fn VertexAttrib3fv(&self, indx: u32, mut v: CustomAutoRooterGuard<Float32Array>) { + self.VertexAttrib3fv_(indx, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn VertexAttrib3fv_(&self, indx: u32, values: Vec<f32>) { + if values.len() < 3 { + return self.webgl_error(InvalidOperation); } - self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], 1f32); - Ok(()) + + self.vertex_attrib(indx, values[0], values[1], values[2], 1f32); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -3203,16 +3146,17 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 - #[allow(unsafe_code)] - unsafe fn VertexAttrib4fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> { - assert!(!data.is_null()); - let data_vec = typed_array_or_sequence_to_vec::<Float32>(cx, data, ())?; - if data_vec.len() < 4 { - return Ok(self.webgl_error(InvalidOperation)); + fn VertexAttrib4fv(&self, indx: u32, mut v: CustomAutoRooterGuard<Float32Array>) { + self.VertexAttrib4fv_(indx, v.to_vec()); + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 + fn VertexAttrib4fv_(&self, indx: u32, values: Vec<f32>) { + if values.len() < 4 { + return self.webgl_error(InvalidOperation); } - self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], data_vec[3]); - Ok(()) + self.vertex_attrib(indx, values[0], values[1], values[2], values[3]); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 @@ -3271,9 +3215,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 - #[allow(unsafe_code)] - unsafe fn TexImage2D(&self, - cx: *mut JSContext, + fn TexImage2D(&self, target: u32, level: i32, internal_format: u32, @@ -3282,17 +3224,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { border: i32, format: u32, data_type: u32, - data_ptr: *mut JSObject) -> Fallible<()> { + mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>) -> Fallible<()> { if !self.extension_manager.is_tex_type_enabled(data_type) { return Ok(self.webgl_error(InvalidEnum)); } - let data = if data_ptr.is_null() { - None - } else { - Some(fallible_array_buffer_view_to_vec(cx, data_ptr)?) - }; - let validator = TexImage2DValidator::new(self, target, level, internal_format, width, height, border, format, data_type); @@ -3316,16 +3252,16 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let expected_byte_length = match { self.validate_tex_image_2d_data(width, height, format, data_type, - unpacking_alignment, data_ptr, cx) } { + unpacking_alignment, &*pixels) } { Ok(byte_length) => byte_length, Err(()) => return Ok(()), }; // If data is null, a buffer of sufficient size // initialized to 0 is passed. - let buff = match data { + let buff = match *pixels { None => vec![0u8; expected_byte_length as usize], - Some(data) => data, + Some(ref mut data) => data.to_vec(), }; // From the WebGL spec: @@ -3443,9 +3379,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 - #[allow(unsafe_code)] - unsafe fn TexSubImage2D(&self, - cx: *mut JSContext, + fn TexSubImage2D(&self, target: u32, level: i32, xoffset: i32, @@ -3454,13 +3388,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { height: i32, format: u32, data_type: u32, - data_ptr: *mut JSObject) -> Fallible<()> { - let data = if data_ptr.is_null() { - None - } else { - Some(fallible_array_buffer_view_to_vec(cx, data_ptr)?) - }; - + mut pixels: CustomAutoRooterGuard<Option<ArrayBufferView>>) -> Fallible<()> { let validator = TexImage2DValidator::new(self, target, level, format, width, height, 0, format, data_type); @@ -3483,16 +3411,16 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { let expected_byte_length = match { self.validate_tex_image_2d_data(width, height, format, data_type, - unpacking_alignment, data_ptr, cx) } { + unpacking_alignment, &*pixels) } { Ok(byte_length) => byte_length, Err(()) => return Ok(()), }; // If data is null, a buffer of sufficient size // initialized to 0 is passed. - let buff = match data { + let buff = match *pixels { None => vec![0u8; expected_byte_length as usize], - Some(data) => data, + Some(ref mut data) => data.to_vec(), }; // From the WebGL spec: |