webgl: Handle both sequences and typed arrays, managing the type error ourselves.

This is a step with multiple intentions:

 * Be correct.
 * Unlock tests that are blocking @anholt.
 * Ease the transition to typed arrays once the changes by @Ms2ger start rolling
   in, since I expect the amount of test expectations to update to be
   non-trivial.
This commit is contained in:
Emilio Cobos Álvarez 2016-09-17 15:59:16 -07:00
parent 602246a14c
commit f985a73cae
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 259 additions and 172 deletions

View file

@ -8,8 +8,10 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGL
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
use dom::bindings::conversions::{ToJSValConvertible, array_buffer_view_data, array_buffer_view_data_checked}; use dom::bindings::conversions::{ArrayBufferViewContents, ConversionResult, FromJSValConvertible, ToJSValConvertible};
use dom::bindings::conversions::{array_buffer_view_to_vec, array_buffer_view_to_vec_checked}; use dom::bindings::conversions::{array_buffer_view_data, array_buffer_view_data_checked, array_buffer_view_to_vec};
use dom::bindings::conversions::array_buffer_view_to_vec_checked;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
@ -34,6 +36,7 @@ use dom::webgltexture::{TexParameterValue, WebGLTexture};
use dom::webgluniformlocation::WebGLUniformLocation; use dom::webgluniformlocation::WebGLUniformLocation;
use euclid::size::Size2D; use euclid::size::Size2D;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use js::conversions::ConversionBehavior;
use js::jsapi::{JSContext, JSObject, JS_GetArrayBufferViewType, Type}; use js::jsapi::{JSContext, JSObject, JS_GetArrayBufferViewType, Type};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
use net_traits::image::base::PixelFormat; use net_traits::image::base::PixelFormat;
@ -288,7 +291,7 @@ impl WebGLRenderingContext {
fn validate_uniform_parameters<T>(&self, fn validate_uniform_parameters<T>(&self,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
uniform_type: UniformSetterType, uniform_type: UniformSetterType,
data: Option<&[T]>) -> bool { data: &[T]) -> bool {
let uniform = match uniform { let uniform = match uniform {
Some(uniform) => uniform, Some(uniform) => uniform,
None => return false, None => return false,
@ -303,14 +306,6 @@ impl WebGLRenderingContext {
}, },
}; };
let data = match data {
Some(data) => data,
None => {
self.webgl_error(InvalidOperation);
return false;
},
};
// TODO(emilio): Get more complex uniform info from ANGLE, and use it to // TODO(emilio): Get more complex uniform info from ANGLE, and use it to
// properly validate that the uniform setter type is compatible with the // properly validate that the uniform setter type is compatible with the
// uniform type, and that the uniform size matches. // uniform type, and that the uniform size matches.
@ -391,12 +386,12 @@ impl WebGLRenderingContext {
// TODO(emilio): Move this logic to a validator. // TODO(emilio): Move this logic to a validator.
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn validate_tex_image_2d_data(&self, unsafe fn validate_tex_image_2d_data(&self,
width: u32, width: u32,
height: u32, height: u32,
format: TexFormat, format: TexFormat,
data_type: TexDataType, data_type: TexDataType,
data: *mut JSObject) data: *mut JSObject)
-> Result<u32, ()> { -> Result<u32, ()> {
let element_size = data_type.element_size(); let element_size = data_type.element_size();
let components_per_element = data_type.components_per_element(); let components_per_element = data_type.components_per_element();
let components = format.components(); let components = format.components();
@ -531,6 +526,45 @@ 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 as FromJSValConvertible>::Config) -> Result<Vec<T>, Error>
where T: ArrayBufferViewContents + FromJSValConvertible,
<T as FromJSValConvertible>::Config: Clone,
{
assert!(!sequence_or_abv.is_null());
if let Some(v) = array_buffer_view_to_vec_checked::<T>(sequence_or_abv) {
return Ok(v);
}
rooted!(in(cx) let mut val = UndefinedValue());
sequence_or_abv.to_jsval(cx, val.handle_mut());
match Vec::<T>::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<T>(abv: *mut JSObject) -> Result<Vec<T>, Error>
where T: ArrayBufferViewContents
{
assert!(!abv.is_null());
match array_buffer_view_to_vec::<T>(abv) {
Some(v) => Ok(v),
None => Err(Error::Type("Not an ArrayBufferView".to_owned())),
}
}
impl WebGLRenderingContextMethods for WebGLRenderingContext { impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
fn Canvas(&self) -> Root<HTMLCanvasElement> { fn Canvas(&self) -> Root<HTMLCanvasElement> {
@ -844,85 +878,92 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn BufferData(&self, _cx: *mut JSContext, target: u32, data: *mut JSObject, usage: u32) { fn BufferData(&self, _cx: *mut JSContext, target: u32, data: *mut JSObject, usage: u32) -> Fallible<()> {
if data.is_null() {
return Ok(self.webgl_error(InvalidValue));
}
let data_vec = try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(data) });
let bound_buffer = match target { let bound_buffer = match target {
constants::ARRAY_BUFFER => self.bound_buffer_array.get(), constants::ARRAY_BUFFER => self.bound_buffer_array.get(),
constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(), constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(),
_ => return self.webgl_error(InvalidEnum), _ => return Ok(self.webgl_error(InvalidEnum)),
}; };
let bound_buffer = match bound_buffer { let bound_buffer = match bound_buffer {
Some(bound_buffer) => bound_buffer, Some(bound_buffer) => bound_buffer,
None => return self.webgl_error(InvalidValue), None => return Ok(self.webgl_error(InvalidValue)),
}; };
match usage { match usage {
constants::STREAM_DRAW | constants::STREAM_DRAW |
constants::STATIC_DRAW | constants::STATIC_DRAW |
constants::DYNAMIC_DRAW => (), constants::DYNAMIC_DRAW => (),
_ => return self.webgl_error(InvalidEnum), _ => return Ok(self.webgl_error(InvalidEnum)),
} }
if let Some(data_vec) = unsafe { array_buffer_view_to_vec::<u8>(data) } { handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, &data_vec, usage));
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, &data_vec, usage));
} else { Ok(())
// NB: array_buffer_view_to_vec should never fail when we have
// WebIDL support for Float32Array etc.
self.webgl_error(InvalidValue);
}
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn BufferSubData(&self, _cx: *mut JSContext, target: u32, offset: i64, data: *mut JSObject) { fn BufferSubData(&self, _cx: *mut JSContext, target: u32, offset: i64, data: *mut JSObject) -> Fallible<()> {
if data.is_null() {
return Ok(self.webgl_error(InvalidValue));
}
let data_vec = try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(data) });
let bound_buffer = match target { let bound_buffer = match target {
constants::ARRAY_BUFFER => self.bound_buffer_array.get(), constants::ARRAY_BUFFER => self.bound_buffer_array.get(),
constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(), constants::ELEMENT_ARRAY_BUFFER => self.bound_buffer_element_array.get(),
_ => return self.webgl_error(InvalidEnum), _ => return Ok(self.webgl_error(InvalidEnum)),
}; };
let bound_buffer = match bound_buffer { let bound_buffer = match bound_buffer {
Some(bound_buffer) => bound_buffer, Some(bound_buffer) => bound_buffer,
None => return self.webgl_error(InvalidOperation), None => return Ok(self.webgl_error(InvalidOperation)),
}; };
if data.is_null() {
return self.webgl_error(InvalidValue);
}
if offset < 0 { if offset < 0 {
return self.webgl_error(InvalidValue); return Ok(self.webgl_error(InvalidValue));
} }
if let Some(data_vec) = unsafe { array_buffer_view_to_vec::<u8>(data) } { if (offset as usize) + data_vec.len() > bound_buffer.capacity() {
if (offset as usize) + data_vec.len() > bound_buffer.capacity() { return Ok(self.webgl_error(InvalidValue));
return self.webgl_error(InvalidValue);
}
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::BufferSubData(target, offset as isize, data_vec)))
.unwrap()
} else {
// NB: array_buffer_view_to_vec should never fail when we have
// WebIDL support for Float32Array etc.
self.webgl_error(InvalidValue);
} }
self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::BufferSubData(target, offset as isize, data_vec)))
.unwrap();
Ok(())
} }
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CompressedTexImage2D(&self, _cx: *mut JSContext, _target: u32, _level: i32, _internal_format: u32, fn CompressedTexImage2D(&self, _cx: *mut JSContext, _target: u32, _level: i32, _internal_format: u32,
_width: i32, _height: i32, _border: i32, _pixels: *mut JSObject) { _width: i32, _height: i32, _border: i32, pixels: *mut JSObject) -> Fallible<()> {
let _data = try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(pixels) });
// FIXME: No compressed texture format is currently supported, so error out as per // 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 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT
self.webgl_error(InvalidEnum) self.webgl_error(InvalidEnum);
Ok(())
} }
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CompressedTexSubImage2D(&self, _cx: *mut JSContext, _target: u32, _level: i32, fn CompressedTexSubImage2D(&self, _cx: *mut JSContext, _target: u32, _level: i32,
_xoffset: i32, _yoffset: i32, _width: i32, _height: i32, _xoffset: i32, _yoffset: i32, _width: i32, _height: i32,
_format: u32, _pixels: *mut JSObject) { _format: u32, pixels: *mut JSObject) -> Fallible<()> {
let _data = try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(pixels) });
// FIXME: No compressed texture format is currently supported, so error out as per // 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 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT
self.webgl_error(InvalidEnum) self.webgl_error(InvalidEnum);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@ -1650,23 +1691,23 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.12 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.12
fn ReadPixels(&self, _cx: *mut JSContext, x: i32, y: i32, width: i32, height: i32, fn ReadPixels(&self, _cx: *mut JSContext, x: i32, y: i32, width: i32, height: i32,
format: u32, pixel_type: u32, pixels: *mut JSObject) { format: u32, pixel_type: u32, pixels: *mut JSObject) -> Fallible<()> {
if pixels.is_null() { if pixels.is_null() {
return self.webgl_error(InvalidValue); return Ok(self.webgl_error(InvalidValue));
} }
let mut data = match unsafe { array_buffer_view_data::<u8>(pixels) } { let mut data = match unsafe { array_buffer_view_data::<u8>(pixels) } {
Some(data) => data, Some(data) => data,
None => return self.webgl_error(InvalidValue), None => return Err(Error::Type("Not an ArrayBufferView".to_owned())),
}; };
if !self.validate_framebuffer_complete() { if !self.validate_framebuffer_complete() {
return; return Ok(());
} }
match unsafe { JS_GetArrayBufferViewType(pixels) } { match unsafe { JS_GetArrayBufferViewType(pixels) } {
Type::Uint8 => (), Type::Uint8 => (),
_ => return self.webgl_error(InvalidOperation) _ => return Ok(self.webgl_error(InvalidOperation)),
} }
let (sender, receiver) = ipc::channel().unwrap(); let (sender, receiver) = ipc::channel().unwrap();
@ -1677,12 +1718,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
let result = receiver.recv().unwrap(); let result = receiver.recv().unwrap();
if result.len() > data.len() { if result.len() > data.len() {
return self.webgl_error(InvalidOperation) return Ok(self.webgl_error(InvalidOperation));
} }
for i in 0..result.len() { for i in 0..result.len() {
data[i] = result[i] data[i] = result[i]
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
@ -1802,7 +1845,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
fn Uniform1f(&self, fn Uniform1f(&self,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
val: f32) { val: f32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::Float, Some(&[val])) { if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &[val]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.unwrap().id(), val))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.unwrap().id(), val)))
.unwrap() .unwrap()
@ -1813,7 +1856,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
fn Uniform1i(&self, fn Uniform1i(&self,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
val: i32) { val: i32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::Int, Some(&[val])) { if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &[val]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1i(uniform.unwrap().id(), val))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform1i(uniform.unwrap().id(), val)))
.unwrap() .unwrap()
@ -1823,40 +1866,44 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform1iv(&self, fn Uniform1iv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<i32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<i32>(cx, data, ConversionBehavior::Default) });
if self.validate_uniform_parameters(uniform, UniformSetterType::Int, data_vec.as_ref().map(Vec::as_slice)) { if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform1fv(&self, fn Uniform1fv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<f32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if self.validate_uniform_parameters(uniform, UniformSetterType::Float, data_vec.as_ref().map(Vec::as_slice)) { if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn Uniform2f(&self, fn Uniform2f(&self,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
x: f32, y: f32) { x: f32, y: f32) {
if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, Some(&[x, y])) { if self.validate_uniform_parameters(uniform, UniformSetterType::FloatVec2, &[x, y]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y)))
.unwrap() .unwrap()
@ -1866,18 +1913,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform2fv(&self, fn Uniform2fv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<f32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec2, UniformSetterType::FloatVec2,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform2fv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -1886,7 +1936,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x: i32, y: i32) { x: i32, y: i32) {
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec2, UniformSetterType::IntVec2,
Some(&[x, y])) { &[x, y]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y)))
.unwrap() .unwrap()
@ -1896,19 +1946,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform2iv(&self, fn Uniform2iv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<i32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<i32>(cx, data, ConversionBehavior::Default) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec2, UniformSetterType::IntVec2,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform2iv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -1917,7 +1969,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x: f32, y: f32, z: f32) { x: f32, y: f32, z: f32) {
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec3, UniformSetterType::FloatVec3,
Some(&[x, y, z])) { &[x, y, z]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z)))
.unwrap() .unwrap()
@ -1927,19 +1979,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform3fv(&self, fn Uniform3fv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<f32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec3, UniformSetterType::FloatVec3,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform3fv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -1948,7 +2002,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x: i32, y: i32, z: i32) { x: i32, y: i32, z: i32) {
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec3, UniformSetterType::IntVec3,
Some(&[x, y, z])) { &[x, y, z]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z)))
.unwrap() .unwrap()
@ -1958,19 +2012,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform3iv(&self, fn Uniform3iv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<i32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<i32>(cx, data, ConversionBehavior::Default) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec3, UniformSetterType::IntVec3,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform3iv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -1979,7 +2035,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x: i32, y: i32, z: i32, w: i32) { x: i32, y: i32, z: i32, w: i32) {
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec4, UniformSetterType::IntVec4,
Some(&[x, y, z, w])) { &[x, y, z, w]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w)))
.unwrap() .unwrap()
@ -1990,19 +2046,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform4iv(&self, fn Uniform4iv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<i32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<i32>(cx, data, ConversionBehavior::Default) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::IntVec4, UniformSetterType::IntVec4,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform4iv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -2011,7 +2069,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
x: f32, y: f32, z: f32, w: f32) { x: f32, y: f32, z: f32, w: f32) {
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec4, UniformSetterType::FloatVec4,
Some(&[x, y, z, w])) { &[x, y, z, w]) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w)))
.unwrap() .unwrap()
@ -2021,19 +2079,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn Uniform4fv(&self, fn Uniform4fv(&self,
_cx: *mut JSContext, cx: *mut JSContext,
uniform: Option<&WebGLUniformLocation>, uniform: Option<&WebGLUniformLocation>,
data: *mut JSObject) { data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
let data_vec = unsafe { array_buffer_view_to_vec::<f32>(data) }; let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if self.validate_uniform_parameters(uniform, if self.validate_uniform_parameters(uniform,
UniformSetterType::FloatVec4, UniformSetterType::FloatVec4,
data_vec.as_ref().map(Vec::as_slice)) { &data_vec) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec.unwrap()))) .send(CanvasMsg::WebGL(WebGLCommand::Uniform4fv(uniform.unwrap().id(), data_vec)))
.unwrap() .unwrap()
} }
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9
@ -2062,16 +2122,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib1fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } { let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if data_vec.len() < 1 { if data_vec.len() < 1 {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
}
self.vertex_attrib(indx, data_vec[0], 0f32, 0f32, 1f32)
} else {
self.webgl_error(InvalidValue);
} }
self.vertex_attrib(indx, data_vec[0], 0f32, 0f32, 1f32);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -2081,16 +2139,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib2fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } { let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if data_vec.len() < 2 { if data_vec.len() < 2 {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
}
self.vertex_attrib(indx, data_vec[0], data_vec[1], 0f32, 1f32)
} else {
self.webgl_error(InvalidValue);
} }
self.vertex_attrib(indx, data_vec[0], data_vec[1], 0f32, 1f32);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -2100,16 +2156,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn VertexAttrib3fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib3fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } { let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if data_vec.len() < 3 { if data_vec.len() < 3 {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
}
self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], 1f32)
} else {
self.webgl_error(InvalidValue);
} }
self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], 1f32);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -2119,16 +2173,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn VertexAttrib4fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib4fv(&self, cx: *mut JSContext, indx: u32, data: *mut JSObject) -> Fallible<()> {
assert!(!data.is_null()); assert!(!data.is_null());
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } { let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
if data_vec.len() < 4 { if data_vec.len() < 4 {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
}
self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], data_vec[3])
} else {
self.webgl_error(InvalidValue);
} }
self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], data_vec[3]);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
@ -2195,7 +2248,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
border: i32, border: i32,
format: u32, format: u32,
data_type: u32, data_type: u32,
data: *mut JSObject) { data_ptr: *mut JSObject) -> Fallible<()> {
let data = if data_ptr.is_null() {
None
} else {
Some(try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(data_ptr) }))
};
let validator = TexImage2DValidator::new(self, target, level, let validator = TexImage2DValidator::new(self, target, level,
internal_format, width, height, internal_format, width, height,
border, format, data_type); border, format, data_type);
@ -2211,34 +2270,32 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
data_type, data_type,
} = match validator.validate() { } = match validator.validate() {
Ok(result) => result, Ok(result) => result,
Err(_) => return, // NB: The validator sets the correct error for us. Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
}; };
let expected_byte_length = let expected_byte_length =
match unsafe { self.validate_tex_image_2d_data(width, height, match unsafe { self.validate_tex_image_2d_data(width, height,
format, data_type, format, data_type,
data) } { data_ptr) } {
Ok(byte_length) => byte_length, Ok(byte_length) => byte_length,
Err(_) => return, Err(()) => return Ok(()),
}; };
// If data is null, a buffer of sufficient size // If data is null, a buffer of sufficient size
// initialized to 0 is passed. // initialized to 0 is passed.
let buff = if data.is_null() { let buff = match data {
vec![0u8; expected_byte_length as usize] None => vec![0u8; expected_byte_length as usize],
} else { Some(data) => data,
unsafe {
array_buffer_view_to_vec::<u8>(data)
.expect("Can't reach here without being an ArrayBufferView!")
}
}; };
if buff.len() != expected_byte_length as usize { if buff.len() != expected_byte_length as usize {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
} }
self.tex_image_2d(texture, target, data_type, format, self.tex_image_2d(texture, target, data_type, format,
level, width, height, border, buff) level, width, height, border, buff);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@ -2248,14 +2305,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
internal_format: u32, internal_format: u32,
format: u32, format: u32,
data_type: u32, data_type: u32,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) { source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) -> Fallible<()> {
// Get pixels from image source // Get pixels from image source
let (pixels, size) = match self.get_image_pixels(source) { let (pixels, size) = match self.get_image_pixels(source) {
Ok((pixels, size)) => (pixels, size), Ok((pixels, size)) => (pixels, size),
Err(_) => return, Err(_) => return Ok(()),
}; };
let validator = TexImage2DValidator::new(self, let validator = TexImage2DValidator::new(self,
target, level, internal_format, target, level, internal_format,
size.width, size.height, size.width, size.height,
@ -2272,11 +2328,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
data_type, data_type,
} = match validator.validate() { } = match validator.validate() {
Ok(result) => result, Ok(result) => result,
Err(_) => return, // NB: The validator sets the correct error for us. Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
}; };
self.tex_image_2d(texture, target, data_type, format, self.tex_image_2d(texture, target, data_type, format,
level, width, height, border, pixels); level, width, height, border, pixels);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@ -2291,7 +2348,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
height: i32, height: i32,
format: u32, format: u32,
data_type: u32, data_type: u32,
data: *mut JSObject) { data_ptr: *mut JSObject) -> Fallible<()> {
let data = if data_ptr.is_null() {
None
} else {
Some(try!(unsafe { fallible_array_buffer_view_to_vec::<u8>(data_ptr) }))
};
let validator = TexImage2DValidator::new(self, target, level, let validator = TexImage2DValidator::new(self, target, level,
format, width, height, format, width, height,
0, format, data_type); 0, format, data_type);
@ -2306,35 +2370,32 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
.. ..
} = match validator.validate() { } = match validator.validate() {
Ok(result) => result, Ok(result) => result,
Err(_) => return, // NB: The validator sets the correct error for us. Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
}; };
let expected_byte_length = let expected_byte_length =
match unsafe { self.validate_tex_image_2d_data(width, height, match unsafe { self.validate_tex_image_2d_data(width, height,
format, data_type, format, data_type,
data) } { data_ptr) } {
Ok(byte_length) => byte_length, Ok(byte_length) => byte_length,
Err(()) => return, Err(()) => return Ok(()),
}; };
// If data is null, a buffer of sufficient size // If data is null, a buffer of sufficient size
// initialized to 0 is passed. // initialized to 0 is passed.
let buff = if data.is_null() { let buff = match data {
vec![0u8; expected_byte_length as usize] None => vec![0u8; expected_byte_length as usize],
} else { Some(data) => data,
unsafe {
array_buffer_view_to_vec::<u8>(data)
.expect("Can't reach here without being an ArrayBufferView!")
}
}; };
if expected_byte_length != 0 && if expected_byte_length != 0 &&
buff.len() != expected_byte_length as usize { buff.len() != expected_byte_length as usize {
return self.webgl_error(InvalidOperation); return Ok(self.webgl_error(InvalidOperation));
} }
self.tex_sub_image_2d(texture, target, level, xoffset, yoffset, self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
width, height, format, data_type, buff); width, height, format, data_type, buff);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@ -2345,10 +2406,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
yoffset: i32, yoffset: i32,
format: u32, format: u32,
data_type: u32, data_type: u32,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) { source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>)
-> Fallible<()> {
let (pixels, size) = match self.get_image_pixels(source) { let (pixels, size) = match self.get_image_pixels(source) {
Ok((pixels, size)) => (pixels, size), Ok((pixels, size)) => (pixels, size),
Err(_) => return, Err(_) => return Ok(()),
}; };
let validator = TexImage2DValidator::new(self, target, level, format, let validator = TexImage2DValidator::new(self, target, level, format,
@ -2365,11 +2427,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
.. ..
} = match validator.validate() { } = match validator.validate() {
Ok(result) => result, Ok(result) => result,
Err(_) => return, // NB: The validator sets the correct error for us. Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
}; };
self.tex_sub_image_2d(texture, target, level, xoffset, yoffset, self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
width, height, format, data_type, pixels); width, height, format, data_type, pixels);
Ok(())
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8

