Bug 1128769 (Part 5) - Record the last draw result for various less common frame types and use it to decide whether to sync decode. r=tn a=lmandel
authorSeth Fowler <seth@mozilla.com>
Mon, 09 Feb 2015 23:27:40 -0800
changeset 250153 498290d95f1c
parent 250152 782bd163aeed
child 250154 7b3c7ba30dfe
push id4514
push usermfowler@mozilla.com
push date2015-03-02 22:11 +0000
treeherdermozilla-beta@7b3c7ba30dfe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstn, lmandel
bugs1128769
milestone37.0
Bug 1128769 (Part 5) - Record the last draw result for various less common frame types and use it to decide whether to sync decode. r=tn a=lmandel
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsButtonFrameRenderer.h
layout/forms/nsFieldSetFrame.cpp
layout/forms/nsFieldSetFrame.h
layout/mathml/nsMathMLChar.cpp
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -14,16 +14,18 @@
 #include "nsFrame.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/Element.h"
 
 #define ACTIVE   "active"
 #define HOVER    "hover"
 #define FOCUS    "focus"
 
+using namespace mozilla::image;
+
 nsButtonFrameRenderer::nsButtonFrameRenderer()
 {
   MOZ_COUNT_CTOR(nsButtonFrameRenderer);
 }
 
 nsButtonFrameRenderer::~nsButtonFrameRenderer()
 {
   MOZ_COUNT_DTOR(nsButtonFrameRenderer);
@@ -125,16 +127,17 @@ public:
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE {
     aOutFrames->AppendElement(mFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) MOZ_OVERRIDE;
+  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion *aInvalidRegion) MOZ_OVERRIDE;
   NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
 private:
   nsButtonFrameRenderer* mBFR;
 };
 
@@ -160,36 +163,52 @@ public:
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
   NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND)
 private:
   nsButtonFrameRenderer* mBFR;
 };
 
+nsDisplayItemGeometry*
+nsDisplayButtonBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
 void
 nsDisplayButtonBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                                            const nsDisplayItemGeometry* aGeometry,
                                                            nsRegion *aInvalidRegion)
 {
-  AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+  auto geometry =
+    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+  if (aBuilder->ShouldSyncDecodeImages() &&
+      geometry->ShouldInvalidateToSyncDecodeImages()) {
+    bool snap;
+    aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+  }
 
   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
 void nsDisplayButtonBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
                                             nsRenderingContext* aCtx)
 {
   NS_ASSERTION(mFrame, "No frame?");
   nsPresContext* pc = mFrame->PresContext();
   nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
   
   // draw the border and background inside the focus and outline borders
-  mBFR->PaintBorderAndBackground(pc, *aCtx, mVisibleRect, r,
-                                 aBuilder->GetBackgroundPaintFlags());
+  DrawResult result =
+    mBFR->PaintBorderAndBackground(pc, *aCtx, mVisibleRect, r,
+                                   aBuilder->GetBackgroundPaintFlags());
+
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder,
                                       nsRenderingContext* aCtx)
 {
   nsPresContext *presContext = mFrame->PresContext();
   const nsStyleDisplay *disp = mFrame->StyleDisplay();
   if (!mFrame->IsThemed(disp) ||
@@ -255,36 +274,39 @@ nsButtonFrameRenderer::PaintOutlineAndFo
     GetButtonInnerFocusRect(aRect, rect);
 
     nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
                                 aDirtyRect, rect, mInnerFocusStyle);
   }
 }
 
 
-void
+DrawResult
 nsButtonFrameRenderer::PaintBorderAndBackground(nsPresContext* aPresContext,
           nsRenderingContext& aRenderingContext,
           const nsRect& aDirtyRect,
           const nsRect& aRect,
           uint32_t aBGFlags)
 
 {
   // get the button rect this is inside the focus and outline rects
   nsRect buttonRect;
   GetButtonRect(aRect, buttonRect);
 
   nsStyleContext* context = mFrame->StyleContext();
 
-  nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
-                                  aDirtyRect, buttonRect, aBGFlags);
+  DrawResult result =
+    nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, mFrame,
+                                    aDirtyRect, buttonRect, aBGFlags);
   nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
                                       mFrame, buttonRect, aDirtyRect);
   nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
                               aDirtyRect, buttonRect, context);
+
+  return result;
 }
 
 
 void
 nsButtonFrameRenderer::GetButtonOuterFocusRect(const nsRect& aRect, nsRect& focusRect)
 {
   focusRect = aRect;
 }
--- a/layout/forms/nsButtonFrameRenderer.h
+++ b/layout/forms/nsButtonFrameRenderer.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsButtonFrameRenderer_h___
 #define nsButtonFrameRenderer_h___
 
+#include "imgIContainer.h"
 #include "nsAutoPtr.h"
 #include "nsMargin.h"
 
 class nsIFrame;
 class nsFrame;
 class nsDisplayList;
 class nsDisplayListBuilder;
 class nsPresContext;
