Bug 1479196 - add support to TextDrawTarget for defining and pushing WR images. r=nical
authorLee Salzman <lsalzman@mozilla.com>
Tue, 21 Aug 2018 12:36:48 -0400
changeset 432624 9c610000042a2457c05c9abb7636693bacb56645
parent 432623 ead8943575c96bf260a5c5b576fa049ec045f971
child 432625 07dabfefeef1dc4e0a7263bb10a504fa8f8252a0
push id34482
push usertoros@mozilla.com
push dateTue, 21 Aug 2018 21:56:56 +0000
treeherdermozilla-central@7c96ad3ab673 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1479196
milestone63.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 1479196 - add support to TextDrawTarget for defining and pushing WR images. r=nical
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi_generated.h
layout/generic/TextDrawTarget.h
layout/generic/TextOverflow.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsTextFrame.cpp
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -1042,39 +1042,41 @@ DisplayListBuilder::PushRadialGradient(c
 }
 
 void
 DisplayListBuilder::PushImage(const wr::LayoutRect& aBounds,
                               const wr::LayoutRect& aClip,
                               bool aIsBackfaceVisible,
                               wr::ImageRendering aFilter,
                               wr::ImageKey aImage,
-                              bool aPremultipliedAlpha)
+                              bool aPremultipliedAlpha,
+                              const wr::ColorF& aColor)
 {
   wr::LayoutSize size;
   size.width = aBounds.size.width;
   size.height = aBounds.size.height;
-  PushImage(aBounds, aClip, aIsBackfaceVisible, size, size, aFilter, aImage, aPremultipliedAlpha);
+  PushImage(aBounds, aClip, aIsBackfaceVisible, size, size, aFilter, aImage, aPremultipliedAlpha, aColor);
 }
 
 void
 DisplayListBuilder::PushImage(const wr::LayoutRect& aBounds,
                               const wr::LayoutRect& aClip,
                               bool aIsBackfaceVisible,
                               const wr::LayoutSize& aStretchSize,
                               const wr::LayoutSize& aTileSpacing,
                               wr::ImageRendering aFilter,
                               wr::ImageKey aImage,
-                              bool aPremultipliedAlpha)
+                              bool aPremultipliedAlpha,
+                              const wr::ColorF& aColor)
 {
   WRDL_LOG("PushImage b=%s cl=%s s=%s t=%s\n", mWrState,
       Stringify(aBounds).c_str(),
       Stringify(aClip).c_str(), Stringify(aStretchSize).c_str(),
       Stringify(aTileSpacing).c_str());
-  wr_dp_push_image(mWrState, aBounds, aClip, aIsBackfaceVisible, aStretchSize, aTileSpacing, aFilter, aImage, aPremultipliedAlpha);
+  wr_dp_push_image(mWrState, aBounds, aClip, aIsBackfaceVisible, aStretchSize, aTileSpacing, aFilter, aImage, aPremultipliedAlpha, aColor);
 }
 
 void
 DisplayListBuilder::PushYCbCrPlanarImage(const wr::LayoutRect& aBounds,
                                          const wr::LayoutRect& aClip,
                                          bool aIsBackfaceVisible,
                                          wr::ImageKey aImageChannel0,
                                          wr::ImageKey aImageChannel1,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -366,26 +366,28 @@ public:
                           const wr::LayoutSize aTileSize,
                           const wr::LayoutSize aTileSpacing);
 
   void PushImage(const wr::LayoutRect& aBounds,
                  const wr::LayoutRect& aClip,
                  bool aIsBackfaceVisible,
                  wr::ImageRendering aFilter,
                  wr::ImageKey aImage,
-                 bool aPremultipliedAlpha = true);
+                 bool aPremultipliedAlpha = true,
+                 const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
 
   void PushImage(const wr::LayoutRect& aBounds,
                  const wr::LayoutRect& aClip,
                  bool aIsBackfaceVisible,
                  const wr::LayoutSize& aStretchSize,
                  const wr::LayoutSize& aTileSpacing,
                  wr::ImageRendering aFilter,
                  wr::ImageKey aImage,
-                 bool aPremultipliedAlpha = true);
+                 bool aPremultipliedAlpha = true,
+                 const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
 
   void PushYCbCrPlanarImage(const wr::LayoutRect& aBounds,
                             const wr::LayoutRect& aClip,
                             bool aIsBackfaceVisible,
                             wr::ImageKey aImageChannel0,
                             wr::ImageKey aImageChannel1,
                             wr::ImageKey aImageChannel2,
                             wr::WrYuvColorSpace aColorSpace,
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1955,17 +1955,18 @@ pub extern "C" fn wr_dp_push_clear_rect(
 pub extern "C" fn wr_dp_push_image(state: &mut WrState,
                                    bounds: LayoutRect,
                                    clip: LayoutRect,
                                    is_backface_visible: bool,
                                    stretch_size: LayoutSize,
                                    tile_spacing: LayoutSize,
                                    image_rendering: ImageRendering,
                                    key: WrImageKey,
-                                   premultiplied_alpha: bool) {
+                                   premultiplied_alpha: bool,
+                                   color: ColorF) {
     debug_assert!(unsafe { is_in_main_thread() || is_in_compositor_thread() });
 
     let mut prim_info = LayoutPrimitiveInfo::with_clip_rect(bounds, clip.into());
     prim_info.is_backface_visible = is_backface_visible;
     prim_info.tag = state.current_tag;
     let alpha_type = if premultiplied_alpha {
         AlphaType::PremultipliedAlpha
     } else {
@@ -1974,17 +1975,17 @@ pub extern "C" fn wr_dp_push_image(state
     state.frame_builder
          .dl_builder
          .push_image(&prim_info,
                      stretch_size,
                      tile_spacing,
                      image_rendering,
                      alpha_type,
                      key,
-                     ColorF::WHITE);
+                     color);
 }
 
 /// Push a 3 planar yuv image.
 #[no_mangle]
 pub extern "C" fn wr_dp_push_yuv_planar_image(state: &mut WrState,
                                               bounds: LayoutRect,
                                               clip: LayoutRect,
                                               is_backface_visible: bool,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1290,17 +1290,18 @@ WR_INLINE
 void wr_dp_push_image(WrState *aState,
                       LayoutRect aBounds,
                       LayoutRect aClip,
                       bool aIsBackfaceVisible,
                       LayoutSize aStretchSize,
                       LayoutSize aTileSpacing,
                       ImageRendering aImageRendering,
                       WrImageKey aKey,
-                      bool aPremultipliedAlpha)
+                      bool aPremultipliedAlpha,
+                      ColorF color)
 WR_FUNC;
 
 WR_INLINE
 void wr_dp_push_line(WrState *aState,
                      const LayoutRect *aClip,
                      bool aIsBackfaceVisible,
                      const LayoutRect *aBounds,
                      float aWavyLineThickness,
--- a/layout/generic/TextDrawTarget.h
+++ b/layout/generic/TextDrawTarget.h
@@ -7,16 +7,17 @@
 #ifndef TextDrawTarget_h
 #define TextDrawTarget_h
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/layers/StackingContextHelper.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 
 namespace mozilla {
 namespace layout {
 
 using namespace gfx;
 
 // This class is fake DrawTarget, used to intercept text draw calls, while
 // also collecting up the other aspects of text natively.
@@ -45,21 +46,22 @@ using namespace gfx;
 // while we further develop the design.
 //
 // TextDrawTarget doesn't yet support all features. See mHasUnsupportedFeatures
 // for details.
 class TextDrawTarget : public DrawTarget
 {
 public:
   explicit TextDrawTarget(wr::DisplayListBuilder& aBuilder,
+                          wr::IpcResourceUpdateQueue& aResources,
                           const layers::StackingContextHelper& aSc,
                           layers::WebRenderLayerManager* aManager,
                           nsDisplayItem* aItem,
                           nsRect& aBounds)
-    : mBuilder(aBuilder), mSc(aSc), mManager(aManager)
+    : mBuilder(aBuilder), mResources(aResources), mSc(aSc), mManager(aManager)
   {
     SetPermitSubpixelAA(!aItem->IsSubpixelAADisabled());
 
     // Compute clip/bounds
     auto appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
     LayoutDeviceRect layoutBoundsRect = LayoutDeviceRect::FromAppUnits(
         aBounds, appUnitsPerDevPixel);
     LayoutDeviceRect layoutClipRect = layoutBoundsRect;
@@ -297,16 +299,43 @@ public:
     decoration.orientation = aVertical
       ? wr::LineOrientation::Vertical
       : wr::LineOrientation::Horizontal;
     decoration.style = wr::LineStyle::Wavy;
 
     mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
   }
 
+  layers::WebRenderBridgeChild* WrBridge() { return mManager->WrBridge(); }
+  layers::WebRenderLayerManager* WrLayerManager() { return mManager; }
+
+  Maybe<wr::ImageKey>
+  DefineImage(const IntSize& aSize,
+              uint32_t aStride,
+              SurfaceFormat aFormat,
+              const uint8_t* aData)
+  {
+    wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
+    wr::ImageDescriptor desc(aSize, aStride, aFormat);
+    Range<uint8_t> bytes(const_cast<uint8_t*>(aData), aStride * aSize.height);
+    if (mResources.AddImage(key, desc, bytes)) {
+        return Some(key);
+    }
+    return Nothing();
+  }
+
+  void PushImage(wr::ImageKey aKey,
+                 const wr::LayoutRect& aBounds,
+                 const wr::LayoutRect& aClip,
+                 wr::ImageRendering aFilter,
+                 const wr::ColorF& aColor)
+  {
+    mBuilder.PushImage(aBounds, aClip, true, aFilter, aKey, true, aColor);
+  }
+
 private:
   wr::LayoutRect ClipRect()
   {
     return wr::ToRoundedLayoutRect(mClipStack.LastElement());
   }
   // Whether anything unsupported was encountered. Currently:
   //
   // * Synthetic bold/italics
@@ -318,16 +347,17 @@ private:
   // * Text stroke
   bool mHasUnsupportedFeatures = false;
 
   // Whether PopAllShadows needs to be called
   bool mHasShadows = false;
 
   // Things used to push to webrender
   wr::DisplayListBuilder& mBuilder;
+  wr::IpcResourceUpdateQueue& mResources;
   const layers::StackingContextHelper& mSc;
   layers::WebRenderLayerManager* mManager;
 
   // Computed facts
   IntSize mSize;
   wr::LayoutRect mBoundsRect;
   nsTArray<LayoutDeviceRect> mClipStack;
   bool mBackfaceVisible;
@@ -413,44 +443,39 @@ public:
 
   void StrokeRect(const Rect &aRect,
                   const Pattern &aPattern,
                   const StrokeOptions &aStrokeOptions,
                   const DrawOptions &aOptions) override {
     MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR &&
                        aStrokeOptions.mDashLength == 0);
 
-    wr::Line line;
-    line.wavyLineThickness = 0; // dummy value, unused
-    line.color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
-    line.style = wr::LineStyle::Solid;
-
-    // Top horizontal line
-    LayoutDevicePoint top(aRect.x, aRect.y - aStrokeOptions.mLineWidth / 2);
-    LayoutDeviceSize horiSize(aRect.width, aStrokeOptions.mLineWidth);
-    line.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(top, horiSize));
-    line.orientation = wr::LineOrientation::Horizontal;
-    mBuilder.PushLine(ClipRect(), mBackfaceVisible, line);
-
-    // Bottom horizontal line
-    LayoutDevicePoint bottom(aRect.x, aRect.YMost() - aStrokeOptions.mLineWidth / 2);
-    line.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(bottom, horiSize));
-    mBuilder.PushLine(ClipRect(), mBackfaceVisible, line);
-
-    // Left vertical line
-    LayoutDevicePoint left(aRect.x + aStrokeOptions.mLineWidth / 2, aRect.y + aStrokeOptions.mLineWidth / 2);
-    LayoutDeviceSize vertSize(aStrokeOptions.mLineWidth, aRect.height - aStrokeOptions.mLineWidth);
-    line.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(left, vertSize));
-    line.orientation = wr::LineOrientation::Vertical;
-    mBuilder.PushLine(ClipRect(), mBackfaceVisible, line);
-
-    // Right vertical line
-    LayoutDevicePoint right(aRect.XMost() - aStrokeOptions.mLineWidth / 2, aRect.y + aStrokeOptions.mLineWidth / 2);
-    line.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(right, vertSize));
-    mBuilder.PushLine(ClipRect(), mBackfaceVisible, line);
+    wr::BorderWidths widths = {
+        aStrokeOptions.mLineWidth,
+        aStrokeOptions.mLineWidth,
+        aStrokeOptions.mLineWidth,
+        aStrokeOptions.mLineWidth
+    };
+    wr::ColorF color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
+    wr::BorderSide sides[4] = {
+        { color, wr::BorderStyle::Solid },
+        { color, wr::BorderStyle::Solid },
+        { color, wr::BorderStyle::Solid },
+        { color, wr::BorderStyle::Solid }
+    };
+    wr::BorderRadius radius = {
+        { 0, 0 },
+        { 0, 0 },
+        { 0, 0 },
+        { 0, 0 }
+    };
+    Rect rect(aRect);
+    rect.Inflate(aStrokeOptions.mLineWidth / 2);
+    wr::LayoutRect bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(rect));
+    mBuilder.PushBorder(bounds, ClipRect(), true, widths, Range<const wr::BorderSide>(sides, 4), radius);
   }
 
   void StrokeLine(const Point &aStart,
                   const Point &aEnd,
                   const Pattern &aPattern,
                   const StrokeOptions &aStrokeOptions,
                   const DrawOptions &aOptions) override {
     MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -299,17 +299,17 @@ nsDisplayTextOverflowMarker::CreateWebRe
 {
   bool snap;
   nsRect bounds = GetBounds(aDisplayListBuilder, &snap);
   if (bounds.IsEmpty()) {
     return true;
   }
 
   // Run the rendering algorithm to capture the glyphs and shadows
-  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, bounds);
+  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aResources, aSc, aManager, this, bounds);
   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
   Paint(aDisplayListBuilder, captureCtx);
   textDrawer->TerminateShadows();
 
   return !textDrawer->HasUnsupportedFeatures();
 }
 
 
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -565,17 +565,17 @@ BulletRenderer::CreateWebRenderCommandsF
 
   bool dummy;
   nsRect bounds = aItem->GetBounds(aDisplayListBuilder, &dummy);
 
   if (bounds.IsEmpty()) {
     return true;
   }
 
-  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, aItem, bounds);
+  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aResources, aSc, aManager, aItem, bounds);
   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
   PaintTextToContext(aItem->Frame(), captureCtx, aItem->IsSubpixelAADisabled());
   textDrawer->TerminateShadows();
 
   return !textDrawer->HasUnsupportedFeatures();
 }
 
 class nsDisplayBullet final : public nsDisplayItem {
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5083,17 +5083,17 @@ nsDisplayText::CreateWebRenderCommands(m
     return true;
   }
 
 
   auto appUnitsPerDevPixel = Frame()->PresContext()->AppUnitsPerDevPixel();
   gfx::Point deviceOffset = LayoutDevicePoint::FromAppUnits(
       mBounds.TopLeft(), appUnitsPerDevPixel).ToUnknownPoint();
 
-  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, mBounds);
+  RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aResources, aSc, aManager, this, mBounds);
   RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer, deviceOffset);
 
   RenderToContext(captureCtx, aDisplayListBuilder, true);
 
   return !textDrawer->HasUnsupportedFeatures();
 }
 
 void