Bug 1387325 - Part2. Add WR support for nsDisplayXULImage. r=mattwoodrow draft
authorEthan Lin <ethlin@mozilla.com>
Thu, 17 Aug 2017 14:47:25 +0800
changeset 661473 37f99b1726dfc801e8aeb34f71f6ca14ef92c2e5
parent 661472 a4106f02b3da5211c0e500488d5ba92244204fda
child 661474 820e5813e6b35de0df1d36732fc1c2434c462110
push id78766
push userbmo:ethlin@mozilla.com
push dateFri, 08 Sep 2017 13:57:10 +0000
reviewersmattwoodrow
bugs1387325
milestone57.0a1
Bug 1387325 - Part2. Add WR support for nsDisplayXULImage. r=mattwoodrow MozReview-Commit-ID: 9DncgchiS44
layout/xul/moz.build
layout/xul/nsImageBoxFrame.cpp
layout/xul/nsImageBoxFrame.h
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -89,16 +89,18 @@ if CONFIG['MOZ_XUL']:
         'nsXULPopupManager.cpp',
         'PopupBoxObject.cpp',
         'ScrollBoxObject.cpp',
     ]
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['tree', 'grid']
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../painting',
     '../style',
     '/dom/base',
     '/dom/xul',
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -47,16 +47,17 @@
 
 #include "nsContentUtils.h"
 
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Maybe.h"
 #include "SVGImageContext.h"
 #include "Units.h"
+#include "mozilla/layers/WebRenderLayerManager.h"
 
 #define ONLOAD_CALLED_TOO_EARLY 1
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 using namespace mozilla::layers;
 
@@ -405,16 +406,64 @@ nsImageBoxFrame::PaintImage(gfxContext& 
            PresContext(), imgCon,
            nsLayoutUtils::GetSamplingFilterForFrame(this),
            dest, dirty,
            svgContext, aFlags,
            anchorPoint.ptrOr(nullptr),
            hasSubRect ? &mSubRect : nullptr);
 }
 
