Bug 1403198 - send font descriptors to WR instead of raw fonts where possible. r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Mon, 06 Nov 2017 20:19:46 -0500
changeset 390416 e0ad40dad503e8d176512140c32d05513a57e4a9
parent 390415 0418d4d4a91ef989fb18d56a1b30e2a6e413cec5
child 390417 87fb72d343ed6942483a99813d58f8203bdc56a2
push id97040
push userlsalzman@mozilla.com
push dateTue, 07 Nov 2017 01:21:59 +0000
treeherdermozilla-inbound@5a38089c0375 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1403198
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1403198 - send font descriptors to WR instead of raw fonts where possible. r=jrmuizel MozReview-Commit-ID: DYcaO3fE1fc
gfx/2d/2D.h
gfx/2d/Factory.cpp
gfx/2d/RecordedEventImpl.h
gfx/2d/ScaledFontFontconfig.cpp
gfx/2d/ScaledFontWin.cpp
gfx/2d/UnscaledFontFreeType.cpp
gfx/2d/UnscaledFontFreeType.h
gfx/2d/UnscaledFontGDI.h
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/wr/IpcResourceUpdateQueue.cpp
gfx/layers/wr/IpcResourceUpdateQueue.h
gfx/layers/wr/WebRenderBridgeChild.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -741,21 +741,26 @@ public:
   virtual ~UnscaledFont();
 
   virtual FontType GetType() const = 0;
 
   static uint32_t DeletionCounter() { return sDeletionCounter; }
 
   typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex,
                                      void *aBaton);
+  typedef void (*WRFontDescriptorOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex,
+                                         void *aBaton);
   typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton);
-  typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton);
+  typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
+                                       void* aBaton);
 
   virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; }
 
+  virtual bool GetWRFontDescriptor(WRFontDescriptorOutput, void *) { return false; }
+
   virtual bool GetFontInstanceData(FontInstanceDataOutput, void *) { return false; }
 
   virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; }
 
   virtual already_AddRefed<ScaledFont>
     CreateScaledFont(Float aGlyphSize,
                      const uint8_t* aInstanceData,
                      uint32_t aInstanceDataLength,
@@ -1560,17 +1565,17 @@ public:
   static already_AddRefed<NativeFontResource>
     CreateNativeFontResource(uint8_t *aData, uint32_t aSize, BackendType aBackendType, FontType aFontType, void* aFontContext = nullptr);
 
   /**
    * This creates an unscaled font of the given type based on font descriptor
    * data retrieved from ScaledFont::GetFontDescriptor.
    */
   static already_AddRefed<UnscaledFont>
-    CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength);
+    CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex);
 
   /**
    * This creates a scaled font with an associated cairo_scaled_font_t, and
    * must be used when using the Cairo backend. The NativeFont and
    * cairo_scaled_font_t* parameters must correspond to the same font.
    */
   static already_AddRefed<ScaledFont>
     CreateScaledFontWithCairo(const NativeFont &aNativeFont,
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -609,26 +609,26 @@ Factory::CreateNativeFontResource(uint8_
 #endif
   default:
     gfxWarning() << "Unable to create requested font resource from truetype data";
     return nullptr;
   }
 }
 
 already_AddRefed<UnscaledFont>
-Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength)
+Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex)
 {
   switch (aType) {
 #ifdef WIN32
   case FontType::GDI:
-    return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength);
+    return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength, aIndex);
 #endif
 #ifdef MOZ_WIDGET_GTK
   case FontType::FONTCONFIG:
