Bug 1364628 - give each webrender blob image renderer thread its own thread-local FT_Library to work around unsafe FT_Face rasterization/metrics calls. r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Wed, 17 May 2017 21:56:58 -0400
changeset 358893 cb7db33245b9e38ff2e9670abd6de69ebf64e6da
parent 358892 f5c1bf433c6a2817041499a25467474f600e9f52
child 358894 04e1c867ef4584fb9e2064927317cd741555e545
push id90408
push userlsalzman@mozilla.com
push dateThu, 18 May 2017 01:57:37 +0000
treeherdermozilla-inbound@cb7db33245b9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1364628
milestone55.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 1364628 - give each webrender blob image renderer thread its own thread-local FT_Library to work around unsafe FT_Face rasterization/metrics calls. r=jrmuizel MozReview-Commit-ID: 5sJznRRV3bq
gfx/2d/2D.h
gfx/2d/Factory.cpp
gfx/2d/InlineTranslator.cpp
gfx/2d/InlineTranslator.h
gfx/2d/NativeFontResourceFontconfig.cpp
gfx/2d/NativeFontResourceFontconfig.h
gfx/2d/RecordedEvent.cpp
gfx/2d/RecordedEvent.h
gfx/webrender_bindings/Moz2DImageRenderer.cpp
gfx/webrender_bindings/moz.build
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1494,20 +1494,21 @@ public:
 #endif
 
   /**
    * This creates a NativeFontResource from TrueType data.
    *
    * @param aData Pointer to the data
    * @param aSize Size of the TrueType data
    * @param aType Type of NativeFontResource that should be created.
+   * @param aFontContext Optional native font context to be used to create the NativeFontResource.
    * @return a NativeFontResource of nullptr if failed.
    */
   static already_AddRefed<NativeFontResource>
-    CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType);
+    CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType, 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);
 
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -541,17 +541,17 @@ Factory::CreateScaledFontForNativeFont(c
 #endif
   default:
     gfxWarning() << "Invalid native font type specified.";
     return nullptr;
   }
 }
 
 already_AddRefed<NativeFontResource>
-Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType)
+Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType, void* aFontContext)
 {
   switch (aType) {
 #ifdef WIN32
   case FontType::DWRITE:
     {
       return NativeFontResourceDWrite::Create(aData, aSize,
                                               /* aNeedsCairo = */ false);
     }
@@ -566,17 +566,18 @@ Factory::CreateNativeFontResource(uint8_
         return NativeFontResourceDWrite::Create(aData, aSize,
                                                 /* aNeedsCairo = */ true);
       } else {
         return NativeFontResourceGDI::Create(aData, aSize);
       }
 #elif defined(XP_DARWIN)
       return NativeFontResourceMac::Create(aData, aSize);
 #elif defined(MOZ_WIDGET_GTK)
-      return NativeFontResourceFontconfig::Create(aData, aSize);
+      return NativeFontResourceFontconfig::Create(aData, aSize,
+                                                  static_cast<FT_Library>(aFontContext));
 #else
       gfxWarning() << "Unable to create cairo scaled font from truetype data";
       return nullptr;
 #endif
     }
   default:
     gfxWarning() << "Unable to create requested font resource from truetype data";
     return nullptr;
--- a/gfx/2d/InlineTranslator.cpp
+++ b/gfx/2d/InlineTranslator.cpp
@@ -12,20 +12,20 @@
 #include "mozilla/gfx/RecordingTypes.h"
 #include "mozilla/UniquePtr.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gfx {
 
-InlineTranslator::InlineTranslator(DrawTarget* aDT, Matrix aMatrix)
+InlineTranslator::InlineTranslator(DrawTarget* aDT, void* aFontContext)
+  : mBaseDT(aDT)
+  , mFontContext(aFontContext)
 {
-  mBaseDT = aDT;
-  mBaseTransform = aMatrix;
 }
 
 bool
 InlineTranslator::TranslateRecording(std::istream& aRecording)
 {
   uint32_t magicInt;
   ReadElement(aRecording, magicInt);
   if (magicInt != mozilla::gfx::kMagicInt) {
--- a/gfx/2d/InlineTranslator.h
+++ b/gfx/2d/InlineTranslator.h
@@ -25,17 +25,17 @@ using gfx::SourceSurface;
 using gfx::FilterNode;
 using gfx::GradientStops;
 using gfx::ScaledFont;
 using gfx::NativeFontResource;
 
 class InlineTranslator final : public Translator
 {
 public:
-  explicit InlineTranslator(DrawTarget* aDT, Matrix aMatrix);
+  explicit InlineTranslator(DrawTarget* aDT, void* aFontContext = nullptr);
 
   bool TranslateRecording(std::istream& aRecording);
 
   DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final
   {
     DrawTarget* result = mDrawTargets.GetWeak(aRefPtr);
     MOZ_ASSERT(result);
     return result;
@@ -170,19 +170,21 @@ public:
   already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
                                                 const gfx::IntSize &aSize,
                                                 gfx::SurfaceFormat aFormat) final;
 
   mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; }
 
   mozilla::gfx::FontType GetDesiredFontType() final;
 
+  void* GetFontContext() final { return mFontContext; }
+
 private:
   RefPtr<DrawTarget> mBaseDT;
-  Matrix             mBaseTransform;
+  void*              mFontContext;
 
   nsRefPtrHashtable<nsPtrHashKey<void>, DrawTarget> mDrawTargets;
   nsRefPtrHashtable<nsPtrHashKey<void>, Path> mPaths;
   nsRefPtrHashtable<nsPtrHashKey<void>, SourceSurface> mSourceSurfaces;
   nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
   nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
   nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
   nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
--- a/gfx/2d/NativeFontResourceFontconfig.cpp
+++ b/gfx/2d/NativeFontResourceFontconfig.cpp
@@ -22,25 +22,25 @@ NativeFontResourceFontconfig::~NativeFon
 {
   if (mFace) {
     Factory::ReleaseFTFace(mFace);
     mFace = nullptr;
   }
 }
 
 already_AddRefed<NativeFontResourceFontconfig>
-NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength)
+NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength, FT_Library aFTLibrary)
 {
   if (!aFontData || !aDataLength) {
     return nullptr;
   }
   UniquePtr<uint8_t[]> fontData(new uint8_t[aDataLength]);
   memcpy(fontData.get(), aFontData, aDataLength);
 
-  FT_Face face = Factory::NewFTFaceFromData(nullptr, fontData.get(), aDataLength, 0);
+  FT_Face face = Factory::NewFTFaceFromData(aFTLibrary, fontData.get(), aDataLength, 0);
   if (!face) {
     return nullptr;
   }
   if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != FT_Err_Ok) {
     Factory::ReleaseFTFace(face);
     return nullptr;
   }
 
--- a/gfx/2d/NativeFontResourceFontconfig.h
+++ b/gfx/2d/NativeFontResourceFontconfig.h
@@ -16,17 +16,17 @@ namespace mozilla {
 namespace gfx {
 
 class NativeFontResourceFontconfig final : public NativeFontResource
 {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFontconfig)
 
   static already_AddRefed<NativeFontResourceFontconfig>
-    Create(uint8_t *aFontData, uint32_t aDataLength);
+    Create(uint8_t *aFontData, uint32_t aDataLength, FT_Library aFTLibrary = nullptr);
 
   already_AddRefed<UnscaledFont>
     CreateUnscaledFont(uint32_t aIndex,
                        const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
 
   ~NativeFontResourceFontconfig();
 
 private:
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -1530,17 +1530,18 @@ RecordedFontData::~RecordedFontData()
   delete[] mData;
 }
 
 bool
 RecordedFontData::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<NativeFontResource> fontResource =
     Factory::CreateNativeFontResource(mData, mFontDetails.size,
-                                      aTranslator->GetDesiredFontType());
+                                      aTranslator->GetDesiredFontType(),
+                                      aTranslator->GetFontContext());
   if (!fontResource) {
     return false;
   }
 
   aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
   return true;
 }
 
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -107,16 +107,17 @@ public:
   virtual void AddNativeFontResource(uint64_t aKey,
                                      NativeFontResource *aNativeFontResource) = 0;
 
   virtual already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
                                                         const IntSize &aSize,
                                                         SurfaceFormat aFormat);
   virtual DrawTarget *GetReferenceDrawTarget() = 0;
   virtual FontType GetDesiredFontType() = 0;
