mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
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:
parent
602246a14c
commit
f985a73cae
2 changed files with 259 additions and 172 deletions
|
@ -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::WebGLRenderingContextMethods;
|
||||
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
|
||||
use dom::bindings::conversions::{ToJSValConvertible, array_buffer_view_data, array_buffer_view_data_checked};
|
||||
use dom::bindings::conversions::{array_buffer_view_to_vec, array_buffer_view_to_vec_checked};
|
||||
use dom::bindings::conversions::{ArrayBufferViewContents, ConversionResult, FromJSValConvertible, ToJSValConvertible};
|
||||
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::js::{JS, LayoutJS, MutNullableHeap, Root};
|
||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||
|
@ -34,6 +36,7 @@ use dom::webgltexture::{TexParameterValue, WebGLTexture};
|
|||
use dom::webgluniformlocation::WebGLUniformLocation;
|
||||
use euclid::size::Size2D;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use js::conversions::ConversionBehavior;
|
||||
use js::jsapi::{JSContext, JSObject, JS_GetArrayBufferViewType, Type};
|
||||
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
|
||||
use net_traits::image::base::PixelFormat;
|
||||
|
@ -288,7 +291,7 @@ impl WebGLRenderingContext {
|
|||
fn validate_uniform_parameters<T>(&self,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
uniform_type: UniformSetterType,
|
||||
data: Option<&[T]>) -> bool {
|
||||
data: &[T]) -> bool {
|
||||
let uniform = match uniform {
|
||||
Some(uniform) => uniform,
|
||||
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
|
||||
// properly validate that the uniform setter type is compatible with the
|
||||
// uniform type, and that the uniform size matches.
|
||||
|
@ -391,12 +386,12 @@ 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,
|
||||
data: *mut JSObject)
|
||||
-> Result<u32, ()> {
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: TexFormat,
|
||||
data_type: TexDataType,
|
||||
data: *mut JSObject)
|
||||
-> Result<u32, ()> {
|
||||
let element_size = data_type.element_size();
|
||||
let components_per_element = data_type.components_per_element();
|
||||
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 {
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.1
|
||||
fn Canvas(&self) -> Root<HTMLCanvasElement> {
|
||||
|
@ -844,85 +878,92 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
// 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 {
|
||||
constants::ARRAY_BUFFER => self.bound_buffer_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 {
|
||||
Some(bound_buffer) => bound_buffer,
|
||||
None => return self.webgl_error(InvalidValue),
|
||||
None => return Ok(self.webgl_error(InvalidValue)),
|
||||
};
|
||||
|
||||
match usage {
|
||||
constants::STREAM_DRAW |
|
||||
constants::STATIC_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));
|
||||
} else {
|
||||
// NB: array_buffer_view_to_vec should never fail when we have
|
||||
// WebIDL support for Float32Array etc.
|
||||
self.webgl_error(InvalidValue);
|
||||
}
|
||||
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, &data_vec, usage));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// 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 {
|
||||
constants::ARRAY_BUFFER => self.bound_buffer_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 {
|
||||
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 {
|
||||
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() {
|
||||
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);
|
||||
if (offset as usize) + data_vec.len() > bound_buffer.capacity() {
|
||||
return Ok(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
|
||||
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
|
||||
// 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
|
||||
fn CompressedTexSubImage2D(&self, _cx: *mut JSContext, _target: u32, _level: 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
|
||||
// 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
|
||||
|
@ -1650,23 +1691,23 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
#[allow(unsafe_code)]
|
||||
// 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,
|
||||
format: u32, pixel_type: u32, pixels: *mut JSObject) {
|
||||
format: u32, pixel_type: u32, pixels: *mut JSObject) -> Fallible<()> {
|
||||
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) } {
|
||||
Some(data) => data,
|
||||
None => return self.webgl_error(InvalidValue),
|
||||
None => return Err(Error::Type("Not an ArrayBufferView".to_owned())),
|
||||
};
|
||||
|
||||
if !self.validate_framebuffer_complete() {
|
||||
return;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match unsafe { JS_GetArrayBufferViewType(pixels) } {
|
||||
Type::Uint8 => (),
|
||||
_ => return self.webgl_error(InvalidOperation)
|
||||
_ => return Ok(self.webgl_error(InvalidOperation)),
|
||||
}
|
||||
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
|
@ -1677,12 +1718,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
let result = receiver.recv().unwrap();
|
||||
|
||||
if result.len() > data.len() {
|
||||
return self.webgl_error(InvalidOperation)
|
||||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
|
||||
for i in 0..result.len() {
|
||||
data[i] = result[i]
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
|
||||
|
@ -1802,7 +1845,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
fn Uniform1f(&self,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
val: f32) {
|
||||
if self.validate_uniform_parameters(uniform, UniformSetterType::Float, Some(&[val])) {
|
||||
if self.validate_uniform_parameters(uniform, UniformSetterType::Float, &[val]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.unwrap().id(), val)))
|
||||
.unwrap()
|
||||
|
@ -1813,7 +1856,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
fn Uniform1i(&self,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
val: i32) {
|
||||
if self.validate_uniform_parameters(uniform, UniformSetterType::Int, Some(&[val])) {
|
||||
if self.validate_uniform_parameters(uniform, UniformSetterType::Int, &[val]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1i(uniform.unwrap().id(), val)))
|
||||
.unwrap()
|
||||
|
@ -1823,40 +1866,44 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform1iv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec.unwrap())))
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1iv(uniform.unwrap().id(), data_vec)))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform1fv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec.unwrap())))
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform1fv(uniform.unwrap().id(), data_vec)))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
fn Uniform2f(&self,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
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
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2f(uniform.unwrap().id(), x, y)))
|
||||
.unwrap()
|
||||
|
@ -1866,18 +1913,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform2fv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::FloatVec2,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if self.validate_uniform_parameters(uniform,
|
||||
UniformSetterType::IntVec2,
|
||||
Some(&[x, y])) {
|
||||
&[x, y]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform2i(uniform.unwrap().id(), x, y)))
|
||||
.unwrap()
|
||||
|
@ -1896,19 +1946,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform2iv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::IntVec2,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if self.validate_uniform_parameters(uniform,
|
||||
UniformSetterType::FloatVec3,
|
||||
Some(&[x, y, z])) {
|
||||
&[x, y, z]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3f(uniform.unwrap().id(), x, y, z)))
|
||||
.unwrap()
|
||||
|
@ -1927,19 +1979,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform3fv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::FloatVec3,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if self.validate_uniform_parameters(uniform,
|
||||
UniformSetterType::IntVec3,
|
||||
Some(&[x, y, z])) {
|
||||
&[x, y, z]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform3i(uniform.unwrap().id(), x, y, z)))
|
||||
.unwrap()
|
||||
|
@ -1958,19 +2012,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform3iv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::IntVec3,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if self.validate_uniform_parameters(uniform,
|
||||
UniformSetterType::IntVec4,
|
||||
Some(&[x, y, z, w])) {
|
||||
&[x, y, z, w]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4i(uniform.unwrap().id(), x, y, z, w)))
|
||||
.unwrap()
|
||||
|
@ -1990,19 +2046,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform4iv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::IntVec4,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if self.validate_uniform_parameters(uniform,
|
||||
UniformSetterType::FloatVec4,
|
||||
Some(&[x, y, z, w])) {
|
||||
&[x, y, z, w]) {
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.unwrap().id(), x, y, z, w)))
|
||||
.unwrap()
|
||||
|
@ -2021,19 +2079,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[allow(unsafe_code)]
|
||||
fn Uniform4fv(&self,
|
||||
_cx: *mut JSContext,
|
||||
cx: *mut JSContext,
|
||||
uniform: Option<&WebGLUniformLocation>,
|
||||
data: *mut JSObject) {
|
||||
data: *mut JSObject) -> Fallible<()> {
|
||||
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::FloatVec4,
|
||||
data_vec.as_ref().map(Vec::as_slice)) {
|
||||
&data_vec) {
|
||||
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()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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
|
||||
#[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());
|
||||
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } {
|
||||
if data_vec.len() < 1 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
self.vertex_attrib(indx, data_vec[0], 0f32, 0f32, 1f32)
|
||||
} else {
|
||||
self.webgl_error(InvalidValue);
|
||||
let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
|
||||
if data_vec.len() < 1 {
|
||||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
self.vertex_attrib(indx, data_vec[0], 0f32, 0f32, 1f32);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 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
|
||||
#[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());
|
||||
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } {
|
||||
if data_vec.len() < 2 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
self.vertex_attrib(indx, data_vec[0], data_vec[1], 0f32, 1f32)
|
||||
} else {
|
||||
self.webgl_error(InvalidValue);
|
||||
let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
|
||||
if data_vec.len() < 2 {
|
||||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
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
|
||||
|
@ -2100,16 +2156,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[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());
|
||||
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } {
|
||||
if data_vec.len() < 3 {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
self.vertex_attrib(indx, data_vec[0], data_vec[1], data_vec[2], 1f32)
|
||||
} else {
|
||||
self.webgl_error(InvalidValue);
|
||||
let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
|
||||
if data_vec.len() < 3 {
|
||||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
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
|
||||
|
@ -2119,16 +2173,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
#[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());
|
||||
if let Some(data_vec) = unsafe { array_buffer_view_to_vec_checked::<f32>(data) } {
|
||||
if data_vec.len() < 4 {
|
||||
return 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);
|
||||
let data_vec = try!(unsafe { typed_array_or_sequence_to_vec::<f32>(cx, data, ()) });
|
||||
if data_vec.len() < 4 {
|
||||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -2195,7 +2248,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
border: i32,
|
||||
format: 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,
|
||||
internal_format, width, height,
|
||||
border, format, data_type);
|
||||
|
@ -2211,34 +2270,32 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
data_type,
|
||||
} = match validator.validate() {
|
||||
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 =
|
||||
match unsafe { self.validate_tex_image_2d_data(width, height,
|
||||
format, data_type,
|
||||
data) } {
|
||||
data_ptr) } {
|
||||
Ok(byte_length) => byte_length,
|
||||
Err(_) => return,
|
||||
Err(()) => return Ok(()),
|
||||
};
|
||||
|
||||
// If data is null, a buffer of sufficient size
|
||||
// initialized to 0 is passed.
|
||||
let buff = if data.is_null() {
|
||||
vec![0u8; expected_byte_length as usize]
|
||||
} else {
|
||||
unsafe {
|
||||
array_buffer_view_to_vec::<u8>(data)
|
||||
.expect("Can't reach here without being an ArrayBufferView!")
|
||||
}
|
||||
let buff = match data {
|
||||
None => vec![0u8; expected_byte_length as usize],
|
||||
Some(data) => data,
|
||||
};
|
||||
|
||||
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,
|
||||
level, width, height, border, buff)
|
||||
level, width, height, border, buff);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||
|
@ -2248,14 +2305,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
internal_format: u32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) {
|
||||
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) -> Fallible<()> {
|
||||
// Get pixels from image source
|
||||
let (pixels, size) = match self.get_image_pixels(source) {
|
||||
Ok((pixels, size)) => (pixels, size),
|
||||
Err(_) => return,
|
||||
Err(_) => return Ok(()),
|
||||
};
|
||||
|
||||
|
||||
let validator = TexImage2DValidator::new(self,
|
||||
target, level, internal_format,
|
||||
size.width, size.height,
|
||||
|
@ -2272,11 +2328,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
data_type,
|
||||
} = match validator.validate() {
|
||||
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,
|
||||
level, width, height, border, pixels);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||
|
@ -2291,7 +2348,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
height: i32,
|
||||
format: 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,
|
||||
format, width, height,
|
||||
0, format, data_type);
|
||||
|
@ -2306,35 +2370,32 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
..
|
||||
} = match validator.validate() {
|
||||
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 =
|
||||
match unsafe { self.validate_tex_image_2d_data(width, height,
|
||||
format, data_type,
|
||||
data) } {
|
||||
data_ptr) } {
|
||||
Ok(byte_length) => byte_length,
|
||||
Err(()) => return,
|
||||
Err(()) => return Ok(()),
|
||||
};
|
||||
|
||||
// If data is null, a buffer of sufficient size
|
||||
// initialized to 0 is passed.
|
||||
let buff = if data.is_null() {
|
||||
vec![0u8; expected_byte_length as usize]
|
||||
} else {
|
||||
unsafe {
|
||||
array_buffer_view_to_vec::<u8>(data)
|
||||
.expect("Can't reach here without being an ArrayBufferView!")
|
||||
}
|
||||
let buff = match data {
|
||||
None => vec![0u8; expected_byte_length as usize],
|
||||
Some(data) => data,
|
||||
};
|
||||
|
||||
if expected_byte_length != 0 &&
|
||||
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,
|
||||
width, height, format, data_type, buff);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||
|
@ -2345,10 +2406,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
yoffset: i32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) {
|
||||
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>)
|
||||
-> Fallible<()> {
|
||||
let (pixels, size) = match self.get_image_pixels(source) {
|
||||
Ok((pixels, size)) => (pixels, size),
|
||||
Err(_) => return,
|
||||
Err(_) => return Ok(()),
|
||||
};
|
||||
|
||||
let validator = TexImage2DValidator::new(self, target, level, format,
|
||||
|
@ -2365,11 +2427,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
..
|
||||
} = match validator.validate() {
|
||||
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,
|
||||
width, height, format, data_type, pixels);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue