Bug 1339683 - Add CreateWebRenderCommands for nsDisplayBullet. r=mattwoodrow draft
authorMorris Tseng <mtseng@mozilla.com>
Thu, 09 Feb 2017 14:57:02 -0500
changeset 485770 ac9dfc475adbea251d4aa6cb76ffc3893d5b61ec
parent 485769 9793319f4082e4eacfb35de2f332d26c3adf1aea
child 485771 89a54b69cdaea0e065026ed0b7a54c6b3a762ddd
push id45837
push userbmo:mtseng@mozilla.com
push dateFri, 17 Feb 2017 04:14:52 +0000
reviewersmattwoodrow
bugs1339683
milestone54.0a1
Bug 1339683 - Add CreateWebRenderCommands for nsDisplayBullet. r=mattwoodrow MozReview-Commit-ID: 6IhKxRCJvZd
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
layout/generic/nsBulletFrame.cpp
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -81,16 +81,23 @@ WebRenderLayer::ParentStackingContextBou
 Rect
 WebRenderLayer::RelativeToParent(Rect aRect)
 {
   Rect parentBounds = ParentStackingContextBounds(-1);
   aRect.MoveBy(-parentBounds.x, -parentBounds.y);
   return aRect;
 }
 
+Point
+WebRenderLayer::GetOffsetToParent()
+{
+  Rect parentBounds = ParentStackingContextBounds(-1);
+  return parentBounds.TopLeft();
+}
+
 Rect
 WebRenderLayer::TransformedVisibleBoundsRelativeToParent()
 {
   IntRect bounds = GetLayer()->GetVisibleRegion().GetBounds().ToUnknownRect();
   Rect transformed = GetLayer()->GetTransform().TransformBounds(IntRectToRect(bounds));
   return RelativeToParent(transformed);
 }
 
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -39,16 +39,17 @@ public:
 
   WebRenderLayerManager* WrManager();
   WebRenderBridgeChild* WrBridge();
 
   gfx::Rect RelativeToVisible(gfx::Rect aRect);
   gfx::Rect RelativeToTransformedVisible(gfx::Rect aRect);
   gfx::Rect ParentStackingContextBounds(size_t aScrollMetadataIndex);
   gfx::Rect RelativeToParent(gfx::Rect aRect);
+  gfx::Point GetOffsetToParent();
   gfx::Rect TransformedVisibleBoundsRelativeToParent();
 protected:
   Maybe<WrImageMask> buildMaskLayer();
 
 };
 
 class MOZ_RAII WrScrollFrameStackingContextGenerator
 {
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -7,16 +7,18 @@
 
 #include "nsBulletFrame.h"
 
 #include "gfx2DGlue.h"
 #include "gfxUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/layers/LayersMessages.h"
+#include "mozilla/layers/WebRenderDisplayItemLayer.h"
+#include "mozilla/layers/WebRenderMessages.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Move.h"
 #include "nsCOMPtr.h"
 #include "nsFontMetrics.h"
 #include "nsGkAtoms.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsPresContext.h"
@@ -223,16 +225,21 @@ public:
   }
 
   already_AddRefed<layers::Layer>
   BuildLayer(nsDisplayListBuilder* aBuilder,
              layers::LayerManager* aManager,
              const ContainerLayerParameters& aContainerParameters,
              nsDisplayItem* aItem);
 
+  void
+  CreateWebRenderCommands(nsDisplayItem* aItem,
+                          nsTArray<layers::WebRenderCommand>& aCommands,
+                          layers::WebRenderDisplayItemLayer* aLayer);
+
   DrawResult
   Paint(nsRenderingContext& aRenderingContext, nsPoint aPt,
         const nsRect& aDirtyRect, uint32_t aFlags,
         bool aDisableSubpixelAA, nsIFrame* aFrame);
 
   bool
   IsImageType() const
   {
@@ -260,16 +267,19 @@ public:
            mListStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_OPEN &&
            mListStyleType != NS_STYLE_LIST_STYLE_DISCLOSURE_CLOSED &&
            !mText.IsEmpty();
   }
 
   bool
   BuildGlyphForText(nsDisplayItem* aItem, bool disableSubpixelAA);
 
+  bool
+  IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags);
+
 private:
   already_AddRefed<layers::Layer>
   BuildLayerForImage(layers::Layer* aOldLayer,
                      nsDisplayListBuilder* aBuilder,
                      layers::LayerManager* aManager,
                      nsDisplayItem* aItem);
 
   already_AddRefed<layers::Layer>
@@ -279,16 +289,31 @@ private:
                     nsDisplayItem* aItem);
 
   already_AddRefed<layers::Layer>
   BuildLayerForText(layers::Layer* aOldLayer,
                     nsDisplayListBuilder* aBuilder,
                     layers::LayerManager* aManager,
                     nsDisplayItem* aItem);
 