@@ -19,16 +20,18 @@ struct nsRect;
 class nsStyleContext;
 
 
 #define NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX  0
 #define NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX  1
 #define NS_BUTTON_RENDERER_LAST_CONTEXT_INDEX   NS_BUTTON_RENDERER_FOCUS_OUTER_CONTEXT_INDEX
 
 class nsButtonFrameRenderer {
+  typedef mozilla::image::DrawResult DrawResult;
+
 public:
 
   nsButtonFrameRenderer();
   ~nsButtonFrameRenderer();
 
   /**
    * Create display list items for the button
    */
@@ -36,21 +39,21 @@ public:
                          nsDisplayList* aBackground, nsDisplayList* aForeground);
 
 
   void PaintOutlineAndFocusBorders(nsPresContext* aPresContext,
                                    nsRenderingContext& aRenderingContext,
                                    const nsRect& aDirtyRect,
                                    const nsRect& aRect);
 
-  void PaintBorderAndBackground(nsPresContext* aPresContext,
-                                nsRenderingContext& aRenderingContext,
-                                const nsRect& aDirtyRect,
-                                const nsRect& aRect,
-                                uint32_t aBGFlags);
+  DrawResult PaintBorderAndBackground(nsPresContext* aPresContext,
+                                      nsRenderingContext& aRenderingContext,
+                                      const nsRect& aDirtyRect,
+                                      const nsRect& aRect,
+                                      uint32_t aBGFlags);
 
   void SetFrame(nsFrame* aFrame, nsPresContext* aPresContext);
  
   void SetDisabled(bool aDisabled, bool notify);
 
   bool isActive();
   bool isDisabled();
 
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -19,16 +19,17 @@
 #include "nsDisplayList.h"
 #include "nsRenderingContext.h"
 #include "nsIScrollableFrame.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Maybe.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::image;
 using namespace mozilla::layout;
 
 nsContainerFrame*
 NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsFieldSetFrame(aContext);
 }
 
@@ -97,16 +98,17 @@ public:
   }
 #endif
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
+  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion *aInvalidRegion) MOZ_OVERRIDE;
   NS_DISPLAY_DECL_NAME("FieldSetBorderBackground", TYPE_FIELDSET_BORDER_BACKGROUND)
 };
 
 void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                                                 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
@@ -116,27 +118,42 @@ void nsDisplayFieldSetBorderBackground::
   // It's not clear whether this is correct.
   aOutFrames->AppendElement(mFrame);
 }
 
 void
 nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
                                          nsRenderingContext* aCtx)
 {
-  static_cast<nsFieldSetFrame*>(mFrame)->
+  DrawResult result = static_cast<nsFieldSetFrame*>(mFrame)->
     PaintBorderBackground(*aCtx, ToReferenceFrame(),
                           mVisibleRect, aBuilder->GetBackgroundPaintFlags());
+
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
+}
+
+nsDisplayItemGeometry*
+nsDisplayFieldSetBorderBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
 }
 
 void
 nsDisplayFieldSetBorderBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                                              const nsDisplayItemGeometry* aGeometry,
                                                              nsRegion *aInvalidRegion)
 {
-  AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+  auto geometry =
+    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+  if (aBuilder->ShouldSyncDecodeImages() &&
+      geometry->ShouldInvalidateToSyncDecodeImages()) {
+    bool snap;
+    aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+  }
 
   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
 void
 nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                   const nsRect&           aDirtyRect,
                                   const nsDisplayListSet& aLists) {
@@ -183,31 +200,32 @@ nsFieldSetFrame::BuildDisplayList(nsDisp
   }
   // Put the inner frame's display items on the master list. Note that this
   // moves its border/background display items to our BorderBackground() list,
   // which isn't really correct, but it's OK because the inner frame is
   // anonymous and can't have its own border and background.
   contentDisplayItems.MoveTo(aLists);
 }
 
-void
+DrawResult
 nsFieldSetFrame::PaintBorderBackground(nsRenderingContext& aRenderingContext,
     nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags)
 {
   // if the border is smaller than the legend. Move the border down
   // to be centered on the legend. 
   // FIXME: This means border-radius clamping is incorrect; we should
   // override nsIFrame::GetBorderRadii.
   nsRect rect = VisualBorderRectRelativeToSelf();
   nscoord yoff = rect.y;
   rect += aPt;
   nsPresContext* presContext = PresContext();
 
-  nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
-                                  aDirtyRect, rect, aBGFlags);
+  DrawResult result =
+    nsCSSRendering::PaintBackground(presContext, aRenderingContext, this,
+                                    aDirtyRect, rect, aBGFlags);
 
   nsCSSRendering::PaintBoxShadowInner(presContext, aRenderingContext,
                                       this, rect, aDirtyRect);
 
    if (nsIFrame* legend = GetLegend()) {
      nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP);
 
     // Use the rect of the legend frame, not mLegendRect, so we draw our
@@ -258,16 +276,18 @@ nsFieldSetFrame::PaintBorderBackground(n
     gfx->Restore();
   } else {
 
     nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
                                 aDirtyRect,
                                 nsRect(aPt, mRect.Size()),
                                 mStyleContext);
   }
