Bug 1354946 - Add an explicit WrMatrix type for passing 4x4 matrices across the FFI boundary. r?rhunt draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 10 Apr 2017 18:24:14 -0400
changeset 559932 81efa1be928e26b55f75662261a790537437db03
parent 559931 f8c97e12c904f86ca47caede00abc6215c307df9
child 623571 7c6809afad12d35d1f8021a08b173ea4cf551c25
push id53284
push userkgupta@mozilla.com
push dateMon, 10 Apr 2017 22:25:08 +0000
reviewersrhunt
bugs1354946
milestone55.0a1
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: 5Lp9zFxYNRd
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -528,17 +528,17 @@ void
 DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
                                         const WrRect& aOverflow,
                                         const WrImageMask* aMask,
                                         const float aOpacity,
                                         const gfx::Matrix4x4& aTransform,
                                         const WrMixBlendMode& aMixBlendMode)
 {
   wr_dp_push_stacking_context(mWrState, aBounds, aOverflow, aMask, aOpacity,
-                              &aTransform.components[0], aMixBlendMode);
+                              ToWrMatrix(aTransform), aMixBlendMode);
 }
 
 void
 DisplayListBuilder::PopStackingContext()
 {
   wr_dp_pop_stacking_context(mWrState);
 }
 
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_WEBRENDERTYPES_H
 #define GFX_WEBRENDERTYPES_H
 
 #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"
 #include "Units.h"
 #include "nsStyleConsts.h"
 
 typedef mozilla::Maybe<WrImageMask> MaybeImageMask;
 
@@ -215,16 +216,26 @@ static inline WrSize ToWrSize(const gfx:
 }
 
 template<class T>
 static inline WrSize ToWrSize(const gfx::IntSizeTyped<T>& size)
 {
   return ToWrSize(IntSizeToSize(size));
 }
 
+template<class S, class T>
+static inline WrMatrix ToWrMatrix(const gfx::Matrix4x4Typed<S, T>& 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) {
   case NS_STYLE_BORDER_STYLE_NONE:
     return WrBorderStyle::None;
   case NS_STYLE_BORDER_STYLE_SOLID:
     return WrBorderStyle::Solid;
   case NS_STYLE_BORDER_STYLE_DOUBLE:
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -200,16 +200,32 @@ impl From<LayoutRect> for WrRect {
             y: rect.origin.y,
             width: rect.size.width,
             height: rect.size.height,
         }
     }
 }
 
 #[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,
     g: f32,
     b: f32,
     a: f32,
 }
 
 impl WrColor {
@@ -1078,17 +1094,17 @@ pub extern "C" fn wr_dp_new_clip_region(
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
                                               bounds: WrRect,
                                               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;
 
     let bounds = bounds.to_rect();
     let overflow = overflow.to_rect();
 
     // convert from the C type to the Rust type
@@ -1109,17 +1125,17 @@ pub extern "C" fn wr_dp_push_stacking_co
         filters.push(FilterOp::Opacity(PropertyBinding::Value(opacity)));
     }
 
     state.frame_builder
         .dl_builder
         .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);
     state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, None);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_dp_pop_stacking_context(state: &mut WrState) {
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -235,16 +235,21 @@ struct WrRect
 
   bool operator==(const WrRect& aRhs) const
   {
     return x == aRhs.x && y == aRhs.y &&
            width == aRhs.width && height == aRhs.height;
   }
 };
 
+struct WrMatrix
+{
+  float values[16];
+};
+
 struct WrColor
 {
   float r;
   float g;
   float b;
   float a;
 
   bool operator==(const WrColor& aRhs) const
@@ -625,17 +630,17 @@ wr_dp_new_clip_region(WrState* wrState,
                       WrRect main,
                       const WrComplexClipRegion* complex, size_t complexCount,
                       const WrImageMask* image_mask)
 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;
 
 //XXX: matrix should use a proper type
 WR_INLINE void
 wr_dp_pop_stacking_context(WrState *wrState)
 WR_FUNC;