This commit is contained in:
Patrick Shaughnessy 2019-11-23 22:08:43 -05:00
commit a2a3ecac93
80 changed files with 1684 additions and 141 deletions

327
Cargo.lock generated
View file

@ -125,12 +125,33 @@ dependencies = [
"nodrop", "nodrop",
] ]
[[package]]
name = "arrayvec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]] [[package]]
name = "ascii" name = "ascii"
version = "0.7.1" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" checksum = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50"
[[package]]
name = "ash"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "003d1fb2eb12eb06d4a03dbe02eea67a9fac910fa97932ab9e3a75b96a1ea5e5"
dependencies = [
"shared_library",
]
[[package]]
name = "atom"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
[[package]] [[package]]
name = "atomic_refcell" name = "atomic_refcell"
version = "0.1.0" version = "0.1.0"
@ -671,6 +692,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d" checksum = "a475fc4af42d83d28adf72968d9bcfaf035a1a9381642d8e85d8a04957767b0d"
[[package]]
name = "colorful"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bca1619ff57dd7a56b58a8e25ef4199f123e78e503fe1653410350a1b98ae65"
[[package]] [[package]]
name = "combine" name = "combine"
version = "3.5.2" version = "3.5.2"
@ -754,6 +781,7 @@ dependencies = [
"servo_remutex", "servo_remutex",
"servo_url", "servo_url",
"style_traits", "style_traits",
"webgpu",
"webrender_api", "webrender_api",
"webvr_traits", "webvr_traits",
"webxr-api", "webxr-api",
@ -782,6 +810,12 @@ dependencies = [
"time", "time",
] ]
[[package]]
name = "copyless"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.6.2" version = "0.6.2"
@ -866,7 +900,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
dependencies = [ dependencies = [
"arrayvec", "arrayvec 0.4.6",
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
"lazy_static", "lazy_static",
@ -941,6 +975,17 @@ dependencies = [
"syn 1.0.3", "syn 1.0.3",
] ]
[[package]]
name = "d3d12"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc7ed48e89905e5e146bcc1951cc3facb9e44aea9adf5dc01078cda1bd24b662"
dependencies = [
"bitflags",
"libloading",
"winapi",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.10.1" version = "0.10.1"
@ -1496,6 +1541,12 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.12.0" version = "0.12.0"
@ -1565,6 +1616,123 @@ dependencies = [
"xml-rs", "xml-rs",
] ]
[[package]]
name = "gfx-auxil"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572eee952a9a23c99cfe3e4fd95d277784058a89ac3c77ff6fa3d80a4e321919"
dependencies = [
"fxhash",
"gfx-hal",
"spirv_cross",
]
[[package]]
name = "gfx-backend-dx11"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66c77836ff26cf9916e5c8745715a22eae1fc61d994ffa0bea8a7dbd708ece2"
dependencies = [
"bitflags",
"gfx-auxil",
"gfx-hal",
"libloading",
"log",
"parking_lot",
"range-alloc",
"raw-window-handle",
"smallvec",
"spirv_cross",
"winapi",
"wio",
]
[[package]]
name = "gfx-backend-dx12"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6e913cc800fb12eaba2c420091a02aca9aafbefd672600dfc5b52654343d341"
dependencies = [
"bitflags",
"d3d12",
"gfx-auxil",
"gfx-hal",
"log",
"range-alloc",
"raw-window-handle",
"smallvec",
"spirv_cross",
"winapi",
]
[[package]]
name = "gfx-backend-empty"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d383e6bc48867cb37d298a20139fd1eec298f8f6d594690cd1c50ef25470cc7"
dependencies = [
"gfx-hal",
"raw-window-handle",
]
[[package]]
name = "gfx-backend-metal"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de5c71f18ba805c95b84d6c78c472ef44485a6fc46e3b49fe1e6739c8d7b0c0"
dependencies = [
"arrayvec 0.5.1",
"bitflags",
"block",
"cocoa 0.19.1",
"copyless",
"core-graphics",
"foreign-types",
"gfx-auxil",
"gfx-hal",
"lazy_static",
"log",
"metal",
"objc",
"parking_lot",
"range-alloc",
"raw-window-handle",
"smallvec",
"spirv_cross",
"storage-map",
]
[[package]]
name = "gfx-backend-vulkan"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62538fedd66a78968a162e8e1a29d085ffbc97f8782634684b2f7da7aea59207"
dependencies = [
"arrayvec 0.5.1",
"ash",
"byteorder",
"core-graphics",
"gfx-hal",
"lazy_static",
"log",
"objc",
"raw-window-handle",
"smallvec",
"winapi",
"x11",
]
[[package]]
name = "gfx-hal"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c88981665c780447bb08eb099e1ded330754a7246719bab927ee4a949c0ba7f"
dependencies = [
"bitflags",
"raw-window-handle",
"smallvec",
]
[[package]] [[package]]
name = "gfx_traits" name = "gfx_traits"
version = "0.0.1" version = "0.0.1"
@ -2130,6 +2298,15 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "hibitset"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e7292fd9f7fe89fa35c98048f2d0a69b79ed243604234d18f6f8a1aa6f408d"
dependencies = [
"atom",
]
[[package]] [[package]]
name = "histogram" name = "histogram"
version = "0.6.8" version = "0.6.8"
@ -2293,7 +2470,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7371aa3c98fad60de2d9b517e2e1ed45593c32b0c77249310fa507749a2a318b" checksum = "7371aa3c98fad60de2d9b517e2e1ed45593c32b0c77249310fa507749a2a318b"
dependencies = [ dependencies = [
"arrayvec", "arrayvec 0.4.6",
"byteorder", "byteorder",
"num-traits", "num-traits",
] ]
@ -2517,17 +2694,21 @@ dependencies = [
"cssparser", "cssparser",
"euclid", "euclid",
"gfx", "gfx",
"gfx_traits",
"ipc-channel", "ipc-channel",
"libc", "libc",
"msg", "msg",
"range",
"rayon", "rayon",
"rayon_croissant", "rayon_croissant",
"script_layout_interface", "script_layout_interface",
"script_traits", "script_traits",
"serde", "serde",
"servo_arc", "servo_arc",
"servo_geometry",
"style", "style",
"style_traits", "style_traits",
"unicode-script",
"webrender_api", "webrender_api",
] ]
@ -2764,6 +2945,7 @@ dependencies = [
"style_traits", "style_traits",
"surfman", "surfman",
"webdriver_server", "webdriver_server",
"webgpu",
"webrender", "webrender",
"webrender_api", "webrender_api",
"webrender_traits", "webrender_traits",
@ -2833,7 +3015,7 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69589b8844c0b3745cc031a35b62bc33b0fb9e5ba7613756d802c52861dcdb4c" checksum = "69589b8844c0b3745cc031a35b62bc33b0fb9e5ba7613756d802c52861dcdb4c"
dependencies = [ dependencies = [
"arrayvec", "arrayvec 0.4.6",
"euclid", "euclid",
"num-traits", "num-traits",
] ]
@ -2988,6 +3170,21 @@ dependencies = [
"rustc_version", "rustc_version",
] ]
[[package]]
name = "metal"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddf8052f20601c7af6293d3f7bf7b9159aee5974804fe65d871d437f933ec1eb"
dependencies = [
"bitflags",
"block",
"cocoa 0.19.1",
"core-graphics",
"foreign-types",
"log",
"objc",
]
[[package]] [[package]]
name = "metrics" name = "metrics"
version = "0.0.1" version = "0.0.1"
@ -3393,6 +3590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d" checksum = "31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
dependencies = [ dependencies = [
"malloc_buf", "malloc_buf",
"objc_exception",
] ]
[[package]] [[package]]
@ -3406,6 +3604,15 @@ dependencies = [
"objc_id", "objc_id",
] ]
[[package]]
name = "objc_exception"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "098cd29a2fa3c230d3463ae069cecccc3fdfd64c0d2496ab5b96f82dab6a00dc"
dependencies = [
"gcc",
]
[[package]] [[package]]
name = "objc_id" name = "objc_id"
version = "0.1.0" version = "0.1.0"
@ -3892,6 +4099,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "range-alloc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5927936723a9e8b715d37d7e4b390455087c4bdf25b9f702309460577b14f9"
[[package]] [[package]]
name = "raqote" name = "raqote"
version = "0.7.4-alpha.0" version = "0.7.4-alpha.0"
@ -3905,6 +4118,15 @@ dependencies = [
"typed-arena", "typed-arena",
] ]
[[package]]
name = "raw-window-handle"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9db80d08d3ed847ce4fb3def46de0af4bfb6155bd09bd6eaf28b5ac72541c1f1"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.2.0" version = "1.2.0"
@ -3988,6 +4210,16 @@ dependencies = [
"ucd-util", "ucd-util",
] ]
[[package]]
name = "relevant"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc232e13d37f4547f5b9b42a5efc380cabe5dbc1807f8b893580640b2ab0308"
dependencies = [
"cfg-if",
"log",
]
[[package]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
version = "0.5.2" version = "0.5.2"
@ -3997,6 +4229,33 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "rendy-descriptor"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f475bcc0505946e998590f1f0545c52ef4b559174a1b353a7ce6638def8b621e"
dependencies = [
"gfx-hal",
"log",
"relevant",
"smallvec",
]
[[package]]
name = "rendy-memory"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed492161a819feae7f27f418bb16035276ac20649c60d756699152cb5c1960ec"
dependencies = [
"colorful",
"gfx-hal",
"hibitset",
"log",
"relevant",
"slab",
"smallvec",
]
[[package]] [[package]]
name = "rle-decode-fast" name = "rle-decode-fast"
version = "1.0.1" version = "1.0.1"
@ -4077,7 +4336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20" checksum = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
dependencies = [ dependencies = [
"approx", "approx",
"arrayvec", "arrayvec 0.4.6",
"ordered-float", "ordered-float",
"stb_truetype", "stb_truetype",
] ]
@ -4199,6 +4458,7 @@ dependencies = [
"utf-8", "utf-8",
"uuid", "uuid",
"webdriver", "webdriver",
"webgpu",
"webrender_api", "webrender_api",
"webvr_traits", "webvr_traits",
"webxr-api", "webxr-api",
@ -4291,6 +4551,7 @@ dependencies = [
"time", "time",
"url", "url",
"webdriver", "webdriver",
"webgpu",
"webrender_api", "webrender_api",
"webvr_traits", "webvr_traits",
"webxr-api", "webxr-api",
@ -4904,6 +5165,14 @@ dependencies = [
"gl_generator 0.13.1", "gl_generator 0.13.1",
] ]
[[package]]
name = "spirv_cross"
version = "0.16.0"
source = "git+https://github.com/kvark/spirv_cross?branch=wgpu#636677bad724797789239c16e6d332e9b4d97b86"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "stable_deref_trait" name = "stable_deref_trait"
version = "1.0.0" version = "1.0.0"
@ -4926,6 +5195,15 @@ dependencies = [
"embedder_traits", "embedder_traits",
] ]
[[package]]
name = "storage-map"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd0a4829a5c591dc24a944a736d6b1e4053e51339a79fd5d4702c4c999a9c45e"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "string" name = "string"
version = "0.2.1" version = "0.2.1"
@ -4971,7 +5249,7 @@ name = "style"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"app_units", "app_units",
"arrayvec", "arrayvec 0.4.6",
"atomic_refcell", "atomic_refcell",
"bindgen", "bindgen",
"bitflags", "bitflags",
@ -5583,7 +5861,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f" checksum = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f"
dependencies = [ dependencies = [
"arrayvec", "arrayvec 0.4.6",
] ]
[[package]] [[package]]
@ -5896,6 +6174,19 @@ dependencies = [
"webdriver", "webdriver",
] ]
[[package]]
name = "webgpu"
version = "0.0.1"
dependencies = [
"embedder_traits",
"ipc-channel",
"log",
"malloc_size_of",
"serde",
"servo_config",
"wgpu-native",
]
[[package]] [[package]]
name = "webrender" name = "webrender"
version = "0.60.0" version = "0.60.0"
@ -6037,6 +6328,30 @@ dependencies = [
"winit", "winit",
] ]
[[package]]
name = "wgpu-native"
version = "0.4.0"
source = "git+https://github.com/zakorgy/wgpu?branch=v0.4#128a16b9887a60a087a9d41ff68b20ce07cf6265"
dependencies = [
"arrayvec 0.5.1",
"bitflags",
"copyless",
"fxhash",
"gfx-backend-dx11",
"gfx-backend-dx12",
"gfx-backend-empty",
"gfx-backend-metal",
"gfx-backend-vulkan",
"gfx-hal",
"log",
"parking_lot",
"rendy-descriptor",
"rendy-memory",
"serde",
"smallvec",
"vec_map",
]
[[package]] [[package]]
name = "which" name = "which"
version = "3.0.0" version = "3.0.0"

