diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index d6452a88043e..1c458778a1cf 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -56,6 +56,24 @@ use std::cell::Cell; use std::cmp; use std::ptr::{self, NonNull}; +#[unrooted_must_root_lint::must_root] +#[derive(JSTraceable, MallocSizeOf)] +struct IndexedBinding { + buffer: MutNullableDom, + start: Cell, + size: Cell, +} + +impl IndexedBinding { + fn new() -> IndexedBinding { + IndexedBinding { + buffer: MutNullableDom::new(None), + start: Cell::new(0), + size: Cell::new(0), + } + } +} + #[dom_struct] pub struct WebGL2RenderingContext { reflector_: Reflector, @@ -69,6 +87,8 @@ pub struct WebGL2RenderingContext { bound_pixel_unpack_buffer: MutNullableDom, bound_transform_feedback_buffer: MutNullableDom, bound_uniform_buffer: MutNullableDom, + indexed_uniform_buffer_bindings: Box<[IndexedBinding]>, + indexed_transform_feedback_buffer_bindings: Box<[IndexedBinding]>, current_transform_feedback: MutNullableDom, texture_pack_row_length: Cell, texture_pack_skip_pixels: Cell, @@ -111,6 +131,15 @@ impl WebGL2RenderingContext { .map(|_| Default::default()) .collect::>() .into(); + let indexed_uniform_buffer_bindings = (0..base.limits().max_uniform_buffer_bindings) + .map(|_| IndexedBinding::new()) + .collect::>() + .into(); + let indexed_transform_feedback_buffer_bindings = + (0..base.limits().max_transform_feedback_separate_attribs) + .map(|_| IndexedBinding::new()) + .collect::>() + .into(); Some(WebGL2RenderingContext { reflector_: Reflector::new(), @@ -124,6 +153,8 @@ impl WebGL2RenderingContext { bound_pixel_unpack_buffer: MutNullableDom::new(None), bound_transform_feedback_buffer: MutNullableDom::new(None), bound_uniform_buffer: MutNullableDom::new(None), + indexed_uniform_buffer_bindings, + indexed_transform_feedback_buffer_bindings, current_transform_feedback: MutNullableDom::new(None), texture_pack_row_length: Cell::new(0), texture_pack_skip_pixels: Cell::new(0), @@ -1396,6 +1427,14 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { 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); + + for binding in self.indexed_uniform_buffer_bindings.iter() { + self.unbind_from(&binding.buffer, &buffer); + } + for binding in self.indexed_transform_feedback_buffer_bindings.iter() { + self.unbind_from(&binding.buffer, &buffer); + } + buffer.mark_for_deletion(false); } @@ -1520,6 +1559,46 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { .GetShaderPrecisionFormat(shader_type, precision_type) } + /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.2 + #[allow(unsafe_code)] + fn GetIndexedParameter(&self, cx: JSContext, target: u32, index: u32) -> JSVal { + let bindings = match target { + constants::TRANSFORM_FEEDBACK_BUFFER_BINDING | + constants::TRANSFORM_FEEDBACK_BUFFER_SIZE | + constants::TRANSFORM_FEEDBACK_BUFFER_START => { + &self.indexed_transform_feedback_buffer_bindings + }, + constants::UNIFORM_BUFFER_BINDING | + constants::UNIFORM_BUFFER_SIZE | + constants::UNIFORM_BUFFER_START => &self.indexed_uniform_buffer_bindings, + _ => { + self.base.webgl_error(InvalidEnum); + return NullValue(); + }, + }; + + let binding = match bindings.get(index as usize) { + Some(binding) => binding, + None => { + self.base.webgl_error(InvalidValue); + return NullValue(); + }, + }; + + match target { + constants::TRANSFORM_FEEDBACK_BUFFER_BINDING | constants::UNIFORM_BUFFER_BINDING => unsafe { + optional_root_object_to_js_or_null!(*cx, binding.buffer.get()) + }, + constants::TRANSFORM_FEEDBACK_BUFFER_START | constants::UNIFORM_BUFFER_START => { + Int32Value(binding.start.get() as _) + }, + constants::TRANSFORM_FEEDBACK_BUFFER_SIZE | constants::UNIFORM_BUFFER_SIZE => { + Int32Value(binding.size.get() as _) + }, + _ => unreachable!(), + } + } + /// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn GetUniformLocation( &self, @@ -3212,20 +3291,21 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16 fn BindBufferBase(&self, target: u32, index: u32, buffer: Option<&WebGLBuffer>) { - let (bind_limit, slot) = match target { + let (generic_slot, indexed_bindings) = match target { constants::TRANSFORM_FEEDBACK_BUFFER => ( - self.base.limits().max_transform_feedback_separate_attribs, &self.bound_transform_feedback_buffer, + &self.indexed_transform_feedback_buffer_bindings, ), constants::UNIFORM_BUFFER => ( - self.base.limits().max_uniform_buffer_bindings, &self.bound_uniform_buffer, + &self.indexed_uniform_buffer_bindings, ), _ => return self.base.webgl_error(InvalidEnum), }; - if index >= bind_limit { - return self.base.webgl_error(InvalidValue); - } + let indexed_binding = match indexed_bindings.get(index as usize) { + Some(slot) => slot, + None => return self.base.webgl_error(InvalidValue), + }; if let Some(buffer) = buffer { handle_potential_webgl_error!(self.base, self.base.validate_ownership(buffer), return); @@ -3234,6 +3314,9 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { return self.base.webgl_error(InvalidOperation); } handle_potential_webgl_error!(self.base, buffer.set_target_maybe(target), return); + + // for both the generic and the indexed bindings + buffer.increment_attached_counter(); buffer.increment_attached_counter(); } @@ -3242,11 +3325,15 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { index, buffer.map(|b| b.id()), )); - if let Some(old) = slot.get() { - old.decrement_attached_counter(); - } - slot.set(buffer); + for slot in &[&generic_slot, &indexed_binding.buffer] { + if let Some(old) = slot.get() { + old.decrement_attached_counter(); + } + slot.set(buffer); + } + indexed_binding.start.set(0); + indexed_binding.size.set(0); } /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16 @@ -3258,20 +3345,21 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { offset: i64, size: i64, ) { - let (bind_limit, slot) = match target { + let (generic_slot, indexed_bindings) = match target { constants::TRANSFORM_FEEDBACK_BUFFER => ( - self.base.limits().max_transform_feedback_separate_attribs, &self.bound_transform_feedback_buffer, + &self.indexed_transform_feedback_buffer_bindings, ), constants::UNIFORM_BUFFER => ( - self.base.limits().max_uniform_buffer_bindings, &self.bound_uniform_buffer, + &self.indexed_uniform_buffer_bindings, ), _ => return self.base.webgl_error(InvalidEnum), }; - if index >= bind_limit { - return self.base.webgl_error(InvalidValue); - } + let indexed_binding = match indexed_bindings.get(index as usize) { + Some(slot) => slot, + None => return self.base.webgl_error(InvalidValue), + }; if offset < 0 || size < 0 { return self.base.webgl_error(InvalidValue); @@ -3302,6 +3390,9 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { return self.base.webgl_error(InvalidOperation); } handle_potential_webgl_error!(self.base, buffer.set_target_maybe(target), return); + + // for both the generic and the indexed bindings + buffer.increment_attached_counter(); buffer.increment_attached_counter(); } @@ -3312,11 +3403,15 @@ impl WebGL2RenderingContextMethods for WebGL2RenderingContext { offset, size, )); - if let Some(old) = slot.get() { - old.decrement_attached_counter(); - } - slot.set(buffer); + for slot in &[&generic_slot, &indexed_binding.buffer] { + if let Some(old) = slot.get() { + old.decrement_attached_counter(); + } + slot.set(buffer); + } + indexed_binding.start.set(offset); + indexed_binding.size.set(size); } /// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.16 diff --git a/components/script/dom/webidls/WebGL2RenderingContext.webidl b/components/script/dom/webidls/WebGL2RenderingContext.webidl index 157fe38f8928..e25174b858d0 100644 --- a/components/script/dom/webidls/WebGL2RenderingContext.webidl +++ b/components/script/dom/webidls/WebGL2RenderingContext.webidl @@ -531,7 +531,7 @@ interface mixin WebGL2RenderingContextBase /* Uniform Buffer Objects and Transform Feedback Buffers */ void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer); void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size); - // any getIndexedParameter(GLenum target, GLuint index); + any getIndexedParameter(GLenum target, GLuint index); sequence? getUniformIndices(WebGLProgram program, sequence uniformNames); any getActiveUniforms(WebGLProgram program, sequence uniformIndices, GLenum pname); GLuint getUniformBlockIndex(WebGLProgram program, DOMString uniformBlockName); diff --git a/tests/wpt/webgl/meta/conformance2/buffers/bound-buffer-size-change-test.html.ini b/tests/wpt/webgl/meta/conformance2/buffers/bound-buffer-size-change-test.html.ini deleted file mode 100644 index 0febcc38adcf..000000000000 --- a/tests/wpt/webgl/meta/conformance2/buffers/bound-buffer-size-change-test.html.ini +++ /dev/null @@ -1,91 +0,0 @@ -[bound-buffer-size-change-test.html] - [WebGL test #38: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #23: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #4: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #28: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #22: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #33: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #16: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #7: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #35: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #37: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #39: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #21: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #40: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #15: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #25: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0) should be 4. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #32: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #14: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #11: gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #36: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 12. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #3: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #5: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #6: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #24: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #34: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 16. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #26: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #2: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #20: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be [object WebGLBuffer\]. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #27: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0) should be 8. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #12: gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - - [WebGL test #13: gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1) should be 0. Threw exception TypeError: gl.getIndexedParameter is not a function] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/buffers/buffer-overflow-test.html.ini b/tests/wpt/webgl/meta/conformance2/buffers/buffer-overflow-test.html.ini deleted file mode 100644 index c2b184185d2f..000000000000 --- a/tests/wpt/webgl/meta/conformance2/buffers/buffer-overflow-test.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[buffer-overflow-test.html] - expected: ERROR - [WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL - diff --git a/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini b/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini index 9dcb07e7e09c..0aa68bae88ab 100644 --- a/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini +++ b/tests/wpt/webgl/meta/conformance2/context/methods-2.html.ini @@ -1,7 +1,4 @@ [methods-2.html] - [WebGL test #19: Property either does not exist or is not a function: getIndexedParameter] - expected: FAIL - [WebGL test #11: Property either does not exist or is not a function: compressedTexSubImage3D] expected: FAIL @@ -14,22 +11,31 @@ [WebGL test #18: Property either does not exist or is not a function: drawBuffers] expected: FAIL + [WebGL test #22: Property either does not exist or is not a function: bindVertexArray] + expected: FAIL + [WebGL test #12: Property either does not exist or is not a function: vertexAttribI4i] expected: FAIL + [WebGL test #19: Property either does not exist or is not a function: createVertexArray] + expected: FAIL + [WebGL test #6: Property either does not exist or is not a function: texStorage2D] expected: FAIL [WebGL test #1: Property either does not exist or is not a function: blitFramebuffer] expected: FAIL - [WebGL test #5: Property either does not exist or is not a function: texImage3D] + [WebGL test #21: Property either does not exist or is not a function: isVertexArray] expected: FAIL - [WebGL test #17: Property either does not exist or is not a function: drawRangeElements] + [WebGL test #20: Property either does not exist or is not a function: deleteVertexArray] + expected: FAIL + + [WebGL test #5: Property either does not exist or is not a function: texImage3D] expected: FAIL - [WebGL test #21: Property either does not exist or is not a function: deleteVertexArray] + [WebGL test #17: Property either does not exist or is not a function: drawRangeElements] expected: FAIL [WebGL test #10: Property either does not exist or is not a function: compressedTexImage3D] @@ -38,9 +44,6 @@ [WebGL test #7: Property either does not exist or is not a function: texStorage3D] expected: FAIL - [WebGL test #22: Property either does not exist or is not a function: isVertexArray] - expected: FAIL - [WebGL test #4: Property either does not exist or is not a function: renderbufferStorageMultisample] expected: FAIL @@ -50,12 +53,6 @@ [WebGL test #0: Property either does not exist or is not a function: isContextLost] expected: FAIL - [WebGL test #20: Property either does not exist or is not a function: createVertexArray] - expected: FAIL - - [WebGL test #23: Property either does not exist or is not a function: bindVertexArray] - expected: FAIL - [WebGL test #16: Property either does not exist or is not a function: vertexAttribIPointer] expected: FAIL diff --git a/tests/wpt/webgl/meta/conformance2/transform_feedback/switching-objects.html.ini b/tests/wpt/webgl/meta/conformance2/transform_feedback/switching-objects.html.ini index d5162d0640bb..d152e655e96b 100644 --- a/tests/wpt/webgl/meta/conformance2/transform_feedback/switching-objects.html.ini +++ b/tests/wpt/webgl/meta/conformance2/transform_feedback/switching-objects.html.ini @@ -1,11 +1,67 @@ [switching-objects.html] - expected: ERROR [WebGL test #6: buffer should match expected values] expected: FAIL + [WebGL test #23: getError expected: NO_ERROR. Was INVALID_OPERATION : begin on tf1] + expected: FAIL + + [WebGL test #41: getError expected: NO_ERROR. Was INVALID_OPERATION : end while paused] + expected: FAIL + + [WebGL test #26: getError expected: NO_ERROR. Was INVALID_OPERATION : end on tf1] + expected: FAIL + + [WebGL test #33: getError expected: INVALID_OPERATION. Was NO_ERROR : wrong primitive mode] + expected: FAIL + + [WebGL test #14: getError expected: NO_ERROR. Was INVALID_OPERATION : begin] + expected: FAIL + + [WebGL test #27: buffer should match expected values] + expected: FAIL + + [WebGL test #22: getError expected: NO_ERROR. Was INVALID_OPERATION : bind while paused] + expected: FAIL + + [WebGL test #34: getError expected: INVALID_OPERATION. Was NO_ERROR : switch program while active] + expected: FAIL + [WebGL test #3: getError expected: NO_ERROR. Was INVALID_OPERATION : begin TF] expected: FAIL + [WebGL test #17: TRANSFORM_FEEDBACK_BINDING was [object WebGLTransformFeedback\], but expected [object WebGLTransformFeedback\]] + expected: FAIL + + [WebGL test #39: getError expected: NO_ERROR. Was INVALID_OPERATION : pause] + expected: FAIL + + [WebGL test #16: getError expected: INVALID_OPERATION. Was NO_ERROR : bind while unpaused] + expected: FAIL + + [WebGL test #28: getError expected: NO_ERROR. Was INVALID_OPERATION : end on tf2] + expected: FAIL + + [WebGL test #36: getError expected: INVALID_OPERATION. Was NO_ERROR : bindTransformFeedback when active] + expected: FAIL + + [WebGL test #9: TRANSFORM_FEEDBACK_BUFFER_BINDING[0\] was [object WebGLBuffer\], but expected [object WebGLBuffer\]] + expected: FAIL + + [WebGL test #20: getError expected: NO_ERROR. Was INVALID_OPERATION : begin on tf2] + expected: FAIL + + [WebGL test #19: buffer should match expected values] + expected: FAIL + + [WebGL test #32: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should begin successfully] + expected: FAIL + + [WebGL test #18: getError expected: NO_ERROR. Was INVALID_OPERATION : transform feedback should complete successfully] + expected: FAIL + [WebGL test #5: getError expected: NO_ERROR. Was INVALID_OPERATION : end TF] expected: FAIL + [WebGL test #38: getError expected: INVALID_OPERATION. Was NO_ERROR : bindBufferBase(TRANSFORM_FEEDBACK_BUFFER) when active] + expected: FAIL + diff --git a/tests/wpt/webgl/meta/conformance2/transform_feedback/transform_feedback.html.ini b/tests/wpt/webgl/meta/conformance2/transform_feedback/transform_feedback.html.ini index 3981f74f97ee..f534e670f1f6 100644 --- a/tests/wpt/webgl/meta/conformance2/transform_feedback/transform_feedback.html.ini +++ b/tests/wpt/webgl/meta/conformance2/transform_feedback/transform_feedback.html.ini @@ -2,10 +2,10 @@ [WebGL test #31: buffer should match expected values] expected: FAIL - [WebGL test #25: buffer should match expected values] + [WebGL test #11: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be null. Was [object WebGLBuffer\].] expected: FAIL - [WebGL test #11: gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0) should be null. Threw exception TypeError: gl.getIndexedParameter is not a function] + [WebGL test #25: buffer should match expected values] expected: FAIL [WebGL test #32: buffer should match expected values]