+
+  return result;
 }
 
 nscoord
 nsFieldSetFrame::GetIntrinsicISize(nsRenderingContext* aRenderingContext,
                                    nsLayoutUtils::IntrinsicISizeType aType)
 {
   nscoord legendWidth = 0;
   nscoord contentWidth = 0;
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -2,20 +2,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsFieldSetFrame_h___
 #define nsFieldSetFrame_h___
 
 #include "mozilla/Attributes.h"
+#include "imgIContainer.h"
 #include "nsContainerFrame.h"
 
 class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame
 {
+  typedef mozilla::image::DrawResult DrawResult;
+
 public:
   NS_DECL_FRAMEARENA_HELPERS
 
   explicit nsFieldSetFrame(nsStyleContext* aContext);
 
   nscoord
     GetIntrinsicISize(nsRenderingContext* aRenderingContext,
                       nsLayoutUtils::IntrinsicISizeType);
@@ -42,18 +45,19 @@ public:
                       nsHTMLReflowMetrics&     aDesiredSize,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus) MOZ_OVERRIDE;
                                
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
 
-  void PaintBorderBackground(nsRenderingContext& aRenderingContext,
-    nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags);
+  DrawResult PaintBorderBackground(nsRenderingContext& aRenderingContext,
+                                   nsPoint aPt, const nsRect& aDirtyRect,
+                                   uint32_t aBGFlags);
 
 #ifdef DEBUG
   virtual void SetInitialChildList(ChildListID    aListID,
                                    nsFrameList&   aChildList) MOZ_OVERRIDE;
   virtual void AppendFrames(ChildListID    aListID,
                             nsFrameList&   aFrameList) MOZ_OVERRIDE;
   virtual void InsertFrames(ChildListID    aListID,
                             nsIFrame*      aPrevFrame,
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -36,16 +36,17 @@
 #include "nsMathMLOperators.h"
 #include <algorithm>
 
 #include "gfxMathTable.h"
 #include "nsUnicodeScriptCodes.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::image;
 
 //#define NOISY_SEARCH 1
 
 // BUG 848725 Drawing failure with stretchy horizontal parenthesis when no fonts
 // are installed. "kMaxScaleFactor" is required to limit the scale for the
 // vertical and horizontal stretchy operators.
 static const float kMaxScaleFactor = 20.0;
 static const float kLargeOpFactor = float(M_SQRT2);
@@ -1880,46 +1881,64 @@ public:
     MOZ_COUNT_CTOR(nsDisplayMathMLCharBackground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLCharBackground() {
     MOZ_COUNT_DTOR(nsDisplayMathMLCharBackground);
   }
 #endif
 
+  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion *aInvalidRegion) MOZ_OVERRIDE;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsRenderingContext* aCtx) MOZ_OVERRIDE;
   NS_DISPLAY_DECL_NAME("MathMLCharBackground", TYPE_MATHML_CHAR_BACKGROUND)
 private:
   nsStyleContext* mStyleContext;
   nsRect          mRect;
 };
 
+nsDisplayItemGeometry*
+nsDisplayMathMLCharBackground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
+{
+  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
+}
+
 void
 nsDisplayMathMLCharBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                                          const nsDisplayItemGeometry* aGeometry,
                                                          nsRegion *aInvalidRegion)
 {
-  AddInvalidRegionForSyncDecodeBackgroundImages(aBuilder, aGeometry, aInvalidRegion);
+  auto geometry =
+    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
+
+  if (aBuilder->ShouldSyncDecodeImages() &&
+      geometry->ShouldInvalidateToSyncDecodeImages()) {
+    bool snap;
+    aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
+  }
 
   nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
 }
 
 void nsDisplayMathMLCharBackground::Paint(nsDisplayListBuilder* aBuilder,
                                           nsRenderingContext* aCtx)
 {
   const nsStyleBorder* border = mStyleContext->StyleBorder();
   nsRect rect(mRect + ToReferenceFrame());
-  nsCSSRendering::PaintBackgroundWithSC(mFrame->PresContext(), *aCtx, mFrame,
-                                        mVisibleRect, rect,
-                                        mStyleContext, *border,
-                                        aBuilder->GetBackgroundPaintFlags());
+
+  DrawResult result =
+    nsCSSRendering::PaintBackgroundWithSC(mFrame->PresContext(), *aCtx, mFrame,
+                                          mVisibleRect, rect,
+                                          mStyleContext, *border,
+                                          aBuilder->GetBackgroundPaintFlags());
+
+  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
 }
 
 class nsDisplayMathMLCharForeground : public nsDisplayItem {
 public:
   nsDisplayMathMLCharForeground(nsDisplayListBuilder* aBuilder,
                                 nsIFrame* aFrame, nsMathMLChar* aChar,
 				                uint32_t aIndex, bool aIsSelected)
     : nsDisplayItem(aBuilder, aFrame), mChar(aChar),