View file

@ -29,3 +29,5 @@ opt-level = 3
mio = { git = "https://github.com/servo/mio.git", branch = "servo" } mio = { git = "https://github.com/servo/mio.git", branch = "servo" }
# https://github.com/retep998/winapi-rs/pull/816 # https://github.com/retep998/winapi-rs/pull/816
winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" } winapi = { git = "https://github.com/servo/winapi-rs", branch = "patch-1" }
spirv_cross = { git = "https://github.com/kvark/spirv_cross", branch = "wgpu" }
wgpu-native = { git = "https://github.com/zakorgy/wgpu", branch = "v0.4" }

View file

@ -713,6 +713,12 @@ pub fn from_cmdline_args(mut opts: Options, args: &[String]) -> ArgumentParsingR
"A preference to set to enable", "A preference to set to enable",
"dom.bluetooth.enabled", "dom.bluetooth.enabled",
); );
opts.optmulti(
"",
"pref",
"A preference to set to enable",
"dom.webgpu.enabled",
);
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
opts.optflag("w", "webrender", "Use webrender backend"); opts.optflag("w", "webrender", "Use webrender backend");
opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl"); opts.optopt("G", "graphics", "Select graphics backend (gl or es2)", "gl");

View file

@ -159,6 +159,9 @@ mod gen {
}, },
}, },
dom: { dom: {
webgpu: {
enabled: bool,
},
bluetooth: { bluetooth: {
enabled: bool, enabled: bool,
testing: { testing: {

View file

@ -47,6 +47,7 @@ servo_geometry = {path = "../geometry"}
servo_rand = {path = "../rand"} servo_rand = {path = "../rand"}
servo_remutex = {path = "../remutex"} servo_remutex = {path = "../remutex"}
servo_url = {path = "../url"} servo_url = {path = "../url"}
webgpu = {path = "../webgpu"}
webvr_traits = {path = "../webvr_traits"} webvr_traits = {path = "../webvr_traits"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]} webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}

View file

@ -172,6 +172,7 @@ use std::sync::Arc;
use std::thread; use std::thread;
use style_traits::viewport::ViewportConstraints; use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use webgpu::WebGPU;
use webvr_traits::{WebVREvent, WebVRMsg}; use webvr_traits::{WebVREvent, WebVRMsg};
type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>; type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;
@ -440,6 +441,10 @@ pub struct Constellation<Message, LTF, STF> {
/// Entry point to create and get channels to a WebGLThread. /// Entry point to create and get channels to a WebGLThread.
webgl_threads: Option<WebGLThreads>, webgl_threads: Option<WebGLThreads>,
/// An IPC channel for the constellation to send messages to the
/// WebGPU threads.
webgpu: Option<WebGPU>,
/// A channel through which messages can be sent to the webvr thread. /// A channel through which messages can be sent to the webvr thread.
webvr_chan: Option<IpcSender<WebVRMsg>>, webvr_chan: Option<IpcSender<WebVRMsg>>,
@ -521,6 +526,9 @@ pub struct InitialConstellationState {
/// Entry point to create and get channels to a WebGLThread. /// Entry point to create and get channels to a WebGLThread.
pub webgl_threads: Option<WebGLThreads>, pub webgl_threads: Option<WebGLThreads>,
/// A channel to the WebGPU threads.
pub webgpu: Option<WebGPU>,
/// A channel to the webgl thread. /// A channel to the webgl thread.
pub webvr_chan: Option<IpcSender<WebVRMsg>>, pub webvr_chan: Option<IpcSender<WebVRMsg>>,
@ -836,6 +844,7 @@ where
(rng, prob) (rng, prob)
}), }),
webgl_threads: state.webgl_threads, webgl_threads: state.webgl_threads,
webgpu: state.webgpu,
webvr_chan: state.webvr_chan, webvr_chan: state.webvr_chan,
webxr_registry: state.webxr_registry, webxr_registry: state.webxr_registry,
canvas_chan: CanvasPaintThread::start(), canvas_chan: CanvasPaintThread::start(),
@ -1090,6 +1099,7 @@ where
.webgl_threads .webgl_threads
.as_ref() .as_ref()
.map(|threads| threads.pipeline()), .map(|threads| threads.pipeline()),
webgpu: self.webgpu.clone(),
webvr_chan: self.webvr_chan.clone(), webvr_chan: self.webvr_chan.clone(),
webxr_registry: self.webxr_registry.clone(), webxr_registry: self.webxr_registry.clone(),
player_context: self.player_context.clone(), player_context: self.player_context.clone(),
@ -2355,6 +2365,17 @@ where
} }
} }
if let Some(webgpu) = self.webgpu.as_ref() {
debug!("Exiting WebGPU thread.");
let (sender, receiver) = ipc::channel().expect("Failed to create IPC channel!");
if let Err(e) = webgpu.exit(sender) {
warn!("Exit WebGPU Thread failed ({})", e);
}
if let Err(e) = receiver.recv() {
warn!("Failed to receive exit response from WebGPU ({})", e);
}
}
if let Some(chan) = self.webvr_chan.as_ref() { if let Some(chan) = self.webvr_chan.as_ref() {
debug!("Exiting WebVR thread."); debug!("Exiting WebVR thread.");
if let Err(e) = chan.send(WebVRMsg::Exit) { if let Err(e) = chan.send(WebVRMsg::Exit) {

View file

@ -46,6 +46,7 @@ use std::process;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use webgpu::WebGPU;
use webvr_traits::WebVRMsg; use webvr_traits::WebVRMsg;
/// A `Pipeline` is the constellation's view of a `Document`. Each pipeline has an /// A `Pipeline` is the constellation's view of a `Document`. Each pipeline has an
@ -188,6 +189,9 @@ pub struct InitialPipelineState {
/// A channel to the WebGL thread. /// A channel to the WebGL thread.
pub webgl_chan: Option<WebGLPipeline>, pub webgl_chan: Option<WebGLPipeline>,
/// A channel to the WebGPU threads.
pub webgpu: Option<WebGPU>,
/// A channel to the webvr thread. /// A channel to the webvr thread.
pub webvr_chan: Option<IpcSender<WebVRMsg>>, pub webvr_chan: Option<IpcSender<WebVRMsg>>,
@ -299,6 +303,7 @@ impl Pipeline {
webrender_document: state.webrender_document, webrender_document: state.webrender_document,
webgl_chan: state.webgl_chan, webgl_chan: state.webgl_chan,
webvr_chan: state.webvr_chan, webvr_chan: state.webvr_chan,
webgpu: state.webgpu,
webxr_registry: state.webxr_registry, webxr_registry: state.webxr_registry,
player_context: state.player_context, player_context: state.player_context,
}; };
@ -504,6 +509,7 @@ pub struct UnprivilegedPipelineContent {
webrender_api_sender: webrender_api::RenderApiSender, webrender_api_sender: webrender_api::RenderApiSender,
webrender_document: webrender_api::DocumentId, webrender_document: webrender_api::DocumentId,
webgl_chan: Option<WebGLPipeline>, webgl_chan: Option<WebGLPipeline>,
webgpu: Option<WebGPU>,
webvr_chan: Option<IpcSender<WebVRMsg>>, webvr_chan: Option<IpcSender<WebVRMsg>>,
webxr_registry: webxr_api::Registry, webxr_registry: webxr_api::Registry,
player_context: WindowGLContext, player_context: WindowGLContext,
@ -556,6 +562,7 @@ impl UnprivilegedPipelineContent {
pipeline_namespace_id: self.pipeline_namespace_id, pipeline_namespace_id: self.pipeline_namespace_id,
content_process_shutdown_chan: content_process_shutdown_chan, content_process_shutdown_chan: content_process_shutdown_chan,
webgl_chan: self.webgl_chan, webgl_chan: self.webgl_chan,
webgpu: self.webgpu,
webvr_chan: self.webvr_chan, webvr_chan: self.webvr_chan,
webxr_registry: self.webxr_registry, webxr_registry: self.webxr_registry,
webrender_document: self.webrender_document, webrender_document: self.webrender_document,

View file

@ -452,6 +452,11 @@ impl<'a> GlyphStore {
} }
} }
#[inline]
pub fn total_advance(&self) -> Au {
self.total_advance
}
#[inline] #[inline]
pub fn len(&self) -> ByteIndex { pub fn len(&self) -> ByteIndex {
ByteIndex(self.entry_buffer.len() as isize) ByteIndex(self.entry_buffer.len() as isize)

View file

@ -18,15 +18,19 @@ atomic_refcell = "0.1"
cssparser = "0.27" cssparser = "0.27"
euclid = "0.20" euclid = "0.20"
gfx = {path = "../gfx"} gfx = {path = "../gfx"}
gfx_traits = {path = "../gfx_traits"}
ipc-channel = "0.12" ipc-channel = "0.12"
libc = "0.2" libc = "0.2"
msg = {path = "../msg"} msg = {path = "../msg"}
range = {path = "../range"}
rayon = "1" rayon = "1"
rayon_croissant = "0.1.1" rayon_croissant = "0.1.1"
script_layout_interface = {path = "../script_layout_interface"} script_layout_interface = {path = "../script_layout_interface"}
script_traits = {path = "../script_traits"} script_traits = {path = "../script_traits"}
serde = "1.0" serde = "1.0"
servo_arc = { path = "../servo_arc" } servo_arc = { path = "../servo_arc" }
servo_geometry = {path = "../geometry"}
style = {path = "../style", features = ["servo", "servo-layout-2020"]} style = {path = "../style", features = ["servo", "servo-layout-2020"]}
style_traits = {path = "../style_traits"} style_traits = {path = "../style_traits"}
unicode-script = {version = "0.3", features = ["harfbuzz"]}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}

View file

@ -3,7 +3,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use gfx::font_cache_thread::FontCacheThread; use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context::FontContext;
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use std::cell::{RefCell, RefMut};
use std::sync::Mutex; use std::sync::Mutex;
use style::context::SharedStyleContext; use style::context::SharedStyleContext;
@ -19,3 +21,18 @@ impl<'a> LayoutContext<'a> {
&self.style_context &self.style_context
} }
} }
pub(crate) type LayoutFontContext = FontContext<FontCacheThread>;
thread_local!(static FONT_CONTEXT: RefCell<Option<LayoutFontContext>> = RefCell::new(None));
pub(crate) fn with_thread_local_font_context<F, R>(layout_context: &LayoutContext, f: F) -> R
where
F: FnOnce(&mut LayoutFontContext) -> R,
{
FONT_CONTEXT.with(|font_context| {
f(font_context.borrow_mut().get_or_insert_with(|| {
FontContext::new(layout_context.font_cache_thread.lock().unwrap().clone())
}))
})
}

View file

@ -6,7 +6,10 @@ use crate::fragments::{BoxFragment, Fragment};
use crate::geom::physical::{Rect, Vec2}; use crate::geom::physical::{Rect, Vec2};
use crate::style_ext::ComputedValuesExt; use crate::style_ext::ComputedValuesExt;
use app_units::Au; use app_units::Au;
use euclid::{self, SideOffsets2D}; use euclid::{Point2D, SideOffsets2D};
use gfx::text::glyph::GlyphStore;
use servo_geometry::MaxRect;
use std::sync::Arc;
use style::values::computed::{BorderStyle, Length}; use style::values::computed::{BorderStyle, Length};
use webrender_api::{self as wr, units, CommonItemProperties, PrimitiveFlags}; use webrender_api::{self as wr, units, CommonItemProperties, PrimitiveFlags};
@ -50,9 +53,30 @@ impl Fragment {
child.build_display_list(builder, is_contentful, &rect) child.build_display_list(builder, is_contentful, &rect)
} }
}, },
Fragment::Text(_) => { Fragment::Text(t) => {
is_contentful.0 = true; is_contentful.0 = true;
// FIXME let rect = t
.content_rect
.to_physical(t.parent_style.writing_mode(), containing_block)
.translate(&containing_block.top_left);
let mut baseline_origin = rect.top_left.clone();
baseline_origin.y += t.ascent;
let common = CommonItemProperties {
clip_rect: rect.clone().into(),
clip_id: wr::ClipId::root(builder.pipeline_id),
spatial_id: wr::SpatialId::root_scroll_node(builder.pipeline_id),
hit_info: None,
// TODO(gw): Make use of the WR backface visibility functionality.
flags: PrimitiveFlags::default(),
};
let glyphs = glyphs(&t.glyphs, baseline_origin);
if glyphs.is_empty() {
return;
}
let color = t.parent_style.clone_color();
builder
.wr
.push_text(&common, rect.into(), &glyphs, t.font_key, rgba(color), None);
}, },
} }
} }
@ -154,3 +178,28 @@ fn rgba(rgba: cssparser::RGBA) -> wr::ColorF {
rgba.alpha_f32(), rgba.alpha_f32(),
) )
} }
fn glyphs(glyph_runs: &[Arc<GlyphStore>], mut origin: Vec2<Length>) -> Vec<wr::GlyphInstance> {
use gfx_traits::ByteIndex;
use range::Range;
let mut glyphs = vec![];
for run in glyph_runs {
for glyph in run.iter_glyphs_for_byte_range(&Range::new(ByteIndex(0), run.len())) {
if !run.is_whitespace() {
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
let point = units::LayoutPoint::new(
origin.x.px() + glyph_offset.x.to_f32_px(),
origin.y.px() + glyph_offset.y.to_f32_px(),
);
let glyph = wr::GlyphInstance {
index: glyph.id(),
point,
};
glyphs.push(glyph);
}
origin.x += Length::from(glyph.advance());
}
}
glyphs
}