+  virtual void* GetFontContext() { return nullptr; }
 };
 
 struct ColorPatternStorage
 {
   Color mColor;
 };
 
 struct LinearGradientPatternStorage
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -8,48 +8,72 @@
 #include "mozilla/Range.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/InlineTranslator.h"
 #include "mozilla/gfx/RecordedEvent.h"
 #include "WebRenderTypes.h"
 
 #include <iostream>
 
+#ifdef MOZ_ENABLE_FREETYPE
+#include "ft2build.h"
+#include FT_FREETYPE_H
+
+#include "mozilla/ThreadLocal.h"
+#endif
+
 namespace mozilla {
 namespace wr {
 
 class InMemoryStreamBuffer: public std::streambuf
 {
 public:
   explicit InMemoryStreamBuffer(const Range<const uint8_t> aBlob)
   {
     // we need to cast away the const because C++ doesn't
     // have a separate type of streambuf that can only
     // be read from
     auto start = const_cast<char*>(reinterpret_cast<const char*>(aBlob.begin().get()));
     setg(start, start, start + aBlob.length());
   }
 };
 
+#ifdef MOZ_ENABLE_FREETYPE
+static MOZ_THREAD_LOCAL(FT_Library) sFTLibrary;
+#endif
+
 static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
                                 gfx::IntSize aSize,
                                 gfx::SurfaceFormat aFormat,
                                 Range<uint8_t> aOutput)
 {
   MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
   if (aSize.width <= 0 || aSize.height <= 0) {
     return false;
   }
 
   auto stride = aSize.width * gfx::BytesPerPixel(aFormat);
 
   if (aOutput.length() < static_cast<size_t>(aSize.height * stride)) {
     return false;
   }
 
+#ifdef MOZ_ENABLE_FREETYPE
+  if (!sFTLibrary.init()) {
+    return false;
+  }
+  if (!sFTLibrary.get()) {
+    FT_Library library;
+    if (FT_Init_FreeType(&library) != FT_Err_Ok) {
+      return false;
+    }
+    sFTLibrary.set(library);
+  }
+#endif
+
   // In bindings.rs we allocate a buffer filled with opaque white.
   bool uninitialized = false;
 
   RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(
     gfx::BackendType::SKIA,
     aOutput.begin().get(),
     aSize,
     stride,
@@ -59,18 +83,21 @@ static bool Moz2DRenderCallback(const Ra
 
   if (!dt) {
     return false;
   }
 
   InMemoryStreamBuffer streamBuffer(aBlob);
   std::istream stream(&streamBuffer);
 
-  gfx::Matrix baseTransform;
-  gfx::InlineTranslator translator(dt, baseTransform);
+#ifdef MOZ_ENABLE_FREETYPE
+  gfx::InlineTranslator translator(dt, sFTLibrary.get());
+#else
+  gfx::InlineTranslator translator(dt);
+#endif
 
   auto ret = translator.TranslateRecording(stream);
 
 #if 0
   static int i = 0;
   char filename[40];
   sprintf(filename, "out%d.png", i++);
   gfxUtils::WriteAsPNG(dt, filename);
--- a/gfx/webrender_bindings/moz.build
+++ b/gfx/webrender_bindings/moz.build
@@ -32,11 +32,15 @@ UNIFIED_SOURCES += [
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     EXPORTS.mozilla.webrender += [
         'RenderMacIOSurfaceTextureHostOGL.h',
     ]
     UNIFIED_SOURCES += [
         'RenderMacIOSurfaceTextureHostOGL.cpp',
     ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3'):
+    DEFINES['MOZ_ENABLE_FREETYPE'] = True
+    CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
+
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'