aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/canvas/webgl_thread.rs37
-rw-r--r--components/canvas_traits/webgl.rs46
-rw-r--r--components/gfx/Cargo.toml2
-rw-r--r--components/layout/Cargo.toml2
-rw-r--r--components/layout_thread/Cargo.toml2
-rw-r--r--components/malloc_size_of/Cargo.toml2
-rw-r--r--components/script/Cargo.toml4
-rw-r--r--components/script/dom/servoparser/xml.rs15
-rw-r--r--components/script/dom/webgl_extensions/ext/mod.rs2
-rw-r--r--components/script/dom/webgl_extensions/ext/webglcompressedtextureetc1.rs58
-rw-r--r--components/script/dom/webgl_extensions/ext/webglcompressedtextures3tc.rs86
-rw-r--r--components/script/dom/webgl_extensions/extensions.rs42
-rw-r--r--components/script/dom/webgl_validations/tex_image_2d.rs309
-rw-r--r--components/script/dom/webglrenderingcontext.rs133
-rw-r--r--components/script/dom/webgltexture.rs21
-rw-r--r--components/script/dom/webidls/WEBGLCompressedTextureETC1.webidl13
-rw-r--r--components/script/dom/webidls/WEBGLCompressedTextureS3TC.webidl16
-rw-r--r--components/script_layout_interface/Cargo.toml2
-rw-r--r--components/style/Cargo.toml2
19 files changed, 746 insertions, 48 deletions
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs
index 175a061cbf4..cec8cc929d6 100644
--- a/components/canvas/webgl_thread.rs
+++ b/components/canvas/webgl_thread.rs
@@ -1168,6 +1168,43 @@ impl WebGLImpl {
&pixels,
);
},
+ WebGLCommand::CompressedTexImage2D {
+ target,
+ level,
+ internal_format,
+ size,
+ ref data,
+ } => {
+ ctx.gl().compressed_tex_image_2d(
+ target,
+ level as i32,
+ internal_format,
+ size.width as i32,
+ size.height as i32,
+ 0,
+ &*data,
+ );
+ },
+ WebGLCommand::CompressedTexSubImage2D {
+ target,
+ level,
+ xoffset,
+ yoffset,
+ size,
+ format,
+ ref data,
+ } => {
+ ctx.gl().compressed_tex_sub_image_2d(
+ target,
+ level as i32,
+ xoffset as i32,
+ yoffset as i32,
+ size.width as i32,
+ size.height as i32,
+ format,
+ &*data,
+ );
+ },
WebGLCommand::DrawingBufferWidth(ref sender) => sender
.send(ctx.borrow_draw_buffer().unwrap().size().width)
.unwrap(),
diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs
index af88ca905aa..a36e8d0e659 100644
--- a/components/canvas_traits/webgl.rs
+++ b/components/canvas_traits/webgl.rs
@@ -331,6 +331,22 @@ pub enum WebGLCommand {
pixel_format: Option<PixelFormat>,
data: TruncatedDebug<IpcSharedMemory>,
},
+ CompressedTexImage2D {
+ target: u32,
+ level: u32,
+ internal_format: u32,
+ size: Size2D<u32>,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
+ CompressedTexSubImage2D {
+ target: u32,
+ level: i32,
+ xoffset: i32,
+ yoffset: i32,
+ size: Size2D<u32>,
+ format: u32,
+ data: TruncatedDebug<IpcSharedMemory>,
+ },
DrawingBufferWidth(WebGLSender<i32>),
DrawingBufferHeight(WebGLSender<i32>),
Finish(WebGLSender<()>),
@@ -740,6 +756,25 @@ macro_rules! gl_enums {
}
}
+// FIXME: These should come from gleam
+mod gl_ext_constants {
+ use gleam::gl::types::GLenum;
+
+ pub const COMPRESSED_RGB_S3TC_DXT1_EXT: GLenum = 0x83F0;
+ pub const COMPRESSED_RGBA_S3TC_DXT1_EXT: GLenum = 0x83F1;
+ pub const COMPRESSED_RGBA_S3TC_DXT3_EXT: GLenum = 0x83F2;
+ pub const COMPRESSED_RGBA_S3TC_DXT5_EXT: GLenum = 0x83F3;
+ pub const COMPRESSED_RGB_ETC1_WEBGL: GLenum = 0x8D64;
+
+ pub static COMPRESSIONS: &'static [GLenum] = &[
+ COMPRESSED_RGB_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ COMPRESSED_RGB_ETC1_WEBGL,
+ ];
+}
+
gl_enums! {
pub enum TexFormat {
DepthComponent = gl::DEPTH_COMPONENT,
@@ -748,6 +783,11 @@ gl_enums! {
RGBA = gl::RGBA,
Luminance = gl::LUMINANCE,
LuminanceAlpha = gl::LUMINANCE_ALPHA,
+ CompressedRgbS3tcDxt1 = gl_ext_constants::COMPRESSED_RGB_S3TC_DXT1_EXT,
+ CompressedRgbaS3tcDxt1 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ CompressedRgbaS3tcDxt3 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT3_EXT,
+ CompressedRgbaS3tcDxt5 = gl_ext_constants::COMPRESSED_RGBA_S3TC_DXT5_EXT,
+ CompressedRgbEtc1 = gl_ext_constants::COMPRESSED_RGB_ETC1_WEBGL,
}
pub enum TexDataType {
@@ -771,8 +811,14 @@ impl TexFormat {
TexFormat::LuminanceAlpha => 2,
TexFormat::RGB => 3,
TexFormat::RGBA => 4,
+ _ => 1,
}
}
+
+ /// Returns whether this format is a known texture compression format.
+ pub fn is_compressed(&self) -> bool {
+ gl_ext_constants::COMPRESSIONS.contains(&self.as_gl_constant())
+ }
}
impl TexDataType {
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml
index b57c70ac0c9..085349f3f23 100644
--- a/components/gfx/Cargo.toml
+++ b/components/gfx/Cargo.toml
@@ -60,7 +60,7 @@ servo_allocator = {path = "../allocator"}
servo-fontconfig = "0.2.1"
[target.'cfg(target_os = "android")'.dependencies]
-xml5ever = {version = "0.12"}
+xml5ever = {version = "0.14"}
[target.'cfg(target_os = "windows")'.dependencies]
dwrote = "0.8"
diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml
index 247a4623a43..abbd43b3e64 100644
--- a/components/layout/Cargo.toml
+++ b/components/layout/Cargo.toml
@@ -24,7 +24,7 @@ fnv = "1.0"
fxhash = "0.2"
gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"}
-html5ever = "0.22"
+html5ever = "0.23"
ipc-channel = "0.11"
libc = "0.2"
log = "0.4"
diff --git a/components/layout_thread/Cargo.toml b/components/layout_thread/Cargo.toml
index 4c1f53ec48c..b042ed7b62c 100644
--- a/components/layout_thread/Cargo.toml
+++ b/components/layout_thread/Cargo.toml
@@ -24,7 +24,7 @@ fxhash = "0.2"
gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"}
histogram = "0.6.8"
-html5ever = "0.22"
+html5ever = "0.23"
ipc-channel = "0.11"
layout = {path = "../layout"}
layout_traits = {path = "../layout_traits"}
diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml
index 609a977b1dd..bd351649b5b 100644
--- a/components/malloc_size_of/Cargo.toml
+++ b/components/malloc_size_of/Cargo.toml
@@ -43,5 +43,5 @@ thin-slice = "0.1.0"
time = { version = "0.1.17", optional = true }
url = { version = "1.2", optional = true }
webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
-xml5ever = { version = "0.12", optional = true }
+xml5ever = { version = "0.14", optional = true }
void = "1.0.2"
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index a9ef147da99..8dcf5bf0e14 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -56,7 +56,7 @@ fnv = "1.0"
gleam = "0.6"
headers-core = "0.0.1"
headers-ext = "0.0.3"
-html5ever = "0.22"
+html5ever = "0.23"
http = "0.1"
hyper = "0.12"
hyper_serde = "0.9"
@@ -110,7 +110,7 @@ unicode-segmentation = "1.1.0"
url = "1.6"
utf-8 = "0.7"
uuid = {version = "0.7", features = ["v4"]}
-xml5ever = {version = "0.12"}
+xml5ever = {version = "0.14"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs
index 2d9c8ac51ec..8f30e54174d 100644
--- a/components/script/dom/servoparser/xml.rs
+++ b/components/script/dom/servoparser/xml.rs
@@ -40,18 +40,9 @@ impl Tokenizer {
}
pub fn feed(&mut self, input: &mut BufferQueue) -> Result<(), DomRoot<HTMLScriptElement>> {
- if !input.is_empty() {
- while let Some(chunk) = input.pop_front() {
- self.inner.feed(chunk);
- if let Some(script) = self.inner.sink.sink.script.take() {
- return Err(script);
- }
- }
- } else {
- self.inner.run();
- if let Some(script) = self.inner.sink.sink.script.take() {
- return Err(script);
- }
+ self.inner.run(input);
+ if let Some(script) = self.inner.sink.sink.script.take() {
+ return Err(script);
}
Ok(())
}
diff --git a/components/script/dom/webgl_extensions/ext/mod.rs b/components/script/dom/webgl_extensions/ext/mod.rs
index 888e977c68e..ccb768cc04f 100644
--- a/components/script/dom/webgl_extensions/ext/mod.rs
+++ b/components/script/dom/webgl_extensions/ext/mod.rs
@@ -18,3 +18,5 @@ pub mod oestexturehalffloat;
pub mod oestexturehalffloatlinear;
pub mod oesvertexarrayobject;
pub mod webglcolorbufferfloat;
+pub mod webglcompressedtextureetc1;
+pub mod webglcompressedtextures3tc;
diff --git a/components/script/dom/webgl_extensions/ext/webglcompressedtextureetc1.rs b/components/script/dom/webgl_extensions/ext/webglcompressedtextureetc1.rs
new file mode 100644
index 00000000000..29805fd4bdd
--- /dev/null
+++ b/components/script/dom/webgl_extensions/ext/webglcompressedtextureetc1.rs
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use super::{WebGLExtension, WebGLExtensionSpec, WebGLExtensions};
+use crate::dom::bindings::codegen::Bindings::WEBGLCompressedTextureETC1Binding;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::webglrenderingcontext::WebGLRenderingContext;
+use crate::dom::webgltexture::{TexCompression, TexCompressionValidation};
+use canvas_traits::webgl::{TexFormat, WebGLVersion};
+use dom_struct::dom_struct;
+
+#[dom_struct]
+pub struct WEBGLCompressedTextureETC1 {
+ reflector_: Reflector,
+}
+
+impl WEBGLCompressedTextureETC1 {
+ fn new_inherited() -> WEBGLCompressedTextureETC1 {
+ Self {
+ reflector_: Reflector::new(),
+ }
+ }
+}
+
+impl WebGLExtension for WEBGLCompressedTextureETC1 {
+ type Extension = WEBGLCompressedTextureETC1;
+ fn new(ctx: &WebGLRenderingContext) -> DomRoot<WEBGLCompressedTextureETC1> {
+ reflect_dom_object(
+ Box::new(WEBGLCompressedTextureETC1::new_inherited()),
+ &*ctx.global(),
+ WEBGLCompressedTextureETC1Binding::Wrap,
+ )
+ }
+
+ fn spec() -> WebGLExtensionSpec {
+ WebGLExtensionSpec::Specific(WebGLVersion::WebGL1)
+ }
+
+ fn is_supported(ext: &WebGLExtensions) -> bool {
+ ext.supports_gl_extension("GL_OES_compressed_ETC1_RGB8_texture")
+ }
+
+ fn enable(ext: &WebGLExtensions) {
+ ext.add_tex_compression_formats(&[TexCompression {
+ format: TexFormat::CompressedRgbEtc1,
+ bytes_per_block: 8,
+ block_width: 4,
+ block_height: 4,
+ validation: TexCompressionValidation::None,
+ }]);
+ }
+
+ fn name() -> &'static str {
+ "WEBGL_compressed_texture_etc1"
+ }
+}
diff --git a/components/script/dom/webgl_extensions/ext/webglcompressedtextures3tc.rs b/components/script/dom/webgl_extensions/ext/webglcompressedtextures3tc.rs
new file mode 100644
index 00000000000..0e4385abd6b
--- /dev/null
+++ b/components/script/dom/webgl_extensions/ext/webglcompressedtextures3tc.rs
@@ -0,0 +1,86 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use super::{WebGLExtension, WebGLExtensionSpec, WebGLExtensions};
+use crate::dom::bindings::codegen::Bindings::WEBGLCompressedTextureS3TCBinding;
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
+use crate::dom::bindings::root::DomRoot;
+use crate::dom::webglrenderingcontext::WebGLRenderingContext;
+use crate::dom::webgltexture::{TexCompression, TexCompressionValidation};
+use canvas_traits::webgl::{TexFormat, WebGLVersion};
+use dom_struct::dom_struct;
+
+#[dom_struct]
+pub struct WEBGLCompressedTextureS3TC {
+ reflector_: Reflector,
+}
+
+impl WEBGLCompressedTextureS3TC {
+ fn new_inherited() -> WEBGLCompressedTextureS3TC {
+ Self {
+ reflector_: Reflector::new(),
+ }
+ }
+}
+
+impl WebGLExtension for WEBGLCompressedTextureS3TC {
+ type Extension = WEBGLCompressedTextureS3TC;
+ fn new(ctx: &WebGLRenderingContext) -> DomRoot<WEBGLCompressedTextureS3TC> {
+ reflect_dom_object(
+ Box::new(WEBGLCompressedTextureS3TC::new_inherited()),
+ &*ctx.global(),
+ WEBGLCompressedTextureS3TCBinding::Wrap,
+ )
+ }
+
+ fn spec() -> WebGLExtensionSpec {
+ WebGLExtensionSpec::Specific(WebGLVersion::WebGL1)
+ }
+
+ fn is_supported(ext: &WebGLExtensions) -> bool {
+ ext.supports_gl_extension("GL_EXT_texture_compression_s3tc") ||
+ ext.supports_all_gl_extension(&[
+ "GL_EXT_texture_compression_dxt1",
+ "GL_ANGLE_texture_compression_dxt3",
+ "GL_ANGLE_texture_compression_dxt5",
+ ])
+ }
+
+ fn enable(ext: &WebGLExtensions) {
+ ext.add_tex_compression_formats(&[
+ TexCompression {
+ format: TexFormat::CompressedRgbS3tcDxt1,
+ bytes_per_block: 8,
+ block_width: 4,
+ block_height: 4,
+ validation: TexCompressionValidation::S3TC,
+ },
+ TexCompression {
+ format: TexFormat::CompressedRgbaS3tcDxt1,
+ bytes_per_block: 8,
+ block_width: 4,
+ block_height: 4,
+ validation: TexCompressionValidation::S3TC,
+ },
+ TexCompression {
+ format: TexFormat::CompressedRgbaS3tcDxt3,
+ bytes_per_block: 16,
+ block_width: 4,
+ block_height: 4,
+ validation: TexCompressionValidation::S3TC,
+ },
+ TexCompression {
+ format: TexFormat::CompressedRgbaS3tcDxt5,
+ bytes_per_block: 16,
+ block_width: 4,
+ block_height: 4,
+ validation: TexCompressionValidation::S3TC,
+ },
+ ]);
+ }
+
+ fn name() -> &'static str {
+ "WEBGL_compressed_texture_s3tc"
+ }
+}
diff --git a/components/script/dom/webgl_extensions/extensions.rs b/components/script/dom/webgl_extensions/extensions.rs
index aa6d128ae89..e71fcf7dac5 100644
--- a/components/script/dom/webgl_extensions/extensions.rs
+++ b/components/script/dom/webgl_extensions/extensions.rs
@@ -17,6 +17,7 @@ use crate::dom::oestexturefloat::OESTextureFloat;
use crate::dom::oestexturehalffloat::OESTextureHalfFloat;
use crate::dom::webglcolorbufferfloat::WEBGLColorBufferFloat;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
+use crate::dom::webgltexture::TexCompression;
use canvas_traits::webgl::WebGLVersion;
use fnv::{FnvHashMap, FnvHashSet};
use gleam::gl::{self, GLenum};
@@ -82,6 +83,8 @@ struct WebGLExtensionFeatures {
element_index_uint_enabled: bool,
/// WebGL EXT_blend_minmax extension.
blend_minmax_enabled: bool,
+ /// WebGL supported texture compression formats enabled by extensions.
+ tex_compression_formats: FnvHashMap<GLenum, TexCompression>,
}
impl WebGLExtensionFeatures {
@@ -131,6 +134,7 @@ impl WebGLExtensionFeatures {
disabled_get_vertex_attrib_names,
element_index_uint_enabled,
blend_minmax_enabled,
+ tex_compression_formats: Default::default(),
}
}
}
@@ -225,6 +229,13 @@ impl WebGLExtensions {
.any(|name| features.gl_extensions.contains(*name))
}
+ pub fn supports_all_gl_extension(&self, names: &[&str]) -> bool {
+ let features = self.features.borrow();
+ names
+ .iter()
+ .all(|name| features.gl_extensions.contains(*name))
+ }
+
pub fn enable_tex_type(&self, data_type: GLenum) {
self.features
.borrow_mut()
@@ -335,6 +346,35 @@ impl WebGLExtensions {
.contains(&name)
}
+ pub fn add_tex_compression_formats(&self, formats: &[TexCompression]) {
+ let formats: FnvHashMap<GLenum, TexCompression> = formats
+ .iter()
+ .map(|&compression| (compression.format.as_gl_constant(), compression))
+ .collect();
+
+ self.features
+ .borrow_mut()
+ .tex_compression_formats
+ .extend(formats.iter());
+ }
+
+ pub fn get_tex_compression_format(&self, format_id: GLenum) -> Option<TexCompression> {
+ self.features
+ .borrow()
+ .tex_compression_formats
+ .get(&format_id)
+ .cloned()
+ }
+
+ pub fn get_tex_compression_ids(&self) -> Vec<GLenum> {
+ self.features
+ .borrow()
+ .tex_compression_formats
+ .keys()
+ .map(|&k| k)
+ .collect()
+ }
+
fn register_all_extensions(&self) {
self.register::<ext::angleinstancedarrays::ANGLEInstancedArrays>();
self.register::<ext::extblendminmax::EXTBlendMinmax>();
@@ -349,6 +389,8 @@ impl WebGLExtensions {
self.register::<ext::oestexturehalffloatlinear::OESTextureHalfFloatLinear>();
self.register::<ext::oesvertexarrayobject::OESVertexArrayObject>();
self.register::<ext::webglcolorbufferfloat::WEBGLColorBufferFloat>();
+ self.register::<ext::webglcompressedtextureetc1::WEBGLCompressedTextureETC1>();
+ self.register::<ext::webglcompressedtextures3tc::WEBGLCompressedTextureS3TC>();
}
pub fn enable_element_index_uint(&self) {
diff --git a/components/script/dom/webgl_validations/tex_image_2d.rs b/components/script/dom/webgl_validations/tex_image_2d.rs
index d9bce435234..329ffd10349 100644
--- a/components/script/dom/webgl_validations/tex_image_2d.rs
+++ b/components/script/dom/webgl_validations/tex_image_2d.rs
@@ -6,7 +6,8 @@ use super::types::TexImageTarget;
use super::WebGLValidator;
use crate::dom::bindings::root::DomRoot;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
-use crate::dom::webgltexture::WebGLTexture;
+use crate::dom::webgltexture::{ImageInfo, WebGLTexture};
+use crate::dom::webgltexture::{TexCompression, TexCompressionValidation};
use canvas_traits::webgl::{TexDataType, TexFormat, WebGLError::*};
use std::{self, fmt};
@@ -40,6 +41,10 @@ pub enum TexImageValidationError {
InvalidBorder,
/// Expected a power of two texture.
NonPotTexture,
+ /// Unrecognized texture compression format.
+ InvalidCompressionFormat,
+ /// Invalid X/Y texture offset parameters.
+ InvalidOffsets,
}
impl std::error::Error for TexImageValidationError {
@@ -61,6 +66,8 @@ impl std::error::Error for TexImageValidationError {
InvalidTypeForFormat => "Invalid type for the given format",
InvalidBorder => "Invalid border",
NonPotTexture => "Expected a power of two texture",
+ InvalidCompressionFormat => "Unrecognized texture compression format",
+ InvalidOffsets => "Invalid X/Y texture offset parameters",
}
}
}
@@ -357,3 +364,303 @@ impl<'a> WebGLValidator for TexImage2DValidator<'a> {
})
}
}
+
+pub struct CommonCompressedTexImage2DValidator<'a> {
+ common_validator: CommonTexImage2DValidator<'a>,
+ data_len: usize,
+}
+
+impl<'a> CommonCompressedTexImage2DValidator<'a> {
+ pub fn new(
+ context: &'a WebGLRenderingContext,
+ target: u32,
+ level: i32,
+ width: i32,
+ height: i32,
+ border: i32,
+ compression_format: u32,
+ data_len: usize,
+ ) -> Self {
+ CommonCompressedTexImage2DValidator {
+ common_validator: CommonTexImage2DValidator::new(
+ context,
+ target,
+ level,
+ compression_format,
+ width,
+ height,
+ border,
+ ),
+ data_len,
+ }
+ }
+}
+
+pub struct CommonCompressedTexImage2DValidatorResult {
+ pub texture: DomRoot<WebGLTexture>,
+ pub target: TexImageTarget,
+ pub level: u32,
+ pub width: u32,
+ pub height: u32,
+ pub compression: TexCompression,
+}
+
+fn valid_s3tc_dimension(level: u32, side_length: u32, block_size: u32) -> bool {
+ (side_length % block_size == 0) || (level > 0 && [0, 1, 2].contains(&side_length))
+}
+
+fn valid_compressed_data_len(
+ data_len: usize,
+ width: u32,
+ height: u32,
+ compression: &TexCompression,
+) -> bool {
+ let block_width = compression.block_width as u32;
+ let block_height = compression.block_height as u32;
+
+ let required_blocks_hor = (width + block_width - 1) / block_width;
+ let required_blocks_ver = (height + block_height - 1) / block_height;
+ let required_blocks = required_blocks_hor * required_blocks_ver;
+
+ let required_bytes = required_blocks * compression.bytes_per_block as u32;
+ data_len == required_bytes as usize
+}
+
+fn is_subimage_blockaligned(
+ xoffset: u32,
+ yoffset: u32,
+ width: u32,
+ height: u32,
+ compression: &TexCompression,
+ tex_info: &ImageInfo,
+) -> bool {
+ let block_width = compression.block_width as u32;
+ let block_height = compression.block_height as u32;
+
+ (xoffset % block_width == 0 && yoffset % block_height == 0) &&
+ (width % block_width == 0 || xoffset + width == tex_info.width()) &&
+ (height % block_height == 0 || yoffset + height == tex_info.height())
+}
+
+impl<'a> WebGLValidator for CommonCompressedTexImage2DValidator<'a> {
+ type Error = TexImageValidationError;
+ type ValidatedOutput = CommonCompressedTexImage2DValidatorResult;
+
+ fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
+ let context = self.common_validator.context;
+ let CommonTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ internal_format,
+ width,
+ height,
+ border: _,
+ } = self.common_validator.validate()?;
+
+ // GL_INVALID_ENUM is generated if internalformat is not a supported
+ // format returned in GL_COMPRESSED_TEXTURE_FORMATS.
+ let compression = context
+ .extension_manager()
+ .get_tex_compression_format(internal_format.as_gl_constant());
+ let compression = match compression {
+ Some(compression) => compression,
+ None => {
+ context.webgl_error(InvalidEnum);
+ return Err(TexImageValidationError::InvalidCompressionFormat);
+ },
+ };
+
+ // GL_INVALID_VALUE is generated if imageSize is not consistent with the
+ // format, dimensions, and contents of the specified compressed image data.
+ if !valid_compressed_data_len(self.data_len, width, height, &compression) {
+ context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::TextureFormatMismatch);
+ }
+
+ Ok(CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ })
+ }
+}
+
+pub struct CompressedTexImage2DValidator<'a> {
+ compression_validator: CommonCompressedTexImage2DValidator<'a>,
+}
+
+impl<'a> CompressedTexImage2DValidator<'a> {
+ pub fn new(
+ context: &'a WebGLRenderingContext,
+ target: u32,
+ level: i32,
+ width: i32,
+ height: i32,
+ border: i32,
+ compression_format: u32,
+ data_len: usize,
+ ) -> Self {
+ CompressedTexImage2DValidator {
+ compression_validator: CommonCompressedTexImage2DValidator::new(
+ context,
+ target,
+ level,
+ width,
+ height,
+ border,
+ compression_format,
+ data_len,
+ ),
+ }
+ }
+}
+
+impl<'a> WebGLValidator for CompressedTexImage2DValidator<'a> {
+ type Error = TexImageValidationError;
+ type ValidatedOutput = CommonCompressedTexImage2DValidatorResult;
+
+ fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
+ let context = self.compression_validator.common_validator.context;
+ let CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ } = self.compression_validator.validate()?;
+
+ // GL_INVALID_OPERATION is generated if parameter combinations are not
+ // supported by the specific compressed internal format as specified
+ // in the specific texture compression extension.
+ let compression_valid = match compression.validation {
+ TexCompressionValidation::S3TC => {
+ let valid_width =
+ valid_s3tc_dimension(level, width, compression.block_width as u32);
+ let valid_height =
+ valid_s3tc_dimension(level, height, compression.block_height as u32);
+ valid_width && valid_height
+ },
+ TexCompressionValidation::None => true,
+ };
+ if !compression_valid {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::TextureFormatMismatch);
+ }
+
+ Ok(CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ })
+ }
+}
+
+pub struct CompressedTexSubImage2DValidator<'a> {
+ compression_validator: CommonCompressedTexImage2DValidator<'a>,
+ xoffset: i32,
+ yoffset: i32,
+}
+
+impl<'a> CompressedTexSubImage2DValidator<'a> {
+ pub fn new(
+ context: &'a WebGLRenderingContext,
+ target: u32,
+ level: i32,
+ xoffset: i32,
+ yoffset: i32,
+ width: i32,
+ height: i32,
+ compression_format: u32,
+ data_len: usize,
+ ) -> Self {
+ CompressedTexSubImage2DValidator {
+ compression_validator: CommonCompressedTexImage2DValidator::new(
+ context,
+ target,
+ level,
+ width,
+ height,
+ 0,
+ compression_format,
+ data_len,
+ ),
+ xoffset,
+ yoffset,
+ }
+ }
+}
+
+impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
+ type Error = TexImageValidationError;
+ type ValidatedOutput = CommonCompressedTexImage2DValidatorResult;
+
+ fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
+ let context = self.compression_validator.common_validator.context;
+ let CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ } = self.compression_validator.validate()?;
+
+ let tex_info = texture.image_info_for_target(&target, level);
+
+ // 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 self.xoffset < 0 ||
+ (self.xoffset as u32 + width) > tex_info.width() ||
+ self.yoffset < 0 ||
+ (self.yoffset as u32 + height) > tex_info.height()
+ {
+ context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::InvalidOffsets);
+ }
+
+ // GL_INVALID_OPERATION is generated if format does not match
+ // internal_format.
+ if compression.format != tex_info.internal_format().unwrap() {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::TextureFormatMismatch);
+ }
+
+ // GL_INVALID_OPERATION is generated if parameter combinations are not
+ // supported by the specific compressed internal format as specified
+ // in the specific texture compression extension.
+ let compression_valid = match compression.validation {
+ TexCompressionValidation::S3TC => is_subimage_blockaligned(
+ self.xoffset as u32,
+ self.yoffset as u32,
+ width,
+ height,
+ &compression,
+ &tex_info,
+ ),
+ TexCompressionValidation::None => true,
+ };
+ if !compression_valid {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::TextureFormatMismatch);
+ }
+
+ Ok(CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ })
+ }
+}
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 3100fbf942d..0ccc2a53825 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -26,9 +26,10 @@ use crate::dom::htmliframeelement::HTMLIFrameElement;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage};
use crate::dom::webgl_extensions::WebGLExtensions;
use crate::dom::webgl_validations::tex_image_2d::{
- CommonTexImage2DValidator, CommonTexImage2DValidatorResult,
+ CommonCompressedTexImage2DValidatorResult, CommonTexImage2DValidator,
+ CommonTexImage2DValidatorResult, CompressedTexImage2DValidator,
+ CompressedTexSubImage2DValidator, TexImage2DValidator, TexImage2DValidatorResult,
};
-use crate::dom::webgl_validations::tex_image_2d::{TexImage2DValidator, TexImage2DValidatorResult};
use crate::dom::webgl_validations::types::TexImageTarget;
use crate::dom::webgl_validations::WebGLValidator;
use crate::dom::webglactiveinfo::WebGLActiveInfo;
@@ -1227,9 +1228,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return Int32Value(constants::UNSIGNED_BYTE as i32);
},
constants::COMPRESSED_TEXTURE_FORMATS => {
- // FIXME(nox): https://github.com/servo/servo/issues/20594
+ let format_ids = self.extension_manager.get_tex_compression_ids();
+
rooted!(in(cx) let mut rval = ptr::null_mut::<JSObject>());
- let _ = Uint32Array::create(cx, CreateWith::Slice(&[]), rval.handle_mut()).unwrap();
+ let _ = Uint32Array::create(cx, CreateWith::Slice(&format_ids), rval.handle_mut())
+ .unwrap();
return ObjectValue(rval.get());
},
constants::VERSION => {
@@ -1756,36 +1759,116 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
+ #[allow(unsafe_code)]
fn CompressedTexImage2D(
&self,
- _target: u32,
- _level: i32,
- _internal_format: u32,
- _width: i32,
- _height: i32,
- _border: i32,
- _data: CustomAutoRooterGuard<ArrayBufferView>,
+ target: u32,
+ level: i32,
+ internal_format: u32,
+ width: i32,
+ height: i32,
+ border: i32,
+ data: CustomAutoRooterGuard<ArrayBufferView>,
) {
- // FIXME: No compressed texture format is currently supported, so error out as per
- // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT
- self.webgl_error(InvalidEnum);
+ let validator = CompressedTexImage2DValidator::new(
+ self,
+ target,
+ level,
+ width,
+ height,
+ border,
+ internal_format,
+ data.len(),
+ );
+ let CommonCompressedTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ compression,
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return,
+ };
+
+ let buff = IpcSharedMemory::from_bytes(unsafe { data.as_slice() });
+ let pixels = TexPixels::from_array(buff, Size2D::new(width, height));
+
+ handle_potential_webgl_error!(
+ self,
+ texture.initialize(
+ target,
+ pixels.size.width,
+ pixels.size.height,
+ 1,
+ compression.format,
+ level,
+ Some(TexDataType::UnsignedByte)
+ )
+ );
+
+ self.send_command(WebGLCommand::CompressedTexImage2D {
+ target: target.as_gl_constant(),
+ level,
+ internal_format,
+ size: Size2D::new(width, height),
+ data: pixels.data.into(),
+ });
+
+ if let Some(fb) = self.bound_framebuffer.get() {
+ fb.invalidate_texture(&*texture);
+ }
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
+ #[allow(unsafe_code)]
fn CompressedTexSubImage2D(
&self,
- _target: u32,
- _level: i32,
- _xoffset: i32,
- _yoffset: i32,
- _width: i32,
- _height: i32,
- _format: u32,
- _data: CustomAutoRooterGuard<ArrayBufferView>,
+ target: u32,
+ level: i32,
+ xoffset: i32,
+ yoffset: i32,
+ width: i32,
+ height: i32,
+ format: u32,
+ data: CustomAutoRooterGuard<ArrayBufferView>,
) {
- // FIXME: No compressed texture format is currently supported, so error out as per
- // https://www.khronos.org/registry/webgl/specs/latest/1.0/#COMPRESSED_TEXTURE_SUPPORT
- self.webgl_error(InvalidEnum);
+ let validator = CompressedTexSubImage2DValidator::new(
+ self,
+ target,
+ level,
+ xoffset,
+ yoffset,
+ width,
+ height,
+ format,
+ data.len(),
+ );
+ let CommonCompressedTexImage2DValidatorResult {
+ texture: _,
+ target,
+ level,
+ width,
+ height,
+ ..
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return,
+ };
+
+ let buff = IpcSharedMemory::from_bytes(unsafe { data.as_slice() });
+ let pixels = TexPixels::from_array(buff, Size2D::new(width, height));
+
+ self.send_command(WebGLCommand::CompressedTexSubImage2D {
+ target: target.as_gl_constant(),
+ level: level as i32,
+ xoffset,
+ yoffset,
+ size: Size2D::new(width, height),
+ format,
+ data: pixels.data.into(),
+ });
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index 261edbe67be..8982e4bca0c 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -470,7 +470,24 @@ impl ImageInfo {
}
fn is_compressed_format(&self) -> bool {
- // TODO: Once Servo supports compressed formats, check for them here
- false
+ match self.internal_format {
+ Some(format) => format.is_compressed(),
+ None => false,
+ }
}
}
+
+#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf)]
+pub enum TexCompressionValidation {
+ None,
+ S3TC,
+}
+
+#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf)]
+pub struct TexCompression {
+ pub format: TexFormat,
+ pub bytes_per_block: u8,
+ pub block_width: u8,
+ pub block_height: u8,
+ pub validation: TexCompressionValidation,
+}
diff --git a/components/script/dom/webidls/WEBGLCompressedTextureETC1.webidl b/components/script/dom/webidls/WEBGLCompressedTextureETC1.webidl
new file mode 100644
index 00000000000..c8ba921764d
--- /dev/null
+++ b/components/script/dom/webidls/WEBGLCompressedTextureETC1.webidl
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+/*
+ * WebGL IDL definitions from the Khronos specification:
+ * https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/
+ */
+
+[NoInterfaceObject]
+interface WEBGLCompressedTextureETC1 {
+ /* Compressed Texture Format */
+ const GLenum COMPRESSED_RGB_ETC1_WEBGL = 0x8D64;
+}; // interface WEBGLCompressedTextureETC1
diff --git a/components/script/dom/webidls/WEBGLCompressedTextureS3TC.webidl b/components/script/dom/webidls/WEBGLCompressedTextureS3TC.webidl
new file mode 100644
index 00000000000..0da53b81c17
--- /dev/null
+++ b/components/script/dom/webidls/WEBGLCompressedTextureS3TC.webidl
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+/*
+ * WebGL IDL definitions from the Khronos specification:
+ * https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
+ */
+
+[NoInterfaceObject]
+interface WEBGLCompressedTextureS3TC {
+ /* Compressed Texture Formats */
+ const GLenum COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
+ const GLenum COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
+ const GLenum COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
+ const GLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
+}; // interface WEBGLCompressedTextureS3TC
diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml
index 1edde2cb613..91ef929ec28 100644
--- a/components/script_layout_interface/Cargo.toml
+++ b/components/script_layout_interface/Cargo.toml
@@ -18,7 +18,7 @@ cssparser = "0.25"
crossbeam-channel = "0.3"
euclid = "0.19"
gfx_traits = {path = "../gfx_traits"}
-html5ever = "0.22"
+html5ever = "0.23"
ipc-channel = "0.11"
libc = "0.2"
time = "0.1.17"
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index e675bb89f31..3947a5d3aa3 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -38,7 +38,7 @@ euclid = "0.19"
fallible = { path = "../fallible" }
fxhash = "0.2"
hashglobe = { path = "../hashglobe" }
-html5ever = {version = "0.22", optional = true}
+html5ever = {version = "0.23", optional = true}
indexmap = "1.0"
itertools = "0.8"
itoa = "0.4"