View file

@ -2,9 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext;
use crate::flow::float::FloatBox; use crate::flow::float::FloatBox;
use crate::flow::FlowChildren; use crate::flow::FlowChildren;
use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragments::{
AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment,
};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment}; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
@ -81,6 +84,7 @@ struct LinesBoxes {
impl InlineFormattingContext { impl InlineFormattingContext {
pub(super) fn layout<'a>( pub(super) fn layout<'a>(
&'a self, &'a self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
@ -107,7 +111,7 @@ impl InlineFormattingContext {
let partial = inline.start_layout(&mut ifc); let partial = inline.start_layout(&mut ifc);
ifc.partial_inline_boxes_stack.push(partial) ifc.partial_inline_boxes_stack.push(partial)
}, },
InlineLevelBox::TextRun(run) => run.layout(&mut ifc), InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc),
InlineLevelBox::Atomic { style: _, contents } => { InlineLevelBox::Atomic { style: _, contents } => {
// FIXME // FIXME
match *contents {} match *contents {}
@ -284,7 +288,141 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
} }
impl TextRun { impl TextRun {
fn layout(&self, _ifc: &mut InlineFormattingContextState) { fn layout(&self, layout_context: &LayoutContext, ifc: &mut InlineFormattingContextState) {
// TODO use gfx::font::{ShapingFlags, ShapingOptions};
use style::computed_values::text_rendering::T as TextRendering;
use style::computed_values::word_break::T as WordBreak;
use style::values::generics::text::LineHeight;
let font_style = self.parent_style.clone_font();
let inherited_text_style = self.parent_style.get_inherited_text();
let letter_spacing = if inherited_text_style.letter_spacing.0.px() != 0. {
Some(app_units::Au::from(inherited_text_style.letter_spacing.0))
} else {
None
};
let mut flags = ShapingFlags::empty();
if letter_spacing.is_some() {
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
}
if inherited_text_style.text_rendering == TextRendering::Optimizespeed {
flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG);
flags.insert(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG)
}
if inherited_text_style.word_break == WordBreak::KeepAll {
flags.insert(ShapingFlags::KEEP_ALL_FLAG);
}
let shaping_options = gfx::font::ShapingOptions {
letter_spacing,
word_spacing: inherited_text_style.word_spacing.to_hash_key(),
script: unicode_script::Script::Common,
flags,
};
let (font_ascent, font_line_gap, font_key, runs) =
crate::context::with_thread_local_font_context(layout_context, |font_context| {
let font_group = font_context.font_group(font_style);
let font = font_group
.borrow_mut()
.first(font_context)
.expect("could not find font");
let mut font = font.borrow_mut();
let (runs, _break_at_start) = gfx::text::text_run::TextRun::break_and_shape(
&mut font,
&self.text,
&shaping_options,
&mut None,
);
(
font.metrics.ascent,
font.metrics.line_gap,
font.font_key,
runs,
)
});
let font_size = self.parent_style.get_font().font_size.size.0;
let mut runs = runs.iter();
loop {
let mut glyphs = vec![];
let mut advance_width = Length::zero();
let mut last_break_opportunity = None;
loop {
let next = runs.next();
if next
.as_ref()
.map_or(true, |run| run.glyph_store.is_whitespace())
{
if advance_width > ifc.containing_block.inline_size - ifc.inline_position {
if let Some((len, width, iter)) = last_break_opportunity.take() {
glyphs.truncate(len);
advance_width = width;
runs = iter;
}
break;
}
}
if let Some(run) = next {
if run.glyph_store.is_whitespace() {
last_break_opportunity = Some((glyphs.len(), advance_width, runs.clone()));
}
glyphs.push(run.glyph_store.clone());
advance_width += Length::from(run.glyph_store.total_advance());
} else {
break;
}
}
let line_height = match self.parent_style.get_inherited_text().line_height {
LineHeight::Normal => font_line_gap.into(),
LineHeight::Number(n) => font_size * n.0,
LineHeight::Length(l) => l.0,
};
let content_rect = Rect {
start_corner: Vec2 {
block: Length::zero(),
inline: ifc.inline_position - ifc.current_nesting_level.inline_start,
},
size: Vec2 {
block: line_height,
inline: advance_width,
},
};
ifc.inline_position += advance_width;
ifc.current_nesting_level
.max_block_size_of_fragments_so_far
.max_assign(line_height);
ifc.current_nesting_level
.fragments_so_far
.push(Fragment::Text(TextFragment {
parent_style: self.parent_style.clone(),
content_rect,
ascent: font_ascent.into(),
font_key,
glyphs,
}));
if runs.is_empty() {
break;
} else {
// New line
ifc.current_nesting_level.inline_start = Length::zero();
let mut nesting_level = &mut ifc.current_nesting_level;
for partial in ifc.partial_inline_boxes_stack.iter_mut().rev() {
partial.finish_layout(nesting_level, &mut ifc.inline_position, true);
partial.start_corner.inline = Length::zero();
partial.padding.inline_start = Length::zero();
partial.border.inline_start = Length::zero();
partial.margin.inline_start = Length::zero();
partial.parent_nesting_level.inline_start = Length::zero();
nesting_level = &mut partial.parent_nesting_level;
}
ifc.line_boxes
.finish_line(nesting_level, ifc.containing_block);
ifc.inline_position = Length::zero();
}
}
} }
} }

View file

@ -4,6 +4,7 @@
//! Flow layout, also known as block-and-inline layout. //! Flow layout, also known as block-and-inline layout.
use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::float::{FloatBox, FloatContext};
use crate::flow::inline::InlineFormattingContext; use crate::flow::inline::InlineFormattingContext;
use crate::fragments::{ use crate::fragments::{
@ -67,6 +68,7 @@ struct CollapsibleWithParentStartMargin(bool);
impl BlockFormattingContext { impl BlockFormattingContext {
pub(super) fn layout<'a>( pub(super) fn layout<'a>(
&'a self, &'a self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
@ -79,6 +81,7 @@ impl BlockFormattingContext {
None None
}; };
let mut flow_children = self.contents.layout( let mut flow_children = self.contents.layout(
layout_context,
containing_block, containing_block,
tree_rank, tree_rank,
absolutely_positioned_fragments, absolutely_positioned_fragments,
@ -97,6 +100,7 @@ impl BlockFormattingContext {
impl BlockContainer { impl BlockContainer {
fn layout<'a>( fn layout<'a>(
&'a self, &'a self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
@ -105,6 +109,7 @@ impl BlockContainer {
) -> FlowChildren { ) -> FlowChildren {
match self { match self {
BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children( BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children(
layout_context,
child_boxes, child_boxes,
containing_block, containing_block,
tree_rank, tree_rank,
@ -112,14 +117,18 @@ impl BlockContainer {
float_context, float_context,
collapsible_with_parent_start_margin, collapsible_with_parent_start_margin,
), ),
BlockContainer::InlineFormattingContext(ifc) => { BlockContainer::InlineFormattingContext(ifc) => ifc.layout(
ifc.layout(containing_block, tree_rank, absolutely_positioned_fragments) layout_context,
}, containing_block,
tree_rank,
absolutely_positioned_fragments,
),
} }
} }
} }
fn layout_block_level_children<'a>( fn layout_block_level_children<'a>(
layout_context: &LayoutContext,
child_boxes: &'a [Arc<BlockLevelBox>], child_boxes: &'a [Arc<BlockLevelBox>],
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
@ -201,6 +210,7 @@ fn layout_block_level_children<'a>(
.enumerate() .enumerate()
.map(|(tree_rank, box_)| { .map(|(tree_rank, box_)| {
let mut fragment = box_.layout( let mut fragment = box_.layout(
layout_context,
containing_block, containing_block,
tree_rank, tree_rank,
absolutely_positioned_fragments, absolutely_positioned_fragments,
@ -218,6 +228,7 @@ fn layout_block_level_children<'a>(
absolutely_positioned_fragments, absolutely_positioned_fragments,
|abspos_fragments, (tree_rank, box_)| { |abspos_fragments, (tree_rank, box_)| {
box_.layout( box_.layout(
layout_context,
containing_block, containing_block,
tree_rank, tree_rank,
abspos_fragments, abspos_fragments,
@ -255,6 +266,7 @@ fn layout_block_level_children<'a>(
impl BlockLevelBox { impl BlockLevelBox {
fn layout<'a>( fn layout<'a>(
&'a self, &'a self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
@ -263,12 +275,14 @@ impl BlockLevelBox {
match self { match self {
BlockLevelBox::SameFormattingContextBlock { style, contents } => { BlockLevelBox::SameFormattingContextBlock { style, contents } => {
Fragment::Box(layout_in_flow_non_replaced_block_level( Fragment::Box(layout_in_flow_non_replaced_block_level(
layout_context,
containing_block, containing_block,
absolutely_positioned_fragments, absolutely_positioned_fragments,
style, style,
BlockLevelKind::SameFormattingContextBlock, BlockLevelKind::SameFormattingContextBlock,
|containing_block, nested_abspos, collapsible_with_parent_start_margin| { |containing_block, nested_abspos, collapsible_with_parent_start_margin| {
contents.layout( contents.layout(
layout_context,
containing_block, containing_block,
tree_rank, tree_rank,
nested_abspos, nested_abspos,
@ -284,12 +298,13 @@ impl BlockLevelBox {
match *replaced {} match *replaced {}
}, },
Err(contents) => Fragment::Box(layout_in_flow_non_replaced_block_level( Err(contents) => Fragment::Box(layout_in_flow_non_replaced_block_level(
layout_context,
containing_block, containing_block,
absolutely_positioned_fragments, absolutely_positioned_fragments,
style, style,
BlockLevelKind::EstablishesAnIndependentFormattingContext, BlockLevelKind::EstablishesAnIndependentFormattingContext,
|containing_block, nested_abspos, _| { |containing_block, nested_abspos, _| {
contents.layout(containing_block, tree_rank, nested_abspos) contents.layout(layout_context, containing_block, tree_rank, nested_abspos)
}, },
)), )),
}, },
@ -314,6 +329,7 @@ enum BlockLevelKind {
/// https://drafts.csswg.org/css2/visudet.html#blockwidth /// https://drafts.csswg.org/css2/visudet.html#blockwidth
/// https://drafts.csswg.org/css2/visudet.html#normal-block /// https://drafts.csswg.org/css2/visudet.html#normal-block
fn layout_in_flow_non_replaced_block_level<'a>( fn layout_in_flow_non_replaced_block_level<'a>(
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
@ -433,6 +449,7 @@ fn layout_in_flow_non_replaced_block_level<'a>(
}; };
if style.get_box().position == Position::Relative { if style.get_box().position == Position::Relative {
AbsolutelyPositionedFragment::in_positioned_containing_block( AbsolutelyPositionedFragment::in_positioned_containing_block(
layout_context,
&nested_abspos, &nested_abspos,
&mut flow_children.fragments, &mut flow_children.fragments,
&content_rect.size, &content_rect.size,

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext;
use crate::display_list::IsContentful; use crate::display_list::IsContentful;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeExt};
use crate::flow::construct::ContainsFloats; use crate::flow::construct::ContainsFloats;
@ -98,7 +99,11 @@ fn construct_for_root_element<'dom>(
} }
impl BoxTreeRoot { impl BoxTreeRoot {
pub fn layout(&self, viewport: geom::Size<CSSPixel>) -> FragmentTreeRoot { pub fn layout(
&self,
layout_context: &LayoutContext,
viewport: geom::Size<CSSPixel>,
) -> FragmentTreeRoot {
let initial_containing_block_size = Vec2 { let initial_containing_block_size = Vec2 {
inline: Length::new(viewport.width), inline: Length::new(viewport.width),
block: Length::new(viewport.height), block: Length::new(viewport.height),
@ -114,6 +119,7 @@ impl BoxTreeRoot {
let dummy_tree_rank = 0; let dummy_tree_rank = 0;
let mut absolutely_positioned_fragments = vec![]; let mut absolutely_positioned_fragments = vec![];
let mut flow_children = self.0.layout( let mut flow_children = self.0.layout(
layout_context,
&initial_containing_block, &initial_containing_block,
dummy_tree_rank, dummy_tree_rank,
&mut absolutely_positioned_fragments, &mut absolutely_positioned_fragments,
@ -126,7 +132,7 @@ impl BoxTreeRoot {
flow_children.fragments.par_extend( flow_children.fragments.par_extend(
absolutely_positioned_fragments absolutely_positioned_fragments
.par_iter() .par_iter()
.map(|a| a.layout(&initial_containing_block)), .map(|a| a.layout(layout_context, &initial_containing_block)),
); );
FragmentTreeRoot(flow_children.fragments) FragmentTreeRoot(flow_children.fragments)
} }

View file

@ -4,11 +4,13 @@
use crate::geom::flow_relative::{Rect, Sides}; use crate::geom::flow_relative::{Rect, Sides};
use crate::style_ext::{Direction, WritingMode}; use crate::style_ext::{Direction, WritingMode};
// use crate::text::ShapedSegment; use gfx::text::glyph::GlyphStore;
use servo_arc::Arc; use servo_arc::Arc as ServoArc;
use std::sync::Arc;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::Length; use style::values::computed::Length;
use style::Zero; use style::Zero;
use webrender_api::FontInstanceKey;
pub(crate) enum Fragment { pub(crate) enum Fragment {
Box(BoxFragment), Box(BoxFragment),
@ -17,7 +19,7 @@ pub(crate) enum Fragment {
} }
pub(crate) struct BoxFragment { pub(crate) struct BoxFragment {
pub style: Arc<ComputedValues>, pub style: ServoArc<ComputedValues>,
pub children: Vec<Fragment>, pub children: Vec<Fragment>,
/// From the containing blocks start corner…? /// From the containing blocks start corner…?
@ -52,9 +54,11 @@ pub(crate) struct AnonymousFragment {
} }
pub(crate) struct TextFragment { pub(crate) struct TextFragment {
pub parent_style: Arc<ComputedValues>, pub parent_style: ServoArc<ComputedValues>,
pub content_rect: Rect<Length>, pub content_rect: Rect<Length>,
// pub text: ShapedSegment, pub ascent: Length,
pub font_key: FontInstanceKey,
pub glyphs: Vec<Arc<GlyphStore>>,
} }
impl AnonymousFragment { impl AnonymousFragment {

View file

@ -7,6 +7,7 @@
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(unused_variables)] #![allow(unused_variables)]
#![deny(unsafe_code)] #![deny(unsafe_code)]
#![feature(exact_size_is_empty)]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
@ -33,6 +34,7 @@ pub mod wrapper;
pub use flow::{BoxTreeRoot, FragmentTreeRoot}; pub use flow::{BoxTreeRoot, FragmentTreeRoot};
use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeExt};
use crate::flow::{BlockFormattingContext, FlowChildren}; use crate::flow::{BlockFormattingContext, FlowChildren};
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
@ -87,13 +89,19 @@ impl IndependentFormattingContext {
fn layout<'a>( fn layout<'a>(
&'a self, &'a self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren { ) -> FlowChildren {
match self.as_replaced() { match self.as_replaced() {
Ok(replaced) => match *replaced {}, Ok(replaced) => match *replaced {},
Err(ifc) => ifc.layout(containing_block, tree_rank, absolutely_positioned_fragments), Err(ifc) => ifc.layout(
layout_context,
containing_block,
tree_rank,
absolutely_positioned_fragments,
),
} }
} }
} }
@ -101,14 +109,18 @@ impl IndependentFormattingContext {
impl<'a> NonReplacedIFC<'a> { impl<'a> NonReplacedIFC<'a> {
fn layout( fn layout(
&self, &self,
layout_context: &LayoutContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>,
) -> FlowChildren { ) -> FlowChildren {
match self { match self {
NonReplacedIFC::Flow(bfc) => { NonReplacedIFC::Flow(bfc) => bfc.layout(
bfc.layout(containing_block, tree_rank, absolutely_positioned_fragments) layout_context,
}, containing_block,
tree_rank,
absolutely_positioned_fragments,
),
} }
} }
} }

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext;
use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::style_ext::{ComputedValuesExt, Direction, WritingMode}; use crate::style_ext::{ComputedValuesExt, Direction, WritingMode};
@ -94,6 +95,7 @@ impl AbsolutelyPositionedBox {
impl<'a> AbsolutelyPositionedFragment<'a> { impl<'a> AbsolutelyPositionedFragment<'a> {
pub(crate) fn in_positioned_containing_block( pub(crate) fn in_positioned_containing_block(
layout_context: &LayoutContext,
absolute: &[Self], absolute: &[Self],
fragments: &mut Vec<Fragment>, fragments: &mut Vec<Fragment>,
content_rect_size: &Vec2<Length>, content_rect_size: &Vec2<Length>,
@ -116,14 +118,18 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
fragments.push(Fragment::Anonymous(AnonymousFragment { fragments.push(Fragment::Anonymous(AnonymousFragment {
children: absolute children: absolute
.par_iter() .par_iter()
.map(|a| a.layout(&containing_block)) .map(|a| a.layout(layout_context, &containing_block))
.collect(), .collect(),
rect: padding_rect, rect: padding_rect,
mode, mode,
})) }))
} }
pub(crate) fn layout(&self, containing_block: &DefiniteContainingBlock) -> Fragment { pub(crate) fn layout(
&self,
layout_context: &LayoutContext,
containing_block: &DefiniteContainingBlock,
) -> Fragment {
let style = &self.absolutely_positioned_box.style; let style = &self.absolutely_positioned_box.style;
let cbis = containing_block.size.inline; let cbis = containing_block.size.inline;
let cbbs = containing_block.size.block; let cbbs = containing_block.size.block;
@ -269,6 +275,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
let dummy_tree_rank = 0; let dummy_tree_rank = 0;
let mut absolutely_positioned_fragments = vec![]; let mut absolutely_positioned_fragments = vec![];
let mut flow_children = self.absolutely_positioned_box.contents.layout( let mut flow_children = self.absolutely_positioned_box.contents.layout(
layout_context,
&containing_block_for_children, &containing_block_for_children,
dummy_tree_rank, dummy_tree_rank,
&mut absolutely_positioned_fragments, &mut absolutely_positioned_fragments,
@ -297,6 +304,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
}; };
AbsolutelyPositionedFragment::in_positioned_containing_block( AbsolutelyPositionedFragment::in_positioned_containing_block(
layout_context,
&absolutely_positioned_fragments, &absolutely_positioned_fragments,
&mut flow_children.fragments, &mut flow_children.fragments,
&content_rect.size, &content_rect.size,

View file

@ -88,7 +88,7 @@ use style::context::{SharedStyleContext, ThreadLocalStyleContextCreationInfo};
use style::dom::{TDocument, TElement, TNode}; use style::dom::{TDocument, TElement, TNode};
use style::driver; use style::driver;
use style::error_reporting::RustLogReporter; use style::error_reporting::RustLogReporter;
use style::global_style_data::GLOBAL_STYLE_DATA; use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL};
use style::invalidation::element::restyle_hints::RestyleHint; use style::invalidation::element::restyle_hints::RestyleHint;
use style::media_queries::{Device, MediaList, MediaType}; use style::media_queries::{Device, MediaList, MediaType};
use style::properties::PropertyId; use style::properties::PropertyId;
@ -1087,16 +1087,29 @@ impl LayoutThread {
RecalcStyle::pre_traverse(element, shared) RecalcStyle::pre_traverse(element, shared)
}; };
if token.should_traverse() { let rayon_pool = STYLE_THREAD_POOL.pool();
let rayon_pool = rayon_pool.as_ref().unwrap();
let box_tree = if token.should_traverse() {
driver::traverse_dom(&traversal, token, None); driver::traverse_dom(&traversal, token, None);
let shared = DomTraversal::<ServoLayoutElement>::shared_context(&traversal); let shared = DomTraversal::<ServoLayoutElement>::shared_context(&traversal);
let box_tree = let root_node = document.root_element().unwrap().as_node();
BoxTreeRoot::construct(shared, document.root_element().unwrap().as_node()); let box_tree = rayon_pool.install(|| BoxTreeRoot::construct(shared, root_node));
let fragment_tree = box_tree.layout(Size2D::new( Some(box_tree)
} else {
None
};
layout_context = traversal.destroy();
if let Some(box_tree) = box_tree {
let viewport_size = Size2D::new(
self.viewport_size.width.to_f32_px(), self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px(), self.viewport_size.height.to_f32_px(),
)); );
let fragment_tree =
rayon_pool.install(|| box_tree.layout(&layout_context, viewport_size));
*self.box_tree_root.borrow_mut() = Some(box_tree); *self.box_tree_root.borrow_mut() = Some(box_tree);
*self.fragment_tree_root.borrow_mut() = Some(fragment_tree); *self.fragment_tree_root.borrow_mut() = Some(fragment_tree);
} }
@ -1105,8 +1118,6 @@ impl LayoutThread {
unsafe { element.unset_snapshot_flags() } unsafe { element.unset_snapshot_flags() }
} }
layout_context = traversal.destroy();
// GC the rule tree if some heuristics are met. // GC the rule tree if some heuristics are met.
unsafe { unsafe {
layout_context.style_context.stylist.rule_tree().maybe_gc(); layout_context.style_context.stylist.rule_tree().maybe_gc();

View file

@ -113,6 +113,7 @@ utf-8 = "0.7"
uuid = {version = "0.8", features = ["v4"]} uuid = {version = "0.8", features = ["v4"]}
xml5ever = "0.16" xml5ever = "0.16"
webdriver = "0.40" webdriver = "0.40"
webgpu = {path = "../webgpu"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"} webvr_traits = {path = "../webvr_traits"}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]} webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}

View file

@ -134,7 +134,10 @@ DOMInterfaces = {
'XR': { 'XR': {
'inCompartments': ['SupportsSessionMode', 'RequestSession'], 'inCompartments': ['SupportsSessionMode', 'RequestSession'],
},
'GPU': {
'inCompartments': ['RequestAdapter'],
} }
} }

View file

@ -145,6 +145,7 @@ use tendril::stream::LossyDecoder;
use tendril::{StrTendril, TendrilSink}; use tendril::{StrTendril, TendrilSink};
use time::{Duration, Timespec}; use time::{Duration, Timespec};
use uuid::Uuid; use uuid::Uuid;
use webgpu::{WebGPU, WebGPUAdapter};
use webrender_api::{DocumentId, ImageKey, RenderApiSender}; use webrender_api::{DocumentId, ImageKey, RenderApiSender};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState}; use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
use webxr_api::SwapChainId as WebXRSwapChainId; use webxr_api::SwapChainId as WebXRSwapChainId;
@ -502,6 +503,8 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId);
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId); unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
unsafe_no_jsmanaged_fields!(WebGLVersion); unsafe_no_jsmanaged_fields!(WebGLVersion);
unsafe_no_jsmanaged_fields!(WebGLSLVersion); unsafe_no_jsmanaged_fields!(WebGLSLVersion);
unsafe_no_jsmanaged_fields!(WebGPU);
unsafe_no_jsmanaged_fields!(WebGPUAdapter);
unsafe_no_jsmanaged_fields!(WebXRSwapChainId); unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList); unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand); unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);

View file

@ -5,7 +5,7 @@
use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods; use crate::dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use crate::dom::bindings::codegen::Bindings::FormDataEventBinding; use crate::dom::bindings::codegen::Bindings::FormDataEventBinding;
use crate::dom::bindings::codegen::Bindings::FormDataEventBinding::FormDataEventMethods; use crate::dom::bindings::codegen::Bindings::FormDataEventBinding::FormDataEventMethods;
use crate::dom::bindings::error::{Error, Fallible}; use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::bindings::root::{Dom, DomRoot};
@ -56,21 +56,12 @@ impl FormDataEvent {
let bubbles = EventBubbles::from(init.parent.bubbles); let bubbles = EventBubbles::from(init.parent.bubbles);
let cancelable = EventCancelable::from(init.parent.cancelable); let cancelable = EventCancelable::from(init.parent.cancelable);
let form_data = match init.formData {
Some(ref form_data) => form_data.clone(),
None => {
return Err(Error::Type(
"required member formData is undefined".to_string(),
));
},
};
let event = FormDataEvent::new( let event = FormDataEvent::new(
&window.global(), &window.global(),
Atom::from(type_), Atom::from(type_),
bubbles, bubbles,
cancelable, cancelable,
&*form_data, &*init.formData.clone(),
); );
Ok(event) Ok(event)

View file

@ -0,0 +1,158 @@
/* 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 crate::compartments::InCompartment;
use crate::dom::bindings::codegen::Bindings::GPUBinding::GPURequestAdapterOptions;
use crate::dom::bindings::codegen::Bindings::GPUBinding::{self, GPUMethods, GPUPowerPreference};
use crate::dom::bindings::error::Error;
use crate::dom::bindings::refcounted::{Trusted, TrustedPromise};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::promise::Promise;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::Heap;
use std::rc::Rc;
use webgpu::wgpu;
use webgpu::{WebGPU, WebGPURequest, WebGPUResponse, WebGPUResponseResult};
#[dom_struct]
pub struct GPU {
reflector_: Reflector,
}
impl GPU {
pub fn new_inherited() -> GPU {
GPU {
reflector_: Reflector::new(),
}
}
pub fn new(global: &GlobalScope) -> DomRoot<GPU> {
reflect_dom_object(Box::new(GPU::new_inherited()), global, GPUBinding::Wrap)
}
fn wgpu_channel(&self) -> Option<WebGPU> {
self.global().as_window().webgpu_channel()
}
}
pub trait AsyncWGPUListener {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>);
}
struct WGPUResponse<T: AsyncWGPUListener + DomObject> {
trusted: TrustedPromise,
receiver: Trusted<T>,
}
impl<T: AsyncWGPUListener + DomObject> WGPUResponse<T> {
#[allow(unrooted_must_root)]
fn response(self, response: WebGPUResponseResult) {
let promise = self.trusted.root();
match response {
Ok(response) => self.receiver.root().handle_response(response, &promise),
Err(error) => promise.reject_error(Error::Type(format!(
"Received error from WebGPU thread: {}",
error
))),
}
}
}
pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
promise: &Rc<Promise>,
receiver: &T,
) -> IpcSender<WebGPUResponseResult> {
let (action_sender, action_receiver) = ipc::channel().unwrap();
let (task_source, canceller) = receiver
.global()
.as_window()
.task_manager()
.dom_manipulation_task_source_with_canceller();
let mut trusted = Some(TrustedPromise::new(promise.clone()));
let trusted_receiver = Trusted::new(receiver);
ROUTER.add_route(
action_receiver.to_opaque(),
Box::new(move |message| {
let trusted = if let Some(trusted) = trusted.take() {
trusted
} else {
error!("WebGPU callback called twice!");
return;
};
let context = WGPUResponse {
trusted,
receiver: trusted_receiver.clone(),
};
let result = task_source.queue_with_canceller(
task!(process_webgpu_task: move|| {
context.response(message.to().unwrap());
}),
&canceller,
);
if let Err(err) = result {
error!("Failed to queue GPU listener-task: {:?}", err);
}
}),
);
action_sender
}
impl GPUMethods for GPU {
// https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter
fn RequestAdapter(
&self,
options: &GPURequestAdapterOptions,
comp: InCompartment,
) -> Rc<Promise> {
let promise = Promise::new_in_current_compartment(&self.global(), comp);
let sender = response_async(&promise, self);
let power_preference = match options.powerPreference {
Some(GPUPowerPreference::Low_power) => wgpu::PowerPreference::LowPower,
Some(GPUPowerPreference::High_performance) => wgpu::PowerPreference::HighPerformance,
None => wgpu::PowerPreference::Default,
};
match self.wgpu_channel() {
Some(channel) => {
channel
.0
.send(WebGPURequest::RequestAdapter(
sender,
wgpu::RequestAdapterOptions { power_preference },
))
.unwrap();
},
None => promise.reject_error(Error::Type("No WebGPU thread...".to_owned())),
};
promise
}
}
impl AsyncWGPUListener for GPU {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) {
match response {
WebGPUResponse::RequestAdapter(name, adapter) => {
let adapter = GPUAdapter::new(
&self.global(),
DOMString::from(name),
Heap::default(),
adapter,
);
promise.resolve_native(&adapter);
},
response => promise.reject_error(Error::Type(format!(
"Wrong response received for GPU from WebGPU thread {:?}",
response,
))),
}
}
}

View file

@ -0,0 +1,63 @@
/* 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 crate::dom::bindings::codegen::Bindings::GPUAdapterBinding::{self, GPUAdapterMethods};
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::JSContext as SafeJSContext;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSObject};
use std::ptr::NonNull;
use webgpu::WebGPUAdapter;
#[dom_struct]
pub struct GPUAdapter {
reflector_: Reflector,
name: DOMString,
#[ignore_malloc_size_of = "mozjs"]
extensions: Heap<*mut JSObject>,
adapter: WebGPUAdapter,
}
impl GPUAdapter {
pub fn new_inherited(
name: DOMString,
extensions: Heap<*mut JSObject>,
adapter: WebGPUAdapter,
) -> GPUAdapter {
GPUAdapter {
reflector_: Reflector::new(),
name,
extensions,
adapter,
}
}
pub fn new(
global: &GlobalScope,
name: DOMString,
extensions: Heap<*mut JSObject>,
adapter: WebGPUAdapter,
) -> DomRoot<GPUAdapter> {
reflect_dom_object(
Box::new(GPUAdapter::new_inherited(name, extensions, adapter)),
global,
GPUAdapterBinding::Wrap,
)
}
}
impl GPUAdapterMethods for GPUAdapter {
// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-name
fn Name(&self) -> DOMString {
self.name.clone()
}
// https://gpuweb.github.io/gpuweb/#dom-gpuadapter-extensions
fn Extensions(&self, _cx: SafeJSContext) -> NonNull<JSObject> {
NonNull::new(self.extensions.get()).unwrap()
}
}

View file

@ -315,6 +315,8 @@ pub mod gamepadbuttonlist;
pub mod gamepadevent; pub mod gamepadevent;
pub mod gamepadlist; pub mod gamepadlist;
pub mod globalscope; pub mod globalscope;
pub mod gpu;
pub mod gpuadapter;
pub mod hashchangeevent; pub mod hashchangeevent;
pub mod headers; pub mod headers;
pub mod history; pub mod history;

View file

@ -11,6 +11,7 @@ use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::bluetooth::Bluetooth; use crate::dom::bluetooth::Bluetooth;
use crate::dom::gamepadlist::GamepadList; use crate::dom::gamepadlist::GamepadList;
use crate::dom::gpu::GPU;
use crate::dom::mediadevices::MediaDevices; use crate::dom::mediadevices::MediaDevices;
use crate::dom::mediasession::MediaSession; use crate::dom::mediasession::MediaSession;
use crate::dom::mimetypearray::MimeTypeArray; use crate::dom::mimetypearray::MimeTypeArray;
@ -36,6 +37,7 @@ pub struct Navigator {
gamepads: MutNullableDom<GamepadList>, gamepads: MutNullableDom<GamepadList>,
permissions: MutNullableDom<Permissions>, permissions: MutNullableDom<Permissions>,
mediasession: MutNullableDom<MediaSession>, mediasession: MutNullableDom<MediaSession>,
gpu: MutNullableDom<GPU>,
} }
impl Navigator { impl Navigator {
@ -51,6 +53,7 @@ impl Navigator {
gamepads: Default::default(), gamepads: Default::default(),
permissions: Default::default(), permissions: Default::default(),
mediasession: Default::default(), mediasession: Default::default(),
gpu: Default::default(),
} }
} }
@ -205,4 +208,9 @@ impl NavigatorMethods for Navigator {
MediaSession::new(window) MediaSession::new(window)
}) })
} }
// https://gpuweb.github.io/gpuweb/#dom-navigator-gpu
fn Gpu(&self) -> DomRoot<GPU> {
self.gpu.or_init(|| GPU::new(&self.global()))
}
} }

View file

@ -5,10 +5,10 @@
// https://html.spec.whatwg.org/multipage/#the-formdataevent-interface // https://html.spec.whatwg.org/multipage/#the-formdataevent-interface
[Exposed=Window] [Exposed=Window]
interface FormDataEvent : Event { interface FormDataEvent : Event {
[Throws] constructor(DOMString type, optional FormDataEventInit eventInitDict = {}); [Throws] constructor(DOMString type, FormDataEventInit eventInitDict);
readonly attribute FormData formData; readonly attribute FormData formData;
}; };
dictionary FormDataEventInit : EventInit { dictionary FormDataEventInit : EventInit {
/*required*/ FormData formData; required FormData formData;
}; };

View file

@ -0,0 +1,21 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpu-interface
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPU {
// May reject with DOMException // TODO: DOMException("OperationError")?
Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {});
};
// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions
dictionary GPURequestAdapterOptions {
GPUPowerPreference powerPreference;
};
// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference
enum GPUPowerPreference {
"low-power",
"high-performance"
};

View file

@ -0,0 +1,14 @@
/* 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/. */
// https://gpuweb.github.io/gpuweb/#gpuadapter
[Exposed=(Window, DedicatedWorker), Pref="dom.webgpu.enabled"]
interface GPUAdapter {
readonly attribute DOMString name;
readonly attribute object extensions;
//readonly attribute GPULimits limits; Dont expose higher limits for now.
// May reject with DOMException // TODO: DOMException("OperationError")?
// Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
};

View file

@ -75,3 +75,8 @@ partial interface Navigator {
partial interface Navigator { partial interface Navigator {
[Pref="dom.gamepad.enabled"] GamepadList getGamepads(); [Pref="dom.gamepad.enabled"] GamepadList getGamepads();
}; };
[Exposed=Window]
partial interface Navigator {
[SameObject, Pref="dom.webgpu.enabled"] readonly attribute GPU gpu;
};

View file

@ -15,3 +15,8 @@ WorkerNavigator includes NavigatorLanguage;
partial interface WorkerNavigator { partial interface WorkerNavigator {
[Pref="dom.permissions.enabled"] readonly attribute Permissions permissions; [Pref="dom.permissions.enabled"] readonly attribute Permissions permissions;
}; };
[Exposed=DedicatedWorker]
partial interface WorkerNavigator {
[SameObject, Pref="dom.webgpu.enabled"] readonly attribute GPU gpu;
};

View file

@ -136,6 +136,7 @@ use style::str::HTML_SPACE_CHARACTERS;
use style::stylesheets::CssRuleType; use style::stylesheets::CssRuleType;
use style_traits::{CSSPixel, DevicePixel, ParsingMode}; use style_traits::{CSSPixel, DevicePixel, ParsingMode};
use url::Position; use url::Position;
use webgpu::WebGPU;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel}; use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId, RenderApiSender}; use webrender_api::{DocumentId, ExternalScrollId, RenderApiSender};
use webvr_traits::WebVRMsg; use webvr_traits::WebVRMsg;
@ -267,6 +268,10 @@ pub struct Window {
#[ignore_malloc_size_of = "channels are hard"] #[ignore_malloc_size_of = "channels are hard"]
webgl_chan: Option<WebGLChan>, webgl_chan: Option<WebGLChan>,
#[ignore_malloc_size_of = "channels are hard"]
/// A handle for communicating messages to the WebGPU threads.
webgpu: Option<WebGPU>,
/// A handle for communicating messages to the webvr thread, if available. /// A handle for communicating messages to the webvr thread, if available.
#[ignore_malloc_size_of = "channels are hard"] #[ignore_malloc_size_of = "channels are hard"]
webvr_chan: Option<IpcSender<WebVRMsg>>, webvr_chan: Option<IpcSender<WebVRMsg>>,
@ -462,6 +467,10 @@ impl Window {
.map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker())) .map(|chan| WebGLCommandSender::new(chan.clone(), self.get_event_loop_waker()))
} }
pub fn webgpu_channel(&self) -> Option<WebGPU> {
self.webgpu.clone()
}
pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> { pub fn webvr_thread(&self) -> Option<IpcSender<WebVRMsg>> {
self.webvr_chan.clone() self.webvr_chan.clone()
} }
@ -2206,6 +2215,7 @@ impl Window {
navigation_start: u64, navigation_start: u64,
navigation_start_precise: u64, navigation_start_precise: u64,
webgl_chan: Option<WebGLChan>, webgl_chan: Option<WebGLChan>,
webgpu: Option<WebGPU>,
webvr_chan: Option<IpcSender<WebVRMsg>>, webvr_chan: Option<IpcSender<WebVRMsg>>,
webxr_registry: webxr_api::Registry, webxr_registry: webxr_api::Registry,
microtask_queue: Rc<MicrotaskQueue>, microtask_queue: Rc<MicrotaskQueue>,
@ -2285,6 +2295,7 @@ impl Window {
media_query_lists: DOMTracker::new(), media_query_lists: DOMTracker::new(),
test_runner: Default::default(), test_runner: Default::default(),
webgl_chan, webgl_chan,
webgpu,
webvr_chan, webvr_chan,
webxr_registry, webxr_registry,
permission_state_invocation_results: Default::default(), permission_state_invocation_results: Default::default(),

View file

@ -7,6 +7,7 @@ use crate::dom::bindings::codegen::Bindings::WorkerNavigatorBinding::WorkerNavig
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{DomRoot, MutNullableDom}; use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString; use crate::dom::bindings::str::DOMString;
use crate::dom::gpu::GPU;
use crate::dom::navigatorinfo; use crate::dom::navigatorinfo;
use crate::dom::permissions::Permissions; use crate::dom::permissions::Permissions;
use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workerglobalscope::WorkerGlobalScope;
@ -17,6 +18,7 @@ use dom_struct::dom_struct;
pub struct WorkerNavigator { pub struct WorkerNavigator {
reflector_: Reflector, reflector_: Reflector,
permissions: MutNullableDom<Permissions>, permissions: MutNullableDom<Permissions>,
gpu: MutNullableDom<GPU>,
} }
impl WorkerNavigator { impl WorkerNavigator {
@ -24,6 +26,7 @@ impl WorkerNavigator {
WorkerNavigator { WorkerNavigator {
reflector_: Reflector::new(), reflector_: Reflector::new(),
permissions: Default::default(), permissions: Default::default(),
gpu: Default::default(),
} }
} }
@ -97,4 +100,9 @@ impl WorkerNavigatorMethods for WorkerNavigator {
self.permissions self.permissions
.or_init(|| Permissions::new(&self.global())) .or_init(|| Permissions::new(&self.global()))
} }
// https://gpuweb.github.io/gpuweb/#dom-navigator-gpu
fn Gpu(&self) -> DomRoot<GPU> {
self.gpu.or_init(|| GPU::new(&self.global()))
}
} }

View file

@ -163,6 +163,7 @@ use style::dom::OpaqueNode;
use style::thread_state::{self, ThreadState}; use style::thread_state::{self, ThreadState};
use time::{at_utc, get_time, precise_time_ns, Timespec}; use time::{at_utc, get_time, precise_time_ns, Timespec};
use url::Position; use url::Position;
use webgpu::WebGPU;
use webrender_api::units::LayoutPixel; use webrender_api::units::LayoutPixel;
use webrender_api::{DocumentId, RenderApiSender}; use webrender_api::{DocumentId, RenderApiSender};
use webvr_traits::{WebVREvent, WebVRMsg}; use webvr_traits::{WebVREvent, WebVRMsg};
@ -629,6 +630,9 @@ pub struct ScriptThread {
/// A handle to the WebGL thread /// A handle to the WebGL thread
webgl_chan: Option<WebGLPipeline>, webgl_chan: Option<WebGLPipeline>,
/// A handle to the WebGPU threads
webgpu: Option<WebGPU>,
/// A handle to the webvr thread, if available /// A handle to the webvr thread, if available
webvr_chan: Option<IpcSender<WebVRMsg>>, webvr_chan: Option<IpcSender<WebVRMsg>>,
@ -1338,6 +1342,7 @@ impl ScriptThread {
layout_to_constellation_chan: state.layout_to_constellation_chan, layout_to_constellation_chan: state.layout_to_constellation_chan,
webgl_chan: state.webgl_chan, webgl_chan: state.webgl_chan,
webgpu: state.webgpu,
webvr_chan: state.webvr_chan, webvr_chan: state.webvr_chan,
webxr_registry: state.webxr_registry, webxr_registry: state.webxr_registry,
@ -3247,6 +3252,7 @@ impl ScriptThread {
incomplete.navigation_start, incomplete.navigation_start,
incomplete.navigation_start_precise, incomplete.navigation_start_precise,
self.webgl_chan.as_ref().map(|chan| chan.channel()), self.webgl_chan.as_ref().map(|chan| chan.channel()),
self.webgpu.clone(),
self.webvr_chan.clone(), self.webvr_chan.clone(),
self.webxr_registry.clone(), self.webxr_registry.clone(),
self.microtask_queue.clone(), self.microtask_queue.clone(),

View file

@ -39,6 +39,7 @@ style_traits = {path = "../style_traits", features = ["servo"]}
time = "0.1.12" time = "0.1.12"
url = "2.0" url = "2.0"
webdriver = "0.40" webdriver = "0.40"
webgpu = {path = "../webgpu"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"} webvr_traits = {path = "../webvr_traits"}
webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]} webxr-api = {git = "https://github.com/servo/webxr", features = ["ipc"]}

View file

@ -60,6 +60,7 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use style_traits::CSSPixel; use style_traits::CSSPixel;
use style_traits::SpeculativePainter; use style_traits::SpeculativePainter;
use webgpu::WebGPU;
use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel}; use webrender_api::units::{DeviceIntSize, DevicePixel, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId, ImageKey, RenderApiSender}; use webrender_api::{DocumentId, ExternalScrollId, ImageKey, RenderApiSender};
use webvr_traits::{WebVREvent, WebVRMsg}; use webvr_traits::{WebVREvent, WebVRMsg};
@ -656,6 +657,8 @@ pub struct InitialScriptState {
pub content_process_shutdown_chan: Sender<()>, pub content_process_shutdown_chan: Sender<()>,
/// A channel to the WebGL thread used in this pipeline. /// A channel to the WebGL thread used in this pipeline.
pub webgl_chan: Option<WebGLPipeline>, pub webgl_chan: Option<WebGLPipeline>,
/// A channel to the WebGPU threads.
pub webgpu: Option<WebGPU>,
/// A channel to the webvr thread, if available. /// A channel to the webvr thread, if available.
pub webvr_chan: Option<IpcSender<WebVRMsg>>, pub webvr_chan: Option<IpcSender<WebVRMsg>>,
/// The XR device registry /// The XR device registry

View file

@ -79,6 +79,7 @@ servo_url = {path = "../url"}
sparkle = "0.1" sparkle = "0.1"
style = {path = "../style", features = ["servo"]} style = {path = "../style", features = ["servo"]}
style_traits = {path = "../style_traits", features = ["servo"]} style_traits = {path = "../style_traits", features = ["servo"]}
webgpu = {path = "../webgpu"}
webrender = {git = "https://github.com/servo/webrender"} webrender = {git = "https://github.com/servo/webrender"}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]} webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webrender_traits = {path = "../webrender_traits"} webrender_traits = {path = "../webrender_traits"}

View file

@ -49,6 +49,7 @@ pub use servo_geometry;
pub use servo_url; pub use servo_url;
pub use style; pub use style;
pub use style_traits; pub use style_traits;
pub use webgpu;
pub use webrender_api; pub use webrender_api;
pub use webrender_traits; pub use webrender_traits;
pub use webvr; pub use webvr;
@ -863,6 +864,8 @@ fn create_constellation(
let resource_sender = public_resource_threads.sender(); let resource_sender = public_resource_threads.sender();
let webgpu = webgpu::WebGPU::new();
let initial_state = InitialConstellationState { let initial_state = InitialConstellationState {
compositor_proxy, compositor_proxy,
embedder_proxy, embedder_proxy,
@ -877,6 +880,7 @@ fn create_constellation(
webrender_document, webrender_document,
webrender_api_sender, webrender_api_sender,
webgl_threads, webgl_threads,
webgpu,
webvr_chan, webvr_chan,
webxr_registry, webxr_registry,
glplayer_threads, glplayer_threads,

View file

@ -63,6 +63,7 @@ ${helpers.predefined_type(
"Float", "Float",
"computed::Float::None", "computed::Float::None",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_specified_value="specified::Float::None", initial_specified_value="specified::Float::None",
spec="https://drafts.csswg.org/css-box/#propdef-float", spec="https://drafts.csswg.org/css-box/#propdef-float",
animation_value_type="discrete", animation_value_type="discrete",

View file

@ -11,7 +11,6 @@ ${helpers.predefined_type(
"font-family", "font-family",
"FontFamily", "FontFamily",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_value="computed::FontFamily::serif()", initial_value="computed::FontFamily::serif()",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family", spec="https://drafts.csswg.org/css-fonts/#propdef-font-family",
@ -22,7 +21,6 @@ ${helpers.predefined_type(
"font-style", "font-style",
"FontStyle", "FontStyle",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_value="computed::FontStyle::normal()", initial_value="computed::FontStyle::normal()",
initial_specified_value="specified::FontStyle::normal()", initial_specified_value="specified::FontStyle::normal()",
animation_value_type="FontStyle", animation_value_type="FontStyle",
@ -40,7 +38,6 @@ ${helpers.single_keyword_system(
"font-variant-caps", "font-variant-caps",
"normal small-caps", "normal small-caps",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps", extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps",
gecko_constant_prefix="NS_FONT_VARIANT_CAPS", gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
gecko_ffi_name="mFont.variantCaps", gecko_ffi_name="mFont.variantCaps",
@ -54,7 +51,6 @@ ${helpers.predefined_type(
"font-weight", "font-weight",
"FontWeight", "FontWeight",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_value="computed::FontWeight::normal()", initial_value="computed::FontWeight::normal()",
initial_specified_value="specified::FontWeight::normal()", initial_specified_value="specified::FontWeight::normal()",
animation_value_type="Number", animation_value_type="Number",
@ -97,7 +93,6 @@ ${helpers.predefined_type(
"font-stretch", "font-stretch",
"FontStretch", "FontStretch",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
initial_value="computed::FontStretch::hundred()", initial_value="computed::FontStretch::hundred()",
initial_specified_value="specified::FontStretch::normal()", initial_specified_value="specified::FontStretch::normal()",
animation_value_type="Percentage", animation_value_type="Percentage",

View file

@ -21,7 +21,6 @@ ${helpers.predefined_type(
"LineHeight", "LineHeight",
"computed::LineHeight::normal()", "computed::LineHeight::normal()",
engines="gecko servo-2013 servo-2020", engines="gecko servo-2013 servo-2020",
servo_2020_pref="layout.2020.unimplemented",
animation_value_type="LineHeight", animation_value_type="LineHeight",
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height", spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height",
servo_restyle_damage="reflow" servo_restyle_damage="reflow"
@ -167,7 +166,7 @@ ${helpers.predefined_type(
"letter-spacing", "letter-spacing",
"LetterSpacing", "LetterSpacing",
"computed::LetterSpacing::normal()", "computed::LetterSpacing::normal()",
engines="gecko servo-2013", engines="gecko servo-2013 servo-2020",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing", spec="https://drafts.csswg.org/css-text/#propdef-letter-spacing",
servo_restyle_damage="rebuild_and_reflow", servo_restyle_damage="rebuild_and_reflow",
@ -177,7 +176,7 @@ ${helpers.predefined_type(
"word-spacing", "word-spacing",
"WordSpacing", "WordSpacing",
"computed::WordSpacing::zero()", "computed::WordSpacing::zero()",
engines="gecko servo-2013", engines="gecko servo-2013 servo-2020",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-text/#propdef-word-spacing", spec="https://drafts.csswg.org/css-text/#propdef-word-spacing",
servo_restyle_damage="rebuild_and_reflow", servo_restyle_damage="rebuild_and_reflow",
@ -360,7 +359,7 @@ ${helpers.single_keyword(
${helpers.single_keyword( ${helpers.single_keyword(
"text-rendering", "text-rendering",
"auto optimizespeed optimizelegibility geometricprecision", "auto optimizespeed optimizelegibility geometricprecision",
engines="gecko servo-2013", engines="gecko servo-2013 servo-2020",
gecko_enum_prefix="StyleTextRendering", gecko_enum_prefix="StyleTextRendering",
animation_value_type="discrete", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty", spec="https://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty",

View file

@ -8,7 +8,6 @@
<%helpers:shorthand <%helpers:shorthand
name="font" name="font"
engines="gecko servo-2013 servo-2020" engines="gecko servo-2013 servo-2020"
servo_2020_pref="layout.2020.unimplemented"
sub_properties=" sub_properties="
font-style font-style
font-variant-caps font-variant-caps

View file

@ -0,0 +1,20 @@
[package]
name = "webgpu"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
edition = "2018"
publish = false
[lib]
name = "webgpu"
path = "lib.rs"
[dependencies]
embedder_traits = {path = "../embedder_traits"}
ipc-channel = "0.12"
log = "0.4"
malloc_size_of = { path = "../malloc_size_of" }
serde = "1.0"
servo_config = {path = "../config"}
wgpu-native = { version = "0.4.0", features = ["serde"] }

153
components/webgpu/lib.rs Normal file
View file

@ -0,0 +1,153 @@
/* 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/. */
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;
#[macro_use]
pub extern crate wgpu_native as wgpu;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_config::pref;
use wgpu::adapter_get_info;
use wgpu::TypedId;
#[derive(Debug, Deserialize, Serialize)]
pub enum WebGPUResponse {
RequestAdapter(String, WebGPUAdapter),
RequestDevice,
}
pub type WebGPUResponseResult = Result<WebGPUResponse, String>;
#[derive(Debug, Deserialize, Serialize)]
pub enum WebGPURequest {
RequestAdapter(IpcSender<WebGPUResponseResult>, wgpu::RequestAdapterOptions),
RequestDevice,
Exit(IpcSender<()>),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct WebGPU(pub IpcSender<WebGPURequest>);
impl WebGPU {
pub fn new() -> Option<Self> {
if !pref!(dom.webgpu.enabled) {
return None;
}
let (sender, receiver) = match ipc::channel() {
Ok(sender_and_receiver) => sender_and_receiver,
Err(e) => {
warn!(
"Failed to create sender and receiciver for WGPU thread ({})",
e
);
return None;
},
};
if let Err(e) = std::thread::Builder::new()
.name("WGPU".to_owned())
.spawn(move || {
WGPU::new(receiver).run();
})
{
warn!("Failed to spwan WGPU thread ({})", e);
return None;
}
Some(WebGPU(sender))
}
pub fn exit(&self, sender: IpcSender<()>) -> Result<(), &'static str> {
self.0
.send(WebGPURequest::Exit(sender))
.map_err(|_| "Failed to send Exit message")
}
}
struct WGPU {
receiver: IpcReceiver<WebGPURequest>,
global: wgpu::Global,
adapters: Vec<WebGPUAdapter>,
// Track invalid adapters https://gpuweb.github.io/gpuweb/#invalid
_invalid_adapters: Vec<WebGPUAdapter>,
}
impl WGPU {
fn new(receiver: IpcReceiver<WebGPURequest>) -> Self {
WGPU {
receiver,
global: wgpu::Global::new("webgpu-native"),
adapters: Vec::new(),
_invalid_adapters: Vec::new(),
}
}
fn deinit(self) {
self.global.delete()
}
fn run(mut self) {
while let Ok(msg) = self.receiver.recv() {
match msg {
WebGPURequest::RequestAdapter(sender, options) => {
let adapter_id = match wgpu::request_adapter(
&self.global,
&options,
// TODO: The ids we pass here should be generated by the client
&[
wgpu::Id::zip(0, 0, wgpu::Backend::Vulkan),
wgpu::Id::zip(0, 0, wgpu::Backend::Metal),
wgpu::Id::zip(0, 0, wgpu::Backend::Dx12),
],
) {
Some(id) => id,
None => {
if let Err(e) =
sender.send(Err("Failed to get webgpu adapter".to_string()))
{
warn!(
"Failed to send response to WebGPURequest::RequestAdapter ({})",
e
)
}
return;
},
};
let adapter = WebGPUAdapter(adapter_id);
self.adapters.push(adapter);
let info =
gfx_select!(adapter_id => adapter_get_info(&self.global, adapter_id));
if let Err(e) =
sender.send(Ok(WebGPUResponse::RequestAdapter(info.name, adapter)))
{
warn!(
"Failed to send response to WebGPURequest::RequestAdapter ({})",
e
)
}
},
WebGPURequest::RequestDevice => {},
WebGPURequest::Exit(sender) => {
self.deinit();
if let Err(e) = sender.send(()) {
warn!("Failed to send response to WebGPURequest::Exit ({})", e)
}
return;
},
}
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct WebGPUAdapter(pub wgpu::AdapterId);
impl MallocSizeOf for WebGPUAdapter {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}

View file

@ -54,6 +54,8 @@
* assorted utility methods and types that are commonly used throughout the project. * assorted utility methods and types that are commonly used throughout the project.
* webdriver_server * webdriver_server
* In-process server to allow manipulating browser instances via a WebDriver client. * In-process server to allow manipulating browser instances via a WebDriver client.
* webgpu
* Implementation of threads for the WebGPU API.
* etc * etc
* Useful tools and scripts for developers. * Useful tools and scripts for developers.
* mach * mach

View file

@ -100,6 +100,7 @@ WEBIDL_STANDARDS = [
"//webaudio.github.io", "//webaudio.github.io",
"//immersive-web.github.io/", "//immersive-web.github.io/",
"//github.com/immersive-web/webxr-test-api/", "//github.com/immersive-web/webxr-test-api/",
"//gpuweb.github.io",
# Not a URL # Not a URL
"// This interface is entirely internal to Servo, and should not be" + "// This interface is entirely internal to Servo, and should not be" +
" accessible to\n// web pages." " accessible to\n// web pages."

View file

@ -26,6 +26,7 @@
"dom.testing.htmlinputelement.select_files.enabled": false, "dom.testing.htmlinputelement.select_files.enabled": false,
"dom.webgl.dom_to_texture.enabled": false, "dom.webgl.dom_to_texture.enabled": false,
"dom.webgl2.enabled": false, "dom.webgl2.enabled": false,
"dom.webgpu.enabled": false,
"dom.webrtc.enabled": false, "dom.webrtc.enabled": false,
"dom.webvr.enabled": false, "dom.webvr.enabled": false,
"dom.webvr.event_polling_interval": 500, "dom.webvr.event_polling_interval": 500,

View file

@ -27,6 +27,7 @@ rand = [
[ignore] [ignore]
# Ignored packages with duplicated versions # Ignored packages with duplicated versions
packages = [ packages = [
"arrayvec",
"cgl", "cgl",
"cocoa", "cocoa",
"gleam", "gleam",

View file

@ -7,7 +7,7 @@
expected: FAIL expected: FAIL
[Opening a blob URL in a new window immediately before revoking it works.] [Opening a blob URL in a new window immediately before revoking it works.]
expected: TIMEOUT expected: FAIL
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.] [Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
expected: FAIL expected: FAIL

View file

@ -206661,6 +206661,30 @@
{} {}
] ]
], ],
"quirks/percentage-height-quirk-excludes-flex-grid-001.html": [
[
"quirks/percentage-height-quirk-excludes-flex-grid-001.html",
[
[
"/quirks/reference/percentage-height-quirk-excludes-flex-grid-001-ref.html",
"=="
]
],
{}
]
],
"quirks/percentage-height-quirk-excludes-flex-grid-002.html": [
[
"quirks/percentage-height-quirk-excludes-flex-grid-002.html",
[
[
"/quirks/reference/percentage-height-quirk-excludes-flex-grid-002-ref.html",
"=="
]
],
{}
]
],
"quirks/table-cell-width-calculation-abspos.html": [ "quirks/table-cell-width-calculation-abspos.html": [
[ [
"quirks/table-cell-width-calculation-abspos.html", "quirks/table-cell-width-calculation-abspos.html",
@ -212784,6 +212808,18 @@
], ],
{} {}
] ]
],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-002-ref.html": [
[
"quirks/reference/percentage-height-quirk-excludes-flex-grid-002-ref.html",
[
[
"/quirks/reference/percentage-height-quirk-excludes-flex-grid-002-notref.html",
"!="
]
],
{}
]
] ]
}, },
"support": { "support": {
@ -279057,6 +279093,12 @@
"quirks/reference/green-100px-square-no-red.html": [ "quirks/reference/green-100px-square-no-red.html": [
[] []
], ],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-001-ref.html": [
[]
],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-002-notref.html": [
[]
],
"quirks/reference/table-cell-width-calculation-abspos-ref.html": [ "quirks/reference/table-cell-width-calculation-abspos-ref.html": [
[] []
], ],
@ -657627,7 +657669,7 @@
"support" "support"
], ],
"html/semantics/forms/form-submission-0/form-submission-algorithm.html": [ "html/semantics/forms/form-submission-0/form-submission-algorithm.html": [
"df39b57353c67ebb02014865f28d739bbf24c690", "2d5ac276374370dd594d3d8f98c1b85e8186eb26",
"testharness" "testharness"
], ],
"html/semantics/forms/form-submission-0/getactionurl.html": [ "html/semantics/forms/form-submission-0/getactionurl.html": [
@ -680954,10 +680996,30 @@
"e56a03b4b41b72edca91ff261e766fc9d2cc5426", "e56a03b4b41b72edca91ff261e766fc9d2cc5426",
"testharness" "testharness"
], ],
"quirks/percentage-height-quirk-excludes-flex-grid-001.html": [
"cb0f772b1fa2fed26992f288cc345e7ab418d919",
"reftest"
],
"quirks/percentage-height-quirk-excludes-flex-grid-002.html": [
"88df89d0932e8f347ffad8faa4e5da9dc2e71b56",
"reftest"
],
"quirks/reference/green-100px-square-no-red.html": [ "quirks/reference/green-100px-square-no-red.html": [
"159d9a52a01a0b328680a530603cb496ab2d5fcf", "159d9a52a01a0b328680a530603cb496ab2d5fcf",
"support" "support"
], ],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-001-ref.html": [
"29f8e26a67f27e9ae250e464c05a8f3af1e0b9a5",
"support"
],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-002-notref.html": [
"19aa243a0045f4378b55a00dd3b2431fc9a9ec23",
"support"
],
"quirks/reference/percentage-height-quirk-excludes-flex-grid-002-ref.html": [
"c63bc0efa85f59eb496875072970016cf77d3c9d",
"reftest_node"
],
"quirks/reference/table-cell-width-calculation-abspos-ref.html": [ "quirks/reference/table-cell-width-calculation-abspos-ref.html": [
"41d2203b4a08323a2d6b9894f1ad133e35130265", "41d2203b4a08323a2d6b9894f1ad133e35130265",
"support" "support"

View file

@ -1,5 +1,5 @@
[perspective-interpolation.html] [perspective-interpolation.html]
expected: ERROR expected: CRASH
[ perspective interpolation] [ perspective interpolation]
expected: FAIL expected: FAIL

View file

@ -14,6 +14,3 @@
[<li>Outside 3</li>] [<li>Outside 3</li>]
expected: FAIL expected: FAIL
[<li>Inside 1</li>]
expected: FAIL

View file

@ -2,7 +2,6 @@
type: testharness type: testharness
[single-byte-decoder.html?document] [single-byte-decoder.html?document]
expected: TIMEOUT
[ISO-8859-4: iso_8859-4:1988 (document.characterSet and document.inputEncoding)] [ISO-8859-4: iso_8859-4:1988 (document.characterSet and document.inputEncoding)]
expected: FAIL expected: FAIL

View file

@ -312,24 +312,18 @@
[<iframe>: combined response Content-Type: */* text/html] [<iframe>: combined response Content-Type: */* text/html]
expected: FAIL expected: FAIL
[<iframe>: combined response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" text/plain] [<iframe>: separate response Content-Type: text/html;" text/plain]
expected: FAIL expected: FAIL
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
expected: FAIL
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/plain */*] [<iframe>: separate response Content-Type: text/plain */*]
expected: FAIL expected: FAIL
[<iframe>: separate response Content-Type: text/html;" \\" text/plain] [<iframe>: combined response Content-Type: text/html */*;charset=gbk]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL expected: FAIL

View file

@ -53,6 +53,3 @@
[combined text/javascript ] [combined text/javascript ]
expected: FAIL expected: FAIL
[separate text/javascript x/x]
expected: FAIL

View file

@ -11,6 +11,3 @@
[X-Content-Type-Options%3A%20nosniff%0C] [X-Content-Type-Options%3A%20nosniff%0C]
expected: FAIL expected: FAIL
[X-Content-Type-Options%3A%0D%0AX-Content-Type-Options%3A%20nosniff]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,4 +0,0 @@
[creating_browsing_context_test_01.html]
[first argument: absolute url]
expected: FAIL

View file

@ -1,5 +1,24 @@
[open-features-negative-innerwidth-innerheight.html] [open-features-negative-innerwidth-innerheight.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight`] [HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight`]
expected: FAIL expected: FAIL
[features "innerheight=-404.5" should NOT set "height=404"]
expected: TIMEOUT
[features "innerwidth=-404.5" should NOT set "width=404"]
expected: TIMEOUT
[features "innerwidth=-404" should NOT set "width=404"]
expected: TIMEOUT
[features "innerheight=-404e1" should NOT set "height=404"]
expected: TIMEOUT
[features "innerheight=-404" should NOT set "height=404"]
expected: TIMEOUT
[features "innerwidth=-404e1" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,5 +1,24 @@
[open-features-negative-top-left.html] [open-features-negative-top-left.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: negative values for `top`, `left`] [HTML: window.open `features`: negative values for `top`, `left`]
expected: FAIL expected: FAIL
[features "top=-204" should NOT set "top=204"]
expected: TIMEOUT
[features "top=-204.5" should NOT set "top=204"]
expected: TIMEOUT
[features "left=-204" should NOT set "left=204"]
expected: TIMEOUT
[features "top=-0" should NOT set "top=204"]
expected: TIMEOUT
[features "left=-204.5" should NOT set "left=204"]
expected: TIMEOUT
[features "left=-0" should NOT set "left=204"]
expected: TIMEOUT

View file

@ -1,24 +1,5 @@
[open-features-negative-width-height.html] [open-features-negative-width-height.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: negative values for `width`, `height`] [HTML: window.open `features`: negative values for `width`, `height`]
expected: FAIL expected: FAIL
[features "height=-404" should NOT set "height=404"]
expected: TIMEOUT
[features "height=-404e1" should NOT set "height=404"]
expected: TIMEOUT
[features "height=-404.5" should NOT set "height=404"]
expected: TIMEOUT
[features "width=-404" should NOT set "width=404"]
expected: TIMEOUT
[features "width=-404e1" should NOT set "width=404"]
expected: TIMEOUT
[features "width=-404.5" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,32 +1,42 @@
[open-features-non-integer-top.html] [open-features-non-integer-top.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `top`] [HTML: window.open `features`: non-integer values for feature `top`]
expected: FAIL expected: FAIL
[features "top=105/5" should set "top=105"] [features "top=105/5" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105*3" should set "top=105"] [features "top=105*3" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105LLl" should set "top=105"] [features "top=105LLl" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105e-1" should set "top=105"] [features "top=105e-1" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105.32" should set "top=105"] [features "top=105.32" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105e1" should set "top=105"] [features "top=105e1" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105 " should set "top=105"] [features "top=105 " should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105^4" should set "top=105"] [features "top=105^4" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=105.5" should set "top=105"] [features "top=105.5" should set "top=105"]
expected: FAIL expected: TIMEOUT
[features "top=/104" should NOT set "top=104"]
expected: TIMEOUT
[features "top=_104" should NOT set "top=104"]
expected: TIMEOUT
[features "top=L104" should NOT set "top=104"]
expected: TIMEOUT

View file

@ -1,32 +1,48 @@
[open-features-non-integer-width.html] [open-features-non-integer-width.html]
type: testharness type: testharness
expected: TIMEOUT
[HTML: window.open `features`: non-integer values for feature `width`] [HTML: window.open `features`: non-integer values for feature `width`]
expected: FAIL expected: FAIL
[features "width=405^4" should set "width=405"] [features "width=405^4" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405.5" should set "width=405"] [features "width=405.5" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405e1" should set "width=405"] [features "width=405e1" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405 " should set "width=405"] [features "width=405 " should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405.32" should set "width=405"] [features "width=405.32" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405LLl" should set "width=405"] [features "width=405LLl" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405*3" should set "width=405"] [features "width=405*3" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405e-1" should set "width=405"] [features "width=405e-1" should set "width=405"]
expected: FAIL expected: TIMEOUT
[features "width=405/5" should set "width=405"] [features "width=405/5" should set "width=405"]
expected: FAIL expected: TIMEOUT
[top=0,left=0: absence of feature "width" should be treated same as "width=0"]
expected: TIMEOUT
[features "width=_404" should NOT set "width=404"]
expected: TIMEOUT
[top=0,left=0,height=401,: absence of feature "width" should be treated same as "width=0"]
expected: TIMEOUT
[features "width=/404" should NOT set "width=404"]
expected: TIMEOUT
[features "width=L404" should NOT set "width=404"]
expected: TIMEOUT

View file

@ -1,5 +1,5 @@
[embedded-opener-remove-frame.html] [embedded-opener-remove-frame.html]
expected: CRASH expected: TIMEOUT
[opener and "removed" embedded documents] [opener and "removed" embedded documents]
expected: FAIL expected: FAIL
@ -7,5 +7,5 @@
expected: FAIL expected: FAIL
[opener of discarded auxiliary browsing context] [opener of discarded auxiliary browsing context]
expected: FAIL expected: TIMEOUT

View file

@ -1409,9 +1409,6 @@
[SubmitEvent interface: existence and properties of interface prototype object's "constructor" property] [SubmitEvent interface: existence and properties of interface prototype object's "constructor" property]
expected: FAIL expected: FAIL
[FormDataEvent interface object length]
expected: FAIL
[idlharness.https.html?include=(Document|Window)] [idlharness.https.html?include=(Document|Window)]
[Document interface: documentWithHandlers must inherit property "queryCommandEnabled(DOMString)" with the proper type] [Document interface: documentWithHandlers must inherit property "queryCommandEnabled(DOMString)" with the proper type]

View file

@ -1,6 +1,6 @@
[iframe_sandbox_popups_nonescaping-1.html] [iframe_sandbox_popups_nonescaping-1.html]
type: testharness type: testharness
expected: TIMEOUT expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox] [Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN expected: NOTRUN

View file

@ -0,0 +1,10 @@
[non-active-document.html]
[DOMParser]
expected: FAIL
[createHTMLDocument]
expected: FAIL
[<template>]
expected: FAIL

View file

@ -1,5 +1,5 @@
[form-double-submit-3.html] [form-double-submit-3.html]
expected: ERROR expected: ERROR
[<button> should have the same double-submit protection as <input type=submit>] [<button> should have the same double-submit protection as <input type=submit>]
expected: FAIL expected: TIMEOUT

View file

@ -1,5 +1,5 @@
[form-double-submit.html] [form-double-submit.html]
expected: ERROR expected: ERROR
[default submit action should supersede onclick submit()] [default submit action should supersede onclick submit()]
expected: FAIL expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[script-onerror-insertion-point-2.html]
expected: TIMEOUT

View file

@ -0,0 +1,5 @@
[promise-rejection-events-onerror.html]
expected: TIMEOUT
[Throwing inside an unhandledrejection handler invokes the error handler.]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[percentage-height-quirk-excludes-flex-grid-002.html]
expected: FAIL

View file

@ -0,0 +1,5 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -0,0 +1,5 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -18,6 +18,21 @@ test(() => {
assert_equals(counter, 2); assert_equals(counter, 2);
}, 'If constructing entry list flag of form is true, then return'); }, 'If constructing entry list flag of form is true, then return');
test(() => {
let form = populateForm('<input><input type=submit>');
let submitter1 = form.querySelector('input[type=submit]');
let valid = form.elements[0];
let counter = 0;
valid.oninvalid = () => {
++counter;
};
form.onsubmit = () => {
valid.required = true;
submitter1.dispatchEvent(new MouseEvent("click"));
};
submitter1.dispatchEvent(new MouseEvent("click"));
assert_equals(counter, 0);
}, "If firing submission events flag of form is true, then return");
test(() => { test(() => {
let form = populateForm('<input required><input type=submit><button type=submit></button>'); let form = populateForm('<input required><input type=submit><button type=submit></button>');

View file

@ -0,0 +1,78 @@
<html>
<head>
<meta charset="utf-8">
<title>Test: Percent height quirk does not traverse flex/grid containers</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk">
<link rel="match" href="reference/percentage-height-quirk-excludes-flex-grid-001-ref.html">
<meta name="assert" content="This quirk is specific to block boxes and table wrapper boxes; if it hits another type of box, it doesn't traverse further. So this file should look the same whether in quirks or standards mode.">
<style>
.fixed-height-outer {
height: 80px;
border: 1px solid gray;
margin-bottom: 5px;
}
.row-flex {
display: flex;
flex-direction: row
}
.column-flex {
display: flex;
flex-direction: column
}
.grid {
display: grid;
}
.container {
border: 3px solid black;
}
.pct {
height: 75%;
min-height: 10px;
width: 50px;
display: inline-block;
vertical-align: top;
background: purple;
}
.px {
height: 50px;
width: 50px;
display: inline-block;
vertical-align: top;
background: blue
}
</style>
</head>
<body>
<div class="fixed-height-outer">
<div class="container column-flex">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
<div class="fixed-height-outer">
<div class="container row-flex">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
<div class="fixed-height-outer">
<div class="container grid">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,56 @@
<html>
<head>
<meta charset="utf-8">
<title>Test: Percent height quirk applies for percent heights on flex/grid containers</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://quirks.spec.whatwg.org/#the-percentage-height-calculation-quirk">
<link rel="match" href="reference/percentage-height-quirk-excludes-flex-grid-002-ref.html">
<meta name="assert" content="This quirk only starts differentiating by box-type when looking at the containing block of the percent-height thing. So, the quirk applies to percent-heights on flex/grid containers, when the ancestors are all blocks up to the nearest definite height.">
<style>
.fixed-height-outer {
height: 80px;
border: 1px solid gray;
margin-bottom: 5px;
}
.row-flex {
display: flex;
flex-direction: row
}
.column-flex {
display: flex;
flex-direction: column
}
.grid {
display: grid;
}
.pct {
height: 75%;
min-height: 10px;
width: 50px;
background: purple;
}
</style>
</head>
<body>
<div class="fixed-height-outer">
<div>
<div class="column-flex pct"></div>
</div>
</div>
<div class="fixed-height-outer">
<div>
<div class="row-flex pct"></div>
</div>
</div>
<div class="fixed-height-outer">
<div>
<div class="grid pct"></div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Reference: Percent height quirk does not traverse flex/grid containers</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
.fixed-height-outer {
height: 80px;
border: 1px solid gray;
margin-bottom: 5px;
}
.row-flex {
display: flex;
flex-direction: row
}
.column-flex {
display: flex;
flex-direction: column
}
.grid {
display: grid;
}
.container {
border: 3px solid black;
}
.pct {
height: 75%;
min-height: 10px;
width: 50px;
display: inline-block;
vertical-align: top;
background: purple;
}
.px {
height: 50px;
width: 50px;
display: inline-block;
vertical-align: top;
background: blue
}
</style>
</head>
<body>
<div class="fixed-height-outer">
<div class="container column-flex">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
<div class="fixed-height-outer">
<div class="container row-flex">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
<div class="fixed-height-outer">
<div class="container grid">
<div>
<div class="pct"></div>
<div class="px"></div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Not-reference case: Percent height quirk applies for percent heights on flex/grid containers</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<style>
.fixed-height-outer {
height: 80px;
border: 1px solid gray;
margin-bottom: 5px;
}
.row-flex {
display: flex;
flex-direction: row
}
.column-flex {
display: flex;
flex-direction: column
}
.grid {
display: grid;
}
.pct {
height: 75%;
min-height: 10px;
width: 50px;
background: purple;
}
</style>
</head>
<body>
<div class="fixed-height-outer">
<div>
<div class="column-flex pct"></div>
</div>
</div>
<div class="fixed-height-outer">
<div>
<div class="row-flex pct"></div>
</div>
</div>
<div class="fixed-height-outer">
<div>
<div class="grid pct"></div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Reference case: Percent height quirk applies for percent heights on flex/grid containers</title>
<link rel="author" title="Daniel Holbert" href="mailto:dholbert@mozilla.com">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="mismatch" href="percentage-height-quirk-excludes-flex-grid-002-notref.html">
<style>
.fixed-height-outer {
height: 80px;
border: 1px solid gray;
margin-bottom: 5px;
}
.row-flex {
display: flex;
flex-direction: row
}
.column-flex {
display: flex;
flex-direction: column
}
.grid {
display: grid;
}
.pct {
height: 75%;
min-height: 10px;
width: 50px;
background: purple;
}
</style>
</head>
<body>
<div class="fixed-height-outer">
<div class="column-flex pct"></div>
</div>
<div class="fixed-height-outer">
<div class="row-flex pct"></div>
</div>
<div class="fixed-height-outer">
<div class="grid pct"></div>
</div>
</body>
</html>