-    return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength);
+    return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aIndex);
 #endif
   default:
     gfxWarning() << "Invalid type specified for UnscaledFont font descriptor";
     return nullptr;
   }
 }
 
 already_AddRefed<ScaledFont>
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -916,26 +916,27 @@ private:
 
   template<class S>
   MOZ_IMPLICIT RecordedFontData(S &aStream);
 };
 
 class RecordedFontDescriptor : public RecordedEventDerived<RecordedFontDescriptor> {
 public:
 
-  static void FontDescCb(const uint8_t* aData, uint32_t aSize,
+  static void FontDescCb(const uint8_t* aData, uint32_t aSize, uint32_t aIndex,
                          void* aBaton)
   {
     auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
-    recordedFontDesc->SetFontDescriptor(aData, aSize);
+    recordedFontDesc->SetFontDescriptor(aData, aSize, aIndex);
   }
 
   explicit RecordedFontDescriptor(UnscaledFont* aUnscaledFont)
     : RecordedEventDerived(FONTDESC)
     , mType(aUnscaledFont->GetType())
+    , mIndex(0)
     , mRefPtr(aUnscaledFont)
   {
     mHasDesc = aUnscaledFont->GetFontDescriptor(FontDescCb, this);
   }
 
   ~RecordedFontDescriptor();
 
   bool IsValid() const { return mHasDesc; }
@@ -946,22 +947,23 @@ public:
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Font Desc"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
 private:
   friend class RecordedEvent;
 
-  void SetFontDescriptor(const uint8_t* aData, uint32_t aSize);
+  void SetFontDescriptor(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
 
   bool mHasDesc;
 
   FontType mType;
   std::vector<uint8_t> mData;
+  uint32_t mIndex;
   ReferencePtr mRefPtr;
 
   template<class S>
   MOZ_IMPLICIT RecordedFontDescriptor(S &aStream);
 };
 
 class RecordedUnscaledFontCreation : public RecordedEventDerived<RecordedUnscaledFontCreation> {
 public:
@@ -2805,17 +2807,17 @@ inline
 RecordedFontDescriptor::~RecordedFontDescriptor()
 {
 }
 
 inline bool
 RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<UnscaledFont> font =
-    Factory::CreateUnscaledFontFromFontDescriptor(mType, mData.data(), mData.size());
+    Factory::CreateUnscaledFontFromFontDescriptor(mType, mData.data(), mData.size(), mIndex);
   if (!font) {
     gfxDevCrash(LogReason::InvalidFont) <<
       "Failed creating UnscaledFont of type " << int(mType) << " from font descriptor";
     return false;
   }
 
   aTranslator->AddUnscaledFont(mRefPtr, font);
   return true;
@@ -2823,38 +2825,41 @@ RecordedFontDescriptor::PlayEvent(Transl
 
 template<class S>
 void
 RecordedFontDescriptor::Record(S &aStream) const
 {
   MOZ_ASSERT(mHasDesc);
   WriteElement(aStream, mType);
   WriteElement(aStream, mRefPtr);
+  WriteElement(aStream, mIndex);
   WriteElement(aStream, (size_t)mData.size());
   aStream.write((char*)mData.data(), mData.size());
 }
 
 inline void
 RecordedFontDescriptor::OutputSimpleEventInfo(std::stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] Font Descriptor";
 }
 
 inline void
-RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData, uint32_t aSize)
+RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData, uint32_t aSize, uint32_t aIndex)
 {
   mData.assign(aData, aData + aSize);
+  mIndex = aIndex;
 }
 
 template<class S>
 RecordedFontDescriptor::RecordedFontDescriptor(S &aStream)
   : RecordedEventDerived(FONTDESC)
 {
   ReadElement(aStream, mType);
   ReadElement(aStream, mRefPtr);
+  ReadElement(aStream, mIndex);
 
   size_t size;
   ReadElement(aStream, size);
   mData.resize(size);
   aStream.read((char*)mData.data(), size);
 }
 
 inline bool
--- a/gfx/2d/ScaledFontFontconfig.cpp
+++ b/gfx/2d/ScaledFontFontconfig.cpp
@@ -458,32 +458,26 @@ ScaledFontFontconfig::CreateFromInstance
 
   cairo_scaled_font_destroy(cairoScaledFont);
   FcPatternDestroy(pattern);
 
   return scaledFont.forget();
 }
 
 already_AddRefed<UnscaledFont>
-UnscaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength)
+UnscaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex)
 {
-  if (aDataLength < sizeof(FontDescriptor)) {
+  if (aDataLength <= 1) {
     gfxWarning() << "Fontconfig font descriptor is truncated.";
     return nullptr;
   }
-  const FontDescriptor* desc = reinterpret_cast<const FontDescriptor*>(aData);
-  if (desc->mPathLength < 1 ||
-      desc->mPathLength > aDataLength - sizeof(FontDescriptor)) {
-    gfxWarning() << "Pathname in Fontconfig font descriptor has invalid size.";
-    return nullptr;
-  }
-  const char* path = reinterpret_cast<const char*>(aData + sizeof(FontDescriptor));
-  if (path[desc->mPathLength - 1] != '\0') {
+  const char* path = reinterpret_cast<const char*>(aData);
+  if (path[aDataLength - 1] != '\0') {
     gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated.";
     return nullptr;
   }
 
-  RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFontconfig(path, desc->mIndex);
+  RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFontconfig(path, aIndex);
   return unscaledFont.forget();
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/2d/ScaledFontWin.cpp
+++ b/gfx/2d/ScaledFontWin.cpp
@@ -74,22 +74,22 @@ UnscaledFontGDI::GetFontInstanceData(Fon
 {
   aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), aBaton);
   return true;
 }
 
 bool
 UnscaledFontGDI::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
 {
-  aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), aBaton);
+  aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), 0, aBaton);
   return true;
 }
 
 already_AddRefed<UnscaledFont>
