Implement the basic WebGL2 buffer data operations

Adds support for `bufferData`, `bufferSubData`, `copyBufferSubData`
and `getBufferSubData`.

Reference: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
This commit is contained in:
Mátyás Mustoha 2019-10-17 11:34:06 +02:00
parent f626355b67
commit 4050b7f9ec
13 changed files with 510 additions and 197 deletions

View file

@ -55,6 +55,7 @@ use sparkle::gl::Gl;
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use std::slice;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread; use std::thread;
use surfman; use surfman;
@ -1013,6 +1014,26 @@ impl WebGLImpl {
WebGLCommand::BufferSubData(buffer_type, offset, ref receiver) => { WebGLCommand::BufferSubData(buffer_type, offset, ref receiver) => {
gl::buffer_sub_data(gl, buffer_type, offset, &receiver.recv().unwrap()) gl::buffer_sub_data(gl, buffer_type, offset, &receiver.recv().unwrap())
}, },
WebGLCommand::CopyBufferSubData(src, dst, src_offset, dst_offset, size) => {
gl.copy_buffer_sub_data(
src,
dst,
src_offset as isize,
dst_offset as isize,
size as isize,
);
},
WebGLCommand::GetBufferSubData(buffer_type, offset, length, ref sender) => {
let ptr = gl.map_buffer_range(
buffer_type,
offset as isize,
length as isize,
gl::MAP_READ_BIT,
);
let data: &[u8] = unsafe { slice::from_raw_parts(ptr as _, length) };
sender.send(data).unwrap();
gl.unmap_buffer(buffer_type);
},
WebGLCommand::Clear(mask) => { WebGLCommand::Clear(mask) => {
gl.clear(mask); gl.clear(mask);
}, },

View file

@ -248,6 +248,8 @@ pub enum WebGLCommand {
BindAttribLocation(WebGLProgramId, u32, String), BindAttribLocation(WebGLProgramId, u32, String),
BufferData(u32, IpcBytesReceiver, u32), BufferData(u32, IpcBytesReceiver, u32),
BufferSubData(u32, isize, IpcBytesReceiver), BufferSubData(u32, isize, IpcBytesReceiver),
GetBufferSubData(u32, usize, usize, IpcBytesSender),
CopyBufferSubData(u32, u32, i64, i64, i64),
Clear(u32), Clear(u32),
ClearColor(f32, f32, f32, f32), ClearColor(f32, f32, f32, f32),
ClearDepth(f32), ClearDepth(f32),

View file

@ -36,11 +36,13 @@ use crate::dom::webgluniformlocation::WebGLUniformLocation;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
use canvas_traits::webgl::WebGLError::*; use canvas_traits::webgl::WebGLError::*;
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/webgl.idl use canvas_traits::webgl::{
use canvas_traits::webgl::{webgl_channel, GLContextAttributes, WebGLCommand, WebGLVersion}; webgl_channel, GLContextAttributes, WebGLCommand, WebGLResult, WebGLVersion,
};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::default::Size2D; use euclid::default::Size2D;
use js::jsapi::JSObject; use ipc_channel::ipc;
use js::jsapi::{JSObject, Type};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value};
use js::rust::CustomAutoRooterGuard; use js::rust::CustomAutoRooterGuard;
use js::typedarray::ArrayBufferView; use js::typedarray::ArrayBufferView;
@ -54,6 +56,22 @@ pub struct WebGL2RenderingContext {
occlusion_query: MutNullableDom<WebGLQuery>, occlusion_query: MutNullableDom<WebGLQuery>,
primitives_query: MutNullableDom<WebGLQuery>, primitives_query: MutNullableDom<WebGLQuery>,
samplers: Box<[MutNullableDom<WebGLSampler>]>, samplers: Box<[MutNullableDom<WebGLSampler>]>,
bound_copy_read_buffer: MutNullableDom<WebGLBuffer>,
bound_copy_write_buffer: MutNullableDom<WebGLBuffer>,
bound_pixel_pack_buffer: MutNullableDom<WebGLBuffer>,
bound_pixel_unpack_buffer: MutNullableDom<WebGLBuffer>,
bound_transform_feedback_buffer: MutNullableDom<WebGLBuffer>,
bound_uniform_buffer: MutNullableDom<WebGLBuffer>,
}
fn typedarray_elem_size(typeid: Type) -> usize {
match typeid {
Type::Int8 | Type::Uint8 | Type::Uint8Clamped => 1,
Type::Int16 | Type::Uint16 => 2,
Type::Int32 | Type::Uint32 | Type::Float32 => 4,
Type::Int64 | Type::Float64 => 8,
Type::MaxTypedArrayViewType => unreachable!(),
}
} }
impl WebGL2RenderingContext { impl WebGL2RenderingContext {
@ -76,6 +94,12 @@ impl WebGL2RenderingContext {
occlusion_query: MutNullableDom::new(None), occlusion_query: MutNullableDom::new(None),
primitives_query: MutNullableDom::new(None), primitives_query: MutNullableDom::new(None),
samplers: samplers, samplers: samplers,
bound_copy_read_buffer: MutNullableDom::new(None),
bound_copy_write_buffer: MutNullableDom::new(None),
bound_pixel_pack_buffer: MutNullableDom::new(None),
bound_pixel_unpack_buffer: MutNullableDom::new(None),
bound_transform_feedback_buffer: MutNullableDom::new(None),
bound_uniform_buffer: MutNullableDom::new(None),
}) })
} }
@ -100,6 +124,25 @@ impl WebGL2RenderingContext {
pub fn base_context(&self) -> DomRoot<WebGLRenderingContext> { pub fn base_context(&self) -> DomRoot<WebGLRenderingContext> {
DomRoot::from_ref(&*self.base) DomRoot::from_ref(&*self.base)
} }
fn bound_buffer(&self, target: u32) -> WebGLResult<Option<DomRoot<WebGLBuffer>>> {
match target {
constants::COPY_READ_BUFFER => Ok(self.bound_copy_read_buffer.get()),
constants::COPY_WRITE_BUFFER => Ok(self.bound_copy_write_buffer.get()),
constants::PIXEL_PACK_BUFFER => Ok(self.bound_pixel_pack_buffer.get()),
constants::PIXEL_UNPACK_BUFFER => Ok(self.bound_pixel_unpack_buffer.get()),
constants::TRANSFORM_FEEDBACK_BUFFER => Ok(self.bound_transform_feedback_buffer.get()),
constants::UNIFORM_BUFFER => Ok(self.bound_uniform_buffer.get()),
_ => self.base.bound_buffer(target),
}
}
fn unbind_from(&self, slot: &MutNullableDom<WebGLBuffer>, buffer: &WebGLBuffer) {
if slot.get().map_or(false, |b| buffer == &*b) {
buffer.decrement_attached_counter();
slot.set(None);
}
}
} }
impl WebGL2RenderingContextMethods for WebGL2RenderingContext { impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
@ -146,6 +189,27 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
let sampler = self.samplers[idx].get(); let sampler = self.samplers[idx].get();
optional_root_object_to_js_or_null!(*cx, sampler) optional_root_object_to_js_or_null!(*cx, sampler)
}, },
constants::COPY_READ_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(*cx, &self.bound_copy_read_buffer.get())
},
constants::COPY_WRITE_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(*cx, &self.bound_copy_write_buffer.get())
},
constants::PIXEL_PACK_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(*cx, &self.bound_pixel_pack_buffer.get())
},
constants::PIXEL_UNPACK_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(*cx, &self.bound_pixel_unpack_buffer.get())
},
constants::TRANSFORM_FEEDBACK_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(
*cx,
&self.bound_transform_feedback_buffer.get()
)
},
constants::UNIFORM_BUFFER_BINDING => unsafe {
optional_root_object_to_js_or_null!(*cx, &self.bound_uniform_buffer.get())
},
_ => self.base.GetParameter(cx, parameter), _ => self.base.GetParameter(cx, parameter),
} }
} }
@ -238,9 +302,18 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.BindAttribLocation(program, index, name) self.base.BindAttribLocation(program, index, name)
} }
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.2
fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) { fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) {
self.base.BindBuffer(target, buffer) let slot = match target {
constants::COPY_READ_BUFFER => &self.bound_copy_read_buffer,
constants::COPY_WRITE_BUFFER => &self.bound_copy_write_buffer,
constants::PIXEL_PACK_BUFFER => &self.bound_pixel_pack_buffer,
constants::PIXEL_UNPACK_BUFFER => &self.bound_pixel_unpack_buffer,
constants::TRANSFORM_FEEDBACK_BUFFER => &self.bound_transform_feedback_buffer,
constants::UNIFORM_BUFFER => &self.bound_uniform_buffer,
_ => return self.base.BindBuffer(target, buffer),
};
self.base.bind_buffer_maybe(&slot, target, buffer);
} }
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
@ -265,12 +338,59 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// 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, target: u32, data: Option<ArrayBufferViewOrArrayBuffer>, usage: u32) { fn BufferData(&self, target: u32, data: Option<ArrayBufferViewOrArrayBuffer>, usage: u32) {
self.base.BufferData(target, data, usage) let bound_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(target), return);
self.base.buffer_data(target, data, usage, bound_buffer)
} }
/// 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, target: u32, size: i64, usage: u32) { fn BufferData_(&self, target: u32, size: i64, usage: u32) {
self.base.BufferData_(target, size, usage) let bound_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(target), return);
self.base.buffer_data_(target, size, usage, bound_buffer)
}
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
#[allow(unsafe_code)]
fn BufferData__(
&self,
target: u32,
data: CustomAutoRooterGuard<ArrayBufferView>,
usage: u32,
elem_offset: u32,
length: u32,
) {
let bound_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(target), return);
let bound_buffer =
handle_potential_webgl_error!(self.base, bound_buffer.ok_or(InvalidOperation), return);
let elem_size = typedarray_elem_size(data.get_array_type());
let elem_count = data.len() / elem_size;
let elem_offset = elem_offset as usize;
let byte_offset = elem_offset * elem_size;
if byte_offset > data.len() {
return self.base.webgl_error(InvalidValue);
}
let copy_count = if length == 0 {
elem_count - elem_offset
} else {
length as usize
};
if copy_count == 0 {
return;
}
let copy_bytes = copy_count * elem_size;
if byte_offset + copy_bytes > data.len() {
return self.base.webgl_error(InvalidValue);
}
let data_end = byte_offset + copy_bytes;
let data: &[u8] = unsafe { &data.as_slice()[byte_offset..data_end] };
handle_potential_webgl_error!(self.base, bound_buffer.buffer_data(target, &data, usage));
} }
/// 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
@ -278,6 +398,171 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
self.base.BufferSubData(target, offset, data) self.base.BufferSubData(target, offset, data)
} }
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
#[allow(unsafe_code)]
fn BufferSubData_(
&self,
target: u32,
dst_byte_offset: i64,
src_data: CustomAutoRooterGuard<ArrayBufferView>,
src_elem_offset: u32,
length: u32,
) {
let bound_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(target), return);
let bound_buffer =
handle_potential_webgl_error!(self.base, bound_buffer.ok_or(InvalidOperation), return);
let src_elem_size = typedarray_elem_size(src_data.get_array_type());
let src_elem_count = src_data.len() / src_elem_size;
let src_elem_offset = src_elem_offset as usize;
let src_byte_offset = src_elem_offset * src_elem_size;
if dst_byte_offset < 0 || src_byte_offset > src_data.len() {
return self.base.webgl_error(InvalidValue);
}
let copy_count = if length == 0 {
src_elem_count - src_elem_offset
} else {
length as usize
};
if copy_count == 0 {
return;
}
let copy_bytes = copy_count * src_elem_size;
let dst_byte_offset = dst_byte_offset as usize;
if dst_byte_offset + copy_bytes > bound_buffer.capacity() ||
src_byte_offset + copy_bytes > src_data.len()
{
return self.base.webgl_error(InvalidValue);
}
let (sender, receiver) = ipc::bytes_channel().unwrap();
self.base.send_command(WebGLCommand::BufferSubData(
target,
dst_byte_offset as isize,
receiver,
));
let src_end = src_byte_offset + copy_bytes;
let data: &[u8] = unsafe { &src_data.as_slice()[src_byte_offset..src_end] };
sender.send(data).unwrap();
}
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
fn CopyBufferSubData(
&self,
read_target: u32,
write_target: u32,
read_offset: i64,
write_offset: i64,
size: i64,
) {
if read_offset < 0 || write_offset < 0 || size < 0 {
return self.base.webgl_error(InvalidValue);
}
let read_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(read_target), return);
let read_buffer =
handle_potential_webgl_error!(self.base, read_buffer.ok_or(InvalidOperation), return);
let write_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(write_target), return);
let write_buffer =
handle_potential_webgl_error!(self.base, write_buffer.ok_or(InvalidOperation), return);
let read_until = read_offset + size;
let write_until = write_offset + size;
if read_until as usize > read_buffer.capacity() ||
write_until as usize > write_buffer.capacity()
{
return self.base.webgl_error(InvalidValue);
}
if read_target == write_target {
let is_separate = read_until <= write_offset || write_until <= read_offset;
if !is_separate {
return self.base.webgl_error(InvalidValue);
}
}
let src_is_elemarray = read_buffer
.target()
.map_or(false, |t| t == constants::ELEMENT_ARRAY_BUFFER);
let dst_is_elemarray = write_buffer
.target()
.map_or(false, |t| t == constants::ELEMENT_ARRAY_BUFFER);
if src_is_elemarray != dst_is_elemarray {
return self.base.webgl_error(InvalidOperation);
}
self.base.send_command(WebGLCommand::CopyBufferSubData(
read_target,
write_target,
read_offset,
write_offset,
size,
));
}
/// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.3
#[allow(unsafe_code)]
fn GetBufferSubData(
&self,
target: u32,
src_byte_offset: i64,
mut dst_buffer: CustomAutoRooterGuard<ArrayBufferView>,
dst_elem_offset: u32,
length: u32,
) {
let bound_buffer =
handle_potential_webgl_error!(self.base, self.bound_buffer(target), return);
let bound_buffer =
handle_potential_webgl_error!(self.base, bound_buffer.ok_or(InvalidOperation), return);
let dst_elem_size = typedarray_elem_size(dst_buffer.get_array_type());
let dst_elem_count = dst_buffer.len() / dst_elem_size;
let dst_elem_offset = dst_elem_offset as usize;
let dst_byte_offset = dst_elem_offset * dst_elem_size;
if src_byte_offset < 0 || dst_byte_offset > dst_buffer.len() {
return self.base.webgl_error(InvalidValue);
}
let copy_count = if length == 0 {
dst_elem_count - dst_elem_offset
} else {
length as usize
};
if copy_count == 0 {
return;
}
let copy_bytes = copy_count * dst_elem_size;
// TODO(mmatyas): Transform Feedback
let src_byte_offset = src_byte_offset as usize;
if src_byte_offset + copy_bytes > bound_buffer.capacity() ||
dst_byte_offset + copy_bytes > dst_buffer.len()
{
return self.base.webgl_error(InvalidValue);
}
let (sender, receiver) = ipc::bytes_channel().unwrap();
self.base.send_command(WebGLCommand::GetBufferSubData(
target,
src_byte_offset,
copy_bytes,
sender,
));
let data = receiver.recv().unwrap();
let dst_end = dst_byte_offset + copy_bytes;
unsafe {
dst_buffer.as_mut_slice()[dst_byte_offset..dst_end].copy_from_slice(&data);
}
}
/// 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( fn CompressedTexImage2D(
&self, &self,
@ -445,7 +730,23 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext {
/// 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 DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) { fn DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) {
self.base.DeleteBuffer(buffer) let buffer = match buffer {
Some(buffer) => buffer,
None => return,
};
handle_potential_webgl_error!(self.base, self.base.validate_ownership(buffer), return);
if buffer.is_marked_for_deletion() {
return;
}
self.base.current_vao().unbind_buffer(buffer);
self.unbind_from(&self.base.array_buffer_slot(), &buffer);
self.unbind_from(&self.bound_copy_read_buffer, &buffer);
self.unbind_from(&self.bound_copy_write_buffer, &buffer);
self.unbind_from(&self.bound_pixel_pack_buffer, &buffer);
self.unbind_from(&self.bound_pixel_unpack_buffer, &buffer);
self.unbind_from(&self.bound_transform_feedback_buffer, &buffer);
self.unbind_from(&self.bound_uniform_buffer, &buffer);
buffer.mark_for_deletion(false);
} }
/// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants;
use crate::dom::bindings::codegen::Bindings::WebGLBufferBinding; use crate::dom::bindings::codegen::Bindings::WebGLBufferBinding;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants; use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
@ -16,6 +17,11 @@ use dom_struct::dom_struct;
use ipc_channel::ipc; use ipc_channel::ipc;
use std::cell::Cell; use std::cell::Cell;
fn target_is_copy_buffer(target: u32) -> bool {
target == WebGL2RenderingContextConstants::COPY_READ_BUFFER ||
target == WebGL2RenderingContextConstants::COPY_WRITE_BUFFER
}
#[dom_struct] #[dom_struct]
pub struct WebGLBuffer { pub struct WebGLBuffer {
webgl_object: WebGLObject, webgl_object: WebGLObject,
@ -65,7 +71,7 @@ impl WebGLBuffer {
self.id self.id
} }
pub fn buffer_data(&self, data: &[u8], usage: u32) -> WebGLResult<()> { pub fn buffer_data(&self, target: u32, data: &[u8], usage: u32) -> WebGLResult<()> {
match usage { match usage {
WebGLRenderingContextConstants::STREAM_DRAW | WebGLRenderingContextConstants::STREAM_DRAW |
WebGLRenderingContextConstants::STATIC_DRAW | WebGLRenderingContextConstants::STATIC_DRAW |
@ -78,11 +84,7 @@ impl WebGLBuffer {
let (sender, receiver) = ipc::bytes_channel().unwrap(); let (sender, receiver) = ipc::bytes_channel().unwrap();
self.upcast::<WebGLObject>() self.upcast::<WebGLObject>()
.context() .context()
.send_command(WebGLCommand::BufferData( .send_command(WebGLCommand::BufferData(target, receiver, usage));
self.target.get().unwrap(),
receiver,
usage,
));
sender.send(data).unwrap(); sender.send(data).unwrap();
Ok(()) Ok(())
} }
@ -124,11 +126,24 @@ impl WebGLBuffer {
self.target.get() self.target.get()
} }
pub fn set_target(&self, target: u32) -> WebGLResult<()> { fn can_bind_to(&self, new_target: u32) -> bool {
if self.target.get().map_or(false, |t| t != target) { if let Some(current_target) = self.target.get() {
if [current_target, new_target]
.contains(&WebGLRenderingContextConstants::ELEMENT_ARRAY_BUFFER)
{
return target_is_copy_buffer(new_target) || new_target == current_target;
}
}
true
}
pub fn set_target_maybe(&self, target: u32) -> WebGLResult<()> {
if !self.can_bind_to(target) {
return Err(WebGLError::InvalidOperation); return Err(WebGLError::InvalidOperation);
} }
self.target.set(Some(target)); if !target_is_copy_buffer(target) {
self.target.set(Some(target));
}
Ok(()) Ok(())
} }

View file

@ -255,7 +255,7 @@ impl WebGLRenderingContext {
&self.limits &self.limits
} }
fn current_vao(&self) -> DomRoot<WebGLVertexArrayObjectOES> { pub fn current_vao(&self) -> DomRoot<WebGLVertexArrayObjectOES> {
self.current_vao.or_init(|| { self.current_vao.or_init(|| {
DomRoot::from_ref( DomRoot::from_ref(
self.default_vao self.default_vao
@ -1004,6 +1004,10 @@ impl WebGLRenderingContext {
self.bound_buffer_array.get() self.bound_buffer_array.get()
} }
pub fn array_buffer_slot(&self) -> &MutNullableDom<WebGLBuffer> {
&self.bound_buffer_array
}
pub fn bound_buffer(&self, target: u32) -> WebGLResult<Option<DomRoot<WebGLBuffer>>> { pub fn bound_buffer(&self, target: u32) -> WebGLResult<Option<DomRoot<WebGLBuffer>>> {
match target { match target {
constants::ARRAY_BUFFER => Ok(self.bound_buffer_array.get()), constants::ARRAY_BUFFER => Ok(self.bound_buffer_array.get()),
@ -1095,6 +1099,72 @@ impl WebGLRenderingContext {
pub fn extension_manager(&self) -> &WebGLExtensions { pub fn extension_manager(&self) -> &WebGLExtensions {
&self.extension_manager &self.extension_manager
} }
#[allow(unsafe_code)]
pub fn buffer_data(
&self,
target: u32,
data: Option<ArrayBufferViewOrArrayBuffer>,
usage: u32,
bound_buffer: Option<DomRoot<WebGLBuffer>>,
) {
let data = handle_potential_webgl_error!(self, data.ok_or(InvalidValue), return);
let bound_buffer =
handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return);
let data = unsafe {
// Safe because we don't do anything with JS until the end of the method.
match data {
ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref data) => data.as_slice(),
ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref data) => data.as_slice(),
}
};
handle_potential_webgl_error!(self, bound_buffer.buffer_data(target, data, usage));
}
pub fn buffer_data_(
&self,
target: u32,
size: i64,
usage: u32,
bound_buffer: Option<DomRoot<WebGLBuffer>>,
) {
let bound_buffer =
handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return);
if size < 0 {
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));
}
pub fn bind_buffer_maybe(
&self,
slot: &MutNullableDom<WebGLBuffer>,
target: u32,
buffer: Option<&WebGLBuffer>,
) {
if let Some(buffer) = buffer {
handle_potential_webgl_error!(self, self.validate_ownership(buffer), return);
if buffer.is_marked_for_deletion() {
return self.webgl_error(InvalidOperation);
}
handle_potential_webgl_error!(self, buffer.set_target_maybe(target), return);
buffer.increment_attached_counter();
}
self.send_command(WebGLCommand::BindBuffer(target, buffer.map(|b| b.id())));
if let Some(old) = slot.get() {
old.decrement_attached_counter();
}
slot.set(buffer);
}
} }
#[cfg(not(feature = "webgl_backtrace"))] #[cfg(not(feature = "webgl_backtrace"))]
@ -1585,10 +1655,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// 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 BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) { fn BindBuffer(&self, target: u32, buffer: Option<&WebGLBuffer>) {
if let Some(buffer) = buffer {
handle_potential_webgl_error!(self, self.validate_ownership(buffer), return);
}
let current_vao; let current_vao;
let slot = match target { let slot = match target {
constants::ARRAY_BUFFER => &self.bound_buffer_array, constants::ARRAY_BUFFER => &self.bound_buffer_array,
@ -1598,19 +1664,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}, },
_ => return self.webgl_error(InvalidEnum), _ => return self.webgl_error(InvalidEnum),
}; };
self.bind_buffer_maybe(&slot, target, buffer);
if let Some(buffer) = buffer {
if buffer.is_marked_for_deletion() {
return self.webgl_error(InvalidOperation);
}
handle_potential_webgl_error!(self, buffer.set_target(target), return);
buffer.increment_attached_counter();
}
self.send_command(WebGLCommand::BindBuffer(target, buffer.map(|b| b.id())));
if let Some(old) = slot.get() {
old.decrement_attached_counter();
}
slot.set(buffer);
} }
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
@ -1701,38 +1755,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
} }
// 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
#[allow(unsafe_code)]
fn BufferData(&self, target: u32, data: Option<ArrayBufferViewOrArrayBuffer>, usage: u32) { fn BufferData(&self, target: u32, data: Option<ArrayBufferViewOrArrayBuffer>, usage: u32) {
let data = handle_potential_webgl_error!(self, data.ok_or(InvalidValue), return);
let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return); let bound_buffer = handle_potential_webgl_error!(self, self.bound_buffer(target), return);
let bound_buffer = self.buffer_data(target, data, usage, bound_buffer)
handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return);
let data = unsafe {
// Safe because we don't do anything with JS until the end of the method.
match data {
ArrayBufferViewOrArrayBuffer::ArrayBuffer(ref data) => data.as_slice(),
ArrayBufferViewOrArrayBuffer::ArrayBufferView(ref data) => data.as_slice(),
}
};
handle_potential_webgl_error!(self, bound_buffer.buffer_data(data, usage));
} }
// 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, target: u32, size: i64, usage: u32) { 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 = handle_potential_webgl_error!(self, self.bound_buffer(target), return);
let bound_buffer = self.buffer_data_(target, size, usage, bound_buffer)
handle_potential_webgl_error!(self, bound_buffer.ok_or(InvalidOperation), return);
if size < 0 {
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(&data, usage));
} }
// 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

