Auto merge of #21523 - servo:webgl, r=avadacatavra,jdm

Some more drive-by WebGL fixes and cleanups

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21523)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-08-30 12:23:31 -04:00 committed by GitHub
commit 6f81ed49f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
164 changed files with 452 additions and 2780 deletions

View file

@ -344,12 +344,17 @@ class CGMethodCall(CGThing):
distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
# We can't handle unions at the distinguishing index.
# We can't handle unions of non-object values at the distinguishing index.
for (returnType, args) in possibleSignatures:
if args[distinguishingIndex].type.isUnion():
raise TypeError("No support for unions as distinguishing "
"arguments yet: %s",
args[distinguishingIndex].location)
type = args[distinguishingIndex].type
if type.isUnion():
if type.nullable():
type = type.inner
for type in type.flatMemberTypes:
if not (type.isObject() or type.isNonCallbackInterface()):
raise TypeError("No support for unions with non-object variants "
"as distinguishing arguments yet: %s",
args[distinguishingIndex].location)
# Convert all our arguments up to the distinguishing index.
# Doesn't matter which of the possible signatures we use, since
@ -388,6 +393,7 @@ class CGMethodCall(CGThing):
interfacesSigs = [
s for s in possibleSignatures
if (s[1][distinguishingIndex].type.isObject() or
s[1][distinguishingIndex].type.isUnion() or
s[1][distinguishingIndex].type.isNonCallbackInterface())]
# There might be more than one of these; we need to check
# which ones we unwrap to.
@ -2366,7 +2372,6 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'dom::bindings::conversions::ConversionBehavior',
'dom::bindings::conversions::StringificationBehavior',
'dom::bindings::conversions::root_from_handlevalue',
'dom::bindings::error::throw_not_in_union',
'std::ptr::NonNull',
'dom::bindings::mozmap::MozMap',
'dom::bindings::root::DomRoot',
@ -4450,8 +4455,8 @@ class CGUnionConversionStruct(CGThing):
other.append(booleanConversion[0])
conversions.append(CGList(other, "\n\n"))
conversions.append(CGGeneric(
"throw_not_in_union(cx, \"%s\");\n"
"Err(())" % ", ".join(names)))
"Ok(ConversionResult::Failure(\"argument could not be converted to any of: %s\".into()))" % ", ".join(names)
))
method = CGWrapper(
CGIndenter(CGList(conversions, "\n\n")),
pre="unsafe fn from_jsval(cx: *mut JSContext,\n"

View file

@ -255,14 +255,6 @@ pub unsafe fn report_pending_exception(cx: *mut JSContext, dispatch_event: bool)
}
}
/// Throw an exception to signal that a `JSVal` can not be converted to any of
/// the types in an IDL union type.
pub unsafe fn throw_not_in_union(cx: *mut JSContext, names: &'static str) {
assert!(!JS_IsExceptionPending(cx));
let error = format!("argument could not be converted to any of: {}", names);
throw_type_error(cx, &error);
}
/// Throw an exception to signal that a `JSObject` can not be converted to a
/// given DOM type.
pub unsafe fn throw_invalid_this(cx: *mut JSContext, proto_id: u16) {

View file

@ -240,14 +240,18 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.GenerateMipmap(target)
}
#[allow(unsafe_code)]
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
unsafe fn BufferData(&self, cx: *mut JSContext, target: u32, data: *mut JSObject, usage: u32) -> Fallible<()> {
self.base.BufferData(cx, target, data, usage)
fn BufferData(
&self,
target: u32,
data: Option<ArrayBufferViewOrArrayBuffer>,
usage: u32,
) {
self.base.BufferData(target, data, usage)
}
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn BufferData_(&self, target: u32, size: i64, usage: u32) -> Fallible<()> {
fn BufferData_(&self, target: u32, size: i64, usage: u32) {
self.base.BufferData_(target, size, usage)
}

View file

@ -154,6 +154,7 @@ impl WebGLBuffer {
impl Drop for WebGLBuffer {
fn drop(&mut self) {
self.delete();
self.mark_for_deletion();
assert!(self.is_deleted());
}
}

View file

@ -1165,14 +1165,16 @@ impl WebGLRenderingContext {
return
);
let array_buffer = handle_potential_webgl_error!(
self,
self.current_vao().element_array_buffer().get().ok_or(InvalidOperation),
return
);
if count > 0 && primcount > 0 {
if let Some(array_buffer) = self.current_vao().element_array_buffer().get() {
// This operation cannot overflow in u64 and we know all those values are nonnegative.
let val = offset as u64 + (count as u64 * type_size as u64);
if val > array_buffer.capacity() as u64 {
return self.webgl_error(InvalidOperation);
}
} else {
// This operation cannot overflow in u64 and we know all those values are nonnegative.
let val = offset as u64 + (count as u64 * type_size as u64);
if val > array_buffer.capacity() as u64 {
return self.webgl_error(InvalidOperation);
}
}
@ -1324,19 +1326,6 @@ impl Drop for WebGLRenderingContext {
}
}
#[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(v) => Ok(v.to_vec()),
Err(_) => 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) -> DomRoot<HTMLCanvasElement> {
@ -1892,52 +1881,44 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
handle_potential_webgl_error!(self, texture.generate_mipmap());
}
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
unsafe fn BufferData(
fn BufferData(
&self,
cx: *mut JSContext,
target: u32,
data: *mut JSObject,
data: Option<ArrayBufferViewOrArrayBuffer>,
usage: u32,
) -> ErrorResult {
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(data) => data.to_vec(),
Err(_) => fallible_array_buffer_view_to_vec(cx, data)?,
) {
let data = match data {
Some(ArrayBufferViewOrArrayBuffer::ArrayBuffer(data)) => data.to_vec(),
Some(ArrayBufferViewOrArrayBuffer::ArrayBufferView(data)) => data.to_vec(),
None => return self.webgl_error(InvalidValue),
};
let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return Ok(()));
let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return);
let bound_buffer = match bound_buffer {
Some(bound_buffer) => bound_buffer,
None => return Ok(self.webgl_error(InvalidOperation)),
None => return self.webgl_error(InvalidOperation),
};
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, data_vec, usage));
Ok(())
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, data, usage));
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn BufferData_(&self, target: u32, size: i64, usage: u32) -> ErrorResult {
let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return Ok(()));
fn BufferData_(&self, target: u32, size: i64, usage: u32) {
let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return);
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 size < 0 {
return Ok(self.webgl_error(InvalidValue));
return self.webgl_error(InvalidValue);
}
// FIXME: Allocating a buffer based on user-requested size is
// not great, but we don't have a fallible allocation to try.
let data = vec![0u8; size as usize];
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, data, usage));
Ok(())
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
@ -2757,7 +2738,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
fn IsBuffer(&self, buffer: Option<&WebGLBuffer>) -> bool {
buffer.map_or(false, |buf| {
self.validate_ownership(buf).is_ok() && buf.target().is_some() && !buf.is_marked_for_deletion()
self.validate_ownership(buf).is_ok() && buf.target().is_some() && !buf.is_deleted()
})
}
@ -3643,7 +3624,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
};
if values.len() < 1 {
return self.webgl_error(InvalidOperation);
// https://github.com/KhronosGroup/WebGL/issues/2700
return self.webgl_error(InvalidValue);
}
self.vertex_attrib(indx, values[0], 0f32, 0f32, 1f32);
}
@ -3660,7 +3642,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
};
if values.len() < 2 {
return self.webgl_error(InvalidOperation);
// https://github.com/KhronosGroup/WebGL/issues/2700
return self.webgl_error(InvalidValue);
}
self.vertex_attrib(indx, values[0], values[1], 0f32, 1f32);
}
@ -3677,7 +3660,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
};
if values.len() < 3 {
return self.webgl_error(InvalidOperation);
// https://github.com/KhronosGroup/WebGL/issues/2700
return self.webgl_error(InvalidValue);
}
self.vertex_attrib(indx, values[0], values[1], values[2], 1f32);
}
@ -3694,7 +3678,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Float32ArrayOrUnrestrictedFloatSequence::UnrestrictedFloatSequence(v) => v,
};
if values.len() < 4 {
return self.webgl_error(InvalidOperation);
// https://github.com/KhronosGroup/WebGL/issues/2700
return self.webgl_error(InvalidValue);
}
self.vertex_attrib(indx, values[0], values[1], values[2], values[3]);
}