View file

@ -493,9 +493,12 @@ interface WebGLRenderingContextBase
// FIXME(dmarcos) The function below is the original function in the webIdl: // FIXME(dmarcos) The function below is the original function in the webIdl:
// void bufferData(GLenum target, BufferDataSource? data, GLenum usage); // void bufferData(GLenum target, BufferDataSource? data, GLenum usage);
// The Code generator doesn't handle BufferDataSource so we're using 'object?' // The Code generator doesn't handle BufferDataSource so we're using 'object?'
// in the meantime // in the meantime, and marking the function as [Throws], so we can handle
// the type error from inside.
[Throws]
void bufferData(GLenum target, object? data, GLenum usage); void bufferData(GLenum target, object? data, GLenum usage);
//void bufferSubData(GLenum target, GLintptr offset, BufferDataSource? data); //void bufferSubData(GLenum target, GLintptr offset, BufferDataSource? data);
[Throws]
void bufferSubData(GLenum target, GLintptr offset, object? data); void bufferSubData(GLenum target, GLintptr offset, object? data);
//[WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target); //[WebGLHandlesContextLoss] GLenum checkFramebufferStatus(GLenum target);
@ -507,10 +510,12 @@ interface WebGLRenderingContextBase
void compileShader(WebGLShader? shader); void compileShader(WebGLShader? shader);
// FIXME(simartin) The Code generator doesn't handle ArrayBufferView so we're // FIXME(simartin) The Code generator doesn't handle ArrayBufferView so we're
// using 'object' in the meantime // using 'object' in the meantime, and marking the function as Throws to
// handle the type error from inside.
// void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, // void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
// GLsizei width, GLsizei height, GLint border, // GLsizei width, GLsizei height, GLint border,
// ArrayBufferView data); // ArrayBufferView data);
[Throws]
void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border, GLsizei width, GLsizei height, GLint border,
object data); object data);
@ -518,6 +523,7 @@ interface WebGLRenderingContextBase
// GLint xoffset, GLint yoffset, // GLint xoffset, GLint yoffset,
// GLsizei width, GLsizei height, GLenum format, // GLsizei width, GLsizei height, GLenum format,
// ArrayBufferView data); // ArrayBufferView data);
[Throws]
void compressedTexSubImage2D(GLenum target, GLint level, void compressedTexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLsizei width, GLsizei height, GLenum format,
@ -616,6 +622,7 @@ interface WebGLRenderingContextBase
//void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, //void readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
// GLenum format, GLenum type, ArrayBufferView? pixels); // GLenum format, GLenum type, ArrayBufferView? pixels);
[Throws]
void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, void readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, object? pixels); GLenum format, GLenum type, object? pixels);
@ -637,56 +644,69 @@ interface WebGLRenderingContextBase
// GLsizei width, GLsizei height, GLint border, GLenum format, // GLsizei width, GLsizei height, GLint border, GLenum format,
// GLenum type, ArrayBufferView? pixels); // GLenum type, ArrayBufferView? pixels);
// FIXME: SM interface arguments // FIXME: SM interface arguments
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat, void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border, GLenum format, GLsizei width, GLsizei height, GLint border, GLenum format,
GLenum type, object? data); GLenum type, object? data);
[Throws]
void texImage2D(GLenum target, GLint level, GLenum internalformat, void texImage2D(GLenum target, GLint level, GLenum internalformat,
GLenum format, GLenum type, TexImageSource? source); // May throw DOMException GLenum format, GLenum type, TexImageSource? source); // May throw DOMException
void texParameterf(GLenum target, GLenum pname, GLfloat param); void texParameterf(GLenum target, GLenum pname, GLfloat param);
void texParameteri(GLenum target, GLenum pname, GLint param); void texParameteri(GLenum target, GLenum pname, GLint param);
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei width, GLsizei height,
GLenum format, GLenum type, object? data); GLenum format, GLenum type, object? data);
[Throws]
void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum format, GLenum type, TexImageSource? source); // May throw DOMException GLenum format, GLenum type, TexImageSource? source); // May throw DOMException
void uniform1f(WebGLUniformLocation? location, GLfloat x); void uniform1f(WebGLUniformLocation? location, GLfloat x);
//void uniform1fv(WebGLUniformLocation? location, Float32Array v); //void uniform1fv(WebGLUniformLocation? location, Float32Array v);
//void uniform1fv(WebGLUniformLocation? location, sequence<GLfloat> v); //void uniform1fv(WebGLUniformLocation? location, sequence<GLfloat> v);
[Throws]
void uniform1fv(WebGLUniformLocation? location, object v); void uniform1fv(WebGLUniformLocation? location, object v);
void uniform1i(WebGLUniformLocation? location, GLint x); void uniform1i(WebGLUniformLocation? location, GLint x);
//void uniform1iv(WebGLUniformLocation? location, Int32Array v); //void uniform1iv(WebGLUniformLocation? location, Int32Array v);
//void uniform1iv(WebGLUniformLocation? location, sequence<long> v); //void uniform1iv(WebGLUniformLocation? location, sequence<long> v);
[Throws]
void uniform1iv(WebGLUniformLocation? location, object v); void uniform1iv(WebGLUniformLocation? location, object v);
void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y);
//void uniform2fv(WebGLUniformLocation? location, Float32Array v); //void uniform2fv(WebGLUniformLocation? location, Float32Array v);
//void uniform2fv(WebGLUniformLocation? location, sequence<GLfloat> v); //void uniform2fv(WebGLUniformLocation? location, sequence<GLfloat> v);
[Throws]
void uniform2fv(WebGLUniformLocation? location, object v); void uniform2fv(WebGLUniformLocation? location, object v);
//void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); //void uniform2i(WebGLUniformLocation? location, GLint x, GLint y);
void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); void uniform2i(WebGLUniformLocation? location, GLint x, GLint y);
//void uniform2iv(WebGLUniformLocation? location, Int32Array v); //void uniform2iv(WebGLUniformLocation? location, Int32Array v);
//void uniform2iv(WebGLUniformLocation? location, sequence<long> v); //void uniform2iv(WebGLUniformLocation? location, sequence<long> v);
[Throws]
void uniform2iv(WebGLUniformLocation? location, object v); void uniform2iv(WebGLUniformLocation? location, object v);
void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z);
[Throws]
void uniform3fv(WebGLUniformLocation? location, object v); void uniform3fv(WebGLUniformLocation? location, object v);
//void uniform3fv(WebGLUniformLocation? location, Float32Array v); //void uniform3fv(WebGLUniformLocation? location, Float32Array v);
//void uniform3fv(WebGLUniformLocation? location, sequence<GLfloat> v); //void uniform3fv(WebGLUniformLocation? location, sequence<GLfloat> v);
void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z);
//void uniform3iv(WebGLUniformLocation? location, Int32Array v); //void uniform3iv(WebGLUniformLocation? location, Int32Array v);
//void uniform3iv(WebGLUniformLocation? location, sequence<long> v); //void uniform3iv(WebGLUniformLocation? location, sequence<long> v);
[Throws]
void uniform3iv(WebGLUniformLocation? location, object v); void uniform3iv(WebGLUniformLocation? location, object v);
void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
// FIXME(dmarcos) The function below is the original function in the webIdl: // FIXME(dmarcos) The function below is the original function in the webIdl:
//void uniform4fv(WebGLUniformLocation? location, Float32Array v); //void uniform4fv(WebGLUniformLocation? location, Float32Array v);
// The Code genearator doesn't handle typed arrays, so we use object instead. // The Code genearator doesn't handle typed arrays, so we use object
// instead, and handle the type error ourselves.
[Throws]
void uniform4fv(WebGLUniformLocation? location, object v); void uniform4fv(WebGLUniformLocation? location, object v);
//void uniform4fv(WebGLUniformLocation? location, sequence<GLfloat> v); //void uniform4fv(WebGLUniformLocation? location, sequence<GLfloat> v);
void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w);
//void uniform4iv(WebGLUniformLocation? location, Int32Array v); //void uniform4iv(WebGLUniformLocation? location, Int32Array v);
//void uniform4iv(WebGLUniformLocation? location, sequence<long> v); //void uniform4iv(WebGLUniformLocation? location, sequence<long> v);
// See FIXME above // See FIXME above
[Throws]
void uniform4iv(WebGLUniformLocation? location, object v); void uniform4iv(WebGLUniformLocation? location, object v);
//void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, //void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose,
@ -709,18 +729,22 @@ interface WebGLRenderingContextBase
// The code generator doesn't handle Float32Array so we're using 'object' // The code generator doesn't handle Float32Array so we're using 'object'
void vertexAttrib1f(GLuint indx, GLfloat x); void vertexAttrib1f(GLuint indx, GLfloat x);
//void vertexAttrib1fv(GLuint indx, Float32Array values); //void vertexAttrib1fv(GLuint indx, Float32Array values);
[Throws]
void vertexAttrib1fv(GLuint indx, object values); void vertexAttrib1fv(GLuint indx, object values);
//void vertexAttrib1fv(GLuint indx, sequence<GLfloat> values); //void vertexAttrib1fv(GLuint indx, sequence<GLfloat> values);
void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
//void vertexAttrib2fv(GLuint indx, Float32Array values); //void vertexAttrib2fv(GLuint indx, Float32Array values);
[Throws]
void vertexAttrib2fv(GLuint indx, object values); void vertexAttrib2fv(GLuint indx, object values);
//void vertexAttrib2fv(GLuint indx, sequence<GLfloat> values); //void vertexAttrib2fv(GLuint indx, sequence<GLfloat> values);
void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
//void vertexAttrib3fv(GLuint indx, Float32Array values); //void vertexAttrib3fv(GLuint indx, Float32Array values);
[Throws]
void vertexAttrib3fv(GLuint indx, object values); void vertexAttrib3fv(GLuint indx, object values);
//void vertexAttrib3fv(GLuint indx, sequence<GLfloat> values); //void vertexAttrib3fv(GLuint indx, sequence<GLfloat> values);
void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
//void vertexAttrib4fv(GLuint indx, Float32Array values); //void vertexAttrib4fv(GLuint indx, Float32Array values);
[Throws]
void vertexAttrib4fv(GLuint indx, object values); void vertexAttrib4fv(GLuint indx, object values);
//void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values); //void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values);
void vertexAttribPointer(GLuint indx, GLint size, GLenum type, void vertexAttribPointer(GLuint indx, GLint size, GLenum type,