Bug 1356371 - Use cbindgen for WebRender bindings generation r?kats draft
authorRyan Hunt <rhunt@eqrion.net>
Thu, 13 Apr 2017 15:45:51 -0400
changeset 562586 380abea4d28568cba0d344fe6645a2774daa06d2
parent 562263 2599db05d104cbfeaacfc8ff4ec51c8c0f262a91
child 624264 7211222b9431d97cabdd8afa0ef1f6fd2c58ca2f
push id54055
push userbmo:rhunt@eqrion.net
push dateFri, 14 Apr 2017 02:59:59 +0000
reviewerskats
bugs1356371
milestone55.0a1
Bug 1356371 - Use cbindgen for WebRender bindings generation r?kats This commit adds some directives to help cbindgen generate correct structs and functions, removes some old FFI code that isn't needed anymore, and autogenerates webrender_ffi_generated.h MozReview-Commit-ID: KZSEZEN671A
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -10,86 +10,67 @@ use webrender_traits::*;
 use webrender::renderer::{Renderer, RendererOptions};
 use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::{ApiRecordingReceiver, BinaryRecorder};
 use app_units::Au;
 use euclid::{TypedPoint2D, TypedSize2D, TypedRect, TypedMatrix4D, SideOffsets2D};
 
 extern crate webrender_traits;
 
-type WrAPI = RenderApi;
-type WrAuxiliaryListsDescriptor = AuxiliaryListsDescriptor;
-type WrBorderStyle = BorderStyle;
-type WrBoxShadowClipMode = BoxShadowClipMode;
-type WrBuiltDisplayListDescriptor = BuiltDisplayListDescriptor;
-type WrEpoch = Epoch;
-type WrFontKey = FontKey;
-type WrIdNamespace = IdNamespace;
-type WrImageFormat = ImageFormat;
-type WrImageRendering = ImageRendering;
-type WrImageKey = ImageKey;
-type WrMixBlendMode = MixBlendMode;
-type WrPipelineId = PipelineId;
-type WrRenderer = Renderer;
-type WrSideOffsets2Du32 = WrSideOffsets2D<u32>;
-type WrSideOffsets2Df32 = WrSideOffsets2D<f32>;
-
 // Enables binary recording that can be used with `wrench replay`
 // Outputs a wr-record-*.bin file for each window that is shown
 // Note: wrench will panic if external images are used, they can
 // be disabled in WebRenderBridgeParent::ProcessWebRenderCommands
 // by commenting out the path that adds an external image ID
 static ENABLE_RECORDING: bool = false;
 
+type WrAPI = RenderApi;
+type WrAuxiliaryListsDescriptor = AuxiliaryListsDescriptor;
+type WrBorderStyle = BorderStyle;
+type WrBoxShadowClipMode = BoxShadowClipMode;
+type WrBuiltDisplayListDescriptor = BuiltDisplayListDescriptor;
+type WrImageFormat = ImageFormat;
+type WrImageRendering = ImageRendering;
+type WrMixBlendMode = MixBlendMode;
+type WrRenderer = Renderer;
+type WrSideOffsets2Du32 = WrSideOffsets2D<u32>;
+type WrSideOffsets2Df32 = WrSideOffsets2D<f32>;
+
+/// cbindgen:field-names=[mHandle]
+/// cbindgen:struct-gen-op-lt=true
+/// cbindgen:struct-gen-op-lte=true
+type WrEpoch = Epoch;
+/// cbindgen:field-names=[mHandle]
+/// cbindgen:struct-gen-op-lt=true
+/// cbindgen:struct-gen-op-lte=true
+type WrIdNamespace = IdNamespace;
+
+/// cbindgen:field-names=[mNamespace, mHandle]
+type WrPipelineId = PipelineId;
+/// cbindgen:field-names=[mNamespace, mHandle]
+type WrImageKey = ImageKey;
+/// cbindgen:field-names=[mNamespace, mHandle]
+type WrFontKey = FontKey;
+
+/// cbindgen:field-names=[mHandle]
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct WrExternalImageId(pub u64);
 
 impl Into<ExternalImageId> for WrExternalImageId {
     fn into(self) -> ExternalImageId {
         ExternalImageId(self.0)
     }
 }
 impl Into<WrExternalImageId> for ExternalImageId {
     fn into(self) -> WrExternalImageId {
         WrExternalImageId(self.0)
     }
 }
 
-// This macro adds some checks to make sure we notice when the memory representation of
-// types change.
-macro_rules! check_ffi_type {
-    ($check_sizes_match:ident struct $TypeName:ident as ($T1:ident, $T2:ident)) => (
-        fn $check_sizes_match() {
-            #[repr(C)] struct TestType($T1, $T2);
-            let _ = mem::transmute::<$TypeName, TestType>;
-        }
-    );
-    ($check_sizes_match:ident struct $TypeName:ident as ($T:ident)) => (
-        fn $check_sizes_match() {
-            #[repr(C)] struct TestType($T);
-            let _ = mem::transmute::<$TypeName, TestType>;
-        }
-    );
-    ($check_sizes_match:ident enum $TypeName:ident as $T:ident) => (
-        fn $check_sizes_match() { let _ = mem::transmute::<$TypeName, $T>; }
-    );
-}
-
-check_ffi_type!(_pipeline_id_repr struct WrPipelineId as (u32, u32));
-check_ffi_type!(_image_key_repr struct WrImageKey as (u32, u32));
-check_ffi_type!(_font_key_repr struct WrFontKey as (u32, u32));
-check_ffi_type!(_epoch_repr struct WrEpoch as (u32));
-check_ffi_type!(_image_format_repr enum WrImageFormat as u32);
-check_ffi_type!(_border_style_repr enum WrBorderStyle as u32);
-check_ffi_type!(_image_rendering_repr enum WrImageRendering as u32);
-check_ffi_type!(_mix_blend_mode_repr enum WrMixBlendMode as u32);
-check_ffi_type!(_box_shadow_clip_mode_repr enum WrBoxShadowClipMode as u32);
-check_ffi_type!(_namespace_id_repr struct WrIdNamespace as (u32));
-
 const GL_FORMAT_BGRA_GL: gl::GLuint = gl::BGRA;
 const GL_FORMAT_BGRA_GLES: gl::GLuint = gl::BGRA_EXT;
 
 fn get_gl_format_bgra(gl: &gl::Gl) -> gl::GLuint {
     match gl.get_type() {
         gl::GlType::Gl => {
             GL_FORMAT_BGRA_GL
         }
@@ -565,16 +546,19 @@ impl ExternalImageHandler for WrExternal
         (self.unlock_func)(self.external_image_obj, id.into());
     }
 
     fn release(&mut self, id: ExternalImageId) {
         (self.release_func)(self.external_image_obj, id.into());
     }
 }
 
+/// cbindgen:field-names=[mHandle]
+/// cbindgen:struct-gen-op-lt=true
+/// cbindgen:struct-gen-op-lte=true
 #[repr(C)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct WrWindowId(u64);
 
 #[repr(C)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct WrImageDescriptor {
     pub format: WrImageFormat,
@@ -747,17 +731,17 @@ pub extern "C" fn wr_renderer_current_ep
                                             -> bool {
     if let Some(epoch) = renderer.current_epoch(pipeline_id) {
         *out_epoch = epoch;
         return true;
     }
     return false;
 }
 
-/// wr-binding:destructor_safe // This is used by the binding generator
+/// cbindgen:function-postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub unsafe extern "C" fn wr_renderer_delete(renderer: *mut WrRenderer) {
     Box::from_raw(renderer);
 }
 
 pub struct WrRenderedEpochs {
     data: Vec<(WrPipelineId, WrEpoch)>,
 }
@@ -780,17 +764,17 @@ pub unsafe extern "C" fn wr_rendered_epo
     if let Some((pipeline, epoch)) = pipeline_epochs.data.pop() {
         *out_pipeline = pipeline;
         *out_epoch = epoch;
         return true;
     }
     return false;
 }
 
-/// wr-binding:destructor_safe // This is used by the binding generator
+/// cbindgen:function-postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub unsafe extern "C" fn wr_rendered_epochs_delete(pipeline_epochs: *mut WrRenderedEpochs) {
     Box::from_raw(pipeline_epochs);
 }
 
 // Call MakeCurrent before this.
 #[no_mangle]
 pub extern "C" fn wr_window_new(window_id: WrWindowId,
@@ -996,17 +980,17 @@ pub unsafe extern "C" fn wr_api_clear_ro
                          preserve_frame_state);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_api_generate_frame(api: &mut WrAPI) {
     api.generate_frame(None);
 }
 
-/// wr-binding:destructor_safe // This is used by the binding generator
+/// cbindgen:function-postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub extern "C" fn wr_api_send_external_event(api: &mut WrAPI, evt: usize) {
     assert!(unsafe { !is_in_render_thread() });
 
     api.send_external_event(ExternalEvent::from_raw(evt));
 }
 
 #[no_mangle]
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -4,70 +4,19 @@
  * 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 WR_h
 #define WR_h
 
 #include "mozilla/gfx/Types.h"
 #include "nsTArray.h"
-#include "mozilla/gfx/Point.h"
-// ---
-#define WR_DECL_FFI_1(WrType, t1)                 \
-struct WrType {                                   \
-  t1 mHandle;                                     \
-  bool operator==(const WrType& rhs) const {      \
-    return mHandle == rhs.mHandle;                \
-  }                                               \
-  bool operator!=(const WrType& rhs) const {      \
-    return mHandle != rhs.mHandle;                \
-  }                                               \
-  bool operator<(const WrType& rhs) const {       \
-    return mHandle < rhs.mHandle;                 \
-  }                                               \
-  bool operator<=(const WrType& rhs) const {      \
-    return mHandle <= rhs.mHandle;                \
-  }                                               \
-};                                                \
-// ---
-
-// ---
-#define WR_DECL_FFI_2(WrType, t1, t2)             \
-struct WrType {                                   \
-  t1 mNamespace;                                  \
-  t2 mHandle;                                     \
-  bool operator==(const WrType& rhs) const {      \
-    return mNamespace == rhs.mNamespace           \
-        && mHandle == rhs.mHandle;                \
-  }                                               \
-  bool operator!=(const WrType& rhs) const {      \
-    return mNamespace != rhs.mNamespace           \
-        || mHandle != rhs.mHandle;                \
-  }                                               \
-};                                                \
-// ---
-
 
 extern "C" {
 
-// If you modify any of the declarations below, make sure to update the
-// serialization code in WebRenderMessageUtils.h and the rust bindings.
-
-WR_DECL_FFI_1(WrEpoch, uint32_t)
-WR_DECL_FFI_1(WrIdNamespace, uint32_t)
-WR_DECL_FFI_1(WrWindowId, uint64_t)
-WR_DECL_FFI_1(WrExternalImageId, uint64_t)
-
-WR_DECL_FFI_2(WrPipelineId, uint32_t, uint32_t)
-WR_DECL_FFI_2(WrImageKey, uint32_t, uint32_t)
-WR_DECL_FFI_2(WrFontKey, uint32_t, uint32_t)
-
-#undef WR_DECL_FFI_1
-#undef WR_DECL_FFI_2
-
 // ----
 // Functions invoked from Rust code
 // ----
 
 bool is_in_compositor_thread();
 bool is_in_main_thread();
 bool is_in_render_thread();
 bool is_glcontext_egl(void* glcontext_ptr);
@@ -86,22 +35,16 @@ void* get_proc_address_from_glcontext(vo
 #  define WR_FUNC
 #  define WR_DESTRUCTOR_SAFE_FUNC
 #else
 #  define WR_INLINE inline
 #  define WR_FUNC { MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("WebRender disabled"); }
 #  define WR_DESTRUCTOR_SAFE_FUNC {}
 #endif
 
-// Structs defined in Rust, but opaque to C++ code.
-struct WrRenderedEpochs;
-struct WrRenderer;
-struct WrState;
-struct WrAPI;
-
 #include "webrender_ffi_generated.h"
 
 #undef WR_FUNC
 #undef WR_DESTRUCTOR_SAFE_FUNC
 } // extern "C"
 
 struct WrGlyphArray
 {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1,129 +1,224 @@
 /* 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 http://mozilla.org/MPL/2.0/. */
 
-/* THIS FILE IS GENERATED! DO NOT MODIFY MANUALLY! See https://github.com/jrmuizel/wr-binding! */
-struct WrVecU8 {
-  uint8_t* data;
-  size_t length;
-  size_t capacity;
+/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
+ * To generate this file, clone `https://github.com/rlhunt/cbindgen` or run `cargo install cbindgen`,
+ * then run `cbindgen -c wr gfx/webrender_bindings/ gfx/webrender_bindings/webrender_ffi_generated.h` */
 
-  bool operator==(const WrVecU8& aOther) const {
-    return data == aOther.data &&
-      length == aOther.length &&
-      capacity == aOther.capacity;
-  }
+enum class WrBorderStyle : uint32_t {
+  None = 0,
+  Solid = 1,
+  Double = 2,
+  Dotted = 3,
+  Dashed = 4,
+  Hidden = 5,
+  Groove = 6,
+  Ridge = 7,
+  Inset = 8,
+  Outset = 9,
+
+  Sentinel /* this must be last for serialization purposes. */
 };
 
-enum class WrExternalImageType: uint32_t {
+enum class WrBoxShadowClipMode : uint32_t {
+  None = 0,
+  Outset = 1,
+  Inset = 2,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
+enum class WrExternalImageType : uint32_t {
   NativeTexture = 0,
   RawData = 1,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
-struct WrExternalImage {
-  WrExternalImageType image_type;
-  uint32_t handle;
-  float u0;
-  float v0;
-  float u1;
-  float v1;
-  const uint8_t* buff;
-  size_t size;
+enum class WrGradientExtendMode : uint32_t {
+  Clamp = 0,
+  Repeat = 1,
 
-  bool operator==(const WrExternalImage& aOther) const {
-    return image_type == aOther.image_type &&
-      handle == aOther.handle &&
-      u0 == aOther.u0 &&
-      v0 == aOther.v0 &&
-      u1 == aOther.u1 &&
-      v1 == aOther.v1 &&
-      buff == aOther.buff &&
-      size == aOther.size;
-  }
+  Sentinel /* this must be last for serialization purposes. */
 };
 
-typedef WrExternalImage (* LockExternalImageCallback)(void*, WrExternalImageId);
-
-typedef void (* ReleaseExternalImageCallback)(void*, WrExternalImageId);
-
-typedef void (* UnlockExternalImageCallback)(void*, WrExternalImageId);
-
-struct WrExternalImageHandler {
-  void* external_image_obj;
-  LockExternalImageCallback lock_func;
-  UnlockExternalImageCallback unlock_func;
-  ReleaseExternalImageCallback release_func;
-
-  bool operator==(const WrExternalImageHandler& aOther) const {
-    return external_image_obj == aOther.external_image_obj &&
-      lock_func == aOther.lock_func &&
-      unlock_func == aOther.unlock_func &&
-      release_func == aOther.release_func;
-  }
-};
-
-struct WrByteSlice {
-  const uint8_t* buffer;
-  size_t len;
-
-  bool operator==(const WrByteSlice& aOther) const {
-    return buffer == aOther.buffer &&
-      len == aOther.len;
-  }
-};
-
-enum class WrImageFormat: uint32_t {
+enum class WrImageFormat : uint32_t {
   Invalid = 0,
   A8 = 1,
   RGB8 = 2,
   RGBA8 = 3,
   RGBAF32 = 4,
 
   Sentinel /* this must be last for serialization purposes. */
 };
 
+enum class WrImageRendering : uint32_t {
+  Auto = 0,
+  CrispEdges = 1,
+  Pixelated = 2,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
+enum class WrMixBlendMode : uint32_t {
+  Normal = 0,
+  Multiply = 1,
+  Screen = 2,
+  Overlay = 3,
+  Darken = 4,
+  Lighten = 5,
+  ColorDodge = 6,
+  ColorBurn = 7,
+  HardLight = 8,
+  SoftLight = 9,
+  Difference = 10,
+  Exclusion = 11,
+  Hue = 12,
+  Saturation = 13,
+  Color = 14,
+  Luminosity = 15,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
+enum class WrRepeatMode : uint32_t {
+  Stretch = 0,
+  Repeat = 1,
+  Round = 2,
+  Space = 3,
+
+  Sentinel /* this must be last for serialization purposes. */
+};
+
+struct WrAPI;
+
+struct WrImageKey {
+  uint32_t mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const WrImageKey& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+      mHandle == aOther.mHandle;
+  }
+};
+
 struct WrImageDescriptor {
   WrImageFormat format;
   uint32_t width;
   uint32_t height;
   uint32_t stride;
   bool is_opaque;
 
   bool operator==(const WrImageDescriptor& aOther) const {
     return format == aOther.format &&
       width == aOther.width &&
       height == aOther.height &&
       stride == aOther.stride &&
       is_opaque == aOther.is_opaque;
   }
 };
 
+struct WrByteSlice {
+  const uint8_t* buffer;
+  size_t len;
+
+  bool operator==(const WrByteSlice& aOther) const {
+    return buffer == aOther.buffer &&
+      len == aOther.len;
+  }
+};
+
+struct WrFontKey {
+  uint32_t mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const WrFontKey& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+      mHandle == aOther.mHandle;
+  }
+};
+
+struct WrEpoch {
+  uint32_t mHandle;
+
+  bool operator==(const WrEpoch& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
+
+  bool operator<(const WrEpoch& aOther) const {
+    return mHandle < aOther.mHandle;
+  }
+
+  bool operator<=(const WrEpoch& aOther) const {
+    return mHandle <= aOther.mHandle;
+  }
+};
+
+struct WrPipelineId {
+  uint32_t mNamespace;
+  uint32_t mHandle;
+
+  bool operator==(const WrPipelineId& aOther) const {
+    return mNamespace == aOther.mNamespace &&
+      mHandle == aOther.mHandle;
+  }
+};
+
+struct WrState;
+
+struct WrBuiltDisplayListDescriptor {
+  size_t display_list_items_size;
+
+  bool operator==(const WrBuiltDisplayListDescriptor& aOther) const {
+    return display_list_items_size == aOther.display_list_items_size;
+  }
+};
+
+struct WrVecU8 {
+  uint8_t* data;
+  size_t length;
+  size_t capacity;
+
+  bool operator==(const WrVecU8& aOther) const {
+    return data == aOther.data &&
+      length == aOther.length &&
+      capacity == aOther.capacity;
+  }
+};
+
 struct WrAuxiliaryListsDescriptor {
   size_t gradient_stops_size;
   size_t complex_clip_regions_size;
   size_t filters_size;
   size_t glyph_instances_size;
 
   bool operator==(const WrAuxiliaryListsDescriptor& aOther) const {
     return gradient_stops_size == aOther.gradient_stops_size &&
       complex_clip_regions_size == aOther.complex_clip_regions_size &&
       filters_size == aOther.filters_size &&
       glyph_instances_size == aOther.glyph_instances_size;
   }
 };
 
-struct WrBuiltDisplayListDescriptor {
-  size_t display_list_items_size;
+struct WrIdNamespace {
+  uint32_t mHandle;
+
+  bool operator==(const WrIdNamespace& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
 
-  bool operator==(const WrBuiltDisplayListDescriptor& aOther) const {
-    return display_list_items_size == aOther.display_list_items_size;
+  bool operator<(const WrIdNamespace& aOther) const {
+    return mHandle < aOther.mHandle;
+  }
+
+  bool operator<=(const WrIdNamespace& aOther) const {
+    return mHandle <= aOther.mHandle;
   }
 };
 
 struct WrRect {
   float x;
   float y;
   float width;
   float height;
@@ -131,38 +226,38 @@ struct WrRect {
   bool operator==(const WrRect& aOther) const {
     return x == aOther.x &&
       y == aOther.y &&
       width == aOther.width &&
       height == aOther.height;
   }
 };
 
+struct WrItemRange {
+  size_t start;
+  size_t length;
+
+  bool operator==(const WrItemRange& aOther) const {
+    return start == aOther.start &&
+      length == aOther.length;
+  }
+};
+
 struct WrImageMask {
   WrImageKey image;
   WrRect rect;
   bool repeat;
 
   bool operator==(const WrImageMask& aOther) const {
     return image == aOther.image &&
       rect == aOther.rect &&
       repeat == aOther.repeat;
   }
 };
 
-struct WrItemRange {
-  size_t start;
-  size_t length;
-
-  bool operator==(const WrItemRange& aOther) const {
-    return start == aOther.start &&
-      length == aOther.length;
-  }
-};
-
 struct WrClipRegion {
   WrRect main;
   WrItemRange complex;
   WrImageMask image_mask;
   bool has_image_mask;
 
   bool operator==(const WrClipRegion& aOther) const {
     return main == aOther.main &&
@@ -201,123 +296,85 @@ struct WrComplexClipRegion {
   WrBorderRadius radii;
 
   bool operator==(const WrComplexClipRegion& aOther) const {
     return rect == aOther.rect &&
       radii == aOther.radii;
   }
 };
 
-struct WrMatrix {
-  float values[16];
-
-  bool operator==(const WrMatrix& aOther) const {
-    return values == aOther.values;
-  }
-};
+struct WrBorderWidths {
+  float left;
+  float top;
+  float right;
+  float bottom;
 
-enum class WrMixBlendMode: uint32_t {
-  Normal = 0,
-  Multiply = 1,
-  Screen = 2,
-  Overlay = 3,
-  Darken = 4,
-  Lighten = 5,
-  ColorDodge = 6,
-  ColorBurn = 7,
-  HardLight = 8,
-  SoftLight = 9,
-  Difference = 10,
-  Exclusion = 11,
-  Hue = 12,
-  Saturation = 13,
-  Color = 14,
-  Luminosity = 15,
-
-  Sentinel /* this must be last for serialization purposes. */
+  bool operator==(const WrBorderWidths& aOther) const {
+    return left == aOther.left &&
+      top == aOther.top &&
+      right == aOther.right &&
+      bottom == aOther.bottom;
+  }
 };
 
 struct WrColor {
   float r;
   float g;
   float b;
   float a;
 
   bool operator==(const WrColor& aOther) const {
     return r == aOther.r &&
       g == aOther.g &&
       b == aOther.b &&
       a == aOther.a;
   }
 };
 
-enum class WrImageRendering: uint32_t {
-  Auto = 0,
-  CrispEdges = 1,
-  Pixelated = 2,
+struct WrBorderSide {
+  WrColor color;
+  WrBorderStyle style;
 
-  Sentinel /* this must be last for serialization purposes. */
+  bool operator==(const WrBorderSide& aOther) const {
+    return color == aOther.color &&
+      style == aOther.style;
+  }
 };
 
 struct WrPoint {
   float x;
   float y;
 
   bool operator==(const WrPoint& aOther) const {
     return x == aOther.x &&
       y == aOther.y;
   }
 };
 
-struct WrGlyphInstance {
-  uint32_t index;
-  WrPoint point;
+struct WrGradientStop {
+  float offset;
+  WrColor color;
 
-  bool operator==(const WrGlyphInstance& aOther) const {
-    return index == aOther.index &&
-      point == aOther.point;
+  bool operator==(const WrGradientStop& aOther) const {
+    return offset == aOther.offset &&
+      color == aOther.color;
   }
 };
 
-enum class WrBorderStyle: uint32_t {
-  None = 0,
-  Solid = 1,
-  Double = 2,
-  Dotted = 3,
-  Dashed = 4,
-  Hidden = 5,
-  Groove = 6,
-  Ridge = 7,
-  Inset = 8,
-  Outset = 9,
-
-  Sentinel /* this must be last for serialization purposes. */
-};
-
-struct WrBorderSide {
-  WrColor color;
-  WrBorderStyle style;
-
-  bool operator==(const WrBorderSide& aOther) const {
-    return color == aOther.color &&
-      style == aOther.style;
-  }
-};
-
-struct WrBorderWidths {
-  float left;
+struct WrSideOffsets2Df32 {
   float top;
   float right;
   float bottom;
+  float left;
 
-  bool operator==(const WrBorderWidths& aOther) const {
-    return left == aOther.left &&
-      top == aOther.top &&
+  bool operator==(const WrSideOffsets2Df32& aOther) const {
+    return top == aOther.top &&
       right == aOther.right &&
-      bottom == aOther.bottom;
+      bottom == aOther.bottom &&
+      left == aOther.left;
   }
 };
 
 struct WrSideOffsets2Du32 {
   uint32_t top;
   uint32_t right;
   uint32_t bottom;
   uint32_t left;
@@ -337,237 +394,214 @@ struct WrNinePatchDescriptor {
 
   bool operator==(const WrNinePatchDescriptor& aOther) const {
     return width == aOther.width &&
       height == aOther.height &&
       slice == aOther.slice;
   }
 };
 
-enum class WrRepeatMode: uint32_t {
-  Stretch = 0,
-  Repeat = 1,
-  Round = 2,
-  Space = 3,
+struct WrMatrix {
+  float values[16];
+
+  bool operator==(const WrMatrix& aOther) const {
+    return values == aOther.values;
+  }
+};
 
-  Sentinel /* this must be last for serialization purposes. */
+struct WrGlyphInstance {
+  uint32_t index;
+  WrPoint point;
+
+  bool operator==(const WrGlyphInstance& aOther) const {
+    return index == aOther.index &&
+      point == aOther.point;
+  }
 };
 
-struct WrSideOffsets2Df32 {
-  float top;
-  float right;
-  float bottom;
-  float left;
+struct WrRenderedEpochs;
+
+struct WrRenderer;
 
-  bool operator==(const WrSideOffsets2Df32& aOther) const {
-    return top == aOther.top &&
-      right == aOther.right &&
-      bottom == aOther.bottom &&
-      left == aOther.left;
+struct WrExternalImage {
+  WrExternalImageType image_type;
+  uint32_t handle;
+  float u0;
+  float v0;
+  float u1;
+  float v1;
+  const uint8_t* buff;
+  size_t size;
+
+  bool operator==(const WrExternalImage& aOther) const {
+    return image_type == aOther.image_type &&
+      handle == aOther.handle &&
+      u0 == aOther.u0 &&
+      v0 == aOther.v0 &&
+      u1 == aOther.u1 &&
+      v1 == aOther.v1 &&
+      buff == aOther.buff &&
+      size == aOther.size;
   }
 };
 
-enum class WrGradientExtendMode: uint32_t {
-  Clamp = 0,
-  Repeat = 1,
-
-  Sentinel /* this must be last for serialization purposes. */
-};
+struct WrExternalImageId {
+  uint64_t mHandle;
 
-struct WrGradientStop {
-  float offset;
-  WrColor color;
-
-  bool operator==(const WrGradientStop& aOther) const {
-    return offset == aOther.offset &&
-      color == aOther.color;
+  bool operator==(const WrExternalImageId& aOther) const {
+    return mHandle == aOther.mHandle;
   }
 };
 
-enum class WrBoxShadowClipMode: uint32_t {
-  None = 0,
-  Outset = 1,
-  Inset = 2,
+typedef WrExternalImage (*LockExternalImageCallback)(void*, WrExternalImageId);
+
+typedef void (*UnlockExternalImageCallback)(void*, WrExternalImageId);
+
+typedef void (*ReleaseExternalImageCallback)(void*, WrExternalImageId);
 
-  Sentinel /* this must be last for serialization purposes. */
+struct WrExternalImageHandler {
+  void* external_image_obj;
+  LockExternalImageCallback lock_func;
+  UnlockExternalImageCallback unlock_func;
+  ReleaseExternalImageCallback release_func;
+
+  bool operator==(const WrExternalImageHandler& aOther) const {
+    return external_image_obj == aOther.external_image_obj &&
+      lock_func == aOther.lock_func &&
+      unlock_func == aOther.unlock_func &&
+      release_func == aOther.release_func;
+  }
 };
 
-/* THIS FILE IS GENERATED! DO NOT MODIFY MANUALLY! See https://github.com/jrmuizel/wr-binding! */
-WR_INLINE void
-wr_vec_u8_free(WrVecU8 v)
-WR_FUNC;
+struct WrWindowId {
+  uint64_t mHandle;
+
+  bool operator==(const WrWindowId& aOther) const {
+    return mHandle == aOther.mHandle;
+  }
+
+  bool operator<(const WrWindowId& aOther) const {
+    return mHandle < aOther.mHandle;
+  }
+
+  bool operator<=(const WrWindowId& aOther) const {
+    return mHandle <= aOther.mHandle;
+  }
+};
+
+/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
+ * To generate this file, clone `https://github.com/rlhunt/cbindgen` or run `cargo install cbindgen`,
+ * then run `cbindgen -c wr gfx/webrender_bindings/ gfx/webrender_bindings/webrender_ffi_generated.h` */
 
 WR_INLINE void
-wr_renderer_set_external_image_handler(WrRenderer* renderer,
-    WrExternalImageHandler* external_image_handler)
+wr_api_add_blob_image(WrAPI* api,
+    WrImageKey image_key,
+    const WrImageDescriptor* descriptor,
+    WrByteSlice bytes)
 WR_FUNC;
 
 WR_INLINE void
-wr_renderer_update(WrRenderer* renderer)
-WR_FUNC;
-
-WR_INLINE void
-wr_renderer_render(WrRenderer* renderer,
-    uint32_t width,
-    uint32_t height)
-WR_FUNC;
-
-WR_INLINE void
-wr_renderer_readback(WrRenderer* renderer,
-    uint32_t width,
-    uint32_t height,
-    uint8_t* dst_buffer,
-    size_t buffer_size)
-WR_FUNC;
-
-WR_INLINE void
-wr_renderer_set_profiler_enabled(WrRenderer* renderer,
-    bool enabled)
-WR_FUNC;
-
-WR_INLINE bool
-wr_renderer_current_epoch(WrRenderer* renderer,
-    WrPipelineId pipeline_id,
-    WrEpoch* out_epoch)
+wr_api_add_external_image_buffer(WrAPI* api,
+    WrImageKey image_key,
+    const WrImageDescriptor* descriptor,
+    uint64_t external_image_id)
 WR_FUNC;
 
 WR_INLINE void
-wr_renderer_delete(WrRenderer* renderer)
-WR_DESTRUCTOR_SAFE_FUNC;
-
-WR_INLINE WrRenderedEpochs*
-wr_renderer_flush_rendered_epochs(WrRenderer* renderer)
-WR_FUNC;
-
-WR_INLINE bool
-wr_rendered_epochs_next(WrRenderedEpochs* pipeline_epochs,
-    WrPipelineId* out_pipeline,
-    WrEpoch* out_epoch)
-WR_FUNC;
-
-WR_INLINE void
-wr_rendered_epochs_delete(WrRenderedEpochs* pipeline_epochs)
-WR_DESTRUCTOR_SAFE_FUNC;
-
-WR_INLINE bool
-wr_window_new(WrWindowId window_id,
-    uint32_t window_width,
-    uint32_t window_height,
-    void* gl_context,
-    bool enable_profiler,
-    WrAPI** out_api,
-    WrRenderer** out_renderer)
-WR_FUNC;
-
-WR_INLINE void
-wr_api_delete(WrAPI* api)
+wr_api_add_external_image_handle(WrAPI* api,
+    WrImageKey image_key,
+    const WrImageDescriptor* descriptor,
+    uint64_t external_image_id)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_add_image(WrAPI* api,
     WrImageKey image_key,
     const WrImageDescriptor* descriptor,
     WrByteSlice bytes)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_add_blob_image(WrAPI* api,
-    WrImageKey image_key,
-    const WrImageDescriptor* descriptor,
-    WrByteSlice bytes)
+wr_api_add_raw_font(WrAPI* api,
+    WrFontKey key,
+    uint8_t* font_buffer,
+    size_t buffer_size)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_add_external_image_handle(WrAPI* api,
-    WrImageKey image_key,
-    const WrImageDescriptor* descriptor,
-    uint64_t external_image_id)
+wr_api_clear_root_display_list(WrAPI* api,
+    WrEpoch epoch,
+    WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_add_external_image_buffer(WrAPI* api,
-    WrImageKey image_key,
-    const WrImageDescriptor* descriptor,
-    uint64_t external_image_id)
+wr_api_delete(WrAPI* api)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_update_image(WrAPI* api,
-    WrImageKey key,
-    const WrImageDescriptor* descriptor,
-    WrByteSlice bytes)
+wr_api_delete_font(WrAPI* api,
+    WrFontKey key)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_delete_image(WrAPI* api,
     WrImageKey key)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_set_root_pipeline(WrAPI* api,
-    WrPipelineId pipeline_id)
+wr_api_finalize_builder(WrState* state,
+    WrBuiltDisplayListDescriptor* dl_descriptor,
+    WrVecU8* dl_data,
+    WrAuxiliaryListsDescriptor* aux_descriptor,
+    WrVecU8* aux_data)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_set_window_parameters(WrAPI* api,
-    int32_t width,
-    int32_t height)
+wr_api_generate_frame(WrAPI* api)
+WR_FUNC;
+
+WR_INLINE WrIdNamespace
+wr_api_get_namespace(WrAPI* api)
 WR_FUNC;
 
 WR_INLINE void
+wr_api_send_external_event(WrAPI* api,
+    size_t evt)
+WR_DESTRUCTOR_SAFE_FUNC;
+
+WR_INLINE void
 wr_api_set_root_display_list(WrAPI* api,
     WrEpoch epoch,
     float viewport_width,
     float viewport_height,
     WrPipelineId pipeline_id,
     WrBuiltDisplayListDescriptor dl_descriptor,
     uint8_t* dl_data,
     size_t dl_size,
     WrAuxiliaryListsDescriptor aux_descriptor,
     uint8_t* aux_data,
     size_t aux_size)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_clear_root_display_list(WrAPI* api,
-    WrEpoch epoch,
+wr_api_set_root_pipeline(WrAPI* api,
     WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_generate_frame(WrAPI* api)
+wr_api_set_window_parameters(WrAPI* api,
+    int32_t width,
+    int32_t height)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_send_external_event(WrAPI* api,
-    size_t evt)
-WR_DESTRUCTOR_SAFE_FUNC;
-
-WR_INLINE void
-wr_api_add_raw_font(WrAPI* api,
-    WrFontKey key,
-    uint8_t* font_buffer,
-    size_t buffer_size)
-WR_FUNC;
-
-WR_INLINE void
-wr_api_delete_font(WrAPI* api,
-    WrFontKey key)
-WR_FUNC;
-
-WR_INLINE WrIdNamespace
-wr_api_get_namespace(WrAPI* api)
-WR_FUNC;
-
-WR_INLINE WrState*
-wr_state_new(WrPipelineId pipeline_id)
-WR_FUNC;
-
-WR_INLINE void
-wr_state_delete(WrState* state)
+wr_api_update_image(WrAPI* api,
+    WrImageKey key,
+    const WrImageDescriptor* descriptor,
+    WrByteSlice bytes)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_begin(WrState* state,
     uint32_t width,
     uint32_t height)
 WR_FUNC;
 
@@ -579,124 +613,112 @@ WR_INLINE WrClipRegion
 wr_dp_new_clip_region(WrState* state,
     WrRect main,
     const WrComplexClipRegion* complex,
     size_t complex_count,
     const WrImageMask* image_mask)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_push_stacking_context(WrState* state,
-    WrRect bounds,
-    float opacity,
-    WrMatrix transform,
-    WrMixBlendMode mix_blend_mode)
-WR_FUNC;
-
-WR_INLINE void
-wr_dp_pop_stacking_context(WrState* state)
-WR_FUNC;
-
-WR_INLINE void
-wr_dp_push_scroll_layer(WrState* state,
-    WrRect bounds,
-    WrRect overflow,
-    const WrImageMask* mask)
-WR_FUNC;
-
-WR_INLINE void
 wr_dp_pop_scroll_layer(WrState* state)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_push_iframe(WrState* state,
-    WrRect rect,
-    WrClipRegion clip,
-    WrPipelineId pipeline_id)
-WR_FUNC;
-
-WR_INLINE void
-wr_dp_push_rect(WrState* state,
-    WrRect rect,
-    WrClipRegion clip,
-    WrColor color)
-WR_FUNC;
-
-WR_INLINE void
-wr_dp_push_image(WrState* state,
-    WrRect bounds,
-    WrClipRegion clip,
-    WrSize stretch_size,
-    WrSize tile_spacing,
-    WrImageRendering image_rendering,
-    WrImageKey key)
-WR_FUNC;
-
-WR_INLINE void
-wr_dp_push_text(WrState* state,
-    WrRect bounds,
-    WrClipRegion clip,
-    WrColor color,
-    WrFontKey font_key,
-    const WrGlyphInstance* glyphs,
-    uint32_t glyph_count,
-    float glyph_size)
+wr_dp_pop_stacking_context(WrState* state)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_border(WrState* state,
     WrRect rect,
     WrClipRegion clip,
     WrBorderWidths widths,
     WrBorderSide top,
     WrBorderSide right,
     WrBorderSide bottom,
     WrBorderSide left,
     WrBorderRadius radius)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_push_border_image(WrState* state,
-    WrRect rect,
-    WrClipRegion clip,
-    WrBorderWidths widths,
-    WrImageKey image,
-    WrNinePatchDescriptor patch,
-    WrSideOffsets2Df32 outset,
-    WrRepeatMode repeat_horizontal,
-    WrRepeatMode repeat_vertical)
-WR_FUNC;
-
-WR_INLINE void
 wr_dp_push_border_gradient(WrState* state,
     WrRect rect,
     WrClipRegion clip,
     WrBorderWidths widths,
     WrPoint start_point,
     WrPoint end_point,
     const WrGradientStop* stops,
     size_t stops_count,
     WrGradientExtendMode extend_mode,
     WrSideOffsets2Df32 outset)
 WR_FUNC;
 
 WR_INLINE void
+wr_dp_push_border_image(WrState* state,
+    WrRect rect,
+    WrClipRegion clip,
+    WrBorderWidths widths,
+    WrImageKey image,
+    WrNinePatchDescriptor patch,
+    WrSideOffsets2Df32 outset,
+    WrRepeatMode repeat_horizontal,
+    WrRepeatMode repeat_vertical)
+WR_FUNC;
+
+WR_INLINE void
 wr_dp_push_border_radial_gradient(WrState* state,
     WrRect rect,
     WrClipRegion clip,
     WrBorderWidths widths,
     WrPoint center,
     WrSize radius,
     const WrGradientStop* stops,
     size_t stops_count,
     WrGradientExtendMode extend_mode,
     WrSideOffsets2Df32 outset)
 WR_FUNC;
 
 WR_INLINE void
+wr_dp_push_box_shadow(WrState* state,
+    WrRect rect,
+    WrClipRegion clip,
+    WrRect box_bounds,
+    WrPoint offset,
+    WrColor color,
+    float blur_radius,
+    float spread_radius,
+    float border_radius,
+    WrBoxShadowClipMode clip_mode)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_built_display_list(WrState* state,
+    WrBuiltDisplayListDescriptor dl_descriptor,
+    WrVecU8 dl_data,
+    WrAuxiliaryListsDescriptor aux_descriptor,
+    WrVecU8 aux_data)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_iframe(WrState* state,
+    WrRect rect,
+    WrClipRegion clip,
+    WrPipelineId pipeline_id)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_image(WrState* state,
+    WrRect bounds,
+    WrClipRegion clip,
+    WrSize stretch_size,
+    WrSize tile_spacing,
+    WrImageRendering image_rendering,
+    WrImageKey key)
+WR_FUNC;
+
+WR_INLINE void
 wr_dp_push_linear_gradient(WrState* state,
     WrRect rect,
     WrClipRegion clip,
     WrPoint start_point,
     WrPoint end_point,
     const WrGradientStop* stops,
     size_t stops_count,
     WrGradientExtendMode extend_mode,
@@ -713,37 +735,117 @@ wr_dp_push_radial_gradient(WrState* stat
     const WrGradientStop* stops,
     size_t stops_count,
     WrGradientExtendMode extend_mode,
     WrSize tile_size,
     WrSize tile_spacing)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_push_box_shadow(WrState* state,
+wr_dp_push_rect(WrState* state,
     WrRect rect,
     WrClipRegion clip,
-    WrRect box_bounds,
-    WrPoint offset,
+    WrColor color)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_scroll_layer(WrState* state,
+    WrRect bounds,
+    WrRect overflow,
+    const WrImageMask* mask)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_stacking_context(WrState* state,
+    WrRect bounds,
+    float opacity,
+    WrMatrix transform,
+    WrMixBlendMode mix_blend_mode)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_push_text(WrState* state,
+    WrRect bounds,
+    WrClipRegion clip,
     WrColor color,
-    float blur_radius,
-    float spread_radius,
-    float border_radius,
-    WrBoxShadowClipMode clip_mode)
+    WrFontKey font_key,
+    const WrGlyphInstance* glyphs,
+    uint32_t glyph_count,
+    float glyph_size)
+WR_FUNC;
+
+WR_INLINE void
+wr_rendered_epochs_delete(WrRenderedEpochs* pipeline_epochs)
+WR_DESTRUCTOR_SAFE_FUNC;
+
+WR_INLINE bool
+wr_rendered_epochs_next(WrRenderedEpochs* pipeline_epochs,
+    WrPipelineId* out_pipeline,
+    WrEpoch* out_epoch)
+WR_FUNC;
+
+WR_INLINE bool
+wr_renderer_current_epoch(WrRenderer* renderer,
+    WrPipelineId pipeline_id,
+    WrEpoch* out_epoch)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_finalize_builder(WrState* state,
-    WrBuiltDisplayListDescriptor* dl_descriptor,
-    WrVecU8* dl_data,
-    WrAuxiliaryListsDescriptor* aux_descriptor,
-    WrVecU8* aux_data)
+wr_renderer_delete(WrRenderer* renderer)
+WR_DESTRUCTOR_SAFE_FUNC;
+
+WR_INLINE WrRenderedEpochs*
+wr_renderer_flush_rendered_epochs(WrRenderer* renderer)
+WR_FUNC;
+
+WR_INLINE void
+wr_renderer_readback(WrRenderer* renderer,
+    uint32_t width,
+    uint32_t height,
+    uint8_t* dst_buffer,
+    size_t buffer_size)
+WR_FUNC;
+
+WR_INLINE void
+wr_renderer_render(WrRenderer* renderer,
+    uint32_t width,
+    uint32_t height)
+WR_FUNC;
+
+WR_INLINE void
+wr_renderer_set_external_image_handler(WrRenderer* renderer,
+    WrExternalImageHandler* external_image_handler)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_push_built_display_list(WrState* state,
-    WrBuiltDisplayListDescriptor dl_descriptor,
-    WrVecU8 dl_data,
-    WrAuxiliaryListsDescriptor aux_descriptor,
-    WrVecU8 aux_data)
+wr_renderer_set_profiler_enabled(WrRenderer* renderer,
+    bool enabled)
+WR_FUNC;
+
+WR_INLINE void
+wr_renderer_update(WrRenderer* renderer)
+WR_FUNC;
+
+WR_INLINE void
+wr_state_delete(WrState* state)
+WR_FUNC;
+
+WR_INLINE WrState*
+wr_state_new(WrPipelineId pipeline_id)
 WR_FUNC;
 
-/* THIS FILE IS GENERATED! DO NOT MODIFY MANUALLY! See https://github.com/jrmuizel/wr-binding! */
+WR_INLINE void
+wr_vec_u8_free(WrVecU8 v)
+WR_FUNC;
+
+WR_INLINE bool
+wr_window_new(WrWindowId window_id,
+    uint32_t window_width,
+    uint32_t window_height,
+    void* gl_context,
+    bool enable_profiler,
+    WrAPI** out_api,
+    WrRenderer** out_renderer)
+WR_FUNC;
+
+/* DO NOT MODIFY THIS MANUALLY! This file was generated using cbindgen.
+ * To generate this file, clone `https://github.com/rlhunt/cbindgen` or run `cargo install cbindgen`,
+ * then run `cbindgen -c wr gfx/webrender_bindings/ gfx/webrender_bindings/webrender_ffi_generated.h` */