View file

@ -299,18 +299,18 @@ interface mixin WebGL2RenderingContextBase
void bufferData(GLenum target, GLsizeiptr size, GLenum usage); void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
void bufferSubData(GLenum target, GLintptr dstByteOffset, /*[AllowShared]*/ BufferSource srcData); void bufferSubData(GLenum target, GLintptr dstByteOffset, /*[AllowShared]*/ BufferSource srcData);
// WebGL2: // WebGL2:
// void bufferData(GLenum target, [AllowShared] ArrayBufferView srcData, GLenum usage, GLuint srcOffset, void bufferData(GLenum target, /*[AllowShared]*/ ArrayBufferView srcData, GLenum usage, GLuint srcOffset,
// optional GLuint length = 0); optional GLuint length = 0);
// void bufferSubData(GLenum target, GLintptr dstByteOffset, [AllowShared] ArrayBufferView srcData, void bufferSubData(GLenum target, GLintptr dstByteOffset, /*[AllowShared]*/ ArrayBufferView srcData,
// GLuint srcOffset, optional GLuint length = 0); GLuint srcOffset, optional GLuint length = 0);
// void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset,
// GLintptr writeOffset, GLsizeiptr size); GLintptr writeOffset, GLsizeiptr size);
// MapBufferRange, in particular its read-only and write-only modes, // MapBufferRange, in particular its read-only and write-only modes,
// can not be exposed safely to JavaScript. GetBufferSubData // can not be exposed safely to JavaScript. GetBufferSubData
// replaces it for the purpose of fetching data back from the GPU. // replaces it for the purpose of fetching data back from the GPU.
// void getBufferSubData(GLenum target, GLintptr srcByteOffset, [AllowShared] ArrayBufferView dstBuffer, void getBufferSubData(GLenum target, GLintptr srcByteOffset, /*[AllowShared]*/ ArrayBufferView dstBuffer,
// optional GLuint dstOffset = 0, optional GLuint length = 0); optional GLuint dstOffset = 0, optional GLuint length = 0);
/* Framebuffer objects */ /* Framebuffer objects */
// void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, // void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,

