servo: Merge #15804 - Update WR (reference frames for fixed position elements) (from glennw:update-wr-transforms); r=pcwalton
authorGlenn Watson <github@intuitionlibrary.com>
Thu, 02 Mar 2017 17:02:26 -0800
changeset 374721 605fd6c8ee11674bda8d1848c41da3557323b2e5
parent 374720 830a13c24b225b54e0bdf0b2585c0f7943f88a7d
child 374722 9c1478a17bf621217bf082281705af5c270764dd
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspcwalton
milestone54.0a1
servo: Merge #15804 - Update WR (reference frames for fixed position elements) (from glennw:update-wr-transforms); r=pcwalton Source-Repo: https://github.com/servo/servo Source-Revision: 0f6b5c3b521686f79a18da64364eed5a03262605
servo/Cargo.lock
servo/components/gfx/display_list/mod.rs
servo/components/layout/block.rs
servo/components/layout/flow.rs
servo/components/layout/fragment.rs
servo/components/layout/webrender_helpers.rs
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -278,31 +278,31 @@ dependencies = [
  "cssparser 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
  "cssparser 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "caseless"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -413,18 +413,18 @@ dependencies = [
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender 0.21.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.22.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "constellation"
 version = "0.0.1"
 dependencies = [
  "backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
@@ -447,17 +447,17 @@ dependencies = [
  "script_traits 0.0.1",
  "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_rand 0.0.1",
  "servo_remutex 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "webvr_traits 0.0.1",
 ]
 
 [[package]]
 name = "content-blocker"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -702,17 +702,17 @@ dependencies = [
  "msg 0.0.1",
  "net_traits 0.0.1",
  "objc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "encoding"
 version = "0.2.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -989,17 +989,17 @@ dependencies = [
  "servo_url 0.0.1",
  "simd 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gfx_tests"
 version = "0.0.1"
 dependencies = [
  "gfx 0.0.1",
@@ -1068,17 +1068,17 @@ dependencies = [
  "script_traits 0.0.1",
  "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-glutin 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style_traits 0.0.1",
  "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "glx"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1370,17 +1370,17 @@ dependencies = [
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_tests"
 version = "0.0.1"
 dependencies = [
  "layout 0.0.1",
 ]
@@ -1410,31 +1410,31 @@ dependencies = [
  "script_traits 0.0.1",
  "selectors 0.18.0",
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_traits"
 version = "0.0.1"
 dependencies = [
  "gfx 0.0.1",
  "ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "servo_url 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "lazy_static"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1509,18 +1509,18 @@ dependencies = [
  "script_layout_interface 0.0.1",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
  "servo_geometry 0.0.1",
  "servo_url 0.0.1",
  "style 0.0.1",
  "style_traits 0.0.1",
  "webdriver_server 0.0.1",
- "webrender 0.21.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.22.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "webvr 0.0.1",
  "webvr_traits 0.0.1",
 ]
 
 [[package]]
 name = "libz-sys"
 version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1657,17 +1657,17 @@ name = "msg"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "net"
 version = "0.0.1"
 dependencies = [
  "brotli 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "content-blocker 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1696,17 +1696,17 @@ dependencies = [
  "servo_config 0.0.1",
  "servo_url 0.0.1",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 2.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "net2"
 version = "0.2.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1755,17 +1755,17 @@ dependencies = [
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-websocket 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_config 0.0.1",
  "servo_url 0.0.1",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "net_traits_tests"
 version = "0.0.1"
 dependencies = [
  "net_traits 0.0.1",
 ]
@@ -2293,17 +2293,17 @@ dependencies = [
  "servo_url 0.0.1",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 2.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "webvr 0.0.1",
  "webvr_traits 0.0.1",
  "xml5ever 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
@@ -3170,18 +3170,18 @@ dependencies = [
  "servo_url 0.0.1",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
-version = "0.21.0"
-source = "git+https://github.com/servo/webrender#040805f31650527311c0a0d58ccf9620b0f3eca9"
+version = "0.22.1"
+source = "git+https://github.com/servo/webrender#68f5b72fb3f871f6930c772c7e2705412512dde2"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0-alpha2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3193,23 +3193,23 @@ dependencies = [
  "gleam 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_traits"
-version = "0.22.0"
-source = "git+https://github.com/servo/webrender#040805f31650527311c0a0d58ccf9620b0f3eca9"
+version = "0.23.1"
+source = "git+https://github.com/servo/webrender#68f5b72fb3f871f6930c772c7e2705412512dde2"
 dependencies = [
  "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3223,17 +3223,17 @@ dependencies = [
 name = "webvr"
 version = "0.0.1"
 dependencies = [
  "ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "script_traits 0.0.1",
  "servo_config 0.0.1",
- "webrender_traits 0.22.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",
  "webvr_traits 0.0.1",
 ]
 
 [[package]]
 name = "winapi"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -3563,18 +3563,18 @@ dependencies = [
 "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
 "checksum utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9aee9ba280438b56d1ebc5329f2094f0ff457f811eeeff0b278d75aa99db400"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cfec50b0842181ba6e713151b72f4ec84a6a7e2c9c8a8a3ffc37bb1cd16b231"
 "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
 "checksum webdriver 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc28802daddee94267a657ffeac2593a33881fb7a3a44fedd320b1319efcaf6"
-"checksum webrender 0.21.0 (git+https://github.com/servo/webrender)" = "<none>"
-"checksum webrender_traits 0.22.0 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender 0.22.1 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender_traits 0.23.1 (git+https://github.com/servo/webrender)" = "<none>"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04614a58714f3fd4a8b1da4bcae9f031c532d35988c3d39627619248113f8be8"
 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "124eb405bf0262a54e1a982d4ffe4cd1c24261bdb306e49996e2ce7d492284a8"
 "checksum x11-dl 2.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf1f9986368c9bbdd8191a783a7ceb42e0c9c6d3348616c873f829b3288a139c"
 "checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453"
 "checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1"
--- a/servo/components/gfx/display_list/mod.rs
+++ b/servo/components/gfx/display_list/mod.rs
@@ -177,27 +177,35 @@ impl DisplayList {
         // Convert the parent translated point into stacking context local transform space if the
         // stacking context isn't fixed.  If it's fixed, we need to use the client point anyway.
         debug_assert!(stacking_context.context_type == StackingContextType::Real);
         let is_fixed = stacking_context.scroll_policy == ScrollPolicy::Fixed;
         *translated_point = if is_fixed {
             *client_point
         } else {
             let point = *translated_point - stacking_context.bounds.origin;
-            let inv_transform = match stacking_context.transform.inverse() {
-                Some(transform) => transform,
+
+            match stacking_context.transform {
+                Some(transform) => {
+                    let inv_transform = match transform.inverse() {
+                        Some(transform) => transform,
+                        None => {
+                            // If a transform function causes the current transformation matrix of an object
+                            // to be non-invertible, the object and its content do not get displayed.
+                            return;
+                        }
+                    };
+                    let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(),
+                                                                                 point.y.to_f32_px()));
+                    Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
+                }
                 None => {
-                    // If a transform function causes the current transformation matrix of an object
-                    // to be non-invertible, the object and its content do not get displayed.
-                    return;
+                    point
                 }
-            };
-            let frac_point = inv_transform.transform_point(&Point2D::new(point.x.to_f32_px(),
-                                                                         point.y.to_f32_px()));
-            Point2D::new(Au::from_f32_px(frac_point.x), Au::from_f32_px(frac_point.y))
+            }
         };
     }
 
     #[inline]
     fn scroll_root<'a>(scroll_root: &ScrollRoot,
                        translated_point: &mut Point2D<Au>,
                        scroll_offsets: &ScrollOffsetMap) {
         // Adjust the translated point to account for the scroll offset if necessary.
@@ -355,20 +363,20 @@ pub struct StackingContext {
 
     /// CSS filters to be applied to this stacking context (including opacity).
     pub filters: filter::T,
 
     /// The blend mode with which this stacking context blends with its backdrop.
     pub blend_mode: mix_blend_mode::T,
 
     /// A transform to be applied to this stacking context.
-    pub transform: Matrix4D<f32>,
+    pub transform: Option<Matrix4D<f32>>,
 
     /// The perspective matrix to be applied to children.
-    pub perspective: Matrix4D<f32>,
+    pub perspective: Option<Matrix4D<f32>>,
 
     /// Whether this stacking context creates a new 3d rendering context.
     pub establishes_3d_context: bool,
 
     /// The scroll policy of this layer.
     pub scroll_policy: ScrollPolicy,
 
     /// The id of the parent scrolling area that contains this StackingContext.
@@ -380,18 +388,18 @@ impl StackingContext {
     #[inline]
     pub fn new(id: StackingContextId,
                context_type: StackingContextType,
                bounds: &Rect<Au>,
                overflow: &Rect<Au>,
                z_index: i32,
                filters: filter::T,
                blend_mode: mix_blend_mode::T,
-               transform: Matrix4D<f32>,
-               perspective: Matrix4D<f32>,
+               transform: Option<Matrix4D<f32>>,
+               perspective: Option<Matrix4D<f32>>,
                establishes_3d_context: bool,
                scroll_policy: ScrollPolicy,
                parent_scroll_id: ScrollRootId)
                -> StackingContext {
         StackingContext {
             id: id,
             context_type: context_type,
             bounds: *bounds,
@@ -411,18 +419,18 @@ impl StackingContext {
     pub fn root() -> StackingContext {
         StackingContext::new(StackingContextId::new(0),
                              StackingContextType::Real,
                              &Rect::zero(),
                              &Rect::zero(),
                              0,
                              filter::T::new(Vec::new()),
                              mix_blend_mode::T::normal,
-                             Matrix4D::identity(),
-                             Matrix4D::identity(),
+                             None,
+                             None,
                              true,
                              ScrollPolicy::Scrollable,
                              ScrollRootId::root())
     }
 
     pub fn to_display_list_items(self) -> (DisplayItem, DisplayItem) {
         let mut base_item = BaseDisplayItem::empty();
         base_item.stacking_context_id = self.id;
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -26,17 +26,17 @@
 //!   http://dev.w3.org/csswg/css-sizing/
 
 #![deny(unsafe_code)]
 
 use app_units::{Au, MAX_AU};
 use context::LayoutContext;
 use display_list_builder::{BorderPaintingMode, DisplayListBuildState, FragmentDisplayListBuilding};
 use display_list_builder::BlockFlowDisplayListBuilding;
-use euclid::{Point2D, Rect, Size2D};
+use euclid::{Matrix4D, Point2D, Rect, Size2D};
 use floats::{ClearType, FloatKind, Floats, PlacementInfo};
 use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
 use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT};
 use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, INLINE_POSITION_IS_STATIC};
 use flow::{FragmentationContext, MARGINS_CANNOT_COLLAPSE, PreorderFlowTraversal};
 use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
 use flow::IS_ABSOLUTELY_POSITIONED;
 use flow_list::FlowList;
@@ -1806,16 +1806,17 @@ impl BlockFlow {
         self.base.clip = self.base.clip.translate(&-stacking_relative_border_box.origin);
 
         // Account for `transform`, if applicable.
         if self.fragment.style.get_box().transform.0.is_none() {
             return
         }
         let transform = match self.fragment
                                   .transform_matrix(&stacking_relative_border_box)
+                                  .unwrap_or(Matrix4D::identity())
                                   .inverse() {
             Some(transform) => transform,
             None => {
                 // Singular matrix. Ignore it.
                 return
             }
         };
 
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -24,17 +24,17 @@
 //!   fragments/flows that are subject to inline layout and line breaking and structs to represent
 //!   line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
 //!   similar methods.
 
 use app_units::Au;
 use block::{BlockFlow, FormattingContextType};
 use context::LayoutContext;
 use display_list_builder::DisplayListBuildState;
-use euclid::{Point2D, Size2D};
+use euclid::{Matrix4D, Point2D, Size2D};
 use flex::FlexFlow;
 use floats::{Floats, SpeculatedFloatPlacement};
 use flow_list::{FlowList, MutFlowListIterator};
 use flow_ref::{FlowRef, WeakFlowRef};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::ClippingRegion;
 use gfx_traits::{ScrollRootId, StackingContextId};
 use gfx_traits::print_tree::PrintTree;
@@ -267,17 +267,21 @@ pub trait Flow: fmt::Debug + Sync + Send
         if !self.as_block().fragment.establishes_stacking_context() ||
            self.as_block().fragment.style.get_box().transform.0.is_none() {
             overflow.translate(&position.origin);
             return overflow;
         }
 
         // TODO: Take into account 3d transforms, even though it's a fairly
         // uncommon case.
-        let transform_2d = self.as_block().fragment.transform_matrix(&position).to_2d();
+        let transform_2d = self.as_block()
+                               .fragment
+                               .transform_matrix(&position)
+                               .unwrap_or(Matrix4D::identity())
+                               .to_2d();
         let transformed_overflow = Overflow {
             paint: f32_rect_to_au_rect(transform_2d.transform_rect(
                                        &au_rect_to_f32_rect(overflow.paint))),
             scroll: f32_rect_to_au_rect(transform_2d.transform_rect(
                                        &au_rect_to_f32_rect(overflow.scroll))),
         };
 
         // TODO: We are taking the union of the overflow and transformed overflow here, which
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -2868,23 +2868,23 @@ impl Fragment {
             SpecificFragmentInfo::ScannedText(_) |
             SpecificFragmentInfo::TruncatedFragment(_) |
             SpecificFragmentInfo::Svg(_) |
             SpecificFragmentInfo::UnscannedText(_) => true
         }
     }
 
     /// Returns the 4D matrix representing this fragment's transform.
-    pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Matrix4D<f32> {
-        let mut transform = Matrix4D::identity();
+    pub fn transform_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Matrix4D<f32>> {
         let operations = match self.style.get_box().transform.0 {
-            None => return transform,
+            None => return None,
             Some(ref operations) => operations,
         };
 
+        let mut transform = Matrix4D::identity();
         let transform_origin = &self.style.get_box().transform_origin;
         let transform_origin_x = model::specified(transform_origin.horizontal,
                                                   stacking_relative_border_box.size
                                                                               .width).to_f32_px();
         let transform_origin_y = model::specified(transform_origin.vertical,
                                                   stacking_relative_border_box.size
                                                                               .height).to_f32_px();
         let transform_origin_z = transform_origin.depth.to_f32_px();
@@ -2923,21 +2923,21 @@ impl Fragment {
                     Matrix4D::create_skew(Radians::new(theta_x.radians()),
                                           Radians::new(theta_y.radians()))
                 }
             };
 
             transform = transform.pre_mul(&matrix);
         }
 
-        pre_transform.pre_mul(&transform).pre_mul(&post_transform)
+        Some(pre_transform.pre_mul(&transform).pre_mul(&post_transform))
     }
 
     /// Returns the 4D matrix representing this fragment's perspective.
-    pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Matrix4D<f32> {
+    pub fn perspective_matrix(&self, stacking_relative_border_box: &Rect<Au>) -> Option<Matrix4D<f32>> {
         match self.style().get_box().perspective {
             Either::First(length) => {
                 let perspective_origin = self.style().get_box().perspective_origin;
                 let perspective_origin =
                     Point2D::new(model::specified(perspective_origin.horizontal,
                                                   stacking_relative_border_box.size.width).to_f32_px(),
                                  model::specified(perspective_origin.vertical,
                                                   stacking_relative_border_box.size.height).to_f32_px());
@@ -2946,20 +2946,20 @@ impl Fragment {
                                                                  perspective_origin.y,
                                                                  0.0);
                 let post_transform = Matrix4D::create_translation(-perspective_origin.x,
                                                                   -perspective_origin.y,
                                                                   0.0);
 
                 let perspective_matrix = create_perspective_matrix(length);
 
-                pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform)
+                Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform))
             }
             Either::Second(values::None_) => {
-                Matrix4D::identity()
+                None
             }
         }
     }
 }
 
 impl fmt::Debug for Fragment {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let border_padding_string = if !self.border_padding.is_zero() {
--- a/servo/components/layout/webrender_helpers.rs
+++ b/servo/components/layout/webrender_helpers.rs
@@ -376,22 +376,29 @@ impl WebRenderDisplayItemConverter for D
             DisplayItem::PushStackingContext(ref item) => {
                 let stacking_context = &item.stacking_context;
                 debug_assert!(stacking_context.context_type == StackingContextType::Real);
 
                 let clip = builder.new_clip_region(&stacking_context.overflow.to_rectf(),
                                                    vec![],
                                                    None);
 
+                let transform = stacking_context.transform.map(|transform| {
+                    LayoutTransform::from_untyped(&transform).into()
+                });
+                let perspective = stacking_context.perspective.map(|perspective| {
+                    LayoutTransform::from_untyped(&perspective)
+                });
+
                 builder.push_stacking_context(stacking_context.scroll_policy,
                                               stacking_context.bounds.to_rectf(),
                                               clip,
                                               stacking_context.z_index,
-                                              LayoutTransform::from_untyped(&stacking_context.transform).into(),
-                                              LayoutTransform::from_untyped(&stacking_context.perspective),
+                                              transform,
+                                              perspective,
                                               stacking_context.blend_mode.to_blend_mode(),
                                               stacking_context.filters.to_filter_ops());
             }
             DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
             DisplayItem::PushScrollRoot(ref item) => {
                 let clip = builder.new_clip_region(&item.scroll_root.clip.to_rectf(),
                                                    vec![],
                                                    None);