From de71f88ab4e40cb1c71c2e00116ca9f7bc05f5ad Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 11 Apr 2017 08:33:58 -0400 Subject: [PATCH] Bug 1354946 - Add an explicit WrMatrix type for passing 4x4 matrices across the FFI boundary. r=rhunt Right now we just cast from a float* on the C++ side to a LayoutTransform on the Rust side, except the LayoutTransform isn't a repr(C) storage type, so there's no guarantee that it will actually have the same layout. Adding an explicit type and conversion code ensure that we are able to pass the matrix across the boundary safely. MozReview-Commit-ID: H3gK3g0K3xz --- gfx/webrender_bindings/WebRenderAPI.cpp | 2 +- gfx/webrender_bindings/WebRenderTypes.h | 11 +++++++++++ gfx/webrender_bindings/src/bindings.rs | 20 ++++++++++++++++++-- gfx/webrender_bindings/webrender_ffi.h | 7 ++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index f2873a7a9c30..935d923cbf2b 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -533,7 +533,7 @@ DisplayListBuilder::PushStackingContext(const WrRect& aBounds, const WrMixBlendMode& aMixBlendMode) { wr_dp_push_stacking_context(mWrState, aBounds, aOverflow, aMask, aOpacity, - &aTransform.components[0], aMixBlendMode); + ToWrMatrix(aTransform), aMixBlendMode); } void diff --git a/gfx/webrender_bindings/WebRenderTypes.h b/gfx/webrender_bindings/WebRenderTypes.h index c05ee9e6a0d4..6650b9d249a4 100644 --- a/gfx/webrender_bindings/WebRenderTypes.h +++ b/gfx/webrender_bindings/WebRenderTypes.h @@ -8,6 +8,7 @@ #include "mozilla/webrender/webrender_ffi.h" #include "mozilla/Maybe.h" +#include "mozilla/gfx/Matrix.h" #include "mozilla/gfx/Types.h" #include "mozilla/gfx/Tools.h" #include "mozilla/Range.h" @@ -220,6 +221,16 @@ static inline WrSize ToWrSize(const gfx::IntSizeTyped& size) return ToWrSize(IntSizeToSize(size)); } +template +static inline WrMatrix ToWrMatrix(const gfx::Matrix4x4Typed& m) +{ + WrMatrix transform; + static_assert(sizeof(m.components) == sizeof(transform.values), + "Matrix components size mismatch!"); + memcpy(transform.values, m.components, sizeof(transform.values)); + return transform; +} + static inline WrBorderStyle ToWrBorderStyle(const uint8_t& style) { switch (style) { diff --git a/gfx/webrender_bindings/src/bindings.rs b/gfx/webrender_bindings/src/bindings.rs index 58832ad2323b..919a2b8987d2 100644 --- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -204,6 +204,22 @@ impl From for WrRect { } } +#[repr(C)] +#[derive(Debug)] +pub struct WrMatrix { + values: [f32; 16], +} + +impl WrMatrix { + pub fn to_layout_transform(&self) -> LayoutTransform { + LayoutTransform::row_major( + self.values[0], self.values[1], self.values[2], self.values[3], + self.values[4], self.values[5], self.values[6], self.values[7], + self.values[8], self.values[9], self.values[10], self.values[11], + self.values[12], self.values[13], self.values[14], self.values[15]) + } +} + #[repr(C)] pub struct WrColor { r: f32, @@ -1083,7 +1099,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState, overflow: WrRect, mask: *const WrImageMask, opacity: f32, - transform: &LayoutTransform, + transform: WrMatrix, mix_blend_mode: WrMixBlendMode) { assert!(unsafe { is_in_main_thread() }); state.z_index += 1; @@ -1114,7 +1130,7 @@ pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState, .push_stacking_context(webrender_traits::ScrollPolicy::Scrollable, bounds, state.z_index, - Some(PropertyBinding::Value(*transform)), + Some(PropertyBinding::Value(transform.to_layout_transform())), None, mix_blend_mode, filters); diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index 77dd94970eb4..f881d8b7a885 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -240,6 +240,11 @@ struct WrRect } }; +struct WrMatrix +{ + float values[16]; +}; + struct WrColor { float r; @@ -630,7 +635,7 @@ WR_FUNC; WR_INLINE void wr_dp_push_stacking_context(WrState *wrState, WrRect bounds, WrRect overflow, const WrImageMask *mask, - float opacity, const float* matrix, + float opacity, WrMatrix transform, WrMixBlendMode mixBlendMode) WR_FUNC;