Skip to content

Commit

Permalink
Add initial support for WebGL compressed textures
Browse files Browse the repository at this point in the history
  • Loading branch information
mmatyas authored and jdm committed May 21, 2019
1 parent a14b952 commit 7f0b820
Show file tree
Hide file tree
Showing 16 changed files with 792 additions and 37 deletions.
37 changes: 37 additions & 0 deletions components/canvas/webgl_thread.rs
Expand Up @@ -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(),
Expand Down
46 changes: 46 additions & 0 deletions components/canvas_traits/webgl.rs
Expand Up @@ -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<()>),
Expand Down Expand Up @@ -736,6 +752,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,
Expand All @@ -744,6 +779,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 {
Expand All @@ -767,8 +807,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 {
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/webgl_extensions/ext/mod.rs
Expand Up @@ -18,3 +18,5 @@ pub mod oestexturehalffloat;
pub mod oestexturehalffloatlinear;
pub mod oesvertexarrayobject;
pub mod webglcolorbufferfloat;
pub mod webglcompressedtextureetc1;
pub mod webglcompressedtextures3tc;
@@ -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"
}
}
@@ -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"
}
}
42 changes: 42 additions & 0 deletions components/script/dom/webgl_extensions/extensions.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -131,6 +134,7 @@ impl WebGLExtensionFeatures {
disabled_get_vertex_attrib_names,
element_index_uint_enabled,
blend_minmax_enabled,
tex_compression_formats: Default::default(),
}
}
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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>();
Expand All @@ -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) {
Expand Down

0 comments on commit 7f0b820

Please sign in to comment.