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
--- 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;