diff --git a/Cargo.lock b/Cargo.lock index 3e16573c287..91e0a042afd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,11 +332,11 @@ dependencies = [ "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "offscreen_gl_context 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "pixels 0.0.1", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", @@ -348,14 +348,17 @@ dependencies = [ name = "canvas_traits" version = "0.0.1" dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of 0.0.1", "malloc_size_of_derive 0.0.1", - "offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "offscreen_gl_context 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pixels 0.0.1", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "servo_config 0.0.1", @@ -399,7 +402,7 @@ name = "cgl" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -509,7 +512,7 @@ dependencies = [ "embedder_traits 0.0.1", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1276,11 +1279,21 @@ dependencies = [ ] [[package]] -name = "gleam" -version = "0.6.5" +name = "gl_generator" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "khronos_api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gleam" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1333,10 +1346,10 @@ dependencies = [ [[package]] name = "glx" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1798,7 +1811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1911,6 +1924,11 @@ name = "khronos_api" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "khronos_api" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "layout" version = "0.0.1" @@ -2094,7 +2112,7 @@ dependencies = [ "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "gaol 0.0.1 (git+https://github.com/servo/gaol)", "gfx 0.0.1", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "layout_thread 0.0.1", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2126,7 +2144,7 @@ dependencies = [ "android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "android_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "libservo 0.0.1", @@ -2691,14 +2709,14 @@ dependencies = [ [[package]] name = "offscreen_gl_context" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3190,8 +3208,7 @@ dependencies = [ "enum-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "headers-core 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "headers-ext 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3217,7 +3234,7 @@ dependencies = [ "msg 0.0.1", "net_traits 0.0.1", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", + "offscreen_gl_context 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3408,7 +3425,7 @@ dependencies = [ "crossbeam-channel 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3525,9 +3542,9 @@ dependencies = [ "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "glx 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "io-surface 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4493,7 +4510,7 @@ dependencies = [ "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4707,6 +4724,11 @@ dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xml-rs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "xml5ever" version = "0.12.0" @@ -4849,13 +4871,14 @@ dependencies = [ "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c" +"checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604" "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" -"checksum gleam 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "962cbec852194e0f5f49ea0ca8407740cb14d760d8d86834b19b1f228cb505dd" +"checksum gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bef810e31d619f5b77a7daea76a26ee50e63036637048a9f2128a33d5474141a" "checksum glib 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740f7fda8dde5f5e3944dabdb4a73ac6094a8a7fdf0af377468e98ca93733e61" "checksum glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3573351e846caed9f11207b275cd67bc07f0c2c94fb628e5d7c92ca056c7882d" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glutin 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0be84b852c1dcccde4b1329be778e5bd9c0801b8bbb8766ea327a3f813c6eafe" -"checksum glx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "63a6e7c2846e12626455f45ebaff9d92161436dd0fa703d9d198012e528ca7b9" +"checksum glx 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52ec1845f1defffd4e469ff2e3a38b2e042345a0f80a82e84ee508ba5f1e11d6" "checksum gobject-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08475e4a08f27e6e2287005950114735ed61cec2cb8c1187682a5aec8c69b715" "checksum gstreamer 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df451f98ea8b987b5fc1b647b9f038ca6ea106b08c3bccc1ef3126d4f0a687c1" "checksum gstreamer-app 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f4f865cf7f22c66907372a2e3b0f0ced3d3fedab823641d6667d2568be71408" @@ -4906,6 +4929,7 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum keyboard-types 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "823bf0e5ec01b80424a318e79a0d1375725281acf311c47543ab3413f704dc25" "checksum khronos_api 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ef23fcc4059260c5936f638c9805ebfc87cb172fa6661d130cba7f97d58f55" +"checksum khronos_api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62237e6d326bd5871cd21469323bf096de81f1618cd82cbaf5d87825335aeb49" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50" "checksum leak 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd100e01f1154f2908dfa7d02219aeab25d0b9c7fa955164192e3245255a0c73" @@ -4957,7 +4981,7 @@ dependencies = [ "checksum objc 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5ffd1ab984e2a5ed8a222a6b567d38a69c1d04d64b19eb7c2b10794c6af9f76c" "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" -"checksum offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95f2e39e3b8c95495cfec835b6fefee3f1e7d63c6f81d99796b4f9926c02db3c" +"checksum offscreen_gl_context 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e86c90338962922a5f623128079b5c01d03784c8fd0809691f4eba233d69a1c" "checksum openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6c24d3508b4fb6da175c10baac54c578b33f09c89ae90c6fe9788b3b4768efdc" "checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129" "checksum ordered-float 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a3c8db0fca1fdb34404f0b1286db252f23930b9f7a481e376c16c0d5c309d4" @@ -5120,5 +5144,6 @@ dependencies = [ "checksum xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" "checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1" "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" +"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum xml5ever 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead952cf8bab253fb5cb56e1fff780747bbf7a7258fb0451afe645a166050b1f" "checksum zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "77ce0ceee93c995954a31f77903925a6a8bb094709445238e344f2107910e29e" diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index ae8eb8e4ec4..d24ba593a88 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -14,14 +14,17 @@ path = "lib.rs" webgl_backtrace = [] [dependencies] +byteorder = "1" cssparser = "0.25" euclid = "0.19" ipc-channel = "0.11" -gleam = "0.6" +gleam = "0.6.7" +half = "1" lazy_static = "1" malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } offscreen_gl_context = {version = "0.21", features = ["serde"]} +pixels = {path = "../pixels"} serde = "1.0" serde_bytes = "0.10" servo_config = {path = "../config"} diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 2e11d1704c6..666e9c9e5b5 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -14,5 +14,6 @@ extern crate malloc_size_of_derive; extern crate serde; pub mod canvas; +#[macro_use] pub mod webgl; mod webgl_channel; diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index dce9c441e1c..a493a4a58cb 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -2,10 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; use euclid::{Rect, Size2D}; use gleam::gl; +use half::f16; use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender}; use offscreen_gl_context::{GLContextAttributes, GLLimits}; +use pixels; use serde_bytes::ByteBuf; use std::borrow::Cow; use std::num::NonZeroU32; @@ -650,3 +653,371 @@ pub fn is_gles() -> bool { // making assumptions based on platform cfg!(any(target_os = "android", target_os = "ios")) } + +#[macro_export] +macro_rules! gl_enums { + ($(pub enum $name:ident { $($variant:ident = $mod:ident::$constant:ident,)+ })*) => { + $( + #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] + #[repr(u32)] + pub enum $name { $($variant = $mod::$constant,)+ } + + impl $name { + pub fn from_gl_constant(constant: u32) -> Option { + Some(match constant { + $($mod::$constant => $name::$variant, )+ + _ => return None, + }) + } + + #[inline] + pub fn as_gl_constant(&self) -> u32 { + *self as u32 + } + } + )* + } +} + +gl_enums! { + pub enum TexFormat { + DepthComponent = gl::DEPTH_COMPONENT, + Alpha = gl::ALPHA, + RGB = gl::RGB, + RGBA = gl::RGBA, + Luminance = gl::LUMINANCE, + LuminanceAlpha = gl::LUMINANCE_ALPHA, + } + + pub enum TexDataType { + UnsignedByte = gl::UNSIGNED_BYTE, + UnsignedShort4444 = gl::UNSIGNED_SHORT_4_4_4_4, + UnsignedShort5551 = gl::UNSIGNED_SHORT_5_5_5_1, + UnsignedShort565 = gl::UNSIGNED_SHORT_5_6_5, + Float = gl::FLOAT, + HalfFloat = gl::HALF_FLOAT_OES, + } +} + +impl TexFormat { + /// Returns how many components does this format need. For example, RGBA + /// needs 4 components, while RGB requires 3. + pub fn components(&self) -> u32 { + match *self { + TexFormat::DepthComponent => 1, + TexFormat::Alpha => 1, + TexFormat::Luminance => 1, + TexFormat::LuminanceAlpha => 2, + TexFormat::RGB => 3, + TexFormat::RGBA => 4, + } + } +} + +impl TexDataType { + /// Returns the size in bytes of each element of data. + pub fn element_size(&self) -> u32 { + use self::*; + match *self { + TexDataType::UnsignedByte => 1, + TexDataType::UnsignedShort4444 | + TexDataType::UnsignedShort5551 | + TexDataType::UnsignedShort565 => 2, + TexDataType::Float => 4, + TexDataType::HalfFloat => 2, + } + } + + /// Returns how many components a single element may hold. For example, a + /// UnsignedShort4444 holds four components, each with 4 bits of data. + pub fn components_per_element(&self) -> u32 { + match *self { + TexDataType::UnsignedByte => 1, + TexDataType::UnsignedShort565 => 3, + TexDataType::UnsignedShort5551 => 4, + TexDataType::UnsignedShort4444 => 4, + TexDataType::Float => 1, + TexDataType::HalfFloat => 1, + } + } +} + +/// Translates an image in rgba8 (red in the first byte) format to +/// the format that was requested of TexImage. +pub fn rgba8_image_to_tex_image_data( + format: TexFormat, + data_type: TexDataType, + mut pixels: Vec, +) -> Vec { + // hint for vector allocation sizing. + let pixel_count = pixels.len() / 4; + + match (format, data_type) { + (TexFormat::RGBA, TexDataType::UnsignedByte) => pixels, + (TexFormat::RGB, TexDataType::UnsignedByte) => { + for i in 0..pixel_count { + let rgb = { + let rgb = &pixels[i * 4..i * 4 + 3]; + [rgb[0], rgb[1], rgb[2]] + }; + pixels[i * 3..i * 3 + 3].copy_from_slice(&rgb); + } + pixels.truncate(pixel_count * 3); + pixels + }, + (TexFormat::Alpha, TexDataType::UnsignedByte) => { + for i in 0..pixel_count { + let p = pixels[i * 4 + 3]; + pixels[i] = p; + } + pixels.truncate(pixel_count); + pixels + }, + (TexFormat::Luminance, TexDataType::UnsignedByte) => { + for i in 0..pixel_count { + let p = pixels[i * 4]; + pixels[i] = p; + } + pixels.truncate(pixel_count); + pixels + }, + (TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => { + for i in 0..pixel_count { + let (lum, a) = { + let rgba = &pixels[i * 4..i * 4 + 4]; + (rgba[0], rgba[3]) + }; + pixels[i * 2] = lum; + pixels[i * 2 + 1] = a; + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::RGBA, TexDataType::UnsignedShort4444) => { + for i in 0..pixel_count { + let p = { + let rgba = &pixels[i * 4..i * 4 + 4]; + (rgba[0] as u16 & 0xf0) << 8 | + (rgba[1] as u16 & 0xf0) << 4 | + (rgba[2] as u16 & 0xf0) | + (rgba[3] as u16 & 0xf0) >> 4 + }; + NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::RGBA, TexDataType::UnsignedShort5551) => { + for i in 0..pixel_count { + let p = { + let rgba = &pixels[i * 4..i * 4 + 4]; + (rgba[0] as u16 & 0xf8) << 8 | + (rgba[1] as u16 & 0xf8) << 3 | + (rgba[2] as u16 & 0xf8) >> 2 | + (rgba[3] as u16) >> 7 + }; + NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::RGB, TexDataType::UnsignedShort565) => { + for i in 0..pixel_count { + let p = { + let rgb = &pixels[i * 4..i * 4 + 3]; + (rgb[0] as u16 & 0xf8) << 8 | + (rgb[1] as u16 & 0xfc) << 3 | + (rgb[2] as u16 & 0xf8) >> 3 + }; + NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::RGBA, TexDataType::Float) => { + let mut rgbaf32 = Vec::::with_capacity(pixel_count * 16); + for rgba8 in pixels.chunks(4) { + rgbaf32.write_f32::(rgba8[0] as f32).unwrap(); + rgbaf32.write_f32::(rgba8[1] as f32).unwrap(); + rgbaf32.write_f32::(rgba8[2] as f32).unwrap(); + rgbaf32.write_f32::(rgba8[3] as f32).unwrap(); + } + rgbaf32 + }, + + (TexFormat::RGB, TexDataType::Float) => { + let mut rgbf32 = Vec::::with_capacity(pixel_count * 12); + for rgba8 in pixels.chunks(4) { + rgbf32.write_f32::(rgba8[0] as f32).unwrap(); + rgbf32.write_f32::(rgba8[1] as f32).unwrap(); + rgbf32.write_f32::(rgba8[2] as f32).unwrap(); + } + rgbf32 + }, + + (TexFormat::Alpha, TexDataType::Float) => { + for rgba8 in pixels.chunks_mut(4) { + let p = rgba8[3] as f32; + NativeEndian::write_f32(rgba8, p); + } + pixels + }, + + (TexFormat::Luminance, TexDataType::Float) => { + for rgba8 in pixels.chunks_mut(4) { + let p = rgba8[0] as f32; + NativeEndian::write_f32(rgba8, p); + } + pixels + }, + + (TexFormat::LuminanceAlpha, TexDataType::Float) => { + let mut data = Vec::::with_capacity(pixel_count * 8); + for rgba8 in pixels.chunks(4) { + data.write_f32::(rgba8[0] as f32).unwrap(); + data.write_f32::(rgba8[3] as f32).unwrap(); + } + data + }, + + (TexFormat::RGBA, TexDataType::HalfFloat) => { + let mut rgbaf16 = Vec::::with_capacity(pixel_count * 8); + for rgba8 in pixels.chunks(4) { + rgbaf16 + .write_u16::(f16::from_f32(rgba8[0] as f32).as_bits()) + .unwrap(); + rgbaf16 + .write_u16::(f16::from_f32(rgba8[1] as f32).as_bits()) + .unwrap(); + rgbaf16 + .write_u16::(f16::from_f32(rgba8[2] as f32).as_bits()) + .unwrap(); + rgbaf16 + .write_u16::(f16::from_f32(rgba8[3] as f32).as_bits()) + .unwrap(); + } + rgbaf16 + }, + + (TexFormat::RGB, TexDataType::HalfFloat) => { + let mut rgbf16 = Vec::::with_capacity(pixel_count * 6); + for rgba8 in pixels.chunks(4) { + rgbf16 + .write_u16::(f16::from_f32(rgba8[0] as f32).as_bits()) + .unwrap(); + rgbf16 + .write_u16::(f16::from_f32(rgba8[1] as f32).as_bits()) + .unwrap(); + rgbf16 + .write_u16::(f16::from_f32(rgba8[2] as f32).as_bits()) + .unwrap(); + } + rgbf16 + }, + (TexFormat::Alpha, TexDataType::HalfFloat) => { + for i in 0..pixel_count { + let p = f16::from_f32(pixels[i * 4 + 3] as f32).as_bits(); + NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::Luminance, TexDataType::HalfFloat) => { + for i in 0..pixel_count { + let p = f16::from_f32(pixels[i * 4] as f32).as_bits(); + NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); + } + pixels.truncate(pixel_count * 2); + pixels + }, + (TexFormat::LuminanceAlpha, TexDataType::HalfFloat) => { + for rgba8 in pixels.chunks_mut(4) { + let lum = f16::from_f32(rgba8[0] as f32).as_bits(); + let a = f16::from_f32(rgba8[3] as f32).as_bits(); + NativeEndian::write_u16(&mut rgba8[0..2], lum); + NativeEndian::write_u16(&mut rgba8[2..4], a); + } + pixels + }, + + // Validation should have ensured that we only hit the + // above cases, but we haven't turned the (format, type) + // into an enum yet so there's a default case here. + _ => unreachable!("Unsupported formats {:?} {:?}", format, data_type), + } +} + +pub fn premultiply_inplace(format: TexFormat, data_type: TexDataType, pixels: &mut [u8]) { + match (format, data_type) { + (TexFormat::RGBA, TexDataType::UnsignedByte) => { + pixels::premultiply_inplace(pixels); + }, + (TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => { + for la in pixels.chunks_mut(2) { + la[0] = pixels::multiply_u8_color(la[0], la[1]); + } + }, + (TexFormat::RGBA, TexDataType::UnsignedShort5551) => { + for rgba in pixels.chunks_mut(2) { + if NativeEndian::read_u16(rgba) & 1 == 0 { + NativeEndian::write_u16(rgba, 0); + } + } + }, + (TexFormat::RGBA, TexDataType::UnsignedShort4444) => { + for rgba in pixels.chunks_mut(2) { + let pix = NativeEndian::read_u16(rgba); + let extend_to_8_bits = |val| (val | val << 4) as u8; + let r = extend_to_8_bits(pix >> 12 & 0x0f); + let g = extend_to_8_bits(pix >> 8 & 0x0f); + let b = extend_to_8_bits(pix >> 4 & 0x0f); + let a = extend_to_8_bits(pix & 0x0f); + NativeEndian::write_u16( + rgba, + ((pixels::multiply_u8_color(r, a) & 0xf0) as u16) << 8 | + ((pixels::multiply_u8_color(g, a) & 0xf0) as u16) << 4 | + ((pixels::multiply_u8_color(b, a) & 0xf0) as u16) | + ((a & 0x0f) as u16), + ); + } + }, + // Other formats don't have alpha, so return their data untouched. + _ => {}, + } +} + +pub fn unmultiply_inplace(pixels: &mut [u8]) { + for rgba in pixels.chunks_mut(4) { + let a = (rgba[3] as f32) / 255.0; + rgba[0] = (rgba[0] as f32 / a) as u8; + rgba[1] = (rgba[1] as f32 / a) as u8; + rgba[2] = (rgba[2] as f32 / a) as u8; + } +} + +/// Flips the pixels in the Vec on the Y axis. +pub fn flip_pixels_y( + internal_format: TexFormat, + data_type: TexDataType, + width: usize, + height: usize, + unpacking_alignment: usize, + pixels: Vec, +) -> Vec { + let cpp = (data_type.element_size() * internal_format.components() / + data_type.components_per_element()) as usize; + + let stride = (width * cpp + unpacking_alignment - 1) & !(unpacking_alignment - 1); + + let mut flipped = Vec::::with_capacity(pixels.len()); + + for y in 0..height { + let flipped_y = height - 1 - y; + let start = flipped_y * stride; + + flipped.extend_from_slice(&pixels[start..(start + width * cpp)]); + flipped.extend(vec![0u8; stride - width * cpp]); + } + + flipped +} diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index a862caadc59..572bf2fb11f 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -53,7 +53,6 @@ enum-iterator = "0.2.0" euclid = "0.19" fnv = "1.0" gleam = "0.6" -half = "1.0" headers-core = "0.0.1" headers-ext = "0.0.3" html5ever = "0.22" diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index d8d3000d037..f3cc904e807 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -34,11 +34,11 @@ use canvas_traits::canvas::{ CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle, }; use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; -use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, WebGLBufferId, WebGLChan}; -use canvas_traits::webgl::{WebGLContextShareMode, WebGLError, WebGLFramebufferId, WebGLMsgSender}; -use canvas_traits::webgl::{WebGLPipeline, WebGLProgramId, WebGLReceiver, WebGLRenderbufferId}; -use canvas_traits::webgl::{WebGLSLVersion, WebGLSender, WebGLShaderId, WebGLTextureId}; -use canvas_traits::webgl::{WebGLVersion, WebGLVertexArrayId}; +use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, TexDataType, TexFormat}; +use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextShareMode, WebGLError}; +use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId}; +use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender}; +use canvas_traits::webgl::{WebGLShaderId, WebGLTextureId, WebGLVersion, WebGLVertexArrayId}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::error::Error; use crate::dom::bindings::refcounted::{Trusted, TrustedPromise}; @@ -148,6 +148,8 @@ unsafe_no_jsmanaged_fields!(Reflector); unsafe_no_jsmanaged_fields!(Duration); +unsafe_no_jsmanaged_fields!(TexDataType, TexFormat); + /// Trace a `JSVal`. pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap) { unsafe { diff --git a/components/script/dom/webgl_validations/tex_image_2d.rs b/components/script/dom/webgl_validations/tex_image_2d.rs index 125ff4918a8..09a96d37a1b 100644 --- a/components/script/dom/webgl_validations/tex_image_2d.rs +++ b/components/script/dom/webgl_validations/tex_image_2d.rs @@ -2,9 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use super::types::{TexDataType, TexFormat, TexImageTarget}; +use super::types::TexImageTarget; use super::WebGLValidator; -use canvas_traits::webgl::WebGLError::*; +use canvas_traits::webgl::{TexDataType, TexFormat, WebGLError::*}; use crate::dom::bindings::root::DomRoot; use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::dom::webgltexture::WebGLTexture; diff --git a/components/script/dom/webgl_validations/types.rs b/components/script/dom/webgl_validations/types.rs index adcc51bf1ff..5ff239ed898 100644 --- a/components/script/dom/webgl_validations/types.rs +++ b/components/script/dom/webgl_validations/types.rs @@ -2,47 +2,21 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crate::dom::bindings::codegen::Bindings::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants; -use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; +use canvas_traits::gl_enums; +use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants; -/// This macro creates type-safe wrappers for WebGL types, associating variants -/// with gl constants. -macro_rules! type_safe_wrapper { - ($name: ident, $($variant:ident => $mod:ident::$constant:ident, )+) => { - #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, MallocSizeOf, PartialEq)] - #[repr(u32)] - pub enum $name { - $( - $variant = $mod::$constant, - )+ - } - - impl $name { - pub fn from_gl_constant(constant: u32) -> Option { - Some(match constant { - $($mod::$constant => $name::$variant, )+ - _ => return None, - }) - } - - #[inline] - pub fn as_gl_constant(&self) -> u32 { - *self as u32 - } - } +gl_enums! { + pub enum TexImageTarget { + Texture2D = WebGLRenderingContextConstants::TEXTURE_2D, + CubeMapPositiveX = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_X, + CubeMapNegativeX = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_X, + CubeMapPositiveY = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_Y, + CubeMapNegativeY = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_Y, + CubeMapPositiveZ = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_Z, + CubeMapNegativeZ = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_Z, } } -type_safe_wrapper! { TexImageTarget, - Texture2D => constants::TEXTURE_2D, - CubeMapPositiveX => constants::TEXTURE_CUBE_MAP_POSITIVE_X, - CubeMapNegativeX => constants::TEXTURE_CUBE_MAP_NEGATIVE_X, - CubeMapPositiveY => constants::TEXTURE_CUBE_MAP_POSITIVE_Y, - CubeMapNegativeY => constants::TEXTURE_CUBE_MAP_NEGATIVE_Y, - CubeMapPositiveZ => constants::TEXTURE_CUBE_MAP_POSITIVE_Z, - CubeMapNegativeZ => constants::TEXTURE_CUBE_MAP_NEGATIVE_Z, -} - impl TexImageTarget { pub fn is_cubic(&self) -> bool { match *self { @@ -51,64 +25,3 @@ impl TexImageTarget { } } } - -type_safe_wrapper! { TexDataType, - UnsignedByte => constants::UNSIGNED_BYTE, - UnsignedShort4444 => constants::UNSIGNED_SHORT_4_4_4_4, - UnsignedShort5551 => constants::UNSIGNED_SHORT_5_5_5_1, - UnsignedShort565 => constants::UNSIGNED_SHORT_5_6_5, - Float => constants::FLOAT, - HalfFloat => OESTextureHalfFloatConstants::HALF_FLOAT_OES, -} - -impl TexDataType { - /// Returns the size in bytes of each element of data. - pub fn element_size(&self) -> u32 { - use self::TexDataType::*; - match *self { - UnsignedByte => 1, - UnsignedShort4444 | UnsignedShort5551 | UnsignedShort565 => 2, - Float => 4, - HalfFloat => 2, - } - } - - /// Returns how many components a single element may hold. For example, a - /// UnsignedShort4444 holds four components, each with 4 bits of data. - pub fn components_per_element(&self) -> u32 { - use self::TexDataType::*; - match *self { - UnsignedByte => 1, - UnsignedShort565 => 3, - UnsignedShort5551 => 4, - UnsignedShort4444 => 4, - Float => 1, - HalfFloat => 1, - } - } -} - -type_safe_wrapper! { TexFormat, - DepthComponent => constants::DEPTH_COMPONENT, - Alpha => constants::ALPHA, - RGB => constants::RGB, - RGBA => constants::RGBA, - Luminance => constants::LUMINANCE, - LuminanceAlpha => constants::LUMINANCE_ALPHA, -} - -impl TexFormat { - /// Returns how many components does this format need. For example, RGBA - /// needs 4 components, while RGB requires 3. - pub fn components(&self) -> u32 { - use self::TexFormat::*; - match *self { - DepthComponent => 1, - Alpha => 1, - Luminance => 1, - LuminanceAlpha => 2, - RGB => 3, - RGBA => 4, - } - } -} diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 346d8905082..b5b22f4f464 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -4,13 +4,13 @@ #[cfg(feature = "webgl_backtrace")] use backtrace::Backtrace; -use byteorder::{ByteOrder, NativeEndian, WriteBytesExt}; use canvas_traits::webgl::WebGLError::*; -use canvas_traits::webgl::{webgl_channel, WebGLVersion, WebVRCommand}; -use canvas_traits::webgl::{DOMToTextureCommand, Parameter, WebGLCommandBacktrace}; -use canvas_traits::webgl::{TexParameter, WebGLCommand, WebGLContextShareMode, WebGLError}; -use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender}; -use canvas_traits::webgl::{WebGLProgramId, WebGLResult, WebGLSLVersion, WebGLSender}; +use canvas_traits::webgl::{ + self, webgl_channel, DOMToTextureCommand, Parameter, TexDataType, TexFormat, TexParameter, + WebGLCommand, WebGLCommandBacktrace, WebGLContextShareMode, WebGLError, + WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult, + WebGLSLVersion, WebGLSender, WebGLVersion, WebVRCommand, +}; use crate::dom::bindings::codegen::Bindings::ANGLEInstancedArraysBinding::ANGLEInstancedArraysConstants; use crate::dom::bindings::codegen::Bindings::EXTBlendMinmaxBinding::EXTBlendMinmaxConstants; use crate::dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants; @@ -38,7 +38,7 @@ use crate::dom::webgl_validations::tex_image_2d::{ CommonTexImage2DValidator, CommonTexImage2DValidatorResult, }; use crate::dom::webgl_validations::tex_image_2d::{TexImage2DValidator, TexImage2DValidatorResult}; -use crate::dom::webgl_validations::types::{TexDataType, TexFormat, TexImageTarget}; +use crate::dom::webgl_validations::types::TexImageTarget; use crate::dom::webgl_validations::WebGLValidator; use crate::dom::webglactiveinfo::WebGLActiveInfo; use crate::dom::webglbuffer::WebGLBuffer; @@ -57,7 +57,6 @@ use crate::dom::webglvertexarrayobjectoes::WebGLVertexArrayObjectOES; use crate::dom::window::Window; use dom_struct::dom_struct; use euclid::{Point2D, Rect, Size2D}; -use half::f16; use ipc_channel::ipc; use js::jsapi::{JSContext, JSObject, Type}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, UInt32Value}; @@ -70,6 +69,7 @@ use js::typedarray::{TypedArray, TypedArrayElementCreator}; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageResponse; use offscreen_gl_context::{GLContextAttributes, GLLimits}; +use pixels; use script_layout_interface::HTMLCanvasDataSource; use serde::{Deserialize, Serialize}; use servo_config::prefs::PREFS; @@ -638,92 +638,6 @@ impl WebGLRenderingContext { } } - /// Flips the pixels in the Vec on the Y axis if - /// UNPACK_FLIP_Y_WEBGL is currently enabled. - fn flip_teximage_y( - &self, - pixels: Vec, - internal_format: TexFormat, - data_type: TexDataType, - width: usize, - height: usize, - unpacking_alignment: usize, - ) -> Vec { - if !self - .texture_unpacking_settings - .get() - .contains(TextureUnpacking::FLIP_Y_AXIS) - { - return pixels; - } - - let cpp = (data_type.element_size() * internal_format.components() / - data_type.components_per_element()) as usize; - - let stride = (width * cpp + unpacking_alignment - 1) & !(unpacking_alignment - 1); - - let mut flipped = Vec::::with_capacity(pixels.len()); - - for y in 0..height { - let flipped_y = height - 1 - y; - let start = flipped_y * stride; - - flipped.extend_from_slice(&pixels[start..(start + width * cpp)]); - flipped.extend(vec![0u8; stride - width * cpp]); - } - - flipped - } - - /// Performs premultiplication of the pixels if - /// UNPACK_PREMULTIPLY_ALPHA_WEBGL is currently enabled. - fn premultiply_pixels(&self, format: TexFormat, data_type: TexDataType, pixels: &mut [u8]) { - if !self - .texture_unpacking_settings - .get() - .contains(TextureUnpacking::PREMULTIPLY_ALPHA) - { - return; - } - - match (format, data_type) { - (TexFormat::RGBA, TexDataType::UnsignedByte) => { - pixels::premultiply_inplace(pixels); - }, - (TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => { - for la in pixels.chunks_mut(2) { - la[0] = pixels::multiply_u8_color(la[0], la[1]); - } - }, - (TexFormat::RGBA, TexDataType::UnsignedShort5551) => { - for rgba in pixels.chunks_mut(2) { - if NativeEndian::read_u16(rgba) & 1 == 0 { - NativeEndian::write_u16(rgba, 0); - } - } - }, - (TexFormat::RGBA, TexDataType::UnsignedShort4444) => { - for rgba in pixels.chunks_mut(2) { - let pix = NativeEndian::read_u16(rgba); - let extend_to_8_bits = |val| (val | val << 4) as u8; - let r = extend_to_8_bits(pix >> 12 & 0x0f); - let g = extend_to_8_bits(pix >> 8 & 0x0f); - let b = extend_to_8_bits(pix >> 4 & 0x0f); - let a = extend_to_8_bits(pix & 0x0f); - NativeEndian::write_u16( - rgba, - ((pixels::multiply_u8_color(r, a) & 0xf0) as u16) << 8 | - ((pixels::multiply_u8_color(g, a) & 0xf0) as u16) << 4 | - ((pixels::multiply_u8_color(b, a) & 0xf0) as u16) | - ((a & 0x0f) as u16), - ); - } - }, - // Other formats don't have alpha, so return their data untouched. - _ => {}, - } - } - fn prepare_pixels( &self, internal_format: TexFormat, @@ -735,34 +649,36 @@ impl WebGLRenderingContext { source_from_image_or_canvas: bool, mut pixels: Vec, ) -> Vec { - let dest_premultiply = self - .texture_unpacking_settings - .get() - .contains(TextureUnpacking::PREMULTIPLY_ALPHA); + let settings = self.texture_unpacking_settings.get(); + let dest_premultiply = settings.contains(TextureUnpacking::PREMULTIPLY_ALPHA); if !source_premultiplied && dest_premultiply { if source_from_image_or_canvas { // When the pixels come from image or canvas or imagedata, use RGBA8 format - self.premultiply_pixels(TexFormat::RGBA, TexDataType::UnsignedByte, &mut pixels); + webgl::premultiply_inplace(TexFormat::RGBA, TexDataType::UnsignedByte, &mut pixels); } else { - self.premultiply_pixels(internal_format, data_type, &mut pixels); + webgl::premultiply_inplace(internal_format, data_type, &mut pixels); } } else if source_premultiplied && !dest_premultiply { - remove_premultiplied_alpha(&mut pixels); + webgl::unmultiply_inplace(&mut pixels); } if source_from_image_or_canvas { - pixels = rgba8_image_to_tex_image_data(internal_format, data_type, pixels); + pixels = webgl::rgba8_image_to_tex_image_data(internal_format, data_type, pixels); } - // FINISHME: Consider doing premultiply and flip in a single mutable Vec. - self.flip_teximage_y( - pixels, - internal_format, - data_type, - width as usize, - height as usize, - unpacking_alignment as usize, - ) + if settings.contains(TextureUnpacking::FLIP_Y_AXIS) { + // FINISHME: Consider doing premultiply and flip in a single mutable Vec. + pixels = webgl::flip_pixels_y( + internal_format, + data_type, + width as usize, + height as usize, + unpacking_alignment as usize, + pixels, + ); + } + + pixels } fn tex_image_2d( @@ -4328,234 +4244,6 @@ impl TextureUnit { } } -// Remove premultiplied alpha. -// This is only called when texImage2D is called using a canvas2d source and -// UNPACK_PREMULTIPLY_ALPHA_WEBGL is disabled. Pixels got from a canvas2D source -// are always RGBA8 with premultiplied alpha, so we don't have to worry about -// additional formats as happens in the premultiply_pixels method. -fn remove_premultiplied_alpha(pixels: &mut [u8]) { - for rgba in pixels.chunks_mut(4) { - let a = (rgba[3] as f32) / 255.0; - rgba[0] = (rgba[0] as f32 / a) as u8; - rgba[1] = (rgba[1] as f32 / a) as u8; - rgba[2] = (rgba[2] as f32 / a) as u8; - } -} - -/// Translates an image in rgba8 (red in the first byte) format to -/// the format that was requested of TexImage. -/// -/// From the WebGL 1.0 spec, 5.14.8: -/// -/// "The source image data is conceptually first converted to -/// the data type and format specified by the format and type -/// arguments, and then transferred to the WebGL -/// implementation. If a packed pixel format is specified -/// which would imply loss of bits of precision from the image -/// data, this loss of precision must occur." -fn rgba8_image_to_tex_image_data( - format: TexFormat, - data_type: TexDataType, - mut pixels: Vec, -) -> Vec { - // hint for vector allocation sizing. - let pixel_count = pixels.len() / 4; - - match (format, data_type) { - (TexFormat::RGBA, TexDataType::UnsignedByte) => pixels, - (TexFormat::RGB, TexDataType::UnsignedByte) => { - for i in 0..pixel_count { - let rgb = { - let rgb = &pixels[i * 4..i * 4 + 3]; - [rgb[0], rgb[1], rgb[2]] - }; - pixels[i * 3..i * 3 + 3].copy_from_slice(&rgb); - } - pixels.truncate(pixel_count * 3); - pixels - }, - (TexFormat::Alpha, TexDataType::UnsignedByte) => { - for i in 0..pixel_count { - let p = pixels[i * 4 + 3]; - pixels[i] = p; - } - pixels.truncate(pixel_count); - pixels - }, - (TexFormat::Luminance, TexDataType::UnsignedByte) => { - for i in 0..pixel_count { - let p = pixels[i * 4]; - pixels[i] = p; - } - pixels.truncate(pixel_count); - pixels - }, - (TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => { - for i in 0..pixel_count { - let (lum, a) = { - let rgba = &pixels[i * 4..i * 4 + 4]; - (rgba[0], rgba[3]) - }; - pixels[i * 2] = lum; - pixels[i * 2 + 1] = a; - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::RGBA, TexDataType::UnsignedShort4444) => { - for i in 0..pixel_count { - let p = { - let rgba = &pixels[i * 4..i * 4 + 4]; - (rgba[0] as u16 & 0xf0) << 8 | - (rgba[1] as u16 & 0xf0) << 4 | - (rgba[2] as u16 & 0xf0) | - (rgba[3] as u16 & 0xf0) >> 4 - }; - NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::RGBA, TexDataType::UnsignedShort5551) => { - for i in 0..pixel_count { - let p = { - let rgba = &pixels[i * 4..i * 4 + 4]; - (rgba[0] as u16 & 0xf8) << 8 | - (rgba[1] as u16 & 0xf8) << 3 | - (rgba[2] as u16 & 0xf8) >> 2 | - (rgba[3] as u16) >> 7 - }; - NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::RGB, TexDataType::UnsignedShort565) => { - for i in 0..pixel_count { - let p = { - let rgb = &pixels[i * 4..i * 4 + 3]; - (rgb[0] as u16 & 0xf8) << 8 | - (rgb[1] as u16 & 0xfc) << 3 | - (rgb[2] as u16 & 0xf8) >> 3 - }; - NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::RGBA, TexDataType::Float) => { - let mut rgbaf32 = Vec::::with_capacity(pixel_count * 16); - for rgba8 in pixels.chunks(4) { - rgbaf32.write_f32::(rgba8[0] as f32).unwrap(); - rgbaf32.write_f32::(rgba8[1] as f32).unwrap(); - rgbaf32.write_f32::(rgba8[2] as f32).unwrap(); - rgbaf32.write_f32::(rgba8[3] as f32).unwrap(); - } - rgbaf32 - }, - - (TexFormat::RGB, TexDataType::Float) => { - let mut rgbf32 = Vec::::with_capacity(pixel_count * 12); - for rgba8 in pixels.chunks(4) { - rgbf32.write_f32::(rgba8[0] as f32).unwrap(); - rgbf32.write_f32::(rgba8[1] as f32).unwrap(); - rgbf32.write_f32::(rgba8[2] as f32).unwrap(); - } - rgbf32 - }, - - (TexFormat::Alpha, TexDataType::Float) => { - for rgba8 in pixels.chunks_mut(4) { - let p = rgba8[3] as f32; - NativeEndian::write_f32(rgba8, p); - } - pixels - }, - - (TexFormat::Luminance, TexDataType::Float) => { - for rgba8 in pixels.chunks_mut(4) { - let p = rgba8[0] as f32; - NativeEndian::write_f32(rgba8, p); - } - pixels - }, - - (TexFormat::LuminanceAlpha, TexDataType::Float) => { - let mut data = Vec::::with_capacity(pixel_count * 8); - for rgba8 in pixels.chunks(4) { - data.write_f32::(rgba8[0] as f32).unwrap(); - data.write_f32::(rgba8[3] as f32).unwrap(); - } - data - }, - - (TexFormat::RGBA, TexDataType::HalfFloat) => { - let mut rgbaf16 = Vec::::with_capacity(pixel_count * 8); - for rgba8 in pixels.chunks(4) { - rgbaf16 - .write_u16::(f16::from_f32(rgba8[0] as f32).as_bits()) - .unwrap(); - rgbaf16 - .write_u16::(f16::from_f32(rgba8[1] as f32).as_bits()) - .unwrap(); - rgbaf16 - .write_u16::(f16::from_f32(rgba8[2] as f32).as_bits()) - .unwrap(); - rgbaf16 - .write_u16::(f16::from_f32(rgba8[3] as f32).as_bits()) - .unwrap(); - } - rgbaf16 - }, - - (TexFormat::RGB, TexDataType::HalfFloat) => { - let mut rgbf16 = Vec::::with_capacity(pixel_count * 6); - for rgba8 in pixels.chunks(4) { - rgbf16 - .write_u16::(f16::from_f32(rgba8[0] as f32).as_bits()) - .unwrap(); - rgbf16 - .write_u16::(f16::from_f32(rgba8[1] as f32).as_bits()) - .unwrap(); - rgbf16 - .write_u16::(f16::from_f32(rgba8[2] as f32).as_bits()) - .unwrap(); - } - rgbf16 - }, - (TexFormat::Alpha, TexDataType::HalfFloat) => { - for i in 0..pixel_count { - let p = f16::from_f32(pixels[i * 4 + 3] as f32).as_bits(); - NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::Luminance, TexDataType::HalfFloat) => { - for i in 0..pixel_count { - let p = f16::from_f32(pixels[i * 4] as f32).as_bits(); - NativeEndian::write_u16(&mut pixels[i * 2..i * 2 + 2], p); - } - pixels.truncate(pixel_count * 2); - pixels - }, - (TexFormat::LuminanceAlpha, TexDataType::HalfFloat) => { - for rgba8 in pixels.chunks_mut(4) { - let lum = f16::from_f32(rgba8[0] as f32).as_bits(); - let a = f16::from_f32(rgba8[3] as f32).as_bits(); - NativeEndian::write_u16(&mut rgba8[0..2], lum); - NativeEndian::write_u16(&mut rgba8[2..4], a); - } - pixels - }, - - // Validation should have ensured that we only hit the - // above cases, but we haven't turned the (format, type) - // into an enum yet so there's a default case here. - _ => unreachable!("Unsupported formats {:?} {:?}", format, data_type), - } -} - struct TexPixels { data: Vec, size: Size2D, diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index 2cc42a91f42..c17747a779a 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -4,7 +4,7 @@ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::webgl::{webgl_channel, WebGLResult, WebGLTextureId}; +use canvas_traits::webgl::{webgl_channel, TexDataType, TexFormat, WebGLResult, WebGLTextureId}; use canvas_traits::webgl::{DOMToTextureCommand, WebGLCommand, WebGLError}; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding::EXTTextureFilterAnisotropicConstants; @@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::WebGLTextureBinding; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::DomRoot; -use crate::dom::webgl_validations::types::{TexDataType, TexFormat, TexImageTarget}; +use crate::dom::webgl_validations::types::TexImageTarget; use crate::dom::webglobject::WebGLObject; use crate::dom::webglrenderingcontext::WebGLRenderingContext; use dom_struct::dom_struct; diff --git a/ports/libsimpleservo/Cargo.toml b/ports/libsimpleservo/Cargo.toml index a2f6805adf1..834ee59c439 100644 --- a/ports/libsimpleservo/Cargo.toml +++ b/ports/libsimpleservo/Cargo.toml @@ -30,7 +30,7 @@ libc = "0.2" winapi = "0.3.2" [build-dependencies] -gl_generator = "0.9" +gl_generator = "0.10" cc = "1.0" [features] diff --git a/servo-tidy.toml b/servo-tidy.toml index 6adf31af23b..64ee72f2c8f 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -36,6 +36,8 @@ packages = [ "crossbeam-deque", "crossbeam-epoch", "crossbeam-utils", + "gl_generator", + "khronos_api", "log", # TODO: remove num-rational when https://github.com/PistonDevelopers/image/pull/809 is merged. "num-rational", @@ -45,6 +47,7 @@ packages = [ "syn", "unicase", "winapi", + "xml-rs", ] # Files that are ignored for all tidy and lint checks. files = [