Bug 1400382 - Implement CreateWebRenderCommands for nsDisplayTextOverflow. r=mstange
authorAlexis Beingessner <a.beingessner@gmail.com>
Thu, 21 Sep 2017 15:15:58 -0400
changeset 669694 8ac3b543af396cb36a6235a594bea71b5600b8be
parent 669693 a30dd89e6d072bd580a38e624847e5b917faef3c
child 669695 344a2ba91f955e359ef560aedd778a9cd521a89b
push id81398
push userhikezoe@mozilla.com
push dateMon, 25 Sep 2017 08:14:31 +0000
reviewersmstange
bugs1400382
milestone58.0a1
Bug 1400382 - Implement CreateWebRenderCommands for nsDisplayTextOverflow. r=mstange MozReview-Commit-ID: EQtFvLQCT2U
layout/base/nsLayoutUtils.cpp
layout/generic/TextOverflow.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -119,16 +119,17 @@
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "RegionBuilder.h"
 #include "SVGSVGElement.h"
 #include "DisplayItemClip.h"
 #include "mozilla/layers/WebRenderLayerManager.h"
 #include "prenv.h"
+#include "TextDrawTarget.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
 
 #include "GeckoProfiler.h"
 #include "nsAnimationManager.h"
 #include "nsTransitionManager.h"
@@ -6062,28 +6063,47 @@ nsLayoutUtils::PaintTextShadow(const nsI
                          shadowDetails->mYOffset);
     nscoord blurRadius = std::max(shadowDetails->mRadius, 0);
 
     nsRect shadowRect(aTextRect);
     shadowRect.MoveBy(shadowOffset);
 
     nsPresContext* presCtx = aFrame->PresContext();
     nsContextBoxBlur contextBoxBlur;
+
+    nscolor shadowColor;
+    if (shadowDetails->mHasColor)
+      shadowColor = shadowDetails->mColor;
+    else
+      shadowColor = aForegroundColor;
+
+    // Webrender just needs the shadow details
+    if (auto* textDrawer = aContext->GetTextDrawer()) {
+      wr::TextShadow wrShadow;
+
+      wrShadow.offset = {
+        presCtx->AppUnitsToFloatDevPixels(shadowDetails->mXOffset),
+        presCtx->AppUnitsToFloatDevPixels(shadowDetails->mYOffset)
+      };
+
+      wrShadow.blur_radius = presCtx->AppUnitsToFloatDevPixels(shadowDetails->mRadius);
+      wrShadow.color = wr::ToColorF(ToDeviceColor(shadowColor));
+
+      textDrawer->AppendShadow(wrShadow);
+      return;
+    }
+
     gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
                                                     presCtx->AppUnitsPerDevPixel(),
                                                     aDestCtx, aDirtyRect, nullptr,
                                                     nsContextBoxBlur::DISABLE_HARDWARE_ACCELERATION_BLUR);
     if (!shadowContext)
       continue;
 
-    nscolor shadowColor;
-    if (shadowDetails->mHasColor)
-      shadowColor = shadowDetails->mColor;
-    else
-      shadowColor = aForegroundColor;
+    
 
     aDestCtx->Save();
     aDestCtx->NewPath();
     aDestCtx->SetColor(Color::FromABGR(shadowColor));
 
     // The callback will draw whatever we want to blur as a shadow.
     aCallback(shadowContext, shadowOffset, shadowColor, aCallbackData);
 
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -19,16 +19,17 @@
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsRect.h"
 #include "nsTextFrame.h"
 #include "nsIFrameInlines.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Likely.h"
 #include "nsISelection.h"
+#include "TextDrawTarget.h"
 
 namespace mozilla {
 namespace css {
 
 class LazyReferenceRenderingDrawTargetGetterFromFrame final :
     public gfxFontGroup::LazyReferenceDrawTargetGetter {
 public:
   typedef mozilla::gfx::DrawTarget DrawTarget;
@@ -203,16 +204,23 @@ public:
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override;
 
   virtual uint32_t GetPerFrameKey() const override {
     return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
   }
   void PaintTextToContext(gfxContext* aCtx,
                           nsPoint aOffsetFromRect);
+
+  virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
+                                       const StackingContextHelper& aSc,
+                                       layers::WebRenderLayerManager* aManager,
+                                       nsDisplayListBuilder* aDisplayListBuilder) override;
+
   NS_DISPLAY_DECL_NAME("TextOverflow", TYPE_TEXT_OVERFLOW)
 private:
   nsRect          mRect;   // in reference frame coordinates
   const nsStyleTextOverflowSide* mStyle;
   nscoord         mAscent; // baseline for the marker text in mRect
   uint32_t        mIndex;
 };
 
@@ -273,16 +281,53 @@ nsDisplayTextOverflowMarker::PaintTextTo
   } else {
     RefPtr<nsFontMetrics> fm =
       nsLayoutUtils::GetInflatedFontMetricsForFrame(mFrame);
     nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(),
                               mStyle->mString.Length(), pt);
   }
 }
 
+bool
+nsDisplayTextOverflowMarker::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                     mozilla::wr::IpcResourceUpdateQueue& aResources,
+                                                     const StackingContextHelper& aSc,
+                                                     layers::WebRenderLayerManager* aManager,
+                                                     nsDisplayListBuilder* aDisplayListBuilder)
+{
+  if (!aManager->IsLayersFreeTransaction() ||
+      !gfxPrefs::LayersAllowTextLayers() ||
+      !CanUseAdvancedLayer(aDisplayListBuilder->GetWidgetLayerManager())) {
+      return false;
+  }
+
+  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();
+  RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
+  // TextOverflowMarker only draws glyphs
+  textDrawer->StartDrawing(TextDrawTarget::Phase::eGlyphs);
+  Paint(aDisplayListBuilder, captureCtx);
+
+  if (!textDrawer->CanSerializeFonts()) {
+    return false;
+  }
+
+  textDrawer->CreateWebRenderCommands(aBuilder, aSc, aManager, this, bounds);
+
+
+  return true;
+}
+
+
 TextOverflow::TextOverflow(nsDisplayListBuilder* aBuilder,
                            nsIFrame* aBlockFrame)
   : mContentArea(aBlockFrame->GetWritingMode(),
                  aBlockFrame->GetContentRectRelativeToSelf(),
                  aBlockFrame->GetSize())
   , mBuilder(aBuilder)
   , mBlock(aBlockFrame)
   , mScrollableFrame(nsLayoutUtils::GetScrollableFrameFor(aBlockFrame))