Bug 1464927 - Make nsImageBoxFrame fallback from WebRender consistently with nsImageFrame. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 22 Jun 2018 09:32:27 -0400
changeset 480112 39936912aca97f641840e8d41da261932143de36
parent 480111 bfd72943e30fb7cb1d38d7babc93ba51c5b96b0d
child 480113 a47021b69969d209e8663e59cd5ec917d60ec6ef
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1464927
milestone62.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 1464927 - Make nsImageBoxFrame fallback from WebRender consistently with nsImageFrame. r=tnikkel Vector images don't support image containers if they are animated. In order to support this with WebRender, we would need to know when the generated shared surface was composited, so that we can update the image container on the next refresh tick. Because images use a different code path (not ImageClient), we don't have the ability at present. Changing vector images naively and just updating on every refresh tick if there is an image container to avoid fallback causes the animation to be very janky. Given nsImageFrame is already using fallback properly in this situation, then we can just fix nsImageBoxFrame to do the same. This gives acceptable performance without any visible slowness on the animation.
layout/xul/nsImageBoxFrame.cpp
layout/xul/nsImageBoxFrame.h
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -412,33 +412,33 @@ nsImageBoxFrame::PaintImage(gfxContext& 
            PresContext(), imgCon,
            nsLayoutUtils::GetSamplingFilterForFrame(this),
            dest, dirty,
            svgContext, aFlags,
            anchorPoint.ptrOr(nullptr),
            hasSubRect ? &mSubRect : nullptr);
 }
 
-ImgDrawResult
+Maybe<ImgDrawResult>
 nsImageBoxFrame::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                          mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayItem* aItem,
                                          nsPoint aPt,
                                          uint32_t aFlags)
 {
   ImgDrawResult result;
   Maybe<nsPoint> anchorPoint;
   nsRect dest;
   nsCOMPtr<imgIContainer> imgCon = GetImageContainerForPainting(aPt, result,
                                                                 anchorPoint,
                                                                 dest);
   if (!imgCon) {
-    return result;
+    return Nothing();
   }
 
   uint32_t containerFlags = imgIContainer::FLAG_ASYNC_NOTIFY;
   if (aFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
     containerFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
   }
   if (aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
     containerFlags |= imgIContainer::FLAG_SYNC_DECODE;
@@ -450,35 +450,35 @@ nsImageBoxFrame::CreateWebRenderCommands
   Maybe<SVGImageContext> svgContext;
   gfx::IntSize decodeSize =
     nsLayoutUtils::ComputeImageContainerDrawingParameters(imgCon, aItem->Frame(), fillRect,
                                                           aSc, containerFlags, svgContext);
   RefPtr<layers::ImageContainer> container =
     imgCon->GetImageContainerAtSize(aManager, decodeSize, svgContext, containerFlags);
   if (!container) {
     NS_WARNING("Failed to get image container");
-    return ImgDrawResult::NOT_READY;
+    return Nothing();
   }
 
   gfx::IntSize size;
   Maybe<wr::ImageKey> key = aManager->CommandBuilder().CreateImageKey(aItem, container,
                                                                       aBuilder, aResources,
                                                                       aSc, size, Nothing());
   if (key.isNothing()) {
-    return ImgDrawResult::NOT_READY;
+    return Some(ImgDrawResult::NOT_READY);
   }
   wr::LayoutRect fill = wr::ToRoundedLayoutRect(fillRect);
 
   LayoutDeviceSize gapSize(0, 0);
   SamplingFilter sampleFilter = nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
   aBuilder.PushImage(fill, fill, !BackfaceIsHidden(),
                      wr::ToLayoutSize(fillRect.Size()), wr::ToLayoutSize(gapSize),
                      wr::ToImageRendering(sampleFilter), key.value());
 
-  return ImgDrawResult::SUCCESS;
+  return Some(ImgDrawResult::SUCCESS);
 }
 
 nsRect
 nsImageBoxFrame::GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint)
 {
   nsCOMPtr<imgIContainer> imgCon;
   mImageRequest->GetImage(getter_AddRefs(imgCon));
   MOZ_ASSERT(imgCon);
@@ -559,20 +559,23 @@ nsDisplayXULImage::CreateWebRenderComman
   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;
   }
 
-  ImgDrawResult result = imageFrame->
+  Maybe<ImgDrawResult> result = imageFrame->
     CreateWebRenderCommands(aBuilder, aResources, aSc, aManager, this, ToReferenceFrame(), flags);
+  if (!result) {
+    return false;
+  }
 
-  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, *result);
   return true;
 }
 
 nsDisplayItemGeometry*
 nsDisplayXULImage::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
   return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
--- a/layout/xul/nsImageBoxFrame.h
+++ b/layout/xul/nsImageBoxFrame.h
@@ -91,23 +91,23 @@ public:
                                                                ImgDrawResult& aDrawResult,
                                                                Maybe<nsPoint>& aAnchorPoint,
                                                                nsRect& aDest);
 
   ImgDrawResult PaintImage(gfxContext& aRenderingContext,
                         const nsRect& aDirtyRect,
                         nsPoint aPt, uint32_t aFlags);
 
-  ImgDrawResult CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
-                                     mozilla::wr::IpcResourceUpdateQueue& aResources,
-                                     const mozilla::layers::StackingContextHelper& aSc,
-                                     mozilla::layers::WebRenderLayerManager* aManager,
-                                     nsDisplayItem* aItem,
-                                     nsPoint aPt,
-                                     uint32_t aFlags);
+  Maybe<ImgDrawResult> CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                               mozilla::wr::IpcResourceUpdateQueue& aResources,
+                                               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(ComputedStyle* aStyle);