View file

@ -1,5 +0,0 @@
[buffer-copying-contents.html]
expected: ERROR
[WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
expected: FAIL

View file

@ -1,2 +0,0 @@
[buffer-copying-restrictions.html]
expected: ERROR

View file

@ -1,14 +0,0 @@
[buffer-data-and-buffer-sub-data-sub-source.html]
expected: ERROR
[WebGL test #3: getError expected: INVALID_VALUE. Was NO_ERROR : calling bufferData when srcOffset + length is larger than source size]
expected: FAIL
[WebGL test #4: getError expected: INVALID_VALUE. Was NO_ERROR : calling bufferData when srcOffset + length is larger than source size]
expected: FAIL
[WebGL test #5: getError expected: INVALID_VALUE. Was NO_ERROR : calling bufferData when srcOffset + length is larger than source size]
expected: FAIL
[WebGL test #7: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
expected: FAIL

View file

@ -1,35 +0,0 @@
[get-buffer-sub-data.html]
expected: ERROR
[WebGL test #2: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #7: The returned array buffer fails to match original data]
expected: FAIL
[WebGL test #8: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #10: areArraysEqual(retArray.slice(2), floatArray.slice(0, floatArray.length - 2)) should be true. Was false.]
expected: FAIL
[WebGL test #11: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #13: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length + 1) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #14: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2, 2) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #16: areArraysEqual(retArray.slice(2, 4), floatArray.slice(0, 2)) should be true. Was false.]
expected: FAIL
[WebGL test #18: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 1) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL
[WebGL test #20: areArraysEqual(retArray.slice(8), floatArray.slice(0, 1)) should be true. Was false.]
expected: FAIL
[WebGL test #21: gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 2) threw exception TypeError: gl.getBufferSubData is not a function]
expected: FAIL

View file

@ -1,199 +1,193 @@
[methods-2.html] [methods-2.html]
[WebGL test #46: Property either does not exist or is not a function: bindTransformFeedback] [WebGL test #32: Property either does not exist or is not a function: vertexAttribI4ui]
expected: FAIL expected: FAIL
[WebGL test #25: Property either does not exist or is not a function: uniform4uiv] [WebGL test #30: Property either does not exist or is not a function: vertexAttribI4i]
expected: FAIL expected: FAIL
[WebGL test #48: Property either does not exist or is not a function: endTransformFeedback] [WebGL test #28: Property either does not exist or is not a function: uniformMatrix3x4fv]
expected: FAIL expected: FAIL
[WebGL test #28: Property either does not exist or is not a function: uniformMatrix2x4fv] [WebGL test #58: Property either does not exist or is not a function: getActiveUniformBlockName]
expected: FAIL expected: FAIL
[WebGL test #1: Property either does not exist or is not a function: getBufferSubData] [WebGL test #49: Property either does not exist or is not a function: pauseTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #30: Property either does not exist or is not a function: uniformMatrix3x4fv] [WebGL test #33: Property either does not exist or is not a function: vertexAttribI4uiv]
expected: FAIL expected: FAIL
[WebGL test #14: Property either does not exist or is not a function: copyTexSubImage3D] [WebGL test #63: Property either does not exist or is not a function: bindVertexArray]
expected: FAIL expected: FAIL
[WebGL test #27: Property either does not exist or is not a function: uniformMatrix3x2fv] [WebGL test #2: Property either does not exist or is not a function: framebufferTextureLayer]
expected: FAIL expected: FAIL
[WebGL test #53: Property either does not exist or is not a function: bindBufferBase] [WebGL test #15: Property either does not exist or is not a function: getFragDataLocation]
expected: FAIL expected: FAIL
[WebGL test #3: Property either does not exist or is not a function: blitFramebuffer] [WebGL test #60: Property either does not exist or is not a function: createVertexArray]
expected: FAIL expected: FAIL
[WebGL test #33: Property either does not exist or is not a function: vertexAttribI4iv] [WebGL test #4: Property either does not exist or is not a function: invalidateFramebuffer]
expected: FAIL expected: FAIL
[WebGL test #44: Property either does not exist or is not a function: deleteTransformFeedback] [WebGL test #45: Property either does not exist or is not a function: beginTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #51: Property either does not exist or is not a function: pauseTransformFeedback] [WebGL test #56: Property either does not exist or is not a function: getUniformBlockIndex]
expected: FAIL expected: FAIL
[WebGL test #49: Property either does not exist or is not a function: transformFeedbackVaryings] [WebGL test #7: Property either does not exist or is not a function: renderbufferStorageMultisample]
expected: FAIL expected: FAIL
[WebGL test #2: Property either does not exist or is not a function: copyBufferSubData] [WebGL test #10: Property either does not exist or is not a function: texStorage3D]
expected: FAIL expected: FAIL
[WebGL test #23: Property either does not exist or is not a function: uniform2uiv] [WebGL test #21: Property either does not exist or is not a function: uniform2uiv]
expected: FAIL expected: FAIL
[WebGL test #55: Property either does not exist or is not a function: getIndexedParameter] [WebGL test #46: Property either does not exist or is not a function: endTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #31: Property either does not exist or is not a function: uniformMatrix4x3fv] [WebGL test #1: Property either does not exist or is not a function: blitFramebuffer]
expected: FAIL expected: FAIL
[WebGL test #36: Property either does not exist or is not a function: vertexAttribIPointer] [WebGL test #55: Property either does not exist or is not a function: getActiveUniforms]
expected: FAIL expected: FAIL
[WebGL test #8: Property either does not exist or is not a function: readBuffer] [WebGL test #11: Property either does not exist or is not a function: texSubImage3D]
expected: FAIL expected: FAIL
[WebGL test #35: Property either does not exist or is not a function: vertexAttribI4uiv] [WebGL test #48: Property either does not exist or is not a function: getTransformFeedbackVarying]
expected: FAIL expected: FAIL
[WebGL test #5: Property either does not exist or is not a function: getInternalformatParameter] [WebGL test #40: Property either does not exist or is not a function: clearBufferfi]
expected: FAIL expected: FAIL
[WebGL test #60: Property either does not exist or is not a function: getActiveUniformBlockName] [WebGL test #44: Property either does not exist or is not a function: bindTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #47: Property either does not exist or is not a function: beginTransformFeedback] [WebGL test #50: Property either does not exist or is not a function: resumeTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #32: Property either does not exist or is not a function: vertexAttribI4i] [WebGL test #25: Property either does not exist or is not a function: uniformMatrix3x2fv]
expected: FAIL expected: FAIL
[WebGL test #43: Property either does not exist or is not a function: createTransformFeedback] [WebGL test #3: Property either does not exist or is not a function: getInternalformatParameter]
expected: FAIL expected: FAIL
[WebGL test #59: Property either does not exist or is not a function: getActiveUniformBlockParameter] [WebGL test #57: Property either does not exist or is not a function: getActiveUniformBlockParameter]
expected: FAIL expected: FAIL
[WebGL test #41: Property either does not exist or is not a function: clearBufferfv] [WebGL test #53: Property either does not exist or is not a function: getIndexedParameter]
expected: FAIL expected: FAIL
[WebGL test #17: Property either does not exist or is not a function: getFragDataLocation] [WebGL test #61: Property either does not exist or is not a function: deleteVertexArray]
expected: FAIL expected: FAIL
[WebGL test #15: Property either does not exist or is not a function: compressedTexImage3D] [WebGL test #13: Property either does not exist or is not a function: compressedTexImage3D]
expected: FAIL expected: FAIL
[WebGL test #65: Property either does not exist or is not a function: bindVertexArray] [WebGL test #51: Property either does not exist or is not a function: bindBufferBase]
expected: FAIL expected: FAIL
[WebGL test #34: Property either does not exist or is not a function: vertexAttribI4ui] [WebGL test #54: Property either does not exist or is not a function: getUniformIndices]
expected: FAIL expected: FAIL
[WebGL test #6: Property either does not exist or is not a function: invalidateFramebuffer] [WebGL test #27: Property either does not exist or is not a function: uniformMatrix4x2fv]
expected: FAIL expected: FAIL
[WebGL test #62: Property either does not exist or is not a function: createVertexArray] [WebGL test #34: Property either does not exist or is not a function: vertexAttribIPointer]
expected: FAIL expected: FAIL
[WebGL test #42: Property either does not exist or is not a function: clearBufferfi] [WebGL test #16: Property either does not exist or is not a function: uniform1ui]
expected: FAIL expected: FAIL
[WebGL test #24: Property either does not exist or is not a function: uniform3uiv] [WebGL test #12: Property either does not exist or is not a function: copyTexSubImage3D]
expected: FAIL expected: FAIL
[WebGL test #37: Property either does not exist or is not a function: drawRangeElements] [WebGL test #52: Property either does not exist or is not a function: bindBufferRange]
expected: FAIL expected: FAIL
[WebGL test #39: Property either does not exist or is not a function: clearBufferiv] [WebGL test #8: Property either does not exist or is not a function: texImage3D]
expected: FAIL expected: FAIL
[WebGL test #58: Property either does not exist or is not a function: getUniformBlockIndex] [WebGL test #18: Property either does not exist or is not a function: uniform3ui]
expected: FAIL expected: FAIL
[WebGL test #56: Property either does not exist or is not a function: getUniformIndices] [WebGL test #41: Property either does not exist or is not a function: createTransformFeedback]
expected: FAIL
[WebGL test #16: Property either does not exist or is not a function: compressedTexSubImage3D]
expected: FAIL
[WebGL test #38: Property either does not exist or is not a function: drawBuffers]
expected: FAIL
[WebGL test #54: Property either does not exist or is not a function: bindBufferRange]
expected: FAIL expected: FAIL
[WebGL test #0: Property either does not exist or is not a function: isContextLost] [WebGL test #0: Property either does not exist or is not a function: isContextLost]
expected: FAIL expected: FAIL
[WebGL test #9: Property either does not exist or is not a function: renderbufferStorageMultisample] [WebGL test #36: Property either does not exist or is not a function: drawBuffers]
expected: FAIL expected: FAIL
[WebGL test #45: Property either does not exist or is not a function: isTransformFeedback] [WebGL test #19: Property either does not exist or is not a function: uniform4ui]
expected: FAIL expected: FAIL
[WebGL test #18: Property either does not exist or is not a function: uniform1ui] [WebGL test #47: Property either does not exist or is not a function: transformFeedbackVaryings]
expected: FAIL expected: FAIL
[WebGL test #7: Property either does not exist or is not a function: invalidateSubFramebuffer] [WebGL test #24: Property either does not exist or is not a function: uniformMatrix2x3fv]
expected: FAIL expected: FAIL
[WebGL test #40: Property either does not exist or is not a function: clearBufferuiv] [WebGL test #9: Property either does not exist or is not a function: texStorage2D]
expected: FAIL expected: FAIL
[WebGL test #64: Property either does not exist or is not a function: isVertexArray] [WebGL test #29: Property either does not exist or is not a function: uniformMatrix4x3fv]
expected: FAIL expected: FAIL
[WebGL test #21: Property either does not exist or is not a function: uniform4ui] [WebGL test #17: Property either does not exist or is not a function: uniform2ui]
expected: FAIL expected: FAIL
[WebGL test #11: Property either does not exist or is not a function: texStorage2D] [WebGL test #43: Property either does not exist or is not a function: isTransformFeedback]
expected: FAIL expected: FAIL
[WebGL test #19: Property either does not exist or is not a function: uniform2ui] [WebGL test #59: Property either does not exist or is not a function: uniformBlockBinding]
expected: FAIL expected: FAIL
[WebGL test #26: Property either does not exist or is not a function: uniformMatrix2x3fv] [WebGL test #31: Property either does not exist or is not a function: vertexAttribI4iv]
expected: FAIL expected: FAIL
[WebGL test #52: Property either does not exist or is not a function: resumeTransformFeedback] [WebGL test #6: Property either does not exist or is not a function: readBuffer]
expected: FAIL expected: FAIL
[WebGL test #29: Property either does not exist or is not a function: uniformMatrix4x2fv] [WebGL test #38: Property either does not exist or is not a function: clearBufferuiv]
expected: FAIL expected: FAIL
[WebGL test #57: Property either does not exist or is not a function: getActiveUniforms] [WebGL test #23: Property either does not exist or is not a function: uniform4uiv]
expected: FAIL expected: FAIL
[WebGL test #20: Property either does not exist or is not a function: uniform3ui] [WebGL test #39: Property either does not exist or is not a function: clearBufferfv]
expected: FAIL expected: FAIL
[WebGL test #22: Property either does not exist or is not a function: uniform1uiv] [WebGL test #35: Property either does not exist or is not a function: drawRangeElements]
expected: FAIL expected: FAIL
[WebGL test #4: Property either does not exist or is not a function: framebufferTextureLayer] [WebGL test #22: Property either does not exist or is not a function: uniform3uiv]
expected: FAIL expected: FAIL
[WebGL test #61: Property either does not exist or is not a function: uniformBlockBinding] [WebGL test #5: Property either does not exist or is not a function: invalidateSubFramebuffer]
expected: FAIL expected: FAIL
[WebGL test #50: Property either does not exist or is not a function: getTransformFeedbackVarying] [WebGL test #26: Property either does not exist or is not a function: uniformMatrix2x4fv]
expected: FAIL expected: FAIL
[WebGL test #12: Property either does not exist or is not a function: texStorage3D] [WebGL test #14: Property either does not exist or is not a function: compressedTexSubImage3D]
expected: FAIL expected: FAIL
[WebGL test #63: Property either does not exist or is not a function: deleteVertexArray] [WebGL test #62: Property either does not exist or is not a function: isVertexArray]
expected: FAIL expected: FAIL
[WebGL test #10: Property either does not exist or is not a function: texImage3D] [WebGL test #37: Property either does not exist or is not a function: clearBufferiv]
expected: FAIL expected: FAIL
[WebGL test #13: Property either does not exist or is not a function: texSubImage3D] [WebGL test #20: Property either does not exist or is not a function: uniform1uiv]
expected: FAIL
[WebGL test #42: Property either does not exist or is not a function: deleteTransformFeedback]
expected: FAIL expected: FAIL

View file

@ -1,5 +1,5 @@
[read-pixels-into-pixel-pack-buffer.html] [read-pixels-into-pixel-pack-buffer.html]
expected: ERROR expected: CRASH
[WebGL test #1: getError expected: INVALID_OPERATION. Was INVALID_ENUM : should generate INVALID_OPERATION if pixel pack buffer is bound] [WebGL test #1: getError expected: INVALID_OPERATION. Was INVALID_ENUM : should generate INVALID_OPERATION if pixel pack buffer is bound]
expected: FAIL expected: FAIL

View file

@ -1,5 +1,10 @@
[out-of-bounds-index-buffers-after-copying.html] [out-of-bounds-index-buffers-after-copying.html]
expected: ERROR
[WebGL test #4: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] [WebGL test #4: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
expected: FAIL expected: FAIL
[WebGL test #9: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,255,255]
expected: FAIL
[WebGL test #6: should be 0,255,0,255\nat (0, 0) expected: 0,255,0,255 was 0,0,255,255]
expected: FAIL