+  void
+  CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
+                                  nsTArray<layers::WebRenderCommand>& aCommands,
+                                  layers::WebRenderDisplayItemLayer* aLayer);
+
+  void
+  CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
+                                 nsTArray<layers::WebRenderCommand>& aCommands,
+                                 layers::WebRenderDisplayItemLayer* aLayer);
+
+  void
+  CreateWebRenderCommandsForText(nsDisplayItem* aItem,
+                                 nsTArray<layers::WebRenderCommand>& aCommands,
+                                 layers::WebRenderDisplayItemLayer* aLayer);
+
 private:
   // mImage and mDest are the properties for list-style-image.
   // mImage is the image content and mDest is the image position.
   RefPtr<imgIContainer> mImage;
   nsRect mDest;
 
   // mColor indicate the color of list-style. Both text and path type would use this memeber.
   nscolor mColor;
@@ -299,16 +324,17 @@ private:
 
   // mText, mFontMertrics, mPoint, mFont and mGlyphs are for other
   // list-style-type which can be drawed by text.
   nsString mText;
   RefPtr<nsFontMetrics> mFontMetrics;
   nsPoint mPoint;
   RefPtr<ScaledFont> mFont;
   nsTArray<layers::GlyphArray> mGlyphs;
+  WebRenderGlyphHelper mGlyphHelper;
 
   // Store the type of list-style-type.
   int32_t mListStyleType;
 };
 
 already_AddRefed<layers::Layer>
 BulletRenderer::BuildLayer(nsDisplayListBuilder* aBuilder,
                            layers::LayerManager* aManager,
@@ -332,16 +358,31 @@ BulletRenderer::BuildLayer(nsDisplayList
 
   if (layer) {
     layer->SetBaseTransform(gfx::Matrix4x4::Translation(offset.x, offset.y, 0));
   }
 
   return layer.forget();
 }
 
+void
+BulletRenderer::CreateWebRenderCommands(nsDisplayItem* aItem,
+                                        nsTArray<layers::WebRenderCommand>& aCommands,
+                                        layers::WebRenderDisplayItemLayer* aLayer)
+{
+  if (IsImageType()) {
+    CreateWebRenderCommandsForImage(aItem, aCommands, aLayer);
+  } else if (IsPathType()) {
+    CreateWebRenderCommandsForPath(aItem, aCommands, aLayer);
+  } else {
+    MOZ_ASSERT(IsTextType());
+    CreateWebRenderCommandsForText(aItem, aCommands, aLayer);
+  }
+}
+
 DrawResult
 BulletRenderer::Paint(nsRenderingContext& aRenderingContext, nsPoint aPt,
                       const nsRect& aDirtyRect, uint32_t aFlags,
                       bool aDisableSubpixelAA, nsIFrame* aFrame)
 {
   if (IsImageType()) {
     SamplingFilter filter = nsLayoutUtils::GetSamplingFilterForFrame(aFrame);
     return nsLayoutUtils::DrawSingleImage(*aRenderingContext.ThebesContext(),
@@ -405,16 +446,17 @@ BulletRenderer::BuildGlyphForText(nsDisp
 
     ctx.ThebesContext()->SetColor(
       Color::FromABGR(mColor));
 
     nsPresContext* presContext = aItem->Frame()->PresContext();
     if (!presContext->BidiEnabled() && HasRTLChars(mText)) {
       presContext->SetBidiEnabled();
     }
+
     nsLayoutUtils::DrawString(aItem->Frame(), *mFontMetrics, &ctx,
                               mText.get(), mText.Length(), mPoint);
   }
 
   layers::GlyphArray* g = mGlyphs.AppendElement();
   std::vector<Glyph> glyphs;
   Color color;
   if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs)) {
@@ -425,16 +467,24 @@ BulletRenderer::BuildGlyphForText(nsDisp
 
   g->glyphs().SetLength(glyphs.size());
   PodCopy(g->glyphs().Elements(), glyphs.data(), glyphs.size());
   g->color() = color;
 
   return true;
 }
 
+bool
+BulletRenderer::IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags)
+{
+  MOZ_ASSERT(IsImageType());
+
+  return mImage->IsImageContainerAvailable(aManager, aFlags);
+}
+
 already_AddRefed<layers::Layer>
 BulletRenderer::BuildLayerForImage(layers::Layer* aOldLayer,
                                    nsDisplayListBuilder* aBuilder,
                                    layers::LayerManager* aManager,
                                    nsDisplayItem* aItem)
 {
   MOZ_ASSERT(IsImageType());
 
@@ -511,16 +561,87 @@ BulletRenderer::BuildLayerForText(layers
   auto A2D = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
   bool dummy;
   const LayoutDeviceIntRect destBounds =
     LayoutDeviceIntRect::FromAppUnitsToOutside(aItem->GetBounds(aBuilder, &dummy), A2D);
   layer->SetBounds(IntRect(destBounds.x, destBounds.y, destBounds.width, destBounds.height));
   return layer.forget();
 }
 
+void
+BulletRenderer::CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
+                                                nsTArray<layers::WebRenderCommand>& aCommands,
+                                                layers::WebRenderDisplayItemLayer* aLayer)
+{
+  MOZ_ASSERT(IsImageType());
+
+  if (!mImage) {
+     return;
+  }
+
+  layers::WebRenderDisplayItemLayer* layer = static_cast<layers::WebRenderDisplayItemLayer*>(aLayer);
+  nsDisplayListBuilder* builder = layer->GetDisplayListBuilder();
+  uint32_t flags = builder->ShouldSyncDecodeImages() ?
+                   imgIContainer::FLAG_SYNC_DECODE :
+                   imgIContainer::FLAG_NONE;
+
+  RefPtr<layers::ImageContainer> container =
+    mImage->GetImageContainer(aLayer->WrManager(), flags);
+  if (!container) {
+    return;
+  }
+
+  uint64_t externalImageId = layer->SendImageContainer(container);
+
+  const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
+  Rect destRect =
+    NSRectToRect(mDest, appUnitsPerDevPixel);
+  Rect destRectTransformed = aLayer->RelativeToParent(destRect);
+  IntRect dest = RoundedToInt(destRectTransformed);
+
+  aCommands.AppendElement(layers::OpDPPushExternalImageId(
+                            LayerIntRegion(),
+                            wr::ToWrRect(dest),
+                            wr::ToWrRect(dest),
+                            Nothing(),
+                            WrImageRendering::Auto,
+                            externalImageId));
+}
+
+void
+BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
+                                               nsTArray<layers::WebRenderCommand>& aCommands,
+                                               layers::WebRenderDisplayItemLayer* aLayer)
+{
+  MOZ_ASSERT(IsPathType());
+  // Not supported yet.
+  MOZ_CRASH("unreachable");
+}
+
+void
+BulletRenderer::CreateWebRenderCommandsForText(nsDisplayItem* aItem,
+                                               nsTArray<layers::WebRenderCommand>& aCommands,
+                                               layers::WebRenderDisplayItemLayer* aLayer)
+{
+  MOZ_ASSERT(IsTextType());
+  MOZ_ASSERT(mFont);
+  MOZ_ASSERT(!mGlyphs.IsEmpty());
+
+  layers::WebRenderDisplayItemLayer* layer = static_cast<layers::WebRenderDisplayItemLayer*>(aLayer);
+  nsDisplayListBuilder* builder = layer->GetDisplayListBuilder();
+  const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
+  bool dummy;
+  Rect destRect =
+    NSRectToRect(aItem->GetBounds(builder, &dummy), appUnitsPerDevPixel);
+  Rect destRectTransformed = aLayer->RelativeToParent(destRect);
+
+  mGlyphHelper.BuildWebRenderCommands(aCommands, mGlyphs, mFont, aLayer->GetOffsetToParent(),
+                                      destRectTransformed, destRectTransformed);
+}
+
 class nsDisplayBullet final : public nsDisplayItem {
 public:
   nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
     , mDisableSubpixelAA(false)
   {
     MOZ_COUNT_CTOR(nsDisplayBullet);
   }
@@ -540,16 +661,19 @@ public:
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aParameters) override;
 
+  virtual void CreateWebRenderCommands(nsTArray<layers::WebRenderCommand>& aCommands,
+                                       layers::WebRenderDisplayItemLayer* aLayer) override;
+
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) override {
     aOutFrames->AppendElement(mFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("Bullet", TYPE_BULLET)
@@ -617,16 +741,26 @@ nsDisplayBullet::GetLayerState(nsDisplay
     return LAYER_NONE;
   }
 
   // Only support image and text type.
   if (!br->IsImageType() && !br->IsTextType()) {
     return LAYER_NONE;
   }
 
+  if (br->IsImageType()) {
+    uint32_t flags = aBuilder->ShouldSyncDecodeImages()
+                   ? imgIContainer::FLAG_SYNC_DECODE
+                   : imgIContainer::FLAG_NONE;
+
+    if (!br->IsImageContainerAvailable(aManager, flags)) {
+      return LAYER_NONE;
+    }
+  }
+
   if (br->IsTextType()) {
     if (!br->BuildGlyphForText(this, mDisableSubpixelAA)) {
       return LAYER_NONE;
     }
   }
 
   mBulletRenderer = br;
   return LAYER_ACTIVE;
@@ -636,17 +770,28 @@ already_AddRefed<layers::Layer>
 nsDisplayBullet::BuildLayer(nsDisplayListBuilder* aBuilder,
                             LayerManager* aManager,
                             const ContainerLayerParameters& aContainerParameters)
 {
   if (!mBulletRenderer) {
     return nullptr;
   }
 
-  return mBulletRenderer->BuildLayer(aBuilder, aManager, aContainerParameters, this);
+  /* return mBulletRenderer->BuildLayer(aBuilder, aManager, aContainerParameters, this); */
+  return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
+}
+
+void
+nsDisplayBullet::CreateWebRenderCommands(nsTArray<layers::WebRenderCommand>& aCommands,
+                                         layers::WebRenderDisplayItemLayer* aLayer)
+{
+  if (!mBulletRenderer)
+    return;
+
+  mBulletRenderer->CreateWebRenderCommands(this, aCommands, aLayer);
 }
 
 void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
                             nsRenderingContext* aCtx)
 {
   uint32_t flags = imgIContainer::FLAG_NONE;
   if (aBuilder->ShouldSyncDecodeImages()) {
     flags |= imgIContainer::FLAG_SYNC_DECODE;