+DrawResult
+nsImageBoxFrame::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         const StackingContextHelper& aSc,
+                                         mozilla::layers::WebRenderLayerManager* aManager,
+                                         nsDisplayItem* aItem,
+                                         nsPoint aPt,
+                                         uint32_t aFlags)
+{
+  DrawResult result;
+  Maybe<nsPoint> anchorPoint;
+  nsRect dest;
+  nsCOMPtr<imgIContainer> imgCon = GetImageContainerForPainting(aPt, result,
+                                                                anchorPoint,
+                                                                dest);
+  if (!imgCon) {
+    return result;
+  }
+
+  uint32_t containerFlags = imgIContainer::FLAG_NONE;
+  if (aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
+    containerFlags |= imgIContainer::FLAG_SYNC_DECODE;
+  }
+  RefPtr<layers::ImageContainer> container =
+    imgCon->GetImageContainer(aManager, containerFlags);
+  if (!container) {
+    NS_WARNING("Failed to get image container");
+    return DrawResult::NOT_READY;
+  }
+
+  gfx::IntSize size;
+  Maybe<wr::ImageKey> key = aManager->CreateImageKey(aItem, container, aBuilder, aSc, size);
+  if (key.isNothing()) {
+    return DrawResult::BAD_IMAGE;
+  }
+  const int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
+  LayoutDeviceRect fillRect = LayoutDeviceRect::FromAppUnits(dest,
+                                                             appUnitsPerDevPixel);
+  wr::LayoutRect fill = aSc.ToRelativeLayoutRect(fillRect);
+
+  LayoutDeviceSize gapSize(0, 0);
+  SamplingFilter sampleFilter = nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
+  aBuilder.PushImage(fill, fill,
+                     wr::ToLayoutSize(fillRect.Size()), wr::ToLayoutSize(gapSize),
+                     wr::ToImageRendering(sampleFilter), key.value());
+
+  return DrawResult::SUCCESS;
+}
+
 nsRect
 nsImageBoxFrame::GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint)
 {
   nsCOMPtr<imgIContainer> imgCon;
   mImageRequest->GetImage(getter_AddRefs(imgCon));
   MOZ_ASSERT(imgCon);
 
   nsRect clientRect;
@@ -469,16 +518,65 @@ void nsDisplayXULImage::Paint(nsDisplayL
     flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
 
   DrawResult result = static_cast<nsImageBoxFrame*>(mFrame)->
     PaintImage(*aCtx, mVisibleRect, ToReferenceFrame(), flags);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
+LayerState
+nsDisplayXULImage::GetLayerState(nsDisplayListBuilder* aBuilder,
+                                 LayerManager* aManager,
+                                 const ContainerLayerParameters& aParameters)
+{
+  if (ShouldUseAdvancedLayer(aManager, gfxPrefs::LayersAllowImageLayers) &&
+      CanOptimizeToImageLayer(aManager, aBuilder)) {
+    return LAYER_ACTIVE;
+  }
+  return LAYER_NONE;
+}
+
+already_AddRefed<Layer>
+nsDisplayXULImage::BuildLayer(nsDisplayListBuilder* aBuilder,
+                           LayerManager* aManager,
+                           const ContainerLayerParameters& aContainerParameters)
+{
+  return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
+}
+
+bool
+nsDisplayXULImage::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                           const StackingContextHelper& aSc,
+                                           nsTArray<WebRenderParentCommand>& aParentCommands,
+                                           mozilla::layers::WebRenderLayerManager* aManager,
+                                           nsDisplayListBuilder* aDisplayListBuilder)
+{
+  if (aManager->IsLayersFreeTransaction()) {
+    ContainerLayerParameters parameter;
+    if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
+      return false;
+    }
+  }
+
+  uint32_t flags = imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
+  if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
+    flags |= imgIContainer::FLAG_SYNC_DECODE;
+  }
+  if (aDisplayListBuilder->IsPaintingToWindow()) {
+    flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
+  }
+
+  DrawResult result = static_cast<nsImageBoxFrame*>(mFrame)->
+    CreateWebRenderCommands(aBuilder, aSc, aManager, this, ToReferenceFrame(), flags);
+
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+  return true;
+}
+
 nsDisplayItemGeometry*
 nsDisplayXULImage::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
 
 void
 nsDisplayXULImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
--- a/layout/xul/nsImageBoxFrame.h
+++ b/layout/xul/nsImageBoxFrame.h
@@ -94,16 +94,23 @@ public:
                                                                DrawResult& aDrawResult,
                                                                Maybe<nsPoint>& aAnchorPoint,
                                                                nsRect& aDest);
 
   DrawResult PaintImage(gfxContext& aRenderingContext,
                         const nsRect& aDirtyRect,
                         nsPoint aPt, uint32_t aFlags);
 
+  DrawResult CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                     const mozilla::layers::StackingContextHelper& aSc,
+                                     mozilla::layers::WebRenderLayerManager* aManager,
+                                     nsDisplayItem* aItem,
+                                     nsPoint aPt,
+                                     uint32_t aFlags);
+
   bool CanOptimizeToImageLayer();
 
   nsRect GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint);
 
 protected:
   explicit nsImageBoxFrame(nsStyleContext* aContext);
 
   virtual void GetImageSize();
@@ -158,12 +165,27 @@ public:
   virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion* aInvalidRegion) override;
   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
   // event receiver for us
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override;
+
+  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager,
+                                   const ContainerLayerParameters& aParameters) override;
+
+  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
+                                             LayerManager* aManager,
+                                             const ContainerLayerParameters& aContainerParameters) override;
+
+  virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       const StackingContextHelper& aSc,
+                                       nsTArray<WebRenderParentCommand>& aParentCommands,
+                                       mozilla::layers::WebRenderLayerManager* aManager,
+                                       nsDisplayListBuilder* aDisplayListBuilder) override;
+
   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
 };
 
 #endif /* nsImageBoxFrame_h___ */