From 867cd9be293d18c3d1ddedd7e6ae886f04da1b0e Mon Sep 17 00:00:00 2001 From: Daniel Robertson Date: Sat, 21 May 2016 10:50:47 -0400 Subject: [PATCH] Impl copyTexImage2D and copyTexSubImage2D Implement copyTexImage2D and copyTexSubImage2D for WebGLRenderingContext. --- .../script/dom/webglrenderingcontext.rs | 324 ++++++++++++------ components/script/dom/webgltexture.rs | 16 +- .../dom/webidls/WebGLRenderingContext.webidl | 12 +- .../more/functions/copyTexImage2D.html.ini | 5 - .../functions/copyTexImage2DBadArgs.html.ini | 5 - .../more/functions/copyTexSubImage2D.html.ini | 5 - .../copyTexSubImage2DBadArgs.html.ini | 5 - .../copy-tex-image-2d-formats.html.ini | 13 +- .../textures/texture-npot.html.ini | 111 +++++- 9 files changed, 365 insertions(+), 131 deletions(-) delete mode 100644 tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2D.html.ini delete mode 100644 tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2DBadArgs.html.ini delete mode 100644 tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2D.html.ini delete mode 100644 tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2DBadArgs.html.ini diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 241aa0aa60e..854095495a1 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -234,39 +234,61 @@ impl WebGLRenderingContext { true } - fn validate_tex_image_parameters(&self, - target: u32, - level: i32, - internal_format: u32, - width: i32, - height: i32, - border: i32, - format: u32, - data_type: u32) -> bool { - // GL_INVALID_ENUM is generated if target is not GL_TEXTURE_2D, - // GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - // GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - // GL_TEXTURE_CUBE_MAP_POSITIVE_Z, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z. - let texture = match target { - constants::TEXTURE_2D - => self.bound_texture_2d.get(), - constants::TEXTURE_CUBE_MAP_POSITIVE_X | - constants::TEXTURE_CUBE_MAP_NEGATIVE_X | - constants::TEXTURE_CUBE_MAP_POSITIVE_Y | - constants::TEXTURE_CUBE_MAP_NEGATIVE_Y | - constants::TEXTURE_CUBE_MAP_POSITIVE_Z | - constants::TEXTURE_CUBE_MAP_NEGATIVE_Z - => self.bound_texture_cube_map.get(), - _ => { - self.webgl_error(InvalidEnum); - return false; + fn texture_for_target(&self, target: u32) -> Option> { + match target { + constants::TEXTURE_2D => self.bound_texture_2d.get(), + constants::TEXTURE_CUBE_MAP_POSITIVE_X | constants::TEXTURE_CUBE_MAP_NEGATIVE_X | + constants::TEXTURE_CUBE_MAP_POSITIVE_Y | constants::TEXTURE_CUBE_MAP_NEGATIVE_Y | + constants::TEXTURE_CUBE_MAP_POSITIVE_Z | constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => { + self.bound_texture_cube_map.get() }, - }; + _ => None, + } + } - // If an attempt is made to call this function with no - // WebGLTexture bound, an INVALID_OPERATION error is generated. - if texture.is_none() { - self.webgl_error(InvalidOperation); + fn face_index_for_target(&self, target: u32) -> Option { + match target { + constants::TEXTURE_2D => Some(0), + constants::TEXTURE_CUBE_MAP_POSITIVE_X => Some(0), + constants::TEXTURE_CUBE_MAP_NEGATIVE_X => Some(1), + constants::TEXTURE_CUBE_MAP_POSITIVE_Y => Some(2), + constants::TEXTURE_CUBE_MAP_NEGATIVE_Y => Some(3), + constants::TEXTURE_CUBE_MAP_POSITIVE_Z => Some(4), + constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => Some(5), + _ => None + } + } + + fn validate_tex_internal_format(&self, internal_format: u32) -> bool { + // GL_INVALID_VALUE is generated if internal_format is not an + // accepted format. + match internal_format { + constants::DEPTH_COMPONENT | + constants::ALPHA | + constants::RGB | + constants::RGBA | + constants::LUMINANCE | + constants::LUMINANCE_ALPHA => true, + + _ => { + self.webgl_error(InvalidValue); + false + }, + } + } + + + fn validate_tex_image_2d_parameters(&self, + target: u32, + level: i32, + internal_format: u32, + width: i32, + height: i32, + border: i32, + format: u32, + data_type: u32) -> bool { + // Validate common tex image parameters + if !self.validate_common_tex_image_parameters(target, level, width, height) { return false; } @@ -282,38 +304,11 @@ impl WebGLRenderingContext { }, } - - // TODO(emilio): GL_INVALID_VALUE may be generated if - // level is greater than log_2(max), where max is - // the returned value of GL_MAX_TEXTURE_SIZE when - // target is GL_TEXTURE_2D or GL_MAX_CUBE_MAP_TEXTURE_SIZE - // when target is not GL_TEXTURE_2D. - let is_cubic = target != constants::TEXTURE_2D; - - // GL_INVALID_VALUE is generated if target is one of the - // six cube map 2D image targets and the width and height - // parameters are not equal. - if is_cubic && width != height { - self.webgl_error(InvalidValue); + // Validate internal_format + if !self.validate_tex_internal_format(internal_format) { return false; } - // GL_INVALID_VALUE is generated if internal_format is not an - // accepted format. - match internal_format { - constants::DEPTH_COMPONENT | - constants::ALPHA | - constants::RGB | - constants::RGBA | - constants::LUMINANCE | - constants::LUMINANCE_ALPHA => {}, - - _ => { - self.webgl_error(InvalidValue); - return false; - }, - } - // GL_INVALID_OPERATION is generated if format does not // match internal_format. if format != internal_format { @@ -321,27 +316,6 @@ impl WebGLRenderingContext { return false; } - // GL_INVALID_VALUE is generated if level is less than 0. - // - // GL_INVALID_VALUE is generated if width or height is less than 0 - // or greater than GL_MAX_TEXTURE_SIZE when target is GL_TEXTURE_2D or - // GL_MAX_CUBE_MAP_TEXTURE_SIZE when target is not GL_TEXTURE_2D. - // - // TODO(emilio): Check limits - if width < 0 || height < 0 || level < 0 { - self.webgl_error(InvalidValue); - return false; - } - - // GL_INVALID_VALUE is generated if level is greater than zero and the - // texture is not power of two. - if level > 0 && - (!(width as u32).is_power_of_two() || - !(height as u32).is_power_of_two()) { - self.webgl_error(InvalidValue); - return false; - } - // GL_INVALID_VALUE is generated if border is not 0. if border != 0 { self.webgl_error(InvalidValue); @@ -369,6 +343,82 @@ impl WebGLRenderingContext { true } + fn validate_common_tex_image_parameters(&self, + target: u32, + level: i32, + width: i32, + height: i32) -> bool { + // GL_INVALID_ENUM is generated if target is not GL_TEXTURE_2D, + // GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + // GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + // GL_TEXTURE_CUBE_MAP_POSITIVE_Z, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z. + // + // max_size is GL_MAX_TEXTURE_SIZE when target is GL_TEXTURE_2D or + // GL_MAX_CUBE_MAP_TEXTURE_SIZE when target is not GL_TEXTURE_2D. + let (texture, max) = match target { + constants::TEXTURE_2D + => (self.bound_texture_2d.get(), self.limits.max_tex_size), + constants::TEXTURE_CUBE_MAP_POSITIVE_X | + constants::TEXTURE_CUBE_MAP_NEGATIVE_X | + constants::TEXTURE_CUBE_MAP_POSITIVE_Y | + constants::TEXTURE_CUBE_MAP_NEGATIVE_Y | + constants::TEXTURE_CUBE_MAP_POSITIVE_Z | + constants::TEXTURE_CUBE_MAP_NEGATIVE_Z + => (self.bound_texture_cube_map.get(), self.limits.max_cube_map_tex_size), + _ => { + self.webgl_error(InvalidEnum); + return false; + }, + }; + + // If an attempt is made to call this function with no + // WebGLTexture bound, an INVALID_OPERATION error is generated. + if texture.is_none() { + self.webgl_error(InvalidOperation); + return false; + } + + let is_cubic = target != constants::TEXTURE_2D; + + // GL_INVALID_VALUE is generated if target is one of the + // six cube map 2D image targets and the width and height + // parameters are not equal. + if is_cubic && width != height { + self.webgl_error(InvalidValue); + return false; + } + + // GL_INVALID_VALUE is generated if level is less than 0. + // + // GL_INVALID_VALUE is generated if width or height is less than 0 + if width < 0 || height < 0 || level < 0 || + width as u32 > max || height as u32 > max { + self.webgl_error(InvalidValue); + return false; + } + + // GL_INVALID_VALUE may be generated if + // level is greater than log_2(max), where max is + // the returned value of GL_MAX_TEXTURE_SIZE when + // target is GL_TEXTURE_2D or GL_MAX_CUBE_MAP_TEXTURE_SIZE + // when target is not GL_TEXTURE_2D. + if level > (max as f32).log2() as i32 { + self.webgl_error(InvalidValue); + return false; + } + + // GL_INVALID_VALUE is generated if level is greater than zero and the + // texture is not power of two. + if level > 0 && + (!(width as u32).is_power_of_two() || + !(height as u32).is_power_of_two()) { + self.webgl_error(InvalidValue); + return false; + } + + true + } + fn tex_image_2d(&self, target: u32, level: i32, @@ -380,11 +430,11 @@ impl WebGLRenderingContext { data_type: u32, pixels: Vec) { // NB: pixels should NOT be premultipied // This should be validated before reaching this function - debug_assert!(self.validate_tex_image_parameters(target, level, - internal_format, - width, height, - border, format, - data_type)); + debug_assert!(self.validate_tex_image_2d_parameters(target, level, + internal_format, + width, height, + border, format, + data_type)); let slot = match target { constants::TEXTURE_2D @@ -791,6 +841,88 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.webgl_error(InvalidEnum) } + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 + fn CopyTexImage2D(&self, target: u32, level: i32, internal_format: u32, + x: i32, y: i32, width: i32, height: i32, border: i32) { + // Validate common tex image parameters + if !self.validate_common_tex_image_parameters(target, level, width, height) || + !self.validate_tex_internal_format(internal_format) { + return; + } + + // GL_INVALID_VALUE is generated if the border is not 0 + if border != 0 { + self.webgl_error(InvalidValue); + return; + } + + let texture = self.texture_for_target(target).unwrap(); + let face_index = self.face_index_for_target(target).unwrap(); + + // We have already validated level + let image_info = texture.image_info_at_face(face_index, level as u32); + + // The color buffer components can be dropped during the conversion to the + // internal_format, but new components cannot be added + let invalid_format = match image_info.internal_format() { + Some(src_format) => match (src_format, internal_format) { + (constants::ALPHA, constants::ALPHA) | (constants::RGB, constants::RGB) | + (constants::RGB, constants::LUMINANCE) | (constants::RGBA, _) => false, + _ => true, + }, + None => false, + }; + + // GL_INVALID_OPERATION is generated if the color buffer cannot be + // converted to the internal_format + if invalid_format { + self.webgl_error(InvalidOperation); + return; + } + + // TexImage2D depth is always equal to 1 + handle_potential_webgl_error!(self, texture.initialize(target, + width as u32, + height as u32, 1, + internal_format, + level as u32)); + + let msg = WebGLCommand::CopyTexImage2D(target, level, internal_format, x, y, + width, height, border); + + self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap() + } + + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 + fn CopyTexSubImage2D(&self, target: u32, level: i32, xoffset: i32, yoffset: i32, + x: i32, y: i32, width: i32, height: i32) { + // Validate common tex image parameters + if !self.validate_common_tex_image_parameters(target, level, width, height) { + return; + } + + let texture = self.texture_for_target(target).unwrap(); + let face_index = self.face_index_for_target(target).unwrap(); + + // We have already validated level + let image_info = texture.image_info_at_face(face_index, level as u32); + + // GL_INVALID_VALUE is generated if: + // - xoffset or yoffset is less than 0 + // - x offset plus the width is greater than the texture width + // - y offset plus the height is greater than the texture height + if xoffset < 0 || ((xoffset + width) as u32) > image_info.width() || + yoffset < 0 || ((yoffset + height) as u32) > image_info.height() { + self.webgl_error(InvalidValue); + return; + } + + let msg = WebGLCommand::CopyTexSubImage2D(target, level, xoffset, yoffset, + x, y, width, height); + + self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap(); + } + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn Clear(&self, mask: u32) { self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap(); @@ -1738,13 +1870,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { format: u32, data_type: u32, data: Option<*mut JSObject>) { - if !self.validate_tex_image_parameters(target, - level, - internal_format, - width, height, - border, - format, - data_type) { + if !self.validate_tex_image_2d_parameters(target, + level, + internal_format, + width, height, + border, + format, + data_type) { return; // Error handled in validate() } @@ -1883,9 +2015,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }; // NB: Border must be zero - if !self.validate_tex_image_parameters(target, level, internal_format, - size.width, size.height, 0, - format, data_type) { + if !self.validate_tex_image_2d_parameters(target, level, internal_format, + size.width, size.height, 0, + format, data_type) { return; // Error handled in validate() } diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index df636a1db59..ccd05182968 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -309,7 +309,7 @@ impl WebGLTexture { true } - fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { + pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo { let pos = (level * self.face_count.get() as u32) + face as u32; self.image_info_array.borrow()[pos as usize] } @@ -340,7 +340,7 @@ impl Drop for WebGLTexture { } #[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)] -struct ImageInfo { +pub struct ImageInfo { width: u32, height: u32, depth: u32, @@ -359,6 +359,18 @@ impl ImageInfo { } } + pub fn width(&self) -> u32 { + self.width + } + + pub fn height(&self) -> u32 { + self.height + } + + pub fn internal_format(&self) -> Option { + self.internal_format + } + fn is_power_of_two(&self) -> bool { self.width.is_power_of_two() && self.height.is_power_of_two() && self.depth.is_power_of_two() } diff --git a/components/script/dom/webidls/WebGLRenderingContext.webidl b/components/script/dom/webidls/WebGLRenderingContext.webidl index 76ff64a1261..680c885345b 100644 --- a/components/script/dom/webidls/WebGLRenderingContext.webidl +++ b/components/script/dom/webidls/WebGLRenderingContext.webidl @@ -523,11 +523,13 @@ interface WebGLRenderingContextBase GLsizei width, GLsizei height, GLenum format, object data); - //void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, - // GLint x, GLint y, GLsizei width, GLsizei height, - // GLint border); - //void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - // GLint x, GLint y, GLsizei width, GLsizei height); + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 + void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border); + // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8 + void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height); WebGLBuffer? createBuffer(); WebGLFramebuffer? createFramebuffer(); diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2D.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2D.html.ini deleted file mode 100644 index 5ca26222fd5..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2D.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[copyTexImage2D.html] - type: testharness - [WebGL test #0: testTexImage2D] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2DBadArgs.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2DBadArgs.html.ini deleted file mode 100644 index fd18b74b943..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexImage2DBadArgs.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[copyTexImage2DBadArgs.html] - type: testharness - [WebGL test #0: testTexImage2D] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2D.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2D.html.ini deleted file mode 100644 index 0a3fd27013e..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2D.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[copyTexSubImage2D.html] - type: testharness - [WebGL test #0: testTexImage2D] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2DBadArgs.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2DBadArgs.html.ini deleted file mode 100644 index 703b8845f33..00000000000 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/more/functions/copyTexSubImage2DBadArgs.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[copyTexSubImage2DBadArgs.html] - type: testharness - [WebGL test #0: testTexImage2D] - expected: FAIL - diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/copy-tex-image-2d-formats.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/copy-tex-image-2d-formats.html.ini index e937ea51941..24c29fd6283 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/copy-tex-image-2d-formats.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/copy-tex-image-2d-formats.html.ini @@ -1,5 +1,14 @@ [copy-tex-image-2d-formats.html] - type: testharness - [WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #3: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors] + expected: FAIL + [WebGL test #6: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors] + expected: FAIL + [WebGL test #9: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors] + expected: FAIL + [WebGL test #12: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors] + expected: FAIL + [WebGL test #15: getError expected: NO_ERROR. Was INVALID_ENUM : should be no errors] + expected: FAIL + [WebGL test #16: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] expected: FAIL diff --git a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-npot.html.ini b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-npot.html.ini index 0d2a36218fb..218d01d3a14 100644 --- a/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-npot.html.ini +++ b/tests/wpt/metadata/webgl/conformance-1.0.3/conformance/textures/texture-npot.html.ini @@ -1,10 +1,5 @@ [texture-npot.html] type: testharness - [WebGL test #1: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL - - [WebGL test #4: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] - expected: FAIL [WebGL test #4: at (0, 0) expected: 0,0,0,255 was 192,0,128,64] expected: FAIL @@ -15,6 +10,110 @@ [WebGL test #7: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] expected: FAIL - [WebGL test #9: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).] + [WebGL test #9: getError expected: INVALID_VALUE. Was INVALID_ENUM : copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.] expected: FAIL + [WebGL test #12: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #14: getError expected: NO_ERROR. Was INVALID_OPERATION : gl.texImage2D with NPOT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #17: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #19: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #20: at (0, 0) expected: 192,0,128,255 was 0,0,0,255] + expected: FAIL + + [WebGL test #21: getError expected: INVALID_VALUE. Was INVALID_ENUM : copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.] + expected: FAIL + + [WebGL test #24: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #26: getError expected: NO_ERROR. Was INVALID_OPERATION : gl.texImage2D with NPOT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #29: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #31: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #32: at (0, 0) expected: 192,192,192,255 was 0,0,0,255] + expected: FAIL + + [WebGL test #33: getError expected: INVALID_VALUE. Was INVALID_ENUM : copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.] + expected: FAIL + + [WebGL test #36: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #38: getError expected: NO_ERROR. Was INVALID_OPERATION : gl.texImage2D with NPOT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #41: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #43: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #44: at (0, 0) expected: 0,0,0,64 was 0,0,0,255] + expected: FAIL + + [WebGL test #45: getError expected: INVALID_VALUE. Was INVALID_ENUM : copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.] + expected: FAIL + + [WebGL test #48: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #50: getError expected: NO_ERROR. Was INVALID_OPERATION : gl.texImage2D with NPOT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #53: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #55: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #56: at (0, 0) expected: 192,192,192,64 was 0,0,0,255] + expected: FAIL + + [WebGL test #57: getError expected: INVALID_VALUE. Was INVALID_ENUM : copyTexImage2D with NPOT texture with level > 0 should return INVALID_VALUE.] + expected: FAIL + + [WebGL test #60: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #64: at (0, 0) expected: 0,0,0,255 was 0,192,128,255] + expected: FAIL + + [WebGL test #65: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from draw.] + expected: FAIL + + [WebGL test #67: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #69: getError expected: NO_ERROR. Was INVALID_ENUM : gl.texImage2D with POT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #71: getError expected: NO_ERROR. Was INVALID_ENUM : gl.generateMipmap with POT texture should return succeed] + expected: FAIL + + [WebGL test #76: at (0, 0) expected: 0,0,0,255 was 0,192,128,255] + expected: FAIL + + [WebGL test #77: getError returned INVALID_ENUM. Possibly Chromium bug where texture unit is set to 0 instead of GL_TEXTURE0.] + expected: FAIL + + [WebGL test #79: getError expected: NO_ERROR. Was INVALID_ENUM : Should be no errors from setup.] + expected: FAIL + + [WebGL test #81: getError expected: NO_ERROR. Was INVALID_ENUM : gl.texImage2D with POT texture at level 0 should succeed] + expected: FAIL + + [WebGL test #83: getError expected: NO_ERROR. Was INVALID_ENUM : gl.generateMipmap with POT texture should return succeed] + expected: FAIL