View file

@ -124,8 +124,15 @@ impl WebGLVertexArrayObjectOES {
}
let context = self.upcast::<WebGLObject>().context();
let buffer = context.array_buffer().ok_or(WebGLError::InvalidOperation)?;
buffer.increment_attached_counter();
let buffer = context.array_buffer();
match buffer {
Some(ref buffer) => buffer.increment_attached_counter(),
None if offset != 0 => {
// https://github.com/KhronosGroup/WebGL/pull/2228
return Err(WebGLError::InvalidOperation)
},
_ => {},
}
context.send_command(WebGLCommand::VertexAttribPointer(
index,
size,
@ -146,7 +153,7 @@ impl WebGLVertexArrayObjectOES {
normalized,
stride: stride as u8,
offset: offset as u32,
buffer: Some(Dom::from_ref(&*buffer)),
buffer: buffer.map(|b| Dom::from_ref(&*b)),
divisor: data.divisor,
};

View file

@ -305,10 +305,7 @@ interface WebGL2RenderingContextBase
/* Buffer objects */
// WebGL1:
// BUG: https://github.com/KhronosGroup/WebGL/issues/2216
// FIXME(xanewok): https://github.com/servo/servo/issues/20513
[Throws]
void bufferData(GLenum target, object? data, GLenum usage);
[Throws]
void bufferData(GLenum target, /*[AllowShared]*/ BufferSource? data, GLenum usage);
void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
void bufferSubData(GLenum target, GLintptr dstByteOffset, /*[AllowShared]*/ BufferSource srcData);
// WebGL2:

View file

@ -421,7 +421,8 @@ interface WebGLRenderingContextBase
const GLenum RGB5_A1 = 0x8057;
const GLenum RGB565 = 0x8D62;
const GLenum DEPTH_COMPONENT16 = 0x81A5;
const GLenum STENCIL_INDEX = 0x1901;
// https://github.com/KhronosGroup/WebGL/pull/2371
// const GLenum STENCIL_INDEX = 0x1901;
const GLenum STENCIL_INDEX8 = 0x8D48;
const GLenum DEPTH_STENCIL = 0x84F9;
@ -687,10 +688,7 @@ interface WebGLRenderingContext
{
// BUG: https://github.com/KhronosGroup/WebGL/issues/2216
// FIXME(xanewok): https://github.com/servo/servo/issues/20513
[Throws]
void bufferData(GLenum target, object? data, GLenum usage);
[Throws]
void bufferData(GLenum target, /*[AllowShared]*/ BufferSource? data, GLenum usage);
void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
void bufferSubData(GLenum target, GLintptr offset, /*[AllowShared]*/ BufferSource data);