-UnscaledFontGDI::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength)
+UnscaledFontGDI::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex)
 {
   if (aDataLength < sizeof(LOGFONT)) {
     gfxWarning() << "GDI font descriptor is truncated.";
     return nullptr;
   }
 
   const LOGFONT* logFont = reinterpret_cast<const LOGFONT*>(aData);
   RefPtr<UnscaledFont> unscaledFont = new UnscaledFontGDI(*logFont);
--- a/gfx/2d/UnscaledFontFreeType.cpp
+++ b/gfx/2d/UnscaledFontFreeType.cpp
@@ -66,23 +66,15 @@ bool
 UnscaledFontFreeType::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
 {
   if (mFile.empty()) {
     return false;
   }
 
   const char* path = mFile.c_str();
   size_t pathLength = strlen(path) + 1;
-  size_t dataLength = sizeof(FontDescriptor) + pathLength;
-  uint8_t* data = new uint8_t[dataLength];
-  FontDescriptor* desc = reinterpret_cast<FontDescriptor*>(data);
-  desc->mPathLength = pathLength;
-  desc->mIndex = mIndex;
-  memcpy(data + sizeof(FontDescriptor), path, pathLength);
-
-  aCb(data, dataLength, aBaton);
-  delete[] data;
+  aCb(reinterpret_cast<const uint8_t*>(path), pathLength, 0, aBaton);
   return true;
 }
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/2d/UnscaledFontFreeType.h
+++ b/gfx/2d/UnscaledFontFreeType.h
@@ -39,27 +39,21 @@ public:
   }
 
   FontType GetType() const override { return FontType::FREETYPE; }
 
   FT_Face GetFace() const { return mFace; }
   const char* GetFile() const { return mFile.c_str(); }
   uint32_t GetIndex() const { return mIndex; }
 
-  struct FontDescriptor
-  {
-    uint32_t mPathLength;
-    uint32_t mIndex;
-  };
-
   bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override;
 
   bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
 
-private:
+protected:
   FT_Face mFace;
   bool mOwnsFace;
   std::string mFile;
   uint32_t mIndex;
 };
 
 #ifdef MOZ_WIDGET_GTK
 class UnscaledFontFontconfig : public UnscaledFontFreeType
@@ -78,17 +72,17 @@ public:
                          NativeFontResource* aNativeFontResource)
     : UnscaledFontFreeType(aFace, false)
     , mNativeFontResource(aNativeFontResource)
   {}
 
   FontType GetType() const override { return FontType::FONTCONFIG; }
 
   static already_AddRefed<UnscaledFont>
-    CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength);
+    CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex);
 
   already_AddRefed<ScaledFont>
     CreateScaledFont(Float aGlyphSize,
                      const uint8_t* aInstanceData,
                      uint32_t aInstanceDataLength,
                      const FontVariation* aVariations,
                      uint32_t aNumVariations) override;
 
--- a/gfx/2d/UnscaledFontGDI.h
+++ b/gfx/2d/UnscaledFontGDI.h
@@ -27,17 +27,17 @@ public:
 
   bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override;
 
   bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
 
   bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
 
   static already_AddRefed<UnscaledFont>
-    CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength);
+    CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex);
 
   already_AddRefed<ScaledFont>
     CreateScaledFont(Float aGlyphSize,
                      const uint8_t* aInstanceData,
                      uint32_t aInstanceDataLength,
                      const FontVariation* aVariations,
                      uint32_t aNumVariations) override;
 
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -105,16 +105,22 @@ struct OpDeleteImage {
 };
 
 struct OpAddRawFont {
   OffsetRange bytes;
   uint32_t fontIndex;
   FontKey key;
 };
 
+struct OpAddFontDescriptor {
+  OffsetRange bytes;
+  uint32_t fontIndex;
+  FontKey key;
+};
+
 struct OpDeleteFont {
   FontKey key;
 };
 
 struct OpAddFontInstance {
   MaybeFontInstanceOptions options;
   MaybeFontInstancePlatformOptions platformOptions;
   OffsetRange variations;
@@ -129,16 +135,17 @@ struct OpDeleteFontInstance {
 
 union OpUpdateResource {
   OpAddImage;
   OpAddBlobImage;
   OpUpdateImage;
   OpUpdateBlobImage;
   OpDeleteImage;
   OpAddRawFont;
+  OpAddFontDescriptor;
   OpDeleteFont;
   OpAddFontInstance;
   OpDeleteFontInstance;
   OpAddExternalImage;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/wr/IpcResourceUpdateQueue.cpp
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp
@@ -304,16 +304,27 @@ IpcResourceUpdateQueue::AddRawFont(wr::F
   auto bytes = mWriter.Write(aBytes);
   if (!bytes.length()) {
     return false;
   }
   mUpdates.AppendElement(layers::OpAddRawFont(bytes, aIndex, aKey));
   return true;
 }
 
+bool
+IpcResourceUpdateQueue::AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
+{
+  auto bytes = mWriter.Write(aBytes);
+  if (!bytes.length()) {
+    return false;
+  }
+  mUpdates.AppendElement(layers::OpAddFontDescriptor(bytes, aIndex, aKey));
+  return true;
+}
+
 void
 IpcResourceUpdateQueue::DeleteFont(wr::FontKey aKey)
 {
   mUpdates.AppendElement(layers::OpDeleteFont(aKey));
 }
 
 void
 IpcResourceUpdateQueue::AddFontInstance(wr::FontInstanceKey aKey,
--- a/gfx/layers/wr/IpcResourceUpdateQueue.h
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.h
@@ -93,16 +93,18 @@ public:
                            ExternalImageId aExtID,
                            wr::WrExternalImageBufferType aBufferType,
                            uint8_t aChannelIndex = 0);
 
   void DeleteImage(wr::ImageKey aKey);
 
   bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
 
+  bool AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
+
   void DeleteFont(wr::FontKey aKey);
 
   void AddFontInstance(wr::FontInstanceKey aKey,
                        wr::FontKey aFontKey,
                        float aGlyphSize,
                        const wr::FontInstanceOptions* aOptions,
                        const wr::FontInstancePlatformOptions* aPlatformOptions,
                        Range<const gfx::FontVariation> aVariations);
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -269,16 +269,27 @@ WriteFontFileData(const uint8_t* aData, 
 {
   FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
 
   *sink->mFontKey = sink->mWrBridge->GetNextFontKey();
 
   sink->mResources->AddRawFont(*sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength), aIndex);
 }
 
+static void
+WriteFontDescriptor(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
+                  void* aBaton)
+{
+  FontFileDataSink* sink = static_cast<FontFileDataSink*>(aBaton);
+
+  *sink->mFontKey = sink->mWrBridge->GetNextFontKey();
+
+  sink->mResources->AddFontDescriptor(*sink->mFontKey, Range<uint8_t>(const_cast<uint8_t*>(aData), aLength), aIndex);
+}
+
 void
 WebRenderBridgeChild::PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<wr::GlyphInstance>& aGlyphs,
                                  gfx::ScaledFont* aFont, const wr::ColorF& aColor, const StackingContextHelper& aSc,
                                  const wr::LayerRect& aBounds, const wr::LayerRect& aClip, bool aBackfaceVisible,
                                  const wr::GlyphOptions* aGlyphOptions)
 {
   MOZ_ASSERT(aFont);
   MOZ_ASSERT(!aGlyphs.IsEmpty());
@@ -339,17 +350,22 @@ wr::FontKey
 WebRenderBridgeChild::GetFontKeyForUnscaledFont(gfx::UnscaledFont* aUnscaled)
 {
   MOZ_ASSERT(!mDestroyed);
 
   wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0};
   if (!mFontKeys.Get(aUnscaled, &fontKey)) {
     wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
     FontFileDataSink sink = { &fontKey, this, &resources };
-    if (!aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
+    // First try to retrieve a descriptor for the font, as this is much cheaper
+    // to send over IPC than the full raw font data. If this is not possible, then
+    // and only then fall back to getting the raw font file data. If that fails,
+    // then the only thing left to do is signal failure by returning a null font key.
+    if (!aUnscaled->GetWRFontDescriptor(WriteFontDescriptor, &sink) &&
+        !aUnscaled->GetFontFileData(WriteFontFileData, &sink)) {
       return fontKey;
     }
     UpdateResources(resources);
 
     mFontKeys.Put(aUnscaled, fontKey);
   }
 
   return fontKey;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -310,16 +310,25 @@ WebRenderBridgeParent::UpdateResources(c
         const auto& op = cmd.get_OpAddRawFont();
         wr::Vec_u8 bytes;
         if (!reader.Read(op.bytes(), bytes)) {
           return false;
         }
         aUpdates.AddRawFont(op.key(), bytes, op.fontIndex());
         break;
       }
+      case OpUpdateResource::TOpAddFontDescriptor: {
+        const auto& op = cmd.get_OpAddFontDescriptor();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.AddFontDescriptor(op.key(), bytes, op.fontIndex());
+        break;
+      }
       case OpUpdateResource::TOpAddFontInstance: {
         const auto& op = cmd.get_OpAddFontInstance();
         wr::Vec_u8 variations;
         if (!reader.Read(op.variations(), variations)) {
             return false;
         }
         aUpdates.AddFontInstance(op.instanceKey(), op.fontKey(),
                                  op.glyphSize(),
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -563,16 +563,22 @@ ResourceUpdateQueue::DeleteImage(ImageKe
 
 void
 ResourceUpdateQueue::AddRawFont(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex)
 {
   wr_resource_updates_add_raw_font(mUpdates, aKey, &aBytes.inner, aIndex);
 }
 
 void
+ResourceUpdateQueue::AddFontDescriptor(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex)
+{
+  wr_resource_updates_add_font_descriptor(mUpdates, aKey, &aBytes.inner, aIndex);
+}
+
+void
 ResourceUpdateQueue::DeleteFont(wr::FontKey aKey)
 {
   wr_resource_updates_delete_font(mUpdates, aKey);
 }
 
 void
 ResourceUpdateQueue::AddFontInstance(wr::FontInstanceKey aKey,
                                      wr::FontKey aFontKey,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -92,16 +92,18 @@ public:
                            ExternalImageId aExtID,
                            wr::WrExternalImageBufferType aBufferType,
                            uint8_t aChannelIndex = 0);
 
   void DeleteImage(wr::ImageKey aKey);
 
   void AddRawFont(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex);
 
+  void AddFontDescriptor(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex);
+
   void DeleteFont(wr::FontKey aKey);
 
   void AddFontInstance(wr::FontInstanceKey aKey,
                        wr::FontKey aFontKey,
                        float aGlyphSize,
                        const wr::FontInstanceOptions* aOptions,
                        const wr::FontInstancePlatformOptions* aPlatformOptions,
                        wr::Vec_u8& aVariations);
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -978,16 +978,27 @@ pub extern "C" fn wr_resource_updates_ad
     key: WrFontKey,
     bytes: &mut WrVecU8,
     index: u32
 ) {
     resources.add_raw_font(key, bytes.flush_into_vec(), index);
 }
 
 #[no_mangle]
+pub extern "C" fn wr_resource_updates_add_font_descriptor(
+    resources: &mut ResourceUpdates,
+    key: WrFontKey,
+    bytes: &mut WrVecU8,
+    index: u32
+) {
+    let native_font_handle = read_font_descriptor(bytes, index);
+    resources.add_native_font(key, native_font_handle);
+}
+
+#[no_mangle]
 pub extern "C" fn wr_resource_updates_delete_font(
     resources: &mut ResourceUpdates,
     key: WrFontKey
 ) {
     resources.delete_font(key);
 }
 
 #[no_mangle]
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1441,16 +1441,23 @@ WR_FUNC;
 WR_INLINE
 void wr_resource_updates_add_raw_font(ResourceUpdates *aResources,
                                       WrFontKey aKey,
                                       WrVecU8 *aBytes,
                                       uint32_t aIndex)
 WR_FUNC;
 
 WR_INLINE
+void wr_resource_updates_add_font_descriptor(ResourceUpdates *aResources,
+                                             WrFontKey aKey,
+                                             WrVecU8 *aBytes,
+                                             uint32_t aIndex)
+WR_FUNC;
+
+WR_INLINE
 void wr_resource_updates_clear(ResourceUpdates *aResources)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_delete(ResourceUpdates *aUpdates)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE