aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/document.rs2
-rw-r--r--components/script/dom/webglrenderingcontext.rs327
-rw-r--r--components/script/dom/webgltexture.rs16
-rw-r--r--components/script/dom/webidls/WebGLRenderingContext.webidl14
4 files changed, 255 insertions, 104 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 2aebe049d21..1962e462282 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -1055,7 +1055,7 @@ impl Document {
key: Key,
state: KeyState,
modifiers: KeyModifiers,
- compositor: &mut IpcSender<ScriptToCompositorMsg>) {
+ compositor: &IpcSender<ScriptToCompositorMsg>) {
let focused = self.get_focused_element();
let body = self.GetBody();
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 241aa0aa60e..29669c9ff15 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -234,70 +234,32 @@ 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<Root<WebGLTexture>> {
+ 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()
},
- };
-
- // 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;
+ _ => None,
}
+ }
- // GL_INVALID_ENUM is generated if data_type is not an accepted value.
- match data_type {
- constants::UNSIGNED_BYTE |
- constants::UNSIGNED_SHORT_4_4_4_4 |
- constants::UNSIGNED_SHORT_5_5_5_1 |
- constants::UNSIGNED_SHORT_5_6_5 => {},
- _ => {
- self.webgl_error(InvalidEnum);
- return false;
- },
- }
-
-
- // 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);
- return false;
+ fn face_index_for_target(&self, target: u32) -> Option<u8> {
+ 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 {
@@ -306,39 +268,51 @@ impl WebGLRenderingContext {
constants::RGB |
constants::RGBA |
constants::LUMINANCE |
- constants::LUMINANCE_ALPHA => {},
+ constants::LUMINANCE_ALPHA => true,
_ => {
self.webgl_error(InvalidValue);
- return false;
+ false
},
}
+ }
- // GL_INVALID_OPERATION is generated if format does not
- // match internal_format.
- if format != internal_format {
- self.webgl_error(InvalidOperation);
+
+ 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;
}
- // 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);
+ // GL_INVALID_ENUM is generated if data_type is not an accepted value.
+ match data_type {
+ constants::UNSIGNED_BYTE |
+ constants::UNSIGNED_SHORT_4_4_4_4 |
+ constants::UNSIGNED_SHORT_5_5_5_1 |
+ constants::UNSIGNED_SHORT_5_6_5 => {},
+ _ => {
+ self.webgl_error(InvalidEnum);
+ return false;
+ },
+ }
+
+ // Validate internal_format
+ if !self.validate_tex_internal_format(internal_format) {
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);
+ // GL_INVALID_OPERATION is generated if format does not
+ // match internal_format.
+ if format != internal_format {
+ self.webgl_error(InvalidOperation);
return false;
}
@@ -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<u8>) { // 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();
@@ -1306,6 +1438,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
}
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
+ fn SampleCoverage(&self, value: f32, invert: bool) {
+ self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::SampleCoverage(value, invert))).unwrap();
+ }
+
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4
fn Scissor(&self, x: i32, y: i32, width: i32, height: i32) {
self.ipc_renderer
@@ -1738,13 +1875,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 +2020,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<u32> {
+ 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..b534c2aeb61 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();
@@ -619,7 +621,7 @@ interface WebGLRenderingContextBase
//void renderbufferStorage(GLenum target, GLenum internalformat,
// GLsizei width, GLsizei height);
- //void sampleCoverage(GLclampf value, GLboolean invert);
+ void sampleCoverage(GLclampf value, GLboolean invert);
void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
void shaderSource(WebGLShader? shader, DOMString source);