LCOV - code coverage report
Current view: top level - layout/painting - nsDisplayList.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 900 4288 21.0 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       6             :  */
       7             : 
       8             : /*
       9             :  * structures that represent things to be painted (ordered in z-order),
      10             :  * used during painting and hit testing
      11             :  */
      12             : 
      13             : #include "nsDisplayList.h"
      14             : 
      15             : #include <stdint.h>
      16             : #include <algorithm>
      17             : #include <limits>
      18             : 
      19             : #include "gfxContext.h"
      20             : #include "gfxUtils.h"
      21             : #include "mozilla/dom/TabChild.h"
      22             : #include "mozilla/dom/KeyframeEffect.h"
      23             : #include "mozilla/dom/Selection.h"
      24             : #include "mozilla/gfx/2D.h"
      25             : #include "mozilla/layers/PLayerTransaction.h"
      26             : #include "nsCSSRendering.h"
      27             : #include "nsCSSRenderingGradients.h"
      28             : #include "nsISelectionController.h"
      29             : #include "nsIPresShell.h"
      30             : #include "nsRegion.h"
      31             : #include "nsStyleStructInlines.h"
      32             : #include "nsStyleTransformMatrix.h"
      33             : #include "gfxMatrix.h"
      34             : #include "gfxPrefs.h"
      35             : #include "nsSVGIntegrationUtils.h"
      36             : #include "nsSVGUtils.h"
      37             : #include "nsLayoutUtils.h"
      38             : #include "nsIScrollableFrame.h"
      39             : #include "nsIFrameInlines.h"
      40             : #include "nsThemeConstants.h"
      41             : #include "BorderConsts.h"
      42             : #include "LayerTreeInvalidation.h"
      43             : #include "mozilla/MathAlgorithms.h"
      44             : 
      45             : #include "imgIContainer.h"
      46             : #include "BasicLayers.h"
      47             : #include "nsBoxFrame.h"
      48             : #include "nsImageFrame.h"
      49             : #include "nsSubDocumentFrame.h"
      50             : #include "SVGObserverUtils.h"
      51             : #include "nsSVGElement.h"
      52             : #include "nsSVGClipPathFrame.h"
      53             : #include "GeckoProfiler.h"
      54             : #include "nsViewManager.h"
      55             : #include "ImageLayers.h"
      56             : #include "ImageContainer.h"
      57             : #include "nsCanvasFrame.h"
      58             : #include "StickyScrollContainer.h"
      59             : #include "mozilla/AnimationPerformanceWarning.h"
      60             : #include "mozilla/AnimationUtils.h"
      61             : #include "mozilla/EffectCompositor.h"
      62             : #include "mozilla/EffectSet.h"
      63             : #include "mozilla/EventStates.h"
      64             : #include "mozilla/LookAndFeel.h"
      65             : #include "mozilla/OperatorNewExtensions.h"
      66             : #include "mozilla/PendingAnimationTracker.h"
      67             : #include "mozilla/Preferences.h"
      68             : #include "mozilla/StyleAnimationValue.h"
      69             : #include "mozilla/ServoBindings.h"
      70             : #include "mozilla/Telemetry.h"
      71             : #include "mozilla/UniquePtr.h"
      72             : #include "mozilla/Unused.h"
      73             : #include "mozilla/ViewportFrame.h"
      74             : #include "mozilla/gfx/gfxVars.h"
      75             : #include "ActiveLayerTracker.h"
      76             : #include "nsContentUtils.h"
      77             : #include "nsPrintfCString.h"
      78             : #include "UnitTransforms.h"
      79             : #include "LayersLogging.h"
      80             : #include "FrameLayerBuilder.h"
      81             : #include "mozilla/EventStateManager.h"
      82             : #include "nsCaret.h"
      83             : #include "nsDOMTokenList.h"
      84             : #include "nsCSSProps.h"
      85             : #include "nsSVGMaskFrame.h"
      86             : #include "nsTableCellFrame.h"
      87             : #include "nsTableColFrame.h"
      88             : #include "nsSliderFrame.h"
      89             : #include "ClientLayerManager.h"
      90             : #include "mozilla/layers/StackingContextHelper.h"
      91             : #include "mozilla/layers/WebRenderBridgeChild.h"
      92             : #include "mozilla/layers/WebRenderLayerManager.h"
      93             : #include "mozilla/layers/WebRenderMessages.h"
      94             : #include "mozilla/layers/WebRenderScrollData.h"
      95             : 
      96             : // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
      97             : // GetTickCount().
      98             : #ifdef GetCurrentTime
      99             : #undef GetCurrentTime
     100             : #endif
     101             : 
     102             : using namespace mozilla;
     103             : using namespace mozilla::layers;
     104             : using namespace mozilla::dom;
     105             : using namespace mozilla::layout;
     106             : using namespace mozilla::gfx;
     107             : 
     108             : typedef FrameMetrics::ViewID ViewID;
     109             : typedef nsStyleTransformMatrix::TransformReferenceBox TransformReferenceBox;
     110             : 
     111             : #ifdef DEBUG
     112             : static bool
     113           0 : SpammyLayoutWarningsEnabled()
     114             : {
     115             :   static bool sValue = false;
     116             :   static bool sValueInitialized = false;
     117             : 
     118           0 :   if (!sValueInitialized) {
     119           0 :     Preferences::GetBool("layout.spammy_warnings.enabled", &sValue);
     120           0 :     sValueInitialized = true;
     121             :   }
     122             : 
     123           0 :   return sValue;
     124             : }
     125             : #endif
     126             : 
     127             : #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     128           0 : void AssertUniqueItem(nsDisplayItem* aItem) {
     129           0 :   nsIFrame::DisplayItemArray* items = aItem->Frame()->GetProperty(nsIFrame::DisplayItems());
     130           0 :   if (!items) {
     131             :     return;
     132             :   }
     133           0 :   for (nsDisplayItem* i : *items) {
     134           0 :     if (i != aItem &&
     135           0 :         !i->HasDeletedFrame() &&
     136           0 :         i->Frame() == aItem->Frame() &&
     137           0 :         i->GetPerFrameKey() == aItem->GetPerFrameKey()) {
     138           0 :       if (i->mPreProcessedItem) {
     139             :         continue;
     140             :       }
     141           0 :       MOZ_DIAGNOSTIC_ASSERT(false, "Duplicate display item!");
     142             :     }
     143             :   }
     144             : }
     145             : #endif
     146             : 
     147             : /* static */ bool
     148           0 : ActiveScrolledRoot::IsAncestor(const ActiveScrolledRoot* aAncestor,
     149             :                                const ActiveScrolledRoot* aDescendant)
     150             : {
     151           0 :   if (!aAncestor) {
     152             :     // nullptr is the root
     153             :     return true;
     154             :   }
     155           0 :   if (Depth(aAncestor) > Depth(aDescendant)) {
     156             :     return false;
     157             :   }
     158             :   const ActiveScrolledRoot* asr = aDescendant;
     159           0 :   while (asr) {
     160           0 :     if (asr == aAncestor) {
     161             :       return true;
     162             :     }
     163           0 :     asr = asr->mParent;
     164             :   }
     165             :   return false;
     166             : }
     167             : 
     168             : /* static */ nsCString
     169           0 : ActiveScrolledRoot::ToString(const ActiveScrolledRoot* aActiveScrolledRoot)
     170             : {
     171           0 :   nsAutoCString str;
     172           0 :   for (auto* asr = aActiveScrolledRoot; asr; asr = asr->mParent) {
     173           0 :     str.AppendPrintf("<0x%p>", asr->mScrollableFrame);
     174           0 :     if (asr->mParent) {
     175           0 :       str.AppendLiteral(", ");
     176             :     }
     177             :   }
     178           0 :   return str;
     179             : }
     180             : 
     181             : static inline CSSAngle
     182           0 : MakeCSSAngle(const nsCSSValue& aValue)
     183             : {
     184           0 :   return CSSAngle(aValue.GetAngleValue(), aValue.GetUnit());
     185             : }
     186             : 
     187           0 : static void AddTransformFunctions(const nsCSSValueList* aList,
     188             :                                   mozilla::ComputedStyle* aStyle,
     189             :                                   nsPresContext* aPresContext,
     190             :                                   TransformReferenceBox& aRefBox,
     191             :                                   InfallibleTArray<TransformFunction>& aFunctions)
     192             : {
     193           0 :   if (aList->mValue.GetUnit() == eCSSUnit_None) {
     194             :     return;
     195             :   }
     196             : 
     197           0 :   for (const nsCSSValueList* curr = aList; curr; curr = curr->mNext) {
     198           0 :     const nsCSSValue& currElem = curr->mValue;
     199           0 :     NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
     200             :                  "Stream should consist solely of functions!");
     201           0 :     nsCSSValue::Array* array = currElem.GetArrayValue();
     202           0 :     switch (nsStyleTransformMatrix::TransformFunctionOf(array)) {
     203             :       case eCSSKeyword_rotatex:
     204             :       {
     205           0 :         CSSAngle theta = MakeCSSAngle(array->Item(1));
     206           0 :         aFunctions.AppendElement(RotationX(theta));
     207             :         break;
     208             :       }
     209             :       case eCSSKeyword_rotatey:
     210             :       {
     211           0 :         CSSAngle theta = MakeCSSAngle(array->Item(1));
     212           0 :         aFunctions.AppendElement(RotationY(theta));
     213             :         break;
     214             :       }
     215             :       case eCSSKeyword_rotatez:
     216             :       {
     217           0 :         CSSAngle theta = MakeCSSAngle(array->Item(1));
     218           0 :         aFunctions.AppendElement(RotationZ(theta));
     219             :         break;
     220             :       }
     221             :       case eCSSKeyword_rotate:
     222             :       {
     223           0 :         CSSAngle theta = MakeCSSAngle(array->Item(1));
     224           0 :         aFunctions.AppendElement(Rotation(theta));
     225             :         break;
     226             :       }
     227             :       case eCSSKeyword_rotate3d:
     228             :       {
     229           0 :         double x = array->Item(1).GetFloatValue();
     230           0 :         double y = array->Item(2).GetFloatValue();
     231           0 :         double z = array->Item(3).GetFloatValue();
     232           0 :         CSSAngle theta = MakeCSSAngle(array->Item(4));
     233           0 :         aFunctions.AppendElement(Rotation3D(x, y, z, theta));
     234             :         break;
     235             :       }
     236             :       case eCSSKeyword_scalex:
     237             :       {
     238           0 :         double x = array->Item(1).GetFloatValue();
     239           0 :         aFunctions.AppendElement(Scale(x, 1, 1));
     240             :         break;
     241             :       }
     242             :       case eCSSKeyword_scaley:
     243             :       {
     244           0 :         double y = array->Item(1).GetFloatValue();
     245           0 :         aFunctions.AppendElement(Scale(1, y, 1));
     246             :         break;
     247             :       }
     248             :       case eCSSKeyword_scalez:
     249             :       {
     250           0 :         double z = array->Item(1).GetFloatValue();
     251           0 :         aFunctions.AppendElement(Scale(1, 1, z));
     252             :         break;
     253             :       }
     254             :       case eCSSKeyword_scale:
     255             :       {
     256           0 :         double x = array->Item(1).GetFloatValue();
     257             :         // scale(x) is shorthand for scale(x, x);
     258           0 :         double y = array->Count() == 2 ? x : array->Item(2).GetFloatValue();
     259           0 :         aFunctions.AppendElement(Scale(x, y, 1));
     260             :         break;
     261             :       }
     262             :       case eCSSKeyword_scale3d:
     263             :       {
     264           0 :         double x = array->Item(1).GetFloatValue();
     265           0 :         double y = array->Item(2).GetFloatValue();
     266           0 :         double z = array->Item(3).GetFloatValue();
     267           0 :         aFunctions.AppendElement(Scale(x, y, z));
     268             :         break;
     269             :       }
     270             :       case eCSSKeyword_translatex:
     271             :       {
     272           0 :         double x = nsStyleTransformMatrix::ProcessTranslatePart(
     273           0 :           array->Item(1),
     274           0 :           &aRefBox, &TransformReferenceBox::Width);
     275           0 :         aFunctions.AppendElement(Translation(x, 0, 0));
     276             :         break;
     277             :       }
     278             :       case eCSSKeyword_translatey:
     279             :       {
     280           0 :         double y = nsStyleTransformMatrix::ProcessTranslatePart(
     281           0 :           array->Item(1),
     282           0 :           &aRefBox, &TransformReferenceBox::Height);
     283           0 :         aFunctions.AppendElement(Translation(0, y, 0));
     284             :         break;
     285             :       }
     286             :       case eCSSKeyword_translatez:
     287             :       {
     288           0 :         double z = nsStyleTransformMatrix::ProcessTranslatePart(
     289           0 :           array->Item(1),
     290           0 :           nullptr);
     291           0 :         aFunctions.AppendElement(Translation(0, 0, z));
     292             :         break;
     293             :       }
     294             :       case eCSSKeyword_translate:
     295             :       {
     296           0 :         double x = nsStyleTransformMatrix::ProcessTranslatePart(
     297           0 :           array->Item(1),
     298           0 :           &aRefBox, &TransformReferenceBox::Width);
     299             :         // translate(x) is shorthand for translate(x, 0)
     300           0 :         double y = 0;
     301           0 :         if (array->Count() == 3) {
     302           0 :            y = nsStyleTransformMatrix::ProcessTranslatePart(
     303           0 :             array->Item(2),
     304             :             &aRefBox, &TransformReferenceBox::Height);
     305             :         }
     306           0 :         aFunctions.AppendElement(Translation(x, y, 0));
     307             :         break;
     308             :       }
     309             :       case eCSSKeyword_translate3d:
     310             :       {
     311           0 :         double x = nsStyleTransformMatrix::ProcessTranslatePart(
     312           0 :           array->Item(1),
     313           0 :           &aRefBox, &TransformReferenceBox::Width);
     314           0 :         double y = nsStyleTransformMatrix::ProcessTranslatePart(
     315           0 :           array->Item(2),
     316           0 :           &aRefBox, &TransformReferenceBox::Height);
     317           0 :         double z = nsStyleTransformMatrix::ProcessTranslatePart(
     318           0 :           array->Item(3),
     319           0 :           nullptr);
     320             : 
     321           0 :         aFunctions.AppendElement(Translation(x, y, z));
     322             :         break;
     323             :       }
     324             :       case eCSSKeyword_skewx:
     325             :       {
     326           0 :         CSSAngle x = MakeCSSAngle(array->Item(1));
     327           0 :         aFunctions.AppendElement(SkewX(x));
     328             :         break;
     329             :       }
     330             :       case eCSSKeyword_skewy:
     331             :       {
     332           0 :         CSSAngle y = MakeCSSAngle(array->Item(1));
     333           0 :         aFunctions.AppendElement(SkewY(y));
     334             :         break;
     335             :       }
     336             :       case eCSSKeyword_skew:
     337             :       {
     338           0 :         CSSAngle x = MakeCSSAngle(array->Item(1));
     339             :         // skew(x) is shorthand for skew(x, 0)
     340           0 :         CSSAngle y(0.0f, eCSSUnit_Degree);
     341           0 :         if (array->Count() == 3) {
     342           0 :           y = MakeCSSAngle(array->Item(2));
     343             :         }
     344           0 :         aFunctions.AppendElement(Skew(x, y));
     345             :         break;
     346             :       }
     347             :       case eCSSKeyword_matrix:
     348             :       {
     349           0 :         gfx::Matrix4x4 matrix;
     350           0 :         matrix._11 = array->Item(1).GetFloatValue();
     351           0 :         matrix._12 = array->Item(2).GetFloatValue();
     352           0 :         matrix._13 = 0;
     353           0 :         matrix._14 = 0;
     354           0 :         matrix._21 = array->Item(3).GetFloatValue();
     355           0 :         matrix._22 = array->Item(4).GetFloatValue();
     356           0 :         matrix._23 = 0;
     357           0 :         matrix._24 = 0;
     358           0 :         matrix._31 = 0;
     359           0 :         matrix._32 = 0;
     360           0 :         matrix._33 = 1;
     361           0 :         matrix._34 = 0;
     362           0 :         matrix._41 = ProcessTranslatePart(array->Item(5),
     363             :                                           &aRefBox, &TransformReferenceBox::Width);
     364           0 :         matrix._42 = ProcessTranslatePart(array->Item(6),
     365             :                                           &aRefBox, &TransformReferenceBox::Height);
     366           0 :         matrix._43 = 0;
     367           0 :         matrix._44 = 1;
     368           0 :         aFunctions.AppendElement(TransformMatrix(matrix));
     369             :         break;
     370             :       }
     371             :       case eCSSKeyword_matrix3d:
     372             :       {
     373           0 :         gfx::Matrix4x4 matrix;
     374           0 :         matrix._11 = array->Item(1).GetFloatValue();
     375           0 :         matrix._12 = array->Item(2).GetFloatValue();
     376           0 :         matrix._13 = array->Item(3).GetFloatValue();
     377           0 :         matrix._14 = array->Item(4).GetFloatValue();
     378           0 :         matrix._21 = array->Item(5).GetFloatValue();
     379           0 :         matrix._22 = array->Item(6).GetFloatValue();
     380           0 :         matrix._23 = array->Item(7).GetFloatValue();
     381           0 :         matrix._24 = array->Item(8).GetFloatValue();
     382           0 :         matrix._31 = array->Item(9).GetFloatValue();
     383           0 :         matrix._32 = array->Item(10).GetFloatValue();
     384           0 :         matrix._33 = array->Item(11).GetFloatValue();
     385           0 :         matrix._34 = array->Item(12).GetFloatValue();
     386           0 :         matrix._41 = ProcessTranslatePart(array->Item(13),
     387             :                                           &aRefBox, &TransformReferenceBox::Width);
     388           0 :         matrix._42 = ProcessTranslatePart(array->Item(14),
     389             :                                           &aRefBox, &TransformReferenceBox::Height);
     390           0 :         matrix._43 = ProcessTranslatePart(array->Item(15),
     391             :                                           &aRefBox, nullptr);
     392           0 :         matrix._44 = array->Item(16).GetFloatValue();
     393           0 :         aFunctions.AppendElement(TransformMatrix(matrix));
     394             :         break;
     395             :       }
     396             :       case eCSSKeyword_interpolatematrix:
     397             :       {
     398             :         bool dummy;
     399           0 :         Matrix4x4 matrix;
     400             :         nsStyleTransformMatrix::ProcessInterpolateMatrix(matrix, array,
     401             :                                                          aRefBox,
     402           0 :                                                          &dummy);
     403           0 :         aFunctions.AppendElement(TransformMatrix(matrix));
     404             :         break;
     405             :       }
     406             :       case eCSSKeyword_accumulatematrix:
     407             :       {
     408             :         bool dummy;
     409           0 :         Matrix4x4 matrix;
     410             :         nsStyleTransformMatrix::ProcessAccumulateMatrix(matrix, array,
     411             :                                                         aRefBox,
     412           0 :                                                         &dummy);
     413           0 :         aFunctions.AppendElement(TransformMatrix(matrix));
     414             :         break;
     415             :       }
     416             :       case eCSSKeyword_perspective:
     417             :       {
     418           0 :         aFunctions.AppendElement(Perspective(array->Item(1).GetFloatValue()));
     419             :         break;
     420             :       }
     421             :       default:
     422           0 :         NS_ERROR("Function not handled yet!");
     423             :     }
     424             :   }
     425             : }
     426             : 
     427             : static void
     428           0 : AddTransformFunctions(const nsCSSValueSharedList* aList,
     429             :                       const nsIFrame* aFrame,
     430             :                       TransformReferenceBox& aRefBox,
     431             :                       layers::Animatable& aAnimatable)
     432             : {
     433           0 :   MOZ_ASSERT(aList->mHead);
     434           0 :   AddTransformFunctions(aList->mHead,
     435             :                         aFrame->Style(),
     436             :                         aFrame->PresContext(),
     437             :                         aRefBox,
     438           0 :                         aAnimatable.get_ArrayOfTransformFunction());
     439           0 : }
     440             : 
     441             : static TimingFunction
     442           0 : ToTimingFunction(const Maybe<ComputedTimingFunction>& aCTF)
     443             : {
     444           0 :   if (aCTF.isNothing()) {
     445           0 :     return TimingFunction(null_t());
     446             :   }
     447             : 
     448           0 :   if (aCTF->HasSpline()) {
     449           0 :     const nsSMILKeySpline* spline = aCTF->GetFunction();
     450           0 :     return TimingFunction(CubicBezierFunction(spline->X1(), spline->Y1(),
     451           0 :                                               spline->X2(), spline->Y2()));
     452             :   }
     453             : 
     454           0 :   if (aCTF->GetType() == nsTimingFunction::Type::Frames) {
     455           0 :     return TimingFunction(FramesFunction(aCTF->GetFrames()));
     456             :   }
     457             : 
     458           0 :   uint32_t type = aCTF->GetType() == nsTimingFunction::Type::StepStart ? 1 : 2;
     459           0 :   return TimingFunction(StepFunction(aCTF->GetSteps(), type));
     460             : }
     461             : 
     462             : static void
     463           0 : SetAnimatable(nsCSSPropertyID aProperty,
     464             :               const AnimationValue& aAnimationValue,
     465             :               nsIFrame* aFrame,
     466             :               TransformReferenceBox& aRefBox,
     467             :               layers::Animatable& aAnimatable)
     468             : {
     469           0 :   MOZ_ASSERT(aFrame);
     470             : 
     471           0 :   if (aAnimationValue.IsNull()) {
     472           0 :     aAnimatable = null_t();
     473           0 :     return;
     474             :   }
     475             : 
     476           0 :   switch (aProperty) {
     477             :     case eCSSProperty_opacity:
     478           0 :       aAnimatable = aAnimationValue.GetOpacity();
     479           0 :       break;
     480             :     case eCSSProperty_transform: {
     481           0 :       aAnimatable = InfallibleTArray<TransformFunction>();
     482           0 :       if (aAnimationValue.mServo) {
     483           0 :         RefPtr<nsCSSValueSharedList> list;
     484           0 :         Servo_AnimationValue_GetTransform(aAnimationValue.mServo, &list);
     485           0 :         AddTransformFunctions(list, aFrame, aRefBox, aAnimatable);
     486             :       } else {
     487           0 :         MOZ_CRASH("old style system disabled");
     488             :       }
     489           0 :       break;
     490             :     }
     491             :     default:
     492           0 :       MOZ_ASSERT_UNREACHABLE("Unsupported property");
     493             :   }
     494             : }
     495             : 
     496             : static void
     497           0 : AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
     498             :                         dom::Animation* aAnimation, AnimationInfo& aAnimationInfo,
     499             :                         AnimationData& aData, bool aPending)
     500             : {
     501           0 :   MOZ_ASSERT(aAnimation->GetEffect(),
     502             :              "Should not be adding an animation without an effect");
     503           0 :   MOZ_ASSERT(!aAnimation->GetCurrentOrPendingStartTime().IsNull() ||
     504             :              !aAnimation->IsPlaying() ||
     505             :              (aAnimation->GetTimeline() &&
     506             :               aAnimation->GetTimeline()->TracksWallclockTime()),
     507             :              "If the animation has an unresolved start time it should either"
     508             :              " be static (so we don't need a start time) or else have a"
     509             :              " timeline capable of converting TimeStamps (so we can calculate"
     510             :              " one later");
     511             : 
     512             :   layers::Animation* animation =
     513           0 :     aPending ?
     514             :     aAnimationInfo.AddAnimationForNextTransaction() :
     515           0 :     aAnimationInfo.AddAnimation();
     516             : 
     517           0 :   const TimingParams& timing = aAnimation->GetEffect()->SpecifiedTiming();
     518             : 
     519             :   // If we are starting a new transition that replaces an existing transition
     520             :   // running on the compositor, it is possible that the animation on the
     521             :   // compositor will have advanced ahead of the main thread. If we use as
     522             :   // the starting point of the new transition, the current value of the
     523             :   // replaced transition as calculated on the main thread using the refresh
     524             :   // driver time, the new transition will jump when it starts. Instead, we
     525             :   // re-calculate the starting point of the new transition by applying the
     526             :   // current TimeStamp to the parameters of the replaced transition.
     527             :   //
     528             :   // We need to do this here, rather than when we generate the new transition,
     529             :   // since after generating the new transition other requestAnimationFrame
     530             :   // callbacks may run that introduce further lag between the main thread and
     531             :   // the compositor.
     532           0 :   if (aAnimation->AsCSSTransition() &&
     533           0 :       aAnimation->GetEffect() &&
     534           0 :       aAnimation->GetEffect()->AsTransition()) {
     535             :     // We update startValue from the replaced transition only if the effect is
     536             :     // an ElementPropertyTransition.
     537           0 :     aAnimation->GetEffect()->AsTransition()->
     538           0 :       UpdateStartValueFromReplacedTransition();
     539             :   }
     540             : 
     541           0 :   animation->originTime() = !aAnimation->GetTimeline()
     542           0 :                             ? TimeStamp()
     543           0 :                             : aAnimation->GetTimeline()->
     544           0 :                                 ToTimeStamp(TimeDuration());
     545             : 
     546           0 :   Nullable<TimeDuration> startTime = aAnimation->GetCurrentOrPendingStartTime();
     547           0 :   if (startTime.IsNull()) {
     548           0 :     animation->startTime() = null_t();
     549             :   } else {
     550           0 :     animation->startTime() = startTime.Value();
     551             :   }
     552             : 
     553           0 :   animation->holdTime() = aAnimation->GetCurrentTime().Value();
     554             : 
     555             :   const ComputedTiming computedTiming =
     556           0 :     aAnimation->GetEffect()->GetComputedTiming();
     557           0 :   animation->delay() = timing.Delay();
     558           0 :   animation->endDelay() = timing.EndDelay();
     559           0 :   animation->duration() = computedTiming.mDuration;
     560           0 :   animation->iterations() = computedTiming.mIterations;
     561           0 :   animation->iterationStart() = computedTiming.mIterationStart;
     562           0 :   animation->direction() = static_cast<uint8_t>(timing.Direction());
     563           0 :   animation->fillMode() = static_cast<uint8_t>(computedTiming.mFill);
     564           0 :   animation->property() = aProperty.mProperty;
     565           0 :   animation->playbackRate() = aAnimation->CurrentOrPendingPlaybackRate();
     566           0 :   animation->previousPlaybackRate() =
     567           0 :     aAnimation->HasPendingPlaybackRate()
     568           0 :       ? aAnimation->PlaybackRate()
     569             :       : std::numeric_limits<float>::quiet_NaN();
     570           0 :   animation->data() = aData;
     571           0 :   animation->easingFunction() = ToTimingFunction(timing.TimingFunction());
     572           0 :   animation->iterationComposite() =
     573           0 :     static_cast<uint8_t>(aAnimation->GetEffect()->
     574           0 :                          AsKeyframeEffect()->IterationComposite());
     575           0 :   animation->isNotPlaying() = !aAnimation->IsPlaying();
     576             : 
     577           0 :   TransformReferenceBox refBox(aFrame);
     578             : 
     579             :   // If the animation is additive or accumulates, we need to pass its base value
     580             :   // to the compositor.
     581             : 
     582             :   AnimationValue baseStyle =
     583           0 :     aAnimation->GetEffect()->AsKeyframeEffect()->BaseStyle(aProperty.mProperty);
     584           0 :   if (!baseStyle.IsNull()) {
     585           0 :     SetAnimatable(aProperty.mProperty,
     586             :                   baseStyle,
     587             :                   aFrame, refBox,
     588           0 :                   animation->baseStyle());
     589             :   } else {
     590           0 :     animation->baseStyle() = null_t();
     591             :   }
     592             : 
     593           0 :   for (uint32_t segIdx = 0; segIdx < aProperty.mSegments.Length(); segIdx++) {
     594           0 :     const AnimationPropertySegment& segment = aProperty.mSegments[segIdx];
     595             : 
     596           0 :     AnimationSegment* animSegment = animation->segments().AppendElement();
     597           0 :     SetAnimatable(aProperty.mProperty,
     598             :                   segment.mFromValue,
     599             :                   aFrame, refBox,
     600           0 :                   animSegment->startState());
     601           0 :     SetAnimatable(aProperty.mProperty,
     602             :                   segment.mToValue,
     603             :                   aFrame, refBox,
     604           0 :                   animSegment->endState());
     605             : 
     606           0 :     animSegment->startPortion() = segment.mFromKey;
     607           0 :     animSegment->endPortion() = segment.mToKey;
     608           0 :     animSegment->startComposite() =
     609           0 :       static_cast<uint8_t>(segment.mFromComposite);
     610           0 :     animSegment->endComposite() =
     611           0 :       static_cast<uint8_t>(segment.mToComposite);
     612           0 :     animSegment->sampleFn() = ToTimingFunction(segment.mTimingFunction);
     613             :   }
     614           0 : }
     615             : 
     616             : static void
     617           0 : AddAnimationsForProperty(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder,
     618             :                          nsDisplayItem* aItem, nsCSSPropertyID aProperty,
     619             :                          AnimationInfo& aAnimationInfo, bool aPending,
     620             :                          bool aIsForWebRender)
     621             : {
     622           0 :   if (aPending) {
     623           0 :     aAnimationInfo.ClearAnimationsForNextTransaction();
     624             :   } else {
     625           0 :     aAnimationInfo.ClearAnimations();
     626             :   }
     627             : 
     628           0 :   nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aFrame);
     629           0 :   if (!styleFrame) {
     630           0 :     return;
     631             :   }
     632             : 
     633             :   // Update the animation generation on the layer. We need to do this before
     634             :   // any early returns since even if we don't add any animations to the
     635             :   // layer, we still need to mark it as up-to-date with regards to animations.
     636             :   // Otherwise, in RestyleManager we'll notice the discrepancy between the
     637             :   // animation generation numbers and update the layer indefinitely.
     638             :   uint64_t animationGeneration =
     639             :     // Note that GetAnimationGenerationForFrame() calles EffectSet::GetEffectSet
     640             :     // that expects to work with the style frame instead of the primary frame.
     641           0 :     RestyleManager::GetAnimationGenerationForFrame(styleFrame);
     642           0 :   aAnimationInfo.SetAnimationGeneration(animationGeneration);
     643             : 
     644           0 :   EffectCompositor::ClearIsRunningOnCompositor(styleFrame, aProperty);
     645             :   nsTArray<RefPtr<dom::Animation>> compositorAnimations =
     646           0 :     EffectCompositor::GetAnimationsForCompositor(styleFrame, aProperty);
     647           0 :   if (compositorAnimations.IsEmpty()) {
     648             :     return;
     649             :   }
     650             : 
     651             :   // If the frame is not prerendered, bail out.
     652             :   // Do this check only during layer construction; during updating the
     653             :   // caller is required to check it appropriately.
     654           0 :   if (aItem && !aItem->CanUseAsyncAnimations(aBuilder)) {
     655             :     // EffectCompositor needs to know that we refused to run this animation
     656             :     // asynchronously so that it will not throttle the main thread
     657             :     // animation.
     658           0 :     aFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), true);
     659             : 
     660             :     // We need to schedule another refresh driver run so that EffectCompositor
     661             :     // gets a chance to unthrottle the animation.
     662           0 :     aFrame->SchedulePaint();
     663           0 :     return;
     664             :   }
     665             : 
     666           0 :   AnimationData data;
     667           0 :   if (aProperty == eCSSProperty_transform) {
     668             :     // XXX Performance here isn't ideal for SVG. We'd prefer to avoid resolving
     669             :     // the dimensions of refBox. That said, we only get here if there are CSS
     670             :     // animations or transitions on this element, and that is likely to be a
     671             :     // lot rarer than transforms on SVG (the frequency of which drives the need
     672             :     // for TransformReferenceBox).
     673           0 :     TransformReferenceBox refBox(aFrame);
     674           0 :     nsRect bounds(0, 0, refBox.Width(), refBox.Height());
     675             :     // all data passed directly to the compositor should be in dev pixels
     676           0 :     int32_t devPixelsToAppUnits = aFrame->PresContext()->AppUnitsPerDevPixel();
     677           0 :     float scale = devPixelsToAppUnits;
     678             :     Point3D offsetToTransformOrigin =
     679           0 :       nsDisplayTransform::GetDeltaToTransformOrigin(aFrame, scale, &bounds);
     680           0 :     nsPoint origin;
     681           0 :     float scaleX = 1.0f;
     682           0 :     float scaleY = 1.0f;
     683           0 :     bool hasPerspectiveParent = false;
     684           0 :     if (aIsForWebRender) {
     685             :       // leave origin empty, because we are sending it separately on the stacking
     686             :       // context that we are pushing to WR, and WR will automatically include
     687             :       // it when picking up the animated transform values
     688           0 :     } else if (aItem) {
     689             :       // This branch is for display items to leverage the cache of
     690             :       // nsDisplayListBuilder.
     691           0 :       origin = aItem->ToReferenceFrame();
     692             :     } else {
     693             :       // This branch is running for restyling.
     694             :       // Animations are animated at the coordination of the reference
     695             :       // frame outside, not the given frame itself.  The given frame
     696             :       // is also reference frame too, so the parent's reference frame
     697             :       // are used.
     698             :       nsIFrame* referenceFrame =
     699           0 :         nsLayoutUtils::GetReferenceFrame(nsLayoutUtils::GetCrossDocParentFrame(aFrame));
     700           0 :       origin = aFrame->GetOffsetToCrossDoc(referenceFrame);
     701             :     }
     702             : 
     703           0 :     data = TransformData(origin, offsetToTransformOrigin,
     704             :                          bounds, devPixelsToAppUnits,
     705           0 :                          scaleX, scaleY, hasPerspectiveParent);
     706           0 :   } else if (aProperty == eCSSProperty_opacity) {
     707           0 :     data = null_t();
     708             :   }
     709             : 
     710           0 :   MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
     711             :                                       CSSPropFlags::CanAnimateOnCompositor),
     712             :              "inconsistent property flags");
     713             : 
     714             :   // Add from first to last (since last overrides)
     715           0 :   for (size_t animIdx = 0; animIdx < compositorAnimations.Length(); animIdx++) {
     716           0 :     dom::Animation* anim = compositorAnimations[animIdx];
     717           0 :     if (!anim->IsRelevant()) {
     718             :       continue;
     719             :     }
     720             : 
     721             :     dom::KeyframeEffect* keyframeEffect =
     722           0 :       anim->GetEffect() ? anim->GetEffect()->AsKeyframeEffect() : nullptr;
     723           0 :     MOZ_ASSERT(keyframeEffect,
     724             :                "A playing animation should have a keyframe effect");
     725             :     const AnimationProperty* property =
     726           0 :       keyframeEffect->GetEffectiveAnimationOfProperty(aProperty);
     727           0 :     if (!property) {
     728             :       continue;
     729             :     }
     730             : 
     731             :     // Note that if the property is overridden by !important rules,
     732             :     // GetEffectiveAnimationOfProperty returns null instead.
     733             :     // This is what we want, since if we have animations overridden by
     734             :     // !important rules, we don't want to send them to the compositor.
     735           0 :     MOZ_ASSERT(anim->CascadeLevel() !=
     736             :                  EffectCompositor::CascadeLevel::Animations ||
     737             :                !EffectSet::GetEffectSet(styleFrame)->PropertiesWithImportantRules()
     738             :                   .HasProperty(aProperty),
     739             :                "GetEffectiveAnimationOfProperty already tested the property "
     740             :                "is not overridden by !important rules");
     741             : 
     742             :     // Don't add animations that are pending if their timeline does not
     743             :     // track wallclock time. This is because any pending animations on layers
     744             :     // will have their start time updated with the current wallclock time.
     745             :     // If we can't convert that wallclock time back to an equivalent timeline
     746             :     // time, we won't be able to update the content animation and it will end
     747             :     // up being out of sync with the layer animation.
     748             :     //
     749             :     // Currently this only happens when the timeline is driven by a refresh
     750             :     // driver under test control. In this case, the next time the refresh
     751             :     // driver is advanced it will trigger any pending animations.
     752           0 :     if (anim->Pending() &&
     753           0 :         (anim->GetTimeline() && !anim->GetTimeline()->TracksWallclockTime())) {
     754             :       continue;
     755             :     }
     756             : 
     757           0 :     AddAnimationForProperty(aFrame, *property, anim, aAnimationInfo, data, aPending);
     758           0 :     keyframeEffect->SetIsRunningOnCompositor(aProperty, true);
     759             :   }
     760             : }
     761             : 
     762             : static bool
     763           0 : GenerateAndPushTextMask(nsIFrame* aFrame, gfxContext* aContext,
     764             :                         const nsRect& aFillRect, nsDisplayListBuilder* aBuilder)
     765             : {
     766           0 :   if (aBuilder->IsForGenerateGlyphMask() ||
     767           0 :       aBuilder->IsForPaintingSelectionBG()) {
     768             :     return false;
     769             :   }
     770             : 
     771             :   // The main function of enabling background-clip:text property value.
     772             :   // When a nsDisplayBackgroundImage detects "text" bg-clip style, it will call
     773             :   // this function to
     774             :   // 1. Paint background color of the selection text if any.
     775             :   // 2. Generate a mask by all descendant text frames
     776             :   // 3. Push the generated mask into aContext.
     777             :   //
     778             :   // TBD: we actually generate display list of aFrame twice here. It's better
     779             :   // to reuse the same display list and paint that one twice, one for selection
     780             :   // background, one for generating text mask.
     781             : 
     782           0 :   gfxContext* sourceCtx = aContext;
     783             :   LayoutDeviceRect bounds =
     784             :     LayoutDeviceRect::FromAppUnits(aFillRect,
     785           0 :                                    aFrame->PresContext()->AppUnitsPerDevPixel());
     786             : 
     787             :   {
     788             :     // Paint text selection background into sourceCtx.
     789           0 :     gfxContextMatrixAutoSaveRestore save(sourceCtx);
     790           0 :     sourceCtx->SetMatrix(sourceCtx->CurrentMatrix().PreTranslate(bounds.TopLeft().ToUnknownPoint()));
     791             : 
     792           0 :     nsLayoutUtils::PaintFrame(aContext, aFrame,
     793           0 :                               nsRect(nsPoint(0, 0), aFrame->GetSize()),
     794             :                               NS_RGB(255, 255, 255),
     795           0 :                               nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND);
     796             :   }
     797             : 
     798             :   // Evaluate required surface size.
     799             :   IntRect drawRect =
     800           0 :     RoundedOut(ToRect(sourceCtx->GetClipExtents(gfxContext::eDeviceSpace)));
     801             : 
     802           0 :   Matrix currentMatrix = sourceCtx->CurrentMatrix();
     803             :   Matrix maskTransform = currentMatrix *
     804           0 :                          Matrix::Translation(-drawRect.x, -drawRect.y);
     805           0 :   maskTransform.Invert();
     806             : 
     807             :   // Create a mask surface.
     808           0 :   RefPtr<DrawTarget> sourceTarget = sourceCtx->GetDrawTarget();
     809             :   RefPtr<DrawTarget> maskDT =
     810           0 :     sourceTarget->CreateClippedDrawTarget(drawRect.Size(),
     811           0 :                                           maskTransform * currentMatrix,
     812           0 :                                           SurfaceFormat::A8);
     813           0 :   if (!maskDT || !maskDT->IsValid()) {
     814             :     return false;
     815             :   }
     816           0 :   RefPtr<gfxContext> maskCtx = gfxContext::CreatePreservingTransformOrNull(maskDT);
     817           0 :   MOZ_ASSERT(maskCtx);
     818           0 :   maskCtx->SetMatrix(Matrix::Translation(bounds.TopLeft().ToUnknownPoint()) *
     819           0 :                      currentMatrix *
     820           0 :                      Matrix::Translation(-drawRect.TopLeft()));
     821             : 
     822             :   // Shade text shape into mask A8 surface.
     823           0 :   nsLayoutUtils::PaintFrame(maskCtx, aFrame,
     824           0 :                             nsRect(nsPoint(0, 0), aFrame->GetSize()),
     825             :                             NS_RGB(255, 255, 255),
     826           0 :                             nsDisplayListBuilderMode::GENERATE_GLYPH);
     827             : 
     828             :   // Push the generated mask into aContext, so that the caller can pop and
     829             :   // blend with it.
     830           0 :   RefPtr<SourceSurface> maskSurface = maskDT->Snapshot();
     831           0 :   sourceCtx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 1.0, maskSurface, maskTransform);
     832             : 
     833             :   return true;
     834             : }
     835             : 
     836             : /* static */ void
     837           0 : nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer,
     838             :                                                          nsDisplayListBuilder* aBuilder,
     839             :                                                          nsDisplayItem* aItem,
     840             :                                                          nsIFrame* aFrame,
     841             :                                                          nsCSSPropertyID aProperty)
     842             : {
     843           0 :   MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
     844             :                                       CSSPropFlags::CanAnimateOnCompositor),
     845             :              "inconsistent property flags");
     846             : 
     847             :   // This function can be called in two ways:  from
     848             :   // nsDisplay*::BuildLayer while constructing a layer (with all
     849             :   // pointers non-null), or from RestyleManager's handling of
     850             :   // UpdateOpacityLayer/UpdateTransformLayer hints.
     851           0 :   MOZ_ASSERT(!aBuilder == !aItem,
     852             :              "should only be called in two configurations, with both "
     853             :              "aBuilder and aItem, or with neither");
     854           0 :   MOZ_ASSERT(!aItem || aFrame == aItem->Frame(), "frame mismatch");
     855             : 
     856             :   // Only send animations to a layer that is actually using
     857             :   // off-main-thread compositing.
     858           0 :   LayersBackend backend = aLayer->Manager()->GetBackendType();
     859           0 :   if (!(backend == layers::LayersBackend::LAYERS_CLIENT ||
     860             :         backend == layers::LayersBackend::LAYERS_WR)) {
     861             :     return;
     862             :   }
     863             : 
     864           0 :   bool pending = !aBuilder;
     865           0 :   AnimationInfo& animationInfo = aLayer->GetAnimationInfo();
     866             :   AddAnimationsForProperty(aFrame, aBuilder, aItem, aProperty,
     867           0 :                            animationInfo, pending, false);
     868           0 :   animationInfo.TransferMutatedFlagToLayer(aLayer);
     869             : }
     870             : 
     871             : nsDisplayItem*
     872           0 : nsDisplayListBuilder::MergeItems(nsTArray<nsDisplayItem*>& aMergedItems)
     873             : {
     874             :   // For merging, we create a temporary item by cloning the last item of the
     875             :   // mergeable items list. This ensures that the temporary item will have the
     876             :   // correct frame and bounds.
     877           0 :   nsDisplayItem* merged = nullptr;
     878             : 
     879           0 :   for (nsDisplayItem* item : Reversed(aMergedItems)) {
     880           0 :     MOZ_ASSERT(item);
     881             : 
     882           0 :     if (!merged) {
     883             :       // Create the temporary item.
     884           0 :       merged = item->Clone(this);
     885           0 :       MOZ_ASSERT(merged);
     886             : 
     887           0 :       AddTemporaryItem(merged);
     888             :     } else {
     889             :       // Merge the item properties (frame/bounds/etc) with the previously
     890             :       // created temporary item.
     891           0 :       MOZ_ASSERT(merged->CanMerge(item));
     892           0 :       merged->Merge(item);
     893             :     }
     894             : 
     895             :     // Create nsDisplayWrapList that points to the internal display list of the
     896             :     // item we are merging. This nsDisplayWrapList is added to the display list
     897             :     // of the temporary item.
     898           0 :     merged->MergeDisplayListFromItem(this, item);
     899             :   }
     900             : 
     901           0 :   return merged;
     902             : }
     903             : 
     904             : void
     905           0 : nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter::SetCurrentActiveScrolledRoot(
     906             :     const ActiveScrolledRoot* aActiveScrolledRoot)
     907             : {
     908           0 :   MOZ_ASSERT(!mUsed);
     909             : 
     910             :   // Set the builder's mCurrentActiveScrolledRoot.
     911           0 :   mBuilder->mCurrentActiveScrolledRoot = aActiveScrolledRoot;
     912             : 
     913             :   // We also need to adjust the builder's mCurrentContainerASR.
     914             :   // mCurrentContainerASR needs to be an ASR that all the container's
     915             :   // contents have finite bounds with respect to. If aActiveScrolledRoot
     916             :   // is an ancestor ASR of mCurrentContainerASR, that means we need to
     917             :   // set mCurrentContainerASR to aActiveScrolledRoot, because otherwise
     918             :   // the items that will be created with aActiveScrolledRoot wouldn't
     919             :   // have finite bounds with respect to mCurrentContainerASR. There's one
     920             :   // exception, in the case where there's a content clip on the builder
     921             :   // that is scrolled by a descendant ASR of aActiveScrolledRoot. This
     922             :   // content clip will clip all items that are created while this
     923             :   // AutoCurrentActiveScrolledRootSetter exists. This means that the items
     924             :   // created during our lifetime will have finite bounds with respect to
     925             :   // the content clip's ASR, even if the items' actual ASR is an ancestor
     926             :   // of that. And it also means that mCurrentContainerASR only needs to be
     927             :   // set to the content clip's ASR and not all the way to aActiveScrolledRoot.
     928             :   // This case is tested by fixed-pos-scrolled-clip-opacity-layerize.html
     929             :   // and fixed-pos-scrolled-clip-opacity-inside-layerize.html.
     930             : 
     931             :   // finiteBoundsASR is the leafmost ASR that all items created during
     932             :   // object's lifetime have finite bounds with respect to.
     933           0 :   const ActiveScrolledRoot* finiteBoundsASR = ActiveScrolledRoot::PickDescendant(
     934           0 :     mContentClipASR, aActiveScrolledRoot);
     935             : 
     936             :   // mCurrentContainerASR is adjusted so that it's still an ancestor of
     937             :   // finiteBoundsASR.
     938           0 :   mBuilder->mCurrentContainerASR = ActiveScrolledRoot::PickAncestor(
     939             :     mBuilder->mCurrentContainerASR, finiteBoundsASR);
     940             : 
     941             :   // If we are entering out-of-flow content inside a CSS filter, mark
     942             :   // scroll frames wrt. which the content is fixed as containing such content.
     943           0 :   if (mBuilder->mFilterASR &&
     944           0 :       ActiveScrolledRoot::IsAncestor(aActiveScrolledRoot, mBuilder->mFilterASR)) {
     945           0 :     for (const ActiveScrolledRoot* asr = mBuilder->mFilterASR;
     946           0 :          asr && asr != aActiveScrolledRoot;
     947           0 :          asr = asr->mParent) {
     948           0 :       asr->mScrollableFrame->SetHasOutOfFlowContentInsideFilter();
     949             :     }
     950             :   }
     951             : 
     952           0 :   mUsed = true;
     953           0 : }
     954             : 
     955             : void
     956           0 : nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter::InsertScrollFrame(nsIScrollableFrame* aScrollableFrame)
     957             : {
     958           0 :   MOZ_ASSERT(!mUsed);
     959           0 :   size_t descendantsEndIndex = mBuilder->mActiveScrolledRoots.Length();
     960           0 :   const ActiveScrolledRoot* parentASR = mBuilder->mCurrentActiveScrolledRoot;
     961           0 :   const ActiveScrolledRoot* asr = mBuilder->AllocateActiveScrolledRoot(parentASR, aScrollableFrame);
     962           0 :   mBuilder->mCurrentActiveScrolledRoot = asr;
     963             : 
     964             :   // All child ASRs of parentASR that were created while this
     965             :   // AutoCurrentActiveScrolledRootSetter object was on the stack belong to us
     966             :   // now. Reparent them to asr.
     967           0 :   for (size_t i = mDescendantsStartIndex; i < descendantsEndIndex; i++) {
     968           0 :     ActiveScrolledRoot* descendantASR = mBuilder->mActiveScrolledRoots[i];
     969           0 :     if (ActiveScrolledRoot::IsAncestor(parentASR, descendantASR)) {
     970             :       descendantASR->IncrementDepth();
     971           0 :       if (descendantASR->mParent == parentASR) {
     972           0 :         descendantASR->mParent = asr;
     973             :       }
     974             :     }
     975             :   }
     976             : 
     977           0 :   mUsed = true;
     978           0 : }
     979             : 
     980           0 : nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
     981           0 :     nsDisplayListBuilderMode aMode, bool aBuildCaret, bool aRetainingDisplayList)
     982             :     : mReferenceFrame(aReferenceFrame),
     983             :       mIgnoreScrollFrame(nullptr),
     984             :       mCompositorHitTestInfo(nullptr),
     985             :       mCurrentTableItem(nullptr),
     986             :       mCurrentActiveScrolledRoot(nullptr),
     987             :       mCurrentContainerASR(nullptr),
     988             :       mCurrentFrame(aReferenceFrame),
     989             :       mCurrentReferenceFrame(aReferenceFrame),
     990          38 :       mRootAGR(AnimatedGeometryRoot::CreateAGRForFrame(aReferenceFrame, nullptr, true, aRetainingDisplayList)),
     991             :       mCurrentAGR(mRootAGR),
     992             :       mUsedAGRBudget(0),
     993             :       mDirtyRect(-1,-1,-1,-1),
     994             :       mGlassDisplayItem(nullptr),
     995             :       mScrollInfoItemsForHoisting(nullptr),
     996             :       mActiveScrolledRootForRootScrollframe(nullptr),
     997             :       mMode(aMode),
     998             :       mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
     999             :       mCurrentScrollbarTarget(FrameMetrics::NULL_SCROLL_ID),
    1000             :       mSVGEffectsBuildingDepth(0),
    1001             :       mFilterASR(nullptr),
    1002             :       mContainsBlendMode(false),
    1003             :       mIsBuildingScrollbar(false),
    1004             :       mCurrentScrollbarWillHaveLayer(false),
    1005             :       mBuildCaret(aBuildCaret),
    1006             :       mRetainingDisplayList(aRetainingDisplayList),
    1007             :       mPartialUpdate(false),
    1008             :       mIgnoreSuppression(false),
    1009             :       mIsAtRootOfPseudoStackingContext(false),
    1010             :       mIncludeAllOutOfFlows(false),
    1011             :       mDescendIntoSubdocuments(true),
    1012             :       mSelectedFramesOnly(false),
    1013             :       mAllowMergingAndFlattening(true),
    1014             :       mWillComputePluginGeometry(false),
    1015             :       mInTransform(false),
    1016             :       mInPageSequence(false),
    1017             :       mIsInChromePresContext(false),
    1018             :       mSyncDecodeImages(false),
    1019             :       mIsPaintingToWindow(false),
    1020             :       mIsCompositingCheap(false),
    1021             :       mContainsPluginItem(false),
    1022             :       mAncestorHasApzAwareEventHandler(false),
    1023             :       mHaveScrollableDisplayPort(false),
    1024             :       mWindowDraggingAllowed(false),
    1025          19 :       mIsBuildingForPopup(nsLayoutUtils::IsPopup(aReferenceFrame)),
    1026             :       mForceLayerForScrollParent(false),
    1027          19 :       mAsyncPanZoomEnabled(nsLayoutUtils::AsyncPanZoomEnabled(aReferenceFrame)),
    1028             :       mBuildingInvisibleItems(false),
    1029             :       mHitTestIsForVisibility(false),
    1030             :       mIsBuilding(false),
    1031             :       mInInvalidSubtree(false),
    1032             :       mDisablePartialUpdates(false),
    1033         437 :       mPartialBuildFailed(false)
    1034             : {
    1035          19 :   MOZ_COUNT_CTOR(nsDisplayListBuilder);
    1036             : 
    1037          19 :   mBuildCompositorHitTestInfo = mAsyncPanZoomEnabled && IsForPainting();
    1038             : 
    1039           0 :   mLessEventRegionItems = gfxPrefs::LessEventRegionItems();
    1040             : 
    1041           0 :   nsPresContext* pc = aReferenceFrame->PresContext();
    1042           0 :   nsIPresShell *shell = pc->PresShell();
    1043          19 :   if (pc->IsRenderingOnlySelection()) {
    1044           0 :     nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell));
    1045           0 :     if (selcon) {
    1046             :       mBoundingSelection =
    1047           0 :         selcon->GetSelection(nsISelectionController::SELECTION_NORMAL);
    1048             :     }
    1049             :   }
    1050             : 
    1051             :   static_assert(static_cast<uint32_t>(DisplayItemType::TYPE_MAX) < (1 << TYPE_BITS),
    1052             :                 "Check TYPE_MAX should not overflow");
    1053          19 : }
    1054             : 
    1055             : void
    1056          19 : nsDisplayListBuilder::BeginFrame()
    1057             : {
    1058           0 :   nsCSSRendering::BeginFrameTreesLocked();
    1059          19 :   mCurrentAGR = mRootAGR;
    1060          19 :   mFrameToAnimatedGeometryRootMap.Put(mReferenceFrame, mRootAGR);
    1061             : 
    1062          19 :   mIsPaintingToWindow = false;
    1063           0 :   mIgnoreSuppression = false;
    1064           0 :   mInTransform = false;
    1065           0 :   mSyncDecodeImages = false;
    1066          19 : }
    1067             : 
    1068             : void
    1069           0 : nsDisplayListBuilder::EndFrame()
    1070             : {
    1071           0 :   NS_ASSERTION(!mInInvalidSubtree, "Someone forgot to cleanup mInInvalidSubtree!");
    1072          38 :   mFrameToAnimatedGeometryRootMap.Clear();
    1073          19 :   mActiveScrolledRoots.Clear();
    1074           0 :   FreeClipChains();
    1075          19 :   FreeTemporaryItems();
    1076           0 :   nsCSSRendering::EndFrameTreesLocked();
    1077             : 
    1078           0 :   MOZ_ASSERT(!mCompositorHitTestInfo);
    1079           0 : }
    1080             : 
    1081             : void
    1082          23 : nsDisplayListBuilder::MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
    1083             : {
    1084           0 :   mFramesMarkedForDisplay.AppendElement(aFrame);
    1085           0 :   for (nsIFrame* f = aFrame; f;
    1086             :        f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
    1087         442 :     if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
    1088             :       return;
    1089         211 :     f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
    1090           0 :     if (f == aStopAtFrame) {
    1091             :       // we've reached a frame that we know will be painted, so we can stop.
    1092             :       break;
    1093             :     }
    1094             :   }
    1095             : }
    1096             : 
    1097             : void
    1098           0 : nsDisplayListBuilder::AddFrameMarkedForDisplayIfVisible(nsIFrame* aFrame)
    1099             : {
    1100           0 :   mFramesMarkedForDisplayIfVisible.AppendElement(aFrame);
    1101           0 : }
    1102             : 
    1103             : void
    1104           0 : nsDisplayListBuilder::MarkFrameForDisplayIfVisible(nsIFrame* aFrame, nsIFrame* aStopAtFrame)
    1105             : {
    1106           0 :   AddFrameMarkedForDisplayIfVisible(aFrame);
    1107           0 :   for (nsIFrame* f = aFrame; f;
    1108             :        f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
    1109           0 :     if (f->ForceDescendIntoIfVisible())
    1110             :       return;
    1111           0 :     f->SetForceDescendIntoIfVisible(true);
    1112           0 :     if (f == aStopAtFrame) {
    1113             :       // we've reached a frame that we know will be painted, so we can stop.
    1114             :       break;
    1115             :     }
    1116             :   }
    1117             : }
    1118             : 
    1119         767 : bool nsDisplayListBuilder::NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem)
    1120             : {
    1121         767 :   return aItem == mGlassDisplayItem || aItem->ClearsBackground();
    1122             : }
    1123             : 
    1124             : AnimatedGeometryRoot*
    1125           0 : nsDisplayListBuilder::WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
    1126             :                                       bool aIsAsync,
    1127             :                                       AnimatedGeometryRoot* aParent /* = nullptr */)
    1128             : {
    1129          32 :   DebugOnly<bool> dummy;
    1130          16 :   MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot, dummy) == AGR_YES);
    1131             : 
    1132          32 :   RefPtr<AnimatedGeometryRoot> result;
    1133          16 :   if (!mFrameToAnimatedGeometryRootMap.Get(aAnimatedGeometryRoot, &result)) {
    1134           0 :     MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(RootReferenceFrame(), aAnimatedGeometryRoot));
    1135           0 :     RefPtr<AnimatedGeometryRoot> parent = aParent;
    1136           0 :     if (!parent) {
    1137           0 :       nsIFrame* parentFrame = nsLayoutUtils::GetCrossDocParentFrame(aAnimatedGeometryRoot);
    1138           0 :       if (parentFrame) {
    1139             :         bool isAsync;
    1140           0 :         nsIFrame* parentAGRFrame = FindAnimatedGeometryRootFrameFor(parentFrame, isAsync);
    1141           0 :         parent = WrapAGRForFrame(parentAGRFrame, isAsync);
    1142             :       }
    1143             :     }
    1144           0 :     result = AnimatedGeometryRoot::CreateAGRForFrame(aAnimatedGeometryRoot, parent, aIsAsync, IsRetainingDisplayList());
    1145           0 :     mFrameToAnimatedGeometryRootMap.Put(aAnimatedGeometryRoot, result);
    1146             :   }
    1147           0 :   MOZ_ASSERT(!aParent || result->mParentAGR == aParent);
    1148          32 :   return result;
    1149             : }
    1150             : 
    1151             : AnimatedGeometryRoot*
    1152           0 : nsDisplayListBuilder::AnimatedGeometryRootForASR(const ActiveScrolledRoot* aASR)
    1153             : {
    1154           0 :   if (!aASR) {
    1155           0 :     return GetRootAnimatedGeometryRoot();
    1156             :   }
    1157           0 :   nsIFrame* scrolledFrame = aASR->mScrollableFrame->GetScrolledFrame();
    1158           0 :   return FindAnimatedGeometryRootFor(scrolledFrame);
    1159             : }
    1160             : 
    1161             : AnimatedGeometryRoot*
    1162         562 : nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsIFrame* aFrame)
    1163             : {
    1164           0 :   if (!IsPaintingToWindow()) {
    1165         114 :     return mRootAGR;
    1166             :   }
    1167         505 :   if (aFrame == mCurrentFrame) {
    1168           0 :     return mCurrentAGR;
    1169             :   }
    1170           0 :   RefPtr<AnimatedGeometryRoot> result;
    1171           0 :   if (mFrameToAnimatedGeometryRootMap.Get(aFrame, &result)) {
    1172           0 :     return result;
    1173             :   }
    1174             : 
    1175             :   bool isAsync;
    1176           0 :   nsIFrame* agrFrame = FindAnimatedGeometryRootFrameFor(aFrame, isAsync);
    1177           0 :   result = WrapAGRForFrame(agrFrame, isAsync);
    1178           0 :   mFrameToAnimatedGeometryRootMap.Put(aFrame, result);
    1179          16 :   return result;
    1180             : }
    1181             : 
    1182             : AnimatedGeometryRoot*
    1183           0 : nsDisplayListBuilder::FindAnimatedGeometryRootFor(nsDisplayItem* aItem)
    1184             : {
    1185           0 :   if (aItem->ShouldFixToViewport(this)) {
    1186             :     // Make its active scrolled root be the active scrolled root of
    1187             :     // the enclosing viewport, since it shouldn't be scrolled by scrolled
    1188             :     // frames in its document. InvalidateFixedBackgroundFramesFromList in
    1189             :     // nsGfxScrollFrame will not repaint this item when scrolling occurs.
    1190           0 :     nsIFrame* viewportFrame = nsLayoutUtils::GetClosestFrameOfType(
    1191           0 :       aItem->Frame(), LayoutFrameType::Viewport, RootReferenceFrame());
    1192           0 :     if (viewportFrame) {
    1193           0 :       return FindAnimatedGeometryRootFor(viewportFrame);
    1194             :     }
    1195             :   }
    1196           0 :   return FindAnimatedGeometryRootFor(aItem->Frame());
    1197             : }
    1198             : 
    1199           0 : bool nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
    1200             :                                                         nsIFrame* aFrame)
    1201             : {
    1202           1 :   MOZ_ASSERT(aFrame->GetParent() == aDirtyFrame);
    1203          36 :   nsRect dirty;
    1204             :   nsRect visible =
    1205             :     OutOfFlowDisplayData::ComputeVisibleRectForFrame(this, aFrame, GetVisibleRect(),
    1206          54 :                                                      GetDirtyRect(), &dirty);
    1207          54 :   if (!(aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) &&
    1208           0 :       visible.IsEmpty()) {
    1209             :     return false;
    1210             :   }
    1211             : 
    1212             :   // Only MarkFrameForDisplay if we're dirty. If this is a nested out-of-flow frame, then it will
    1213             :   // also mark any outer frames to ensure that building reaches the dirty feame.
    1214           0 :   if (!dirty.IsEmpty() ||
    1215           0 :       aFrame->ForceDescendIntoIfVisible()) {
    1216          18 :     MarkFrameForDisplay(aFrame, aDirtyFrame);
    1217             :   }
    1218             : 
    1219             :   return true;
    1220             : }
    1221             : 
    1222           0 : static void UnmarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
    1223         226 :   for (nsIFrame* f = aFrame; f;
    1224             :        f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
    1225         452 :     if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
    1226             :       return;
    1227         211 :     f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
    1228           0 :     if (f == aStopAtFrame) {
    1229             :       // we've reached a frame that we know will be painted, so we can stop.
    1230             :       break;
    1231             :     }
    1232             :   }
    1233             : }
    1234             : 
    1235           0 : static void UnmarkFrameForDisplayIfVisible(nsIFrame* aFrame) {
    1236           0 :   for (nsIFrame* f = aFrame; f;
    1237             :        f = nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(f)) {
    1238           0 :     if (!f->ForceDescendIntoIfVisible())
    1239             :       return;
    1240           0 :     f->SetForceDescendIntoIfVisible(false);
    1241             :   }
    1242             : }
    1243             : 
    1244           0 : nsDisplayListBuilder::~nsDisplayListBuilder() {
    1245          38 :   NS_ASSERTION(mFramesMarkedForDisplay.Length() == 0,
    1246             :                "All frames should have been unmarked");
    1247          38 :   NS_ASSERTION(mFramesWithOOFData.Length() == 0,
    1248             :                "All OOF data should have been removed");
    1249          38 :   NS_ASSERTION(mPresShellStates.Length() == 0,
    1250             :                "All presshells should have been exited");
    1251           0 :   NS_ASSERTION(!mCurrentTableItem, "No table item should be active");
    1252             : 
    1253           0 :   for (DisplayItemClipChain* c : mClipChainsToDestroy) {
    1254           0 :     c->DisplayItemClipChain::~DisplayItemClipChain();
    1255             :   }
    1256             : 
    1257           0 :   MOZ_COUNT_DTOR(nsDisplayListBuilder);
    1258          19 : }
    1259             : 
    1260             : uint32_t
    1261          48 : nsDisplayListBuilder::GetBackgroundPaintFlags() {
    1262          48 :   uint32_t flags = 0;
    1263           0 :   if (mSyncDecodeImages) {
    1264           0 :     flags |= nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES;
    1265             :   }
    1266          48 :   if (mIsPaintingToWindow) {
    1267           0 :     flags |= nsCSSRendering::PAINTBG_TO_WINDOW;
    1268             :   }
    1269           0 :   return flags;
    1270             : }
    1271             : 
    1272             : void
    1273           0 : nsDisplayListBuilder::SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
    1274             :                                                 const nsRegion& aRegion)
    1275             : {
    1276         103 :   if (aRegion.IsEmpty())
    1277          90 :     return;
    1278             : 
    1279           0 :   nsRegion tmp;
    1280          13 :   tmp.Sub(*aVisibleRegion, aRegion);
    1281             :   // Don't let *aVisibleRegion get too complex, but don't let it fluff out
    1282             :   // to its bounds either, which can be very bad (see bug 516740).
    1283             :   // Do let aVisibleRegion get more complex if by doing so we reduce its
    1284             :   // area by at least half.
    1285           0 :   if (GetAccurateVisibleRegions() || tmp.GetNumRects() <= 15 ||
    1286           0 :       tmp.Area() <= aVisibleRegion->Area()/2) {
    1287             :     *aVisibleRegion = tmp;
    1288             :   }
    1289             : }
    1290             : 
    1291             : nsCaret *
    1292           0 : nsDisplayListBuilder::GetCaret() {
    1293          15 :   RefPtr<nsCaret> caret = CurrentPresShellState()->mPresShell->GetCaret();
    1294          10 :   return caret;
    1295             : }
    1296             : 
    1297             : void
    1298           0 : nsDisplayListBuilder::IncrementPresShellPaintCount(nsIPresShell* aPresShell)
    1299             : {
    1300           0 :   if (mIsPaintingToWindow) {
    1301           8 :     mReferenceFrame->AddPaintedPresShell(aPresShell);
    1302           8 :     aPresShell->IncrementPaintCount();
    1303             :   }
    1304           0 : }
    1305             : 
    1306             : void
    1307           0 : nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
    1308             :                                      bool aPointerEventsNoneDoc)
    1309             : {
    1310           0 :   PresShellState* state = mPresShellStates.AppendElement();
    1311          19 :   state->mPresShell = aReferenceFrame->PresShell();
    1312          19 :   state->mCaretFrame = nullptr;
    1313           0 :   state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
    1314          38 :   state->mFirstFrameWithOOFData = mFramesWithOOFData.Length();
    1315             : 
    1316           0 :   nsIScrollableFrame* sf = state->mPresShell->GetRootScrollFrameAsScrollable();
    1317           0 :   if (sf && IsInSubdocument()) {
    1318             :     // We are forcing a rebuild of nsDisplayCanvasBackgroundColor to make sure
    1319             :     // that the canvas background color will be set correctly, and that only one
    1320             :     // unscrollable item will be created.
    1321             :     // This is done to avoid, for example, a case where only scrollbar frames
    1322             :     // are invalidated - we would skip creating nsDisplayCanvasBackgroundColor
    1323             :     // and possibly end up with an extra nsDisplaySolidColor item.
    1324             :     // We skip this for the root document, since we don't want to use
    1325             :     // MarkFrameForDisplayIfVisible before ComputeRebuildRegion. We'll
    1326             :     // do it manually there.
    1327           0 :     nsCanvasFrame* canvasFrame = do_QueryFrame(sf->GetScrolledFrame());
    1328           0 :     if (canvasFrame) {
    1329           0 :       MarkFrameForDisplayIfVisible(canvasFrame, aReferenceFrame);
    1330             :     }
    1331             :   }
    1332             : 
    1333             : #ifdef DEBUG
    1334           0 :   state->mAutoLayoutPhase.emplace(aReferenceFrame->PresContext(), eLayoutPhase_DisplayListBuilding);
    1335             : #endif
    1336             : 
    1337          19 :   state->mPresShell->UpdateCanvasBackground();
    1338             : 
    1339          19 :   bool buildCaret = mBuildCaret;
    1340           0 :   if (mIgnoreSuppression || !state->mPresShell->IsPaintingSuppressed()) {
    1341          19 :     state->mIsBackgroundOnly = false;
    1342             :   } else {
    1343           0 :     state->mIsBackgroundOnly = true;
    1344           0 :     buildCaret = false;
    1345             :   }
    1346             : 
    1347           0 :   bool pointerEventsNone = aPointerEventsNoneDoc;
    1348          19 :   if (IsInSubdocument()) {
    1349           0 :     pointerEventsNone |= mPresShellStates[mPresShellStates.Length() - 2].mInsidePointerEventsNoneDoc;
    1350             :   }
    1351          19 :   state->mInsidePointerEventsNoneDoc = pointerEventsNone;
    1352             : 
    1353           0 :   if (!buildCaret)
    1354           0 :     return;
    1355             : 
    1356          24 :   RefPtr<nsCaret> caret = state->mPresShell->GetCaret();
    1357           0 :   state->mCaretFrame = caret->GetPaintGeometry(&state->mCaretRect);
    1358           8 :   if (state->mCaretFrame) {
    1359           0 :     MarkFrameForDisplay(state->mCaretFrame, aReferenceFrame);
    1360             :   }
    1361             : 
    1362           0 :   nsPresContext* pc = aReferenceFrame->PresContext();
    1363           0 :   nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
    1364           0 :   if (docShell) {
    1365           0 :     docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
    1366             :   }
    1367           8 :   mIsInChromePresContext = pc->IsChrome();
    1368             : }
    1369             : 
    1370             : // A non-blank paint is a paint that does not just contain the canvas background.
    1371             : static bool
    1372           1 : DisplayListIsNonBlank(nsDisplayList* aList)
    1373             : {
    1374           1 :   for (nsDisplayItem* i = aList->GetBottom(); i != nullptr; i = i->GetAbove()) {
    1375           1 :     switch (i->GetType()) {
    1376             :       case DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO:
    1377             :       case DisplayItemType::TYPE_CANVAS_BACKGROUND_COLOR:
    1378             :       case DisplayItemType::TYPE_CANVAS_BACKGROUND_IMAGE:
    1379             :         continue;
    1380             :       case DisplayItemType::TYPE_SOLID_COLOR:
    1381             :       case DisplayItemType::TYPE_BACKGROUND:
    1382             :       case DisplayItemType::TYPE_BACKGROUND_COLOR:
    1383           1 :         if (i->Frame()->IsCanvasFrame()) {
    1384             :           continue;
    1385             :         }
    1386             :         return true;
    1387             :       default:
    1388             :         return true;
    1389             :     }
    1390             :   }
    1391             :   return false;
    1392             : }
    1393             : 
    1394             : void
    1395          19 : nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame, nsDisplayList* aPaintedContents)
    1396             : {
    1397          19 :   NS_ASSERTION(CurrentPresShellState()->mPresShell ==
    1398             :       aReferenceFrame->PresShell(),
    1399             :       "Presshell mismatch");
    1400             : 
    1401          19 :   if (mIsPaintingToWindow) {
    1402           0 :     nsPresContext* pc = aReferenceFrame->PresContext();
    1403           8 :     if (!pc->HadNonBlankPaint()) {
    1404           0 :       if (!CurrentPresShellState()->mIsBackgroundOnly &&
    1405           1 :           DisplayListIsNonBlank(aPaintedContents)) {
    1406           1 :         pc->NotifyNonBlankPaint();
    1407             :       }
    1408             :     }
    1409             :   }
    1410             : 
    1411           0 :   ResetMarkedFramesForDisplayList(aReferenceFrame);
    1412           0 :   mPresShellStates.SetLength(mPresShellStates.Length() - 1);
    1413             : 
    1414          38 :   if (!mPresShellStates.IsEmpty()) {
    1415           0 :     nsPresContext* pc = CurrentPresContext();
    1416           0 :     nsCOMPtr<nsIDocShell> docShell = pc->GetDocShell();
    1417           0 :     if (docShell) {
    1418           0 :       docShell->GetWindowDraggingAllowed(&mWindowDraggingAllowed);
    1419             :     }
    1420           0 :     mIsInChromePresContext = pc->IsChrome();
    1421             :   } else {
    1422           0 :     mCurrentAGR = mRootAGR;
    1423             : 
    1424           0 :     for (uint32_t i = 0;
    1425           0 :        i < mFramesMarkedForDisplayIfVisible.Length(); ++i) {
    1426           0 :       UnmarkFrameForDisplayIfVisible(mFramesMarkedForDisplayIfVisible[i]);
    1427             :     }
    1428          19 :     mFramesMarkedForDisplayIfVisible.SetLength(0);
    1429             :   }
    1430          19 : }
    1431             : 
    1432             : void
    1433           0 : nsDisplayListBuilder::FreeClipChains()
    1434             : {
    1435             :   // Iterate the clip chains from newest to oldest (forward
    1436             :   // iteration), so that we destroy descendants first which
    1437             :   // will drop the ref count on their ancestors.
    1438          38 :   auto it = mClipChainsToDestroy.begin();
    1439             : 
    1440           0 :   while(it != mClipChainsToDestroy.end()) {
    1441         101 :     DisplayItemClipChain* clip = *it;
    1442             : 
    1443         101 :     if (!clip->mRefCount) {
    1444         101 :       mClipDeduplicator.erase(clip);
    1445           0 :       it = mClipChainsToDestroy.erase(it);
    1446         101 :       clip->DisplayItemClipChain::~DisplayItemClipChain();
    1447           0 :       Destroy(DisplayItemType::TYPE_ZERO, clip);
    1448             :     } else {
    1449             :       ++it;
    1450             :     }
    1451             :   }
    1452           0 : }
    1453             : 
    1454             : void
    1455          19 : nsDisplayListBuilder::FreeTemporaryItems()
    1456             : {
    1457          57 :   for (nsDisplayItem* i : mTemporaryItems) {
    1458             :     // Temporary display items are not added to the frames.
    1459           0 :     MOZ_ASSERT(i->Frame());
    1460           0 :     i->RemoveFrame(i->Frame());
    1461           0 :     i->Destroy(this);
    1462             :   }
    1463             : 
    1464           0 :   mTemporaryItems.Clear();
    1465          19 : }
    1466             : 
    1467             : void
    1468           0 : nsDisplayListBuilder::ResetMarkedFramesForDisplayList(nsIFrame* aReferenceFrame)
    1469             : {
    1470             :   // Unmark and pop off the frames marked for display in this pres shell.
    1471           0 :   uint32_t firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
    1472           0 :   for (uint32_t i = firstFrameForShell;
    1473          84 :        i < mFramesMarkedForDisplay.Length(); ++i) {
    1474          46 :     UnmarkFrameForDisplay(mFramesMarkedForDisplay[i], aReferenceFrame);
    1475             :   }
    1476          19 :   mFramesMarkedForDisplay.SetLength(firstFrameForShell);
    1477             : 
    1478           0 :   firstFrameForShell = CurrentPresShellState()->mFirstFrameWithOOFData;
    1479           0 :   for (uint32_t i = firstFrameForShell; i < mFramesWithOOFData.Length(); ++i) {
    1480           0 :     mFramesWithOOFData[i]->DeleteProperty(OutOfFlowDisplayDataProperty());
    1481             :   }
    1482          19 :   mFramesWithOOFData.SetLength(firstFrameForShell);
    1483           0 : }
    1484             : 
    1485             : void
    1486           0 : nsDisplayListBuilder::ClearFixedBackgroundDisplayData()
    1487             : {
    1488           0 :   CurrentPresShellState()->mFixedBackgroundDisplayData = Nothing();
    1489           0 : }
    1490             : 
    1491             : void
    1492         116 : nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
    1493             :                                                const nsFrameList& aFrames)
    1494             : {
    1495           1 :   bool markedFrames = false;
    1496           1 :   for (nsIFrame* e : aFrames) {
    1497             :     // Skip the AccessibleCaret frame when building no caret.
    1498          18 :     if (!IsBuildingCaret()) {
    1499           0 :       nsIContent* content = e->GetContent();
    1500           0 :       if (content && content->IsInNativeAnonymousSubtree() && content->IsElement()) {
    1501           0 :         auto classList = content->AsElement()->ClassList();
    1502           0 :         if (classList->Contains(NS_LITERAL_STRING("moz-accessiblecaret"))) {
    1503             :           continue;
    1504             :         }
    1505             :       }
    1506             :     }
    1507           0 :     if (MarkOutOfFlowFrameForDisplay(aDirtyFrame, e)) {
    1508           0 :       markedFrames = true;
    1509             :     }
    1510             :   }
    1511             : 
    1512         116 :   if (markedFrames) {
    1513             :     // mClipState.GetClipChainForContainingBlockDescendants can return pointers
    1514             :     // to objects on the stack, so we need to clone the chain.
    1515             :     const DisplayItemClipChain* clipChain =
    1516          18 :       CopyWholeChain(mClipState.GetClipChainForContainingBlockDescendants());
    1517          18 :     const DisplayItemClipChain* combinedClipChain = mClipState.GetCurrentCombinedClipChain(this);
    1518          18 :     const ActiveScrolledRoot* asr = mCurrentActiveScrolledRoot;
    1519           0 :     OutOfFlowDisplayData* data = new OutOfFlowDisplayData(clipChain, combinedClipChain, asr, GetVisibleRect(), GetDirtyRect());
    1520          18 :     aDirtyFrame->SetProperty(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
    1521          18 :     mFramesWithOOFData.AppendElement(aDirtyFrame);
    1522             :   }
    1523             : 
    1524           0 :   if (!aDirtyFrame->GetParent()) {
    1525             :     // This is the viewport frame of aDirtyFrame's presshell.
    1526             :     // Store the current display data so that it can be used for fixed
    1527             :     // background images.
    1528           0 :     NS_ASSERTION(CurrentPresShellState()->mPresShell ==
    1529             :         aDirtyFrame->PresShell(),
    1530             :         "Presshell mismatch");
    1531           0 :     MOZ_ASSERT(!CurrentPresShellState()->mFixedBackgroundDisplayData,
    1532             :                "already traversed this presshell's root frame?");
    1533             : 
    1534             :     const DisplayItemClipChain* clipChain =
    1535           0 :       CopyWholeChain(mClipState.GetClipChainForContainingBlockDescendants());
    1536          19 :     const DisplayItemClipChain* combinedClipChain = mClipState.GetCurrentCombinedClipChain(this);
    1537          19 :     const ActiveScrolledRoot* asr = mCurrentActiveScrolledRoot;
    1538           0 :     CurrentPresShellState()->mFixedBackgroundDisplayData.emplace(
    1539          19 :       clipChain, combinedClipChain, asr, GetVisibleRect(), GetDirtyRect());
    1540             :   }
    1541         116 : }
    1542             : 
    1543             : /**
    1544             :  * Mark all preserve-3d children with
    1545             :  * NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO to make sure
    1546             :  * nsFrame::BuildDisplayListForChild() would visit them.  Also compute
    1547             :  * dirty rect for preserve-3d children.
    1548             :  *
    1549             :  * @param aDirtyFrame is the frame to mark children extending context.
    1550             :  */
    1551             : void
    1552           0 : nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame)
    1553             : {
    1554           0 :   AutoTArray<nsIFrame::ChildList,4> childListArray;
    1555           0 :   aDirtyFrame->GetChildLists(&childListArray);
    1556             :   nsIFrame::ChildListArrayIterator lists(childListArray);
    1557           0 :   for (; !lists.IsDone(); lists.Next()) {
    1558           0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    1559           0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    1560           0 :       nsIFrame *child = childFrames.get();
    1561           0 :       if (child->Combines3DTransformWithAncestors()) {
    1562           0 :         MarkFrameForDisplay(child, aDirtyFrame);
    1563             :       }
    1564             :     }
    1565             :   }
    1566           0 : }
    1567             : 
    1568             : uint32_t gDisplayItemSizes[static_cast<uint32_t>(DisplayItemType::TYPE_MAX)] = { 0 };
    1569             : 
    1570             : void*
    1571         775 : nsDisplayListBuilder::Allocate(size_t aSize, DisplayItemType aType)
    1572             : {
    1573           0 :   size_t roundedUpSize = RoundUpPow2(aSize);
    1574         775 :   uint_fast8_t type = FloorLog2Size(roundedUpSize);
    1575             : 
    1576         775 :   MOZ_RELEASE_ASSERT(gDisplayItemSizes[static_cast<uint32_t>(aType)] == type ||
    1577             :                      gDisplayItemSizes[static_cast<uint32_t>(aType)] == 0);
    1578           0 :   gDisplayItemSizes[static_cast<uint32_t>(aType)] = type;
    1579        1550 :   return mPool.AllocateByCustomID(type, roundedUpSize);
    1580             : }
    1581             : 
    1582             : void
    1583           0 : nsDisplayListBuilder::Destroy(DisplayItemType aType, void* aPtr)
    1584             : {
    1585           0 :   mPool.FreeByCustomID(gDisplayItemSizes[static_cast<uint32_t>(aType)], aPtr);
    1586           0 : }
    1587             : 
    1588             : ActiveScrolledRoot*
    1589           0 : nsDisplayListBuilder::AllocateActiveScrolledRoot(const ActiveScrolledRoot* aParent,
    1590             :                                                  nsIScrollableFrame* aScrollableFrame)
    1591             : {
    1592           0 :   RefPtr<ActiveScrolledRoot> asr = ActiveScrolledRoot::CreateASRForFrame(aParent, aScrollableFrame, IsRetainingDisplayList());
    1593           0 :   mActiveScrolledRoots.AppendElement(asr);
    1594           0 :   return asr;
    1595             : }
    1596             : 
    1597             : const DisplayItemClipChain*
    1598         240 : nsDisplayListBuilder::AllocateDisplayItemClipChain(const DisplayItemClip& aClip,
    1599             :                                                    const ActiveScrolledRoot* aASR,
    1600             :                                                    const DisplayItemClipChain* aParent)
    1601             : {
    1602         240 :   MOZ_ASSERT(!(aParent && aParent->mOnStack));
    1603         240 :   void* p = Allocate(sizeof(DisplayItemClipChain), DisplayItemType::TYPE_ZERO);
    1604         240 :   DisplayItemClipChain* c = new (KnownNotNull, p) DisplayItemClipChain(aClip, aASR, aParent);
    1605             : #ifdef DEBUG
    1606         240 :   c->mOnStack = false;
    1607             : #endif
    1608         240 :   auto result = mClipDeduplicator.insert(c);
    1609           0 :   if (!result.second) {
    1610             :     // An equivalent clip chain item was already created, so let's return that
    1611             :     // instead. Destroy the one we just created.
    1612             :     // Note that this can cause clip chains from different coordinate systems to
    1613             :     // collapse into the same clip chain object, because clip chains do not keep
    1614             :     // track of the reference frame that they were created in.
    1615           0 :     c->DisplayItemClipChain::~DisplayItemClipChain();
    1616           0 :     Destroy(DisplayItemType::TYPE_ZERO, c);
    1617         139 :     return *(result.first);
    1618             :   }
    1619         101 :   mClipChainsToDestroy.emplace_front(c);
    1620         101 :   return c;
    1621             : }
    1622             : 
    1623           0 : struct ClipChainItem {
    1624             :   DisplayItemClip clip;
    1625             :   const ActiveScrolledRoot* asr;
    1626             : };
    1627             : 
    1628             : const DisplayItemClipChain*
    1629         256 : nsDisplayListBuilder::CreateClipChainIntersection(const DisplayItemClipChain* aAncestor,
    1630             :                                                   const DisplayItemClipChain* aLeafClip1,
    1631             :                                                   const DisplayItemClipChain* aLeafClip2)
    1632             : {
    1633         512 :   AutoTArray<ClipChainItem,8> intersectedClips;
    1634             : 
    1635         256 :   const DisplayItemClipChain* clip1 = aLeafClip1;
    1636           0 :   const DisplayItemClipChain* clip2 = aLeafClip2;
    1637             : 
    1638             :   const ActiveScrolledRoot* asr =
    1639         256 :     ActiveScrolledRoot::PickDescendant(clip1 ? clip1->mASR : nullptr,
    1640           0 :                                        clip2 ? clip2->mASR : nullptr);
    1641             : 
    1642             :   // Build up the intersection from the leaf to the root and put it into
    1643             :   // intersectedClips. The loop below will convert intersectedClips into an
    1644             :   // actual DisplayItemClipChain.
    1645             :   // (We need to do this in two passes because we need the parent clip in order
    1646             :   // to create the DisplayItemClipChain object, but the parent clip has not
    1647             :   // been created at that point.)
    1648         256 :   while (!aAncestor || asr != aAncestor->mASR) {
    1649         256 :     if (clip1 && clip1->mASR == asr) {
    1650          42 :       if (clip2 && clip2->mASR == asr) {
    1651          64 :         DisplayItemClip intersection = clip1->mClip;
    1652          32 :         intersection.IntersectWith(clip2->mClip);
    1653          64 :         intersectedClips.AppendElement(ClipChainItem{ intersection, asr });
    1654          96 :         clip2 = clip2->mParent;
    1655             :       } else {
    1656           0 :         intersectedClips.AppendElement(ClipChainItem{ clip1->mClip, asr });
    1657             :       }
    1658           0 :       clip1 = clip1->mParent;
    1659           0 :     } else if (clip2 && clip2->mASR == asr) {
    1660           0 :       intersectedClips.AppendElement(ClipChainItem{ clip2->mClip, asr });
    1661           0 :       clip2 = clip2->mParent;
    1662             :     }
    1663           0 :     if (!asr) {
    1664         256 :       MOZ_ASSERT(!aAncestor, "We should have exited this loop earlier");
    1665             :       break;
    1666             :     }
    1667           0 :     asr = asr->mParent;
    1668             :   }
    1669             : 
    1670             :   // Convert intersectedClips into a DisplayItemClipChain.
    1671           0 :   const DisplayItemClipChain* parentSC = aAncestor;
    1672         997 :   for (auto& sc : Reversed(intersectedClips)) {
    1673         229 :     parentSC = AllocateDisplayItemClipChain(sc.clip, sc.asr, parentSC);
    1674             :   }
    1675         512 :   return parentSC;
    1676             : }
    1677             : 
    1678             : const DisplayItemClipChain*
    1679           0 : nsDisplayListBuilder::CopyWholeChain(const DisplayItemClipChain* aClipChain)
    1680             : {
    1681          37 :   return CreateClipChainIntersection(nullptr, aClipChain, nullptr);
    1682             : }
    1683             : 
    1684             : const nsIFrame*
    1685        1900 : nsDisplayListBuilder::FindReferenceFrameFor(const nsIFrame *aFrame,
    1686             :                                             nsPoint* aOffset) const
    1687             : {
    1688           0 :   if (aFrame == mCurrentFrame) {
    1689        1819 :     if (aOffset) {
    1690        1688 :       *aOffset = mCurrentOffsetToReferenceFrame;
    1691             :     }
    1692           0 :     return mCurrentReferenceFrame;
    1693             :   }
    1694         577 :   for (const nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f))
    1695             :   {
    1696           0 :     if (f == mReferenceFrame || f->IsTransformed()) {
    1697           0 :       if (aOffset) {
    1698          70 :         *aOffset = aFrame->GetOffsetToCrossDoc(f);
    1699             :       }
    1700             :       return f;
    1701             :     }
    1702             :   }
    1703           0 :   if (aOffset) {
    1704           0 :     *aOffset = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
    1705             :   }
    1706           0 :   return mReferenceFrame;
    1707             : }
    1708             : 
    1709             : // Sticky frames are active if their nearest scrollable frame is also active.
    1710             : static bool
    1711           0 : IsStickyFrameActive(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame* aParent)
    1712             : {
    1713           0 :   MOZ_ASSERT(aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY);
    1714             : 
    1715             :   // Find the nearest scrollframe.
    1716           0 :   nsIFrame* cursor = aFrame;
    1717           0 :   nsIFrame* parent = aParent;
    1718           0 :   if (!parent) {
    1719           0 :     parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
    1720             :   }
    1721           0 :   while (!parent->IsScrollFrame()) {
    1722           0 :     cursor = parent;
    1723           0 :     if ((parent = nsLayoutUtils::GetCrossDocParentFrame(cursor)) == nullptr) {
    1724             :       return false;
    1725             :     }
    1726             :   }
    1727             : 
    1728           0 :   nsIScrollableFrame* sf = do_QueryFrame(parent);
    1729           0 :   return sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == cursor;
    1730             : }
    1731             : 
    1732             : nsDisplayListBuilder::AGRState
    1733         947 : nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame,
    1734             :                                              bool& aIsAsync,
    1735             :                                              nsIFrame** aParent)
    1736             : {
    1737         947 :   aIsAsync = false;
    1738         947 :   if (aFrame == mReferenceFrame) {
    1739          54 :     aIsAsync = true;
    1740           0 :     return AGR_YES;
    1741             :   }
    1742         893 :   if (!IsPaintingToWindow()) {
    1743          79 :     if (aParent) {
    1744           0 :       *aParent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
    1745             :     }
    1746             :     return AGR_NO;
    1747             :   }
    1748             : 
    1749           0 :   nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
    1750           0 :   if (!parent) {
    1751           0 :     aIsAsync = true;
    1752           0 :     return AGR_YES;
    1753             :   }
    1754             : 
    1755         814 :   AGRState result = AGR_NO; // Possible to transition from not being an AGR
    1756             :                             // to being an AGR without a style change.
    1757             : 
    1758           1 :   LayoutFrameType parentType = parent->Type();
    1759             : 
    1760         814 :   if (aFrame->IsTransformed()) {
    1761           0 :     aIsAsync = EffectCompositor::HasAnimationsForCompositor(aFrame, eCSSProperty_transform);
    1762           0 :     result = AGR_YES;
    1763             :   }
    1764             : 
    1765           0 :   if (parentType == LayoutFrameType::Scroll ||
    1766         814 :       parentType == LayoutFrameType::ListControl) {
    1767           0 :     nsIScrollableFrame* sf = do_QueryFrame(parent);
    1768           0 :     if (sf->GetScrolledFrame() == aFrame) {
    1769           0 :       if (sf->IsScrollingActive(this)) {
    1770           0 :         aIsAsync = aIsAsync || sf->IsMaybeAsynchronouslyScrolled();
    1771           0 :         result = AGR_YES;
    1772             :       } else {
    1773             :         result = AGR_MAYBE;
    1774             :       }
    1775             :     }
    1776             :   }
    1777             : 
    1778             :   // Finished checking all conditions that might set aIsAsync, so we can
    1779             :   // early return now.
    1780         814 :   if (result == AGR_YES) {
    1781             :     return result;
    1782             :   }
    1783             : 
    1784         814 :   if (nsLayoutUtils::IsPopup(aFrame))
    1785             :     return AGR_YES;
    1786         814 :   if (ActiveLayerTracker::IsOffsetStyleAnimated(aFrame)) {
    1787           0 :     const bool inBudget = AddToAGRBudget(aFrame);
    1788           0 :     if (inBudget) {
    1789             :       return AGR_YES;
    1790             :     }
    1791             :   }
    1792         814 :   if (!aFrame->GetParent() &&
    1793           0 :       nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext())) {
    1794             :     // Viewport frames in a display port need to be animated geometry roots
    1795             :     // for background-attachment:fixed elements.
    1796             :     return AGR_YES;
    1797             :   }
    1798             : 
    1799             : 
    1800             :   // Treat the slider thumb as being as an active scrolled root when it wants
    1801             :   // its own layer so that it can move without repainting.
    1802         814 :   if (parentType == LayoutFrameType::Slider) {
    1803           0 :     nsIScrollableFrame* sf = static_cast<nsSliderFrame*>(parent)->GetScrollFrame();
    1804             :     // The word "Maybe" in IsMaybeScrollingActive might be confusing but we do
    1805             :     // indeed need to always consider scroll thumbs as AGRs if
    1806             :     // IsMaybeScrollingActive is true because that is the same condition we use
    1807             :     // in ScrollFrameHelper::AppendScrollPartsTo to layerize scroll thumbs.
    1808           0 :     if (sf && sf->IsMaybeScrollingActive()) {
    1809             :       return AGR_YES;
    1810             :     }
    1811             :     result = AGR_MAYBE;
    1812             :   }
    1813             : 
    1814         814 :   if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
    1815           0 :     if (IsStickyFrameActive(this, aFrame, parent)) {
    1816             :       return AGR_YES;
    1817             :     }
    1818             :     result = AGR_MAYBE;
    1819             :   }
    1820             : 
    1821             : 
    1822             :   // Fixed-pos frames are parented by the viewport frame, which has no parent.
    1823         814 :   if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) {
    1824             :     return AGR_YES;
    1825             :   }
    1826             : 
    1827        1628 :   if ((aFrame->GetStateBits() & NS_FRAME_MAY_BE_TRANSFORMED) &&
    1828           0 :       aFrame->IsFrameOfType(nsIFrame::eSVG)) {
    1829             :     // For SVG containers, they always have
    1830             :     // NS_FRAME_MAY_BE_TRANSFORMED bit.  However, they would be
    1831             :     // affected by the fragement identifiers in the svgView form at
    1832             :     // runtime without a new ComputedStyle.
    1833             :     // For example, layout/reftests/svg/fragmentIdentifier-01.xhtml
    1834             :     //
    1835             :     // see https://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers
    1836           0 :     result = AGR_MAYBE;
    1837             :   }
    1838             : 
    1839         814 :   if (aParent) {
    1840          48 :     *aParent = parent;
    1841             :   }
    1842             :   return result;
    1843             : }
    1844             : 
    1845             : nsIFrame*
    1846           0 : nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame, bool& aIsAsync)
    1847             : {
    1848          16 :   MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(RootReferenceFrame(), aFrame));
    1849             :   nsIFrame* cursor = aFrame;
    1850         112 :   while (cursor != RootReferenceFrame()) {
    1851             :     nsIFrame* next;
    1852          48 :     if (IsAnimatedGeometryRoot(cursor, aIsAsync, &next) == AGR_YES)
    1853           0 :       return cursor;
    1854          48 :     cursor = next;
    1855             :   }
    1856             :   // Root frame is always an async agr.
    1857           0 :   aIsAsync = true;
    1858          16 :   return cursor;
    1859             : }
    1860             : 
    1861             : void
    1862           0 : nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot()
    1863             : {
    1864             :   bool isAsync;
    1865           0 :   if (*mCurrentAGR != mCurrentFrame &&
    1866           0 :       IsAnimatedGeometryRoot(const_cast<nsIFrame*>(mCurrentFrame), isAsync) == AGR_YES) {
    1867           0 :     AnimatedGeometryRoot* oldAGR = mCurrentAGR;
    1868           0 :     mCurrentAGR = WrapAGRForFrame(const_cast<nsIFrame*>(mCurrentFrame), isAsync, mCurrentAGR);
    1869             : 
    1870             :     // Iterate the AGR cache and look for any objects that reference the old AGR and check
    1871             :     // to see if they need to be updated. AGRs can be in the cache multiple times, so we may
    1872             :     // end up doing the work multiple times for AGRs that don't change.
    1873           0 :     for (auto iter = mFrameToAnimatedGeometryRootMap.Iter(); !iter.Done(); iter.Next()) {
    1874           0 :       RefPtr<AnimatedGeometryRoot> cached = iter.UserData();
    1875           0 :       if (cached->mParentAGR == oldAGR && cached != mCurrentAGR) {
    1876             :         // It's possible that this cached AGR struct that has the old AGR as a parent
    1877             :         // should instead have mCurrentFrame has a parent.
    1878           0 :         nsIFrame* parent = FindAnimatedGeometryRootFrameFor(*cached, isAsync);
    1879           0 :         MOZ_ASSERT(parent == mCurrentFrame || parent == *oldAGR);
    1880           0 :         if (parent == mCurrentFrame) {
    1881           0 :           cached->mParentAGR = mCurrentAGR;
    1882             :         }
    1883             :       }
    1884             :     }
    1885             :   }
    1886           0 : }
    1887             : 
    1888             : static nsRect
    1889         104 : ApplyAllClipNonRoundedIntersection(const DisplayItemClipChain* aClipChain, const nsRect& aRect)
    1890             : {
    1891         104 :   nsRect result = aRect;
    1892         312 :   while (aClipChain) {
    1893           0 :     result = aClipChain->mClip.ApplyNonRoundedIntersection(result);
    1894         208 :     aClipChain = aClipChain->mParent;
    1895             :   }
    1896           0 :   return result;
    1897             : }
    1898             : 
    1899             : void
    1900           0 : nsDisplayListBuilder::AdjustWindowDraggingRegion(nsIFrame* aFrame)
    1901             : {
    1902         688 :   if (!mWindowDraggingAllowed || !IsForPainting()) {
    1903           0 :     return;
    1904             :   }
    1905             : 
    1906         620 :   const nsStyleUIReset* styleUI = aFrame->StyleUIReset();
    1907           0 :   if (styleUI->mWindowDragging == StyleWindowDragging::Default) {
    1908             :     // This frame has the default value and doesn't influence the window
    1909             :     // dragging region.
    1910             :     return;
    1911             :   }
    1912             : 
    1913           0 :   LayoutDeviceToLayoutDeviceMatrix4x4 referenceFrameToRootReferenceFrame;
    1914             : 
    1915             :   // The const_cast is for nsLayoutUtils::GetTransformToAncestor.
    1916         104 :   nsIFrame* referenceFrame = const_cast<nsIFrame*>(FindReferenceFrameFor(aFrame));
    1917             : 
    1918         104 :   if (IsInTransform()) {
    1919             :     // Only support 2d rectilinear transforms. Transform support is needed for
    1920             :     // the horizontal flip transform that's applied to the urlbar textbox in
    1921             :     // RTL mode - it should be able to exclude itself from the draggable region.
    1922           0 :     referenceFrameToRootReferenceFrame =
    1923           0 :       ViewAs<LayoutDeviceToLayoutDeviceMatrix4x4>(
    1924           0 :           nsLayoutUtils::GetTransformToAncestor(referenceFrame, mReferenceFrame).GetMatrix());
    1925           0 :     Matrix referenceFrameToRootReferenceFrame2d;
    1926           0 :     if (!referenceFrameToRootReferenceFrame.Is2D(&referenceFrameToRootReferenceFrame2d) ||
    1927           0 :         !referenceFrameToRootReferenceFrame2d.IsRectilinear()) {
    1928           0 :       return;
    1929             :     }
    1930             :   } else {
    1931           0 :     MOZ_ASSERT(referenceFrame == mReferenceFrame,
    1932             :                "referenceFrameToRootReferenceFrame needs to be adjusted");
    1933             :   }
    1934             : 
    1935             :   // We do some basic visibility checking on the frame's border box here.
    1936             :   // We intersect it both with the current dirty rect and with the current
    1937             :   // clip. Either one is just a conservative approximation on its own, but
    1938             :   // their intersection luckily works well enough for our purposes, so that
    1939             :   // we don't have to do full-blown visibility computations.
    1940             :   // The most important case we need to handle is the scrolled-off tab:
    1941             :   // If the tab bar overflows, tab parts that are clipped by the scrollbox
    1942             :   // should not be allowed to interfere with the window dragging region. Using
    1943             :   // just the current DisplayItemClip is not enough to cover this case
    1944             :   // completely because clips are reset while building stacking context
    1945             :   // contents, so for example we'd fail to clip frames that have a clip path
    1946             :   // applied to them. But the current dirty rect doesn't get reset in that
    1947             :   // case, so we use it to make this case work.
    1948         104 :   nsRect borderBox = aFrame->GetRectRelativeToSelf().Intersect(mVisibleRect);
    1949         208 :   borderBox += ToReferenceFrame(aFrame);
    1950         104 :   const DisplayItemClipChain* clip = ClipState().GetCurrentCombinedClipChain(this);
    1951         104 :   borderBox = ApplyAllClipNonRoundedIntersection(clip, borderBox);
    1952         208 :   if (borderBox.IsEmpty()) {
    1953         104 :     return;
    1954             :   }
    1955             : 
    1956             :   LayoutDeviceRect devPixelBorderBox =
    1957           0 :     LayoutDevicePixel::FromAppUnits(borderBox, aFrame->PresContext()->AppUnitsPerDevPixel());
    1958             : 
    1959             :   LayoutDeviceRect transformedDevPixelBorderBox =
    1960           0 :     TransformBy(referenceFrameToRootReferenceFrame, devPixelBorderBox);
    1961         104 :   transformedDevPixelBorderBox.Round();
    1962         104 :   LayoutDeviceIntRect transformedDevPixelBorderBoxInt;
    1963             : 
    1964           0 :   if (!transformedDevPixelBorderBox.ToIntRect(&transformedDevPixelBorderBoxInt)) {
    1965             :     return;
    1966             :   }
    1967             : 
    1968             :   LayoutDeviceIntRegion& region =
    1969           0 :     styleUI->mWindowDragging == StyleWindowDragging::Drag
    1970         104 :       ? mWindowDraggingRegion : mWindowNoDraggingRegion;
    1971             : 
    1972         104 :   if (!IsRetainingDisplayList()) {
    1973         104 :     region.OrWith(transformedDevPixelBorderBoxInt);
    1974         104 :     return;
    1975             :   }
    1976             : 
    1977           0 :   mozilla::gfx::IntRect rect(transformedDevPixelBorderBoxInt.ToUnknownRect());
    1978           0 :   if (styleUI->mWindowDragging == StyleWindowDragging::Drag) {
    1979           0 :     mRetainedWindowDraggingRegion.Add(aFrame, rect);
    1980             :   } else {
    1981           0 :     mRetainedWindowNoDraggingRegion.Add(aFrame, rect);
    1982             :   }
    1983             : }
    1984             : 
    1985             : LayoutDeviceIntRegion
    1986           1 : nsDisplayListBuilder::GetWindowDraggingRegion() const
    1987             : {
    1988           1 :   LayoutDeviceIntRegion result;
    1989           8 :   if (!IsRetainingDisplayList()) {
    1990           8 :     result.Sub(mWindowDraggingRegion, mWindowNoDraggingRegion);
    1991             :     return result;
    1992             :   }
    1993             : 
    1994             :   LayoutDeviceIntRegion dragRegion =
    1995           0 :     mRetainedWindowDraggingRegion.ToLayoutDeviceIntRegion();
    1996             : 
    1997             :   LayoutDeviceIntRegion noDragRegion =
    1998           0 :     mRetainedWindowNoDraggingRegion.ToLayoutDeviceIntRegion();
    1999             : 
    2000           0 :   result.Sub(dragRegion, noDragRegion);
    2001             :   return result;
    2002             : }
    2003             : 
    2004             : /**
    2005             :  * Removes modified frames and rects from |aRegion|.
    2006             :  */
    2007             : static void
    2008           0 : RemoveModifiedFramesAndRects(nsDisplayListBuilder::WeakFrameRegion& aRegion)
    2009             : {
    2010           0 :   std::vector<WeakFrame>& frames = aRegion.mFrames;
    2011           0 :   nsTArray<pixman_box32_t>& rects = aRegion.mRects;
    2012             : 
    2013           0 :   MOZ_ASSERT(frames.size() == rects.Length());
    2014             : 
    2015           0 :   uint32_t i = 0;
    2016           0 :   uint32_t length = frames.size();
    2017             : 
    2018           0 :   while(i < length) {
    2019           0 :     WeakFrame& frame = frames[i];
    2020             : 
    2021           0 :     if (!frame.IsAlive() || frame->IsFrameModified()) {
    2022             :       // To avoid O(n) shifts in the array, move the last element of the array
    2023             :       // to the current position and decrease the array length. Moving WeakFrame
    2024             :       // inside of the array causes a new WeakFrame to be created and registered
    2025             :       // with PresShell. We could avoid this by, for example, using a wrapper
    2026             :       // class for WeakFrame, or by storing raw  WeakFrame pointers.
    2027           0 :       frames[i] = frames[length - 1];
    2028           0 :       rects[i] = rects[length - 1];
    2029           0 :       length--;
    2030             :     } else {
    2031           0 :       i++;
    2032             :     }
    2033             :   }
    2034             : 
    2035           0 :   frames.resize(length);
    2036           0 :   rects.TruncateLength(length);
    2037           0 : }
    2038             : 
    2039             : void
    2040           0 : nsDisplayListBuilder::RemoveModifiedWindowRegions()
    2041             : {
    2042           0 :   RemoveModifiedFramesAndRects(mRetainedWindowDraggingRegion);
    2043           0 :   RemoveModifiedFramesAndRects(mRetainedWindowNoDraggingRegion);
    2044           0 :   RemoveModifiedFramesAndRects(mWindowExcludeGlassRegion);
    2045           0 : }
    2046             : 
    2047             : void
    2048          19 : nsDisplayListBuilder::ClearRetainedWindowRegions()
    2049             : {
    2050           0 :   mRetainedWindowDraggingRegion.Clear();
    2051           0 :   mRetainedWindowNoDraggingRegion.Clear();
    2052           0 :   mWindowExcludeGlassRegion.Clear();
    2053          19 : }
    2054             : 
    2055             : const uint32_t gWillChangeAreaMultiplier = 3;
    2056           0 : static uint32_t GetLayerizationCost(const nsSize& aSize) {
    2057             :   // There's significant overhead for each layer created from Gecko
    2058             :   // (IPC+Shared Objects) and from the backend (like an OpenGL texture).
    2059             :   // Therefore we set a minimum cost threshold of a 64x64 area.
    2060           0 :   int minBudgetCost = 64 * 64;
    2061             : 
    2062             :   uint32_t budgetCost =
    2063           0 :     std::max(minBudgetCost,
    2064           0 :       nsPresContext::AppUnitsToIntCSSPixels(aSize.width) *
    2065           0 :       nsPresContext::AppUnitsToIntCSSPixels(aSize.height));
    2066             : 
    2067           0 :   return budgetCost;
    2068             : }
    2069             : 
    2070             : bool
    2071           0 : nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
    2072             :                                             const nsSize& aSize) {
    2073           0 :   if (mWillChangeBudgetSet.Get(aFrame, nullptr)) {
    2074             :     return true; // Already accounted
    2075             :   }
    2076             : 
    2077           0 :   nsPresContext* key = aFrame->PresContext();
    2078           0 :   DocumentWillChangeBudget budget;
    2079           0 :   auto willChangeBudgetEntry = mWillChangeBudget.LookupForAdd(key);
    2080           0 :   if (willChangeBudgetEntry) {
    2081             :     // We have an existing entry.
    2082           0 :     budget = willChangeBudgetEntry.Data();
    2083             :   } else {
    2084           0 :     budget = DocumentWillChangeBudget();
    2085           0 :     willChangeBudgetEntry.OrInsert([&budget] () { return budget; });
    2086             :   }
    2087             : 
    2088           0 :   nsRect area = aFrame->PresContext()->GetVisibleArea();
    2089           0 :   uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
    2090           0 :     nsPresContext::AppUnitsToIntCSSPixels(area.height);
    2091             : 
    2092           0 :   uint32_t cost = GetLayerizationCost(aSize);
    2093           0 :   bool onBudget = (budget.mBudget + cost) /
    2094           0 :                     gWillChangeAreaMultiplier < budgetLimit;
    2095             : 
    2096           0 :   if (onBudget) {
    2097           0 :     budget.mBudget += cost;
    2098           0 :     willChangeBudgetEntry.Data() = budget;
    2099           0 :     mWillChangeBudgetSet.Put(aFrame, cost);
    2100             :     aFrame->SetMayHaveWillChangeBudget(true);
    2101             :   }
    2102             : 
    2103             :   return onBudget;
    2104             : }
    2105             : 
    2106             : bool
    2107           0 : nsDisplayListBuilder::IsInWillChangeBudget(nsIFrame* aFrame,
    2108             :                                            const nsSize& aSize) {
    2109           0 :   bool onBudget = AddToWillChangeBudget(aFrame, aSize);
    2110             : 
    2111           0 :   if (!onBudget) {
    2112           0 :     nsString usageStr;
    2113           0 :     usageStr.AppendInt(GetLayerizationCost(aSize));
    2114             : 
    2115           0 :     nsString multiplierStr;
    2116           0 :     multiplierStr.AppendInt(gWillChangeAreaMultiplier);
    2117             : 
    2118           0 :     nsString limitStr;
    2119           0 :     nsRect area = aFrame->PresContext()->GetVisibleArea();
    2120           0 :     uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
    2121           0 :       nsPresContext::AppUnitsToIntCSSPixels(area.height);
    2122           0 :     limitStr.AppendInt(budgetLimit);
    2123             : 
    2124           0 :     const char16_t* params[] = { multiplierStr.get(), limitStr.get() };
    2125           0 :     aFrame->PresContext()->Document()->WarnOnceAbout(
    2126             :       nsIDocument::eIgnoringWillChangeOverBudget, false,
    2127           0 :       params, ArrayLength(params));
    2128             :   }
    2129           0 :   return onBudget;
    2130             : }
    2131             : 
    2132             : void
    2133        1225 : nsDisplayListBuilder::ClearWillChangeBudget(nsIFrame* aFrame)
    2134             : {
    2135        1225 :   if (!aFrame->MayHaveWillChangeBudget()) {
    2136           0 :     return;
    2137             :   }
    2138           0 :   aFrame->SetMayHaveWillChangeBudget(false);
    2139             : 
    2140           0 :   uint32_t cost = 0;
    2141           0 :   if (!mWillChangeBudgetSet.Get(aFrame, &cost)) {
    2142             :     return;
    2143             :   }
    2144           0 :   mWillChangeBudgetSet.Remove(aFrame);
    2145             : 
    2146             :   DocumentWillChangeBudget& budget =
    2147           0 :     mWillChangeBudget.GetOrInsert(aFrame->PresContext());
    2148           0 :   MOZ_ASSERT(budget.mBudget >= cost);
    2149           0 :   budget.mBudget -= cost;
    2150             : }
    2151             : 
    2152             : #ifdef MOZ_GFX_OPTIMIZE_MOBILE
    2153             : const float gAGRBudgetAreaMultiplier = 0.3;
    2154             : #else
    2155             : const float gAGRBudgetAreaMultiplier = 3.0;
    2156             : #endif
    2157             : 
    2158             : bool
    2159           0 : nsDisplayListBuilder::AddToAGRBudget(nsIFrame* aFrame)
    2160             : {
    2161           0 :   if (mAGRBudgetSet.Contains(aFrame)) {
    2162             :     return true;
    2163             :   }
    2164             : 
    2165           0 :   const nsPresContext* presContext = aFrame->PresContext()->GetRootPresContext();
    2166           0 :   if (!presContext) {
    2167             :     return false;
    2168             :   }
    2169             : 
    2170           0 :   const nsRect area = presContext->GetVisibleArea();
    2171           0 :   const uint32_t budgetLimit = gAGRBudgetAreaMultiplier *
    2172           0 :     nsPresContext::AppUnitsToIntCSSPixels(area.width) *
    2173           0 :     nsPresContext::AppUnitsToIntCSSPixels(area.height);
    2174             : 
    2175           0 :   const uint32_t cost = GetLayerizationCost(aFrame->GetSize());
    2176           0 :   const bool onBudget = mUsedAGRBudget + cost < budgetLimit;
    2177             : 
    2178           0 :   if (onBudget) {
    2179           0 :     mUsedAGRBudget += cost;
    2180           0 :     mAGRBudgetSet.PutEntry(aFrame);
    2181             :   }
    2182             : 
    2183             :   return onBudget;
    2184             : }
    2185             : 
    2186             : void
    2187           0 : nsDisplayListBuilder::EnterSVGEffectsContents(nsDisplayList* aHoistedItemsStorage)
    2188             : {
    2189           0 :   MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0);
    2190           0 :   MOZ_ASSERT(aHoistedItemsStorage);
    2191           0 :   if (mSVGEffectsBuildingDepth == 0) {
    2192           0 :     MOZ_ASSERT(!mScrollInfoItemsForHoisting);
    2193           0 :     mScrollInfoItemsForHoisting = aHoistedItemsStorage;
    2194             :   }
    2195           0 :   mSVGEffectsBuildingDepth++;
    2196           0 : }
    2197             : 
    2198             : void
    2199           0 : nsDisplayListBuilder::ExitSVGEffectsContents()
    2200             : {
    2201           0 :   mSVGEffectsBuildingDepth--;
    2202           0 :   MOZ_ASSERT(mSVGEffectsBuildingDepth >= 0);
    2203           0 :   MOZ_ASSERT(mScrollInfoItemsForHoisting);
    2204           0 :   if (mSVGEffectsBuildingDepth == 0) {
    2205           0 :     mScrollInfoItemsForHoisting = nullptr;
    2206             :   }
    2207           0 : }
    2208             : 
    2209             : void
    2210           0 : nsDisplayListBuilder::AppendNewScrollInfoItemForHoisting(nsDisplayScrollInfoLayer* aScrollInfoItem)
    2211             : {
    2212           0 :   MOZ_ASSERT(ShouldBuildScrollInfoItemsForHoisting());
    2213           0 :   MOZ_ASSERT(mScrollInfoItemsForHoisting);
    2214           0 :   mScrollInfoItemsForHoisting->AppendToTop(aScrollInfoItem);
    2215           0 : }
    2216             : 
    2217             : static nsRect
    2218         556 : GetFrameArea(const nsDisplayListBuilder* aBuilder, const nsIFrame* aFrame)
    2219             : {
    2220           0 :   nsRect area;
    2221             : 
    2222           0 :   nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(aFrame);
    2223         556 :   if (scrollFrame) {
    2224             :     // If the frame is content of a scrollframe, then we need to pick up the
    2225             :     // area corresponding to the overflow rect as well. Otherwise the parts of
    2226             :     // the overflow that are not occupied by descendants get skipped and the
    2227             :     // APZ code sends touch events to the content underneath instead.
    2228             :     // See https://bugzilla.mozilla.org/show_bug.cgi?id=1127773#c15.
    2229           0 :     area = aFrame->GetScrollableOverflowRect();
    2230             :   } else {
    2231        1028 :     area = nsRect(nsPoint(0, 0), aFrame->GetSize());
    2232             :   }
    2233             : 
    2234        1112 :   if (!area.IsEmpty()) {
    2235         548 :     return area + aBuilder->ToReferenceFrame(aFrame);
    2236             :   }
    2237             : 
    2238           0 :   return area;
    2239             : }
    2240             : 
    2241             : void
    2242           0 : nsDisplayListBuilder::BuildCompositorHitTestInfoIfNeeded(nsIFrame* aFrame,
    2243             :                                                          nsDisplayList* aList,
    2244             :                                                          const bool aBuildNew)
    2245             : {
    2246         688 :   MOZ_ASSERT(aFrame);
    2247         688 :   MOZ_ASSERT(aList);
    2248             : 
    2249           0 :   if (!BuildCompositorHitTestInfo()) {
    2250         574 :     return;
    2251             :   }
    2252             : 
    2253           0 :   CompositorHitTestInfo info = aFrame->GetCompositorHitTestInfo(this);
    2254           0 :   if (!ShouldBuildCompositorHitTestInfo(aFrame, info, aBuildNew)) {
    2255             :     // Either the parent hit test info can be reused, or this frame has no hit
    2256             :     // test flags set.
    2257             :     return;
    2258             :   }
    2259             : 
    2260             :   nsDisplayCompositorHitTestInfo* item =
    2261           0 :     MakeDisplayItem<nsDisplayCompositorHitTestInfo>(this, aFrame, info);
    2262             : 
    2263         228 :   SetCompositorHitTestInfo(item);
    2264         114 :   aList->AppendToTop(item);
    2265             : }
    2266             : 
    2267             : bool
    2268           0 : nsDisplayListBuilder::ShouldBuildCompositorHitTestInfo(const nsIFrame* aFrame,
    2269             :                                                        const CompositorHitTestInfo& aInfo,
    2270             :                                                        const bool aBuildNew) const
    2271             : {
    2272         620 :   MOZ_ASSERT(mBuildCompositorHitTestInfo);
    2273             : 
    2274         620 :   if (aInfo == CompositorHitTestInfo::eInvisibleToHitTest) {
    2275             :     return false;
    2276             :   }
    2277             : 
    2278         556 :   if (!mCompositorHitTestInfo || !mLessEventRegionItems || aBuildNew) {
    2279             :     return true;
    2280             :   }
    2281             : 
    2282         442 :   if (mCompositorHitTestInfo->HitTestInfo() != aInfo) {
    2283             :     // Hit test flags are different.
    2284             :     return true;
    2285             :   }
    2286             : 
    2287             :   // Create a new item if the parent does not contain the child completely.
    2288         442 :   return !mCompositorHitTestInfo->Area().Contains(GetFrameArea(this, aFrame));
    2289             : }
    2290             : 
    2291         118 : void nsDisplayListSet::MoveTo(const nsDisplayListSet& aDestination) const
    2292             : {
    2293         118 :   aDestination.BorderBackground()->AppendToTop(BorderBackground());
    2294         118 :   aDestination.BlockBorderBackgrounds()->AppendToTop(BlockBorderBackgrounds());
    2295           0 :   aDestination.Floats()->AppendToTop(Floats());
    2296         118 :   aDestination.Content()->AppendToTop(Content());
    2297         118 :   aDestination.PositionedDescendants()->AppendToTop(PositionedDescendants());
    2298         118 :   aDestination.Outlines()->AppendToTop(Outlines());
    2299           0 : }
    2300             : 
    2301             : static void
    2302          16 : MoveListTo(nsDisplayList* aList, nsTArray<nsDisplayItem*>* aElements) {
    2303             :   nsDisplayItem* item;
    2304          96 :   while ((item = aList->RemoveBottom()) != nullptr) {
    2305          40 :     aElements->AppendElement(item);
    2306             :   }
    2307           0 : }
    2308             : 
    2309             : nsRect
    2310          16 : nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
    2311           0 :   nsRect bounds;
    2312           0 :   for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
    2313          40 :     bounds.UnionRect(bounds, i->GetClippedBounds(aBuilder));
    2314             :   }
    2315          16 :   return bounds;
    2316             : }
    2317             : 
    2318             : nsRect
    2319         166 : nsDisplayList::GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
    2320             :                                                 const ActiveScrolledRoot* aASR,
    2321             :                                                 nsRect* aBuildingRect) const {
    2322         166 :   nsRect bounds;
    2323           0 :   for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
    2324           0 :     nsRect r = i->GetClippedBounds(aBuilder);
    2325         546 :     if (aASR != i->GetActiveScrolledRoot() && !r.IsEmpty()) {
    2326           0 :       if (Maybe<nsRect> clip = i->GetClipWithRespectToASR(aBuilder, aASR)) {
    2327           0 :         r = clip.ref();
    2328             :       }
    2329             :     }
    2330           0 :     if (aBuildingRect) {
    2331           0 :       aBuildingRect->UnionRect(*aBuildingRect, i->GetBuildingRect());
    2332             :     }
    2333           0 :     bounds.UnionRect(bounds, r);
    2334             :   }
    2335           0 :   return bounds;
    2336             : }
    2337             : 
    2338             : nsRect
    2339           0 : nsDisplayList::GetBuildingRect() const {
    2340           0 :   nsRect result;
    2341           0 :   for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
    2342           0 :     result.UnionRect(result, i->GetBuildingRect());
    2343             :   }
    2344           0 :   return result;
    2345             : }
    2346             : 
    2347             : bool
    2348           0 : nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
    2349             :                                         nsRegion* aVisibleRegion) {
    2350           0 :   AUTO_PROFILER_LABEL("nsDisplayList::ComputeVisibilityForRoot", GRAPHICS);
    2351             : 
    2352           0 :   nsRegion r;
    2353           0 :   const ActiveScrolledRoot* rootASR = nullptr;
    2354           0 :   if (gfxPrefs::LayoutUseContainersForRootFrames()) {
    2355           0 :     rootASR = aBuilder->ActiveScrolledRootForRootScrollframe();
    2356             :   }
    2357           0 :   r.And(*aVisibleRegion, GetClippedBoundsWithRespectToASR(aBuilder, rootASR));
    2358           0 :   return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds());
    2359             : }
    2360             : 
    2361             : static nsRegion
    2362           0 : TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
    2363             : {
    2364             :   bool snap;
    2365         174 :   nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
    2366           0 :   if (aBuilder->IsForPluginGeometry() &&
    2367           0 :       aItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO)
    2368             :   {
    2369             :     // Treat all leaf chrome items as opaque, unless their frames are opacity:0.
    2370             :     // Since opacity:0 frames generate an nsDisplayOpacity, that item will
    2371             :     // not be treated as opaque here, so opacity:0 chrome content will be
    2372             :     // effectively ignored, as it should be.
    2373             :     // We treat leaf chrome items as opaque to ensure that they cover
    2374             :     // content plugins, for security reasons.
    2375             :     // Non-leaf chrome items don't render contents of their own so shouldn't
    2376             :     // be treated as opaque (and their bounds is just the union of their
    2377             :     // children, which might be a large area their contents don't really cover).
    2378           0 :     nsIFrame* f = aItem->Frame();
    2379           0 :     if (f->PresContext()->IsChrome() && !aItem->GetChildren() &&
    2380           0 :         f->StyleEffects()->mOpacity != 0.0) {
    2381           0 :       opaque = aItem->GetBounds(aBuilder, &snap);
    2382             :     }
    2383             :   }
    2384           0 :   if (opaque.IsEmpty()) {
    2385          74 :     return opaque;
    2386             :   }
    2387          26 :   nsRegion opaqueClipped;
    2388           0 :   for (auto iter = opaque.RectIter(); !iter.Done(); iter.Next()) {
    2389             :     opaqueClipped.Or(opaqueClipped,
    2390           0 :                      aItem->GetClip().ApproximateIntersectInward(iter.Get()));
    2391             :   }
    2392          13 :   return opaqueClipped;
    2393             : }
    2394             : 
    2395             : bool
    2396          16 : nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
    2397             :                                            nsRegion* aVisibleRegion,
    2398             :                                            const nsRect& aListVisibleBounds)
    2399             : {
    2400             : #ifdef DEBUG
    2401           0 :   nsRegion r;
    2402           0 :   r.And(*aVisibleRegion, GetBounds(aBuilder));
    2403             :   // XXX this fails sometimes:
    2404           0 :   NS_WARNING_ASSERTION(r.GetBounds().IsEqualInterior(aListVisibleBounds),
    2405             :                        "bad aListVisibleBounds");
    2406             : #endif
    2407             : 
    2408          16 :   bool anyVisible = false;
    2409             : 
    2410          32 :   AutoTArray<nsDisplayItem*, 512> elements;
    2411          16 :   MoveListTo(this, &elements);
    2412             : 
    2413          56 :   for (int32_t i = elements.Length() - 1; i >= 0; --i) {
    2414          80 :     nsDisplayItem* item = elements[i];
    2415             : 
    2416           0 :     if (item->ForceNotVisible() && !item->GetSameCoordinateSystemChildren()) {
    2417           0 :       NS_ASSERTION(item->GetBuildingRect().IsEmpty(),
    2418             :         "invisible items should have empty vis rect");
    2419           0 :       item->SetPaintRect(nsRect());
    2420             :     } else {
    2421           0 :       nsRect bounds = item->GetClippedBounds(aBuilder);
    2422             : 
    2423          80 :       nsRegion itemVisible;
    2424           0 :       itemVisible.And(*aVisibleRegion, bounds);
    2425           0 :       item->SetPaintRect(itemVisible.GetBounds());
    2426             :     }
    2427             : 
    2428          40 :     if (item->ComputeVisibility(aBuilder, aVisibleRegion)) {
    2429           0 :       anyVisible = true;
    2430             : 
    2431          20 :       nsRegion opaque = TreatAsOpaque(item, aBuilder);
    2432             :       // Subtract opaque item from the visible region
    2433           0 :       aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
    2434             :     }
    2435          40 :     AppendToBottom(item);
    2436             :   }
    2437             : 
    2438           0 :   mIsOpaque = !aVisibleRegion->Intersects(aListVisibleBounds);
    2439           0 :   return anyVisible;
    2440             : }
    2441             : 
    2442             : static bool
    2443          16 : TriggerPendingAnimationsOnSubDocuments(nsIDocument* aDocument, void* aReadyTime)
    2444             : {
    2445           0 :   PendingAnimationTracker* tracker = aDocument->GetPendingAnimationTracker();
    2446          16 :   if (tracker) {
    2447           0 :     nsIPresShell* shell = aDocument->GetShell();
    2448             :     // If paint-suppression is in effect then we haven't finished painting
    2449             :     // this document yet so we shouldn't start animations
    2450           0 :     if (!shell || !shell->IsPaintingSuppressed()) {
    2451           0 :       const TimeStamp& readyTime = *static_cast<TimeStamp*>(aReadyTime);
    2452           8 :       tracker->TriggerPendingAnimationsOnNextTick(readyTime);
    2453             :     }
    2454             :   }
    2455             :   aDocument->EnumerateSubDocuments(TriggerPendingAnimationsOnSubDocuments,
    2456           1 :                                    aReadyTime);
    2457          16 :   return true;
    2458             : }
    2459             : 
    2460             : static void
    2461           0 : TriggerPendingAnimations(nsIDocument* aDocument,
    2462             :                        const TimeStamp& aReadyTime) {
    2463           8 :   MOZ_ASSERT(!aReadyTime.IsNull(),
    2464             :              "Animation ready time is not set. Perhaps we're using a layer"
    2465             :              " manager that doesn't update it");
    2466             :   TriggerPendingAnimationsOnSubDocuments(aDocument,
    2467           8 :                                          const_cast<TimeStamp*>(&aReadyTime));
    2468           0 : }
    2469             : 
    2470             : LayerManager*
    2471          30 : nsDisplayListBuilder::GetWidgetLayerManager(nsView** aView)
    2472             : {
    2473          30 :   if (aView) {
    2474           8 :     *aView = RootReferenceFrame()->GetView();
    2475             :   }
    2476           0 :   if (RootReferenceFrame() != nsLayoutUtils::GetDisplayRootFrame(RootReferenceFrame())) {
    2477             :     return nullptr;
    2478             :   }
    2479          30 :   nsIWidget* window = RootReferenceFrame()->GetNearestWidget();
    2480           0 :   if (window) {
    2481           8 :     return window->GetLayerManager();
    2482             :   }
    2483             :   return nullptr;
    2484             : }
    2485             : 
    2486             : FrameLayerBuilder*
    2487           0 : nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
    2488             :                            LayerManager* aLayerManager,
    2489             :                            uint32_t aFlags,
    2490             :                            bool aIsWidgetTransaction)
    2491             : {
    2492          19 :   nsIFrame* frame = aBuilder->RootReferenceFrame();
    2493           0 :   nsPresContext* presContext = frame->PresContext();
    2494           0 :   nsIPresShell* presShell = presContext->PresShell();
    2495             : 
    2496          19 :   FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
    2497          19 :   layerBuilder->Init(aBuilder, aLayerManager);
    2498             : 
    2499          19 :   if (aFlags & PAINT_COMPRESSED) {
    2500           0 :     layerBuilder->SetLayerTreeCompressionMode();
    2501             :   }
    2502             : 
    2503          38 :   RefPtr<ContainerLayer> root;
    2504             :   {
    2505           0 :     AUTO_PROFILER_TRACING("Paint", "LayerBuilding");
    2506             : 
    2507          19 :     if (XRE_IsContentProcess() && gfxPrefs::AlwaysPaint()) {
    2508           0 :       FrameLayerBuilder::InvalidateAllLayers(aLayerManager);
    2509             :     }
    2510             : 
    2511           0 :     if (aIsWidgetTransaction) {
    2512           8 :       layerBuilder->DidBeginRetainedLayerTransaction(aLayerManager);
    2513             :     }
    2514             : 
    2515             :     // Clear any ScrollMetadata that may have been set on the root layer on a
    2516             :     // previous paint. This paint will set new metrics if necessary, and if we
    2517             :     // don't clear the old one here, we may be left with extra metrics.
    2518           0 :     if (Layer* rootLayer = aLayerManager->GetRoot()) {
    2519          14 :       rootLayer->SetScrollMetadata(nsTArray<ScrollMetadata>());
    2520             :     }
    2521             : 
    2522             :     ContainerLayerParameters containerParameters
    2523          19 :       (presShell->GetResolution(), presShell->GetResolution());
    2524             : 
    2525             :     {
    2526          38 :       PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
    2527             : 
    2528             :       root = layerBuilder->
    2529           0 :         BuildContainerLayerFor(aBuilder, aLayerManager, frame, nullptr, this,
    2530           0 :                                containerParameters, nullptr);
    2531             : 
    2532          19 :       if (!record.GetStart().IsNull() && gfxPrefs::LayersDrawFPS()) {
    2533           0 :         if (PaintTiming* pt = ClientLayerManager::MaybeGetPaintTiming(aLayerManager)) {
    2534           0 :           pt->flbMs() = (TimeStamp::Now() - record.GetStart()).ToMilliseconds();
    2535             :         }
    2536             :       }
    2537             :     }
    2538             : 
    2539          19 :     if (!root) {
    2540           0 :       return nullptr;
    2541             :     }
    2542             :     // Root is being scaled up by the X/Y resolution. Scale it back down.
    2543          19 :     root->SetPostScale(1.0f/containerParameters.mXScale,
    2544           0 :                        1.0f/containerParameters.mYScale);
    2545           1 :     root->SetScaleToResolution(presShell->ScaleToResolution(),
    2546          19 :         containerParameters.mXScale);
    2547             : 
    2548           0 :     auto callback = [root](FrameMetrics::ViewID aScrollId) -> bool {
    2549           0 :       return nsLayoutUtils::ContainsMetricsWithId(root, aScrollId);
    2550          38 :     };
    2551          19 :     if (Maybe<ScrollMetadata> rootMetadata = nsLayoutUtils::GetRootMetadata(
    2552          76 :           aBuilder, root->Manager(), containerParameters, callback)) {
    2553           8 :       root->SetScrollMetadata(rootMetadata.value());
    2554             :     }
    2555             : 
    2556             :     // NS_WARNING is debug-only, so don't even bother checking the conditions in
    2557             :     // a release build.
    2558             : #ifdef DEBUG
    2559          19 :     bool usingDisplayport = false;
    2560           0 :     if (nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame()) {
    2561          11 :       nsIContent* content = rootScrollFrame->GetContent();
    2562          11 :       if (content) {
    2563           0 :         usingDisplayport = nsLayoutUtils::HasDisplayPort(content);
    2564             :       }
    2565             :     }
    2566           0 :     if (usingDisplayport &&
    2567           0 :         !(root->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
    2568           0 :         SpammyLayoutWarningsEnabled()) {
    2569             :       // See bug 693938, attachment 567017
    2570           0 :       NS_WARNING("Transparent content with displayports can be expensive.");
    2571             :     }
    2572             : #endif
    2573             : 
    2574          38 :     aLayerManager->SetRoot(root);
    2575          19 :     layerBuilder->WillEndTransaction();
    2576             :   }
    2577           1 :   return layerBuilder;
    2578             : }
    2579             : 
    2580             : /**
    2581             :  * We paint by executing a layer manager transaction, constructing a
    2582             :  * single layer representing the display list, and then making it the
    2583             :  * root of the layer manager, drawing into the PaintedLayers.
    2584             :  */
    2585           0 : already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
    2586             :                                                         gfxContext* aCtx,
    2587             :                                                         uint32_t aFlags)
    2588             : {
    2589           0 :   AUTO_PROFILER_LABEL("nsDisplayList::PaintRoot", GRAPHICS);
    2590             : 
    2591          38 :   RefPtr<LayerManager> layerManager;
    2592          19 :   bool widgetTransaction = false;
    2593          19 :   bool doBeginTransaction = true;
    2594          19 :   nsView *view = nullptr;
    2595          19 :   if (aFlags & PAINT_USE_WIDGET_LAYERS) {
    2596           0 :     layerManager = aBuilder->GetWidgetLayerManager(&view);
    2597           0 :     if (layerManager) {
    2598           0 :       doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
    2599           0 :       widgetTransaction = true;
    2600             :     }
    2601             :   }
    2602          19 :   if (!layerManager) {
    2603           0 :     if (!aCtx) {
    2604           0 :       NS_WARNING("Nowhere to paint into");
    2605             :       return nullptr;
    2606             :     }
    2607           1 :     layerManager = new BasicLayerManager(BasicLayerManager::BLM_OFFSCREEN);
    2608             :   }
    2609             : 
    2610          19 :   nsIFrame* frame = aBuilder->RootReferenceFrame();
    2611           0 :   nsPresContext* presContext = frame->PresContext();
    2612           0 :   nsIPresShell* presShell = presContext->PresShell();
    2613          19 :   nsIDocument* document = presShell->GetDocument();
    2614             : 
    2615          19 :   if (layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
    2616           0 :     if (doBeginTransaction) {
    2617           0 :       if (aCtx) {
    2618           0 :         if (!layerManager->BeginTransactionWithTarget(aCtx)) {
    2619             :           return nullptr;
    2620             :         }
    2621             :       } else {
    2622           0 :         if (!layerManager->BeginTransaction()) {
    2623             :           return nullptr;
    2624             :         }
    2625             :       }
    2626             :     }
    2627             : 
    2628             :     bool prevIsCompositingCheap =
    2629           0 :       aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
    2630           0 :     MaybeSetupTransactionIdAllocator(layerManager, presContext);
    2631             : 
    2632           0 :     bool sent = false;
    2633           0 :     if (aFlags & PAINT_IDENTICAL_DISPLAY_LIST) {
    2634           0 :       sent = layerManager->EndEmptyTransaction();
    2635             :     }
    2636             : 
    2637           0 :     if (!sent) {
    2638             :       // Windowed plugins are not supported with WebRender enabled.
    2639             :       // But PluginGeometry needs to be updated to show plugin.
    2640             :       // Windowed plugins are going to be removed by Bug 1296400.
    2641           0 :       nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
    2642           0 :       if (rootPresContext && XRE_IsContentProcess()) {
    2643           0 :         if (aBuilder->WillComputePluginGeometry()) {
    2644           0 :           rootPresContext->ComputePluginGeometryUpdates(aBuilder->RootReferenceFrame(), aBuilder, this);
    2645             :         }
    2646             :         // This must be called even if PluginGeometryUpdates were not computed.
    2647           0 :         rootPresContext->CollectPluginGeometryUpdates(layerManager);
    2648             :       }
    2649             : 
    2650           0 :       WebRenderLayerManager* wrManager = static_cast<WebRenderLayerManager*>(layerManager.get());
    2651             : 
    2652           0 :       nsIDocShell* docShell = presContext->GetDocShell();
    2653           0 :       nsTArray<wr::WrFilterOp> wrFilters;
    2654           0 :       gfx::Matrix5x4* colorMatrix = nsDocShell::Cast(docShell)->GetColorMatrix();
    2655           0 :       if (colorMatrix) {
    2656             :         wr::WrFilterOp gs = {
    2657             :           wr::WrFilterOpType::ColorMatrix
    2658           0 :         };
    2659             :         MOZ_ASSERT(sizeof(gs.matrix) == sizeof(colorMatrix->components));
    2660           0 :         memcpy(&(gs.matrix), colorMatrix->components, sizeof(gs.matrix));
    2661           0 :         wrFilters.AppendElement(gs);
    2662             :       }
    2663             : 
    2664           0 :       wrManager->EndTransactionWithoutLayer(this, aBuilder, wrFilters);
    2665             :     }
    2666             : 
    2667             :     // For layers-free mode, we check the invalidation state bits in the EndTransaction.
    2668             :     // So we clear the invalidation state bits after EndTransaction.
    2669           0 :     if (widgetTransaction ||
    2670             :         // SVG-as-an-image docs don't paint as part of the retained layer tree,
    2671             :         // but they still need the invalidation state bits cleared in order for
    2672             :         // invalidation for CSS/SMIL animation to work properly.
    2673           0 :         (document && document->IsBeingUsedAsImage())) {
    2674           0 :       frame->ClearInvalidationStateBits();
    2675             :     }
    2676             : 
    2677           0 :     aBuilder->SetIsCompositingCheap(prevIsCompositingCheap);
    2678           0 :     if (document && widgetTransaction) {
    2679           0 :       TriggerPendingAnimations(document, layerManager->GetAnimationReadyTime());
    2680             :     }
    2681             : 
    2682           0 :     if (presContext->RefreshDriver()->HasScheduleFlush()) {
    2683           0 :       presContext->NotifyInvalidation(layerManager->GetLastTransactionId(), frame->GetRect());
    2684             :     }
    2685             : 
    2686             :     return layerManager.forget();
    2687             :   }
    2688             : 
    2689             :   NotifySubDocInvalidationFunc computeInvalidFunc =
    2690           1 :     presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
    2691             : 
    2692           1 :   UniquePtr<LayerProperties> props;
    2693             : 
    2694          11 :   bool computeInvalidRect = (computeInvalidFunc ||
    2695           1 :                              (!layerManager->IsCompositingCheap() && layerManager->NeedsWidgetInvalidation())) &&
    2696          19 :                             widgetTransaction;
    2697             : 
    2698           1 :   if (computeInvalidRect) {
    2699          16 :     props = LayerProperties::CloneFrom(layerManager->GetRoot());
    2700             :   }
    2701             : 
    2702          19 :   if (doBeginTransaction) {
    2703          11 :     if (aCtx) {
    2704          11 :       if (!layerManager->BeginTransactionWithTarget(aCtx)) {
    2705             :         return nullptr;
    2706             :       }
    2707             :     } else {
    2708           0 :       if (!layerManager->BeginTransaction()) {
    2709             :         return nullptr;
    2710             :       }
    2711             :     }
    2712             :   }
    2713             : 
    2714           1 :   bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
    2715           1 :   LayerManager::EndTransactionFlags flags = LayerManager::END_DEFAULT;
    2716           1 :   if (layerManager->NeedsWidgetInvalidation()) {
    2717          11 :     if (aFlags & PAINT_NO_COMPOSITE) {
    2718           0 :       flags = LayerManager::END_NO_COMPOSITE;
    2719             :     }
    2720             :   } else {
    2721             :     // Client layer managers never composite directly, so
    2722             :     // we don't need to worry about END_NO_COMPOSITE.
    2723           8 :     if (aBuilder->WillComputePluginGeometry()) {
    2724           0 :       flags = LayerManager::END_NO_REMOTE_COMPOSITE;
    2725             :     }
    2726             :   }
    2727             : 
    2728          19 :   MaybeSetupTransactionIdAllocator(layerManager, presContext);
    2729             : 
    2730             :   // Store the existing layer builder to reinstate it on return.
    2731           0 :   FrameLayerBuilder *oldBuilder = layerManager->GetLayerBuilder();
    2732           0 :   FrameLayerBuilder *layerBuilder = nullptr;
    2733             : 
    2734          19 :   bool sent = false;
    2735           0 :   if (aFlags & PAINT_IDENTICAL_DISPLAY_LIST) {
    2736           0 :     sent = layerManager->EndEmptyTransaction(flags);
    2737             :   }
    2738             : 
    2739           0 :   if (!sent) {
    2740           0 :     layerBuilder = BuildLayers(aBuilder, layerManager,
    2741           0 :                                aFlags, widgetTransaction);
    2742             : 
    2743          19 :     if (!layerBuilder) {
    2744           0 :       layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);
    2745             :       return nullptr;
    2746             :     }
    2747             : 
    2748             :     // If this is the content process, we ship plugin geometry updates over with layer
    2749             :     // updates, so calculate that now before we call EndTransaction.
    2750          19 :     nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
    2751           0 :     if (rootPresContext && XRE_IsContentProcess()) {
    2752           0 :       if (aBuilder->WillComputePluginGeometry()) {
    2753           0 :         rootPresContext->ComputePluginGeometryUpdates(aBuilder->RootReferenceFrame(), aBuilder, this);
    2754             :       }
    2755             :       // The layer system caches plugin configuration information for forwarding
    2756             :       // with layer updates which needs to get set during reflow. This must be
    2757             :       // called even if there are no windowed plugins in the page.
    2758           0 :       rootPresContext->CollectPluginGeometryUpdates(layerManager);
    2759             :     }
    2760             : 
    2761           0 :     layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
    2762          19 :                                  aBuilder, flags);
    2763          19 :     layerBuilder->DidEndTransaction();
    2764             :   }
    2765             : 
    2766          38 :   if (widgetTransaction ||
    2767             :       // SVG-as-an-image docs don't paint as part of the retained layer tree,
    2768             :       // but they still need the invalidation state bits cleared in order for
    2769             :       // invalidation for CSS/SMIL animation to work properly.
    2770          11 :       (document && document->IsBeingUsedAsImage())) {
    2771           0 :     frame->ClearInvalidationStateBits();
    2772             :   }
    2773             : 
    2774          38 :   aBuilder->SetIsCompositingCheap(temp);
    2775             : 
    2776           0 :   if (document && widgetTransaction) {
    2777           0 :     TriggerPendingAnimations(document, layerManager->GetAnimationReadyTime());
    2778             :   }
    2779             : 
    2780           0 :   nsIntRegion invalid;
    2781           1 :   bool areaOverflowed = false;
    2782          19 :   if (props) {
    2783          16 :     if (!props->ComputeDifferences(layerManager->GetRoot(), invalid, computeInvalidFunc)) {
    2784           0 :       areaOverflowed = true;
    2785             :     }
    2786          11 :   } else if (widgetTransaction) {
    2787           0 :     LayerProperties::ClearInvalidations(layerManager->GetRoot());
    2788             :   }
    2789             : 
    2790           0 :   bool shouldInvalidate = layerManager->NeedsWidgetInvalidation();
    2791          19 :   if (view) {
    2792           8 :     if (props && !areaOverflowed) {
    2793           8 :       if (!invalid.IsEmpty()) {
    2794           4 :         nsIntRect bounds = invalid.GetBounds();
    2795             :         nsRect rect(presContext->DevPixelsToAppUnits(bounds.x),
    2796             :                     presContext->DevPixelsToAppUnits(bounds.y),
    2797             :                     presContext->DevPixelsToAppUnits(bounds.width),
    2798           0 :                     presContext->DevPixelsToAppUnits(bounds.height));
    2799           0 :         if (shouldInvalidate) {
    2800           0 :           view->GetViewManager()->InvalidateViewNoSuppression(view, rect);
    2801             :         }
    2802           4 :         presContext->NotifyInvalidation(layerManager->GetLastTransactionId(), bounds);
    2803             :       }
    2804           0 :     } else if (shouldInvalidate) {
    2805           0 :       view->GetViewManager()->InvalidateView(view);
    2806             :     }
    2807             :   }
    2808             : 
    2809          19 :   layerManager->SetUserData(&gLayerManagerLayerBuilder, oldBuilder);
    2810          19 :   return layerManager.forget();
    2811             : }
    2812             : 
    2813           0 : nsDisplayItem* nsDisplayList::RemoveBottom() {
    2814           0 :   nsDisplayItem* item = mSentinel.mAbove;
    2815        1102 :   if (!item)
    2816             :     return nullptr;
    2817           0 :   mSentinel.mAbove = item->mAbove;
    2818           0 :   if (item == mTop) {
    2819             :     // must have been the only item
    2820           0 :     mTop = &mSentinel;
    2821             :   }
    2822         692 :   item->mAbove = nullptr;
    2823           0 :   mLength--;
    2824           0 :   return item;
    2825             : }
    2826             : 
    2827           0 : void nsDisplayList::DeleteAll(nsDisplayListBuilder* aBuilder) {
    2828             :   nsDisplayItem* item;
    2829           0 :   while ((item = RemoveBottom()) != nullptr) {
    2830           0 :     item->Destroy(aBuilder);
    2831             :   }
    2832         174 : }
    2833             : 
    2834             : static bool
    2835           0 : GetMouseThrough(const nsIFrame* aFrame)
    2836             : {
    2837           0 :   if (!aFrame->IsXULBoxFrame())
    2838             :     return false;
    2839             : 
    2840             :   const nsIFrame* frame = aFrame;
    2841           0 :   while (frame) {
    2842           0 :     if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_ALWAYS) {
    2843             :       return true;
    2844           0 :     } else if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_NEVER) {
    2845             :       return false;
    2846             :     }
    2847           0 :     frame = nsBox::GetParentXULBox(frame);
    2848             :   }
    2849             :   return false;
    2850             : }
    2851             : 
    2852             : static bool
    2853           0 : IsFrameReceivingPointerEvents(nsIFrame* aFrame)
    2854             : {
    2855             :   return NS_STYLE_POINTER_EVENTS_NONE !=
    2856           0 :     aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame);
    2857             : }
    2858             : 
    2859             : // A list of frames, and their z depth. Used for sorting
    2860             : // the results of hit testing.
    2861           0 : struct FramesWithDepth
    2862             : {
    2863           0 :   explicit FramesWithDepth(float aDepth) :
    2864           0 :     mDepth(aDepth)
    2865             :   {}
    2866             : 
    2867           0 :   bool operator<(const FramesWithDepth& aOther) const {
    2868           0 :     if (!FuzzyEqual(mDepth, aOther.mDepth, 0.1f)) {
    2869             :       // We want to sort so that the shallowest item (highest depth value) is first
    2870           0 :       return mDepth > aOther.mDepth;
    2871             :     }
    2872           0 :     return this < &aOther;
    2873             :   }
    2874             :   bool operator==(const FramesWithDepth& aOther) const {
    2875             :     return this == &aOther;
    2876             :   }
    2877             : 
    2878             :   float mDepth;
    2879             :   nsTArray<nsIFrame*> mFrames;
    2880             : };
    2881             : 
    2882             : // Sort the frames by depth and then moves all the contained frames to the destination
    2883             : static void
    2884           0 : FlushFramesArray(nsTArray<FramesWithDepth>& aSource, nsTArray<nsIFrame*>* aDest)
    2885             : {
    2886           0 :   if (aSource.IsEmpty()) {
    2887             :     return;
    2888             :   }
    2889           0 :   aSource.Sort();
    2890           0 :   uint32_t length = aSource.Length();
    2891           0 :   for (uint32_t i = 0; i < length; i++) {
    2892           0 :     aDest->AppendElements(std::move(aSource[i].mFrames));
    2893             :   }
    2894           0 :   aSource.Clear();
    2895             : }
    2896             : 
    2897           0 : void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    2898             :                             nsDisplayItem::HitTestState* aState,
    2899             :                             nsTArray<nsIFrame*> *aOutFrames) const {
    2900             :   nsDisplayItem* item;
    2901             : 
    2902           0 :   if (aState->mInPreserves3D) {
    2903             :     // Collect leaves of the current 3D rendering context.
    2904           0 :     for (item = GetBottom(); item; item = item->GetAbove()) {
    2905           0 :       auto itemType = item->GetType();
    2906           0 :       if (itemType != DisplayItemType::TYPE_TRANSFORM ||
    2907           0 :           !static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext()) {
    2908           0 :         item->HitTest(aBuilder, aRect, aState, aOutFrames);
    2909             :       } else {
    2910             :         // One of leaves in the current 3D rendering context.
    2911           0 :         aState->mItemBuffer.AppendElement(item);
    2912             :       }
    2913             :     }
    2914           0 :     return;
    2915             :   }
    2916             : 
    2917           0 :   int32_t itemBufferStart = aState->mItemBuffer.Length();
    2918           0 :   for (item = GetBottom(); item; item = item->GetAbove()) {
    2919           0 :     aState->mItemBuffer.AppendElement(item);
    2920             :   }
    2921             : 
    2922           0 :   AutoTArray<FramesWithDepth, 16> temp;
    2923           0 :   for (int32_t i = aState->mItemBuffer.Length() - 1; i >= itemBufferStart; --i) {
    2924             :     // Pop element off the end of the buffer. We want to shorten the buffer
    2925             :     // so that recursive calls to HitTest have more buffer space.
    2926           0 :     item = aState->mItemBuffer[i];
    2927           0 :     aState->mItemBuffer.SetLength(i);
    2928             : 
    2929             :     bool snap;
    2930           0 :     nsRect r = item->GetBounds(aBuilder, &snap).Intersect(aRect);
    2931           0 :     auto itemType = item->GetType();
    2932             :     bool same3DContext =
    2933           0 :       (itemType == DisplayItemType::TYPE_TRANSFORM &&
    2934           0 :        static_cast<nsDisplayTransform*>(item)->IsParticipating3DContext()) ||
    2935           0 :       (itemType == DisplayItemType::TYPE_PERSPECTIVE &&
    2936           0 :        item->Frame()->Extend3DContext());
    2937           0 :     if (same3DContext &&
    2938           0 :         (itemType != DisplayItemType::TYPE_TRANSFORM ||
    2939           0 :          !static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext())) {
    2940           0 :       if (!item->GetClip().MayIntersect(aRect)) {
    2941             :         continue;
    2942             :       }
    2943           0 :       AutoTArray<nsIFrame*, 1> neverUsed;
    2944             :       // Start gethering leaves of the 3D rendering context, and
    2945             :       // append leaves at the end of mItemBuffer.  Leaves are
    2946             :       // processed at following iterations.
    2947           0 :       aState->mInPreserves3D = true;
    2948           0 :       item->HitTest(aBuilder, aRect, aState, &neverUsed);
    2949           0 :       aState->mInPreserves3D = false;
    2950           0 :       i = aState->mItemBuffer.Length();
    2951             :       continue;
    2952             :     }
    2953           0 :     if (same3DContext || item->GetClip().MayIntersect(r)) {
    2954           0 :       AutoTArray<nsIFrame*, 16> outFrames;
    2955           0 :       item->HitTest(aBuilder, aRect, aState, &outFrames);
    2956             : 
    2957             :       // For 3d transforms with preserve-3d we add hit frames into the temp list
    2958             :       // so we can sort them later, otherwise we add them directly to the output list.
    2959           0 :       nsTArray<nsIFrame*> *writeFrames = aOutFrames;
    2960           0 :       if (item->GetType() == DisplayItemType::TYPE_TRANSFORM &&
    2961           0 :           static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext()) {
    2962           0 :         if (outFrames.Length()) {
    2963           0 :           nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
    2964           0 :           nsPoint point = aRect.TopLeft();
    2965             :           // A 1x1 rect means a point, otherwise use the center of the rect
    2966           0 :           if (aRect.width != 1 || aRect.height != 1) {
    2967           0 :             point = aRect.Center();
    2968             :           }
    2969           0 :           temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(aBuilder, point)));
    2970           0 :           writeFrames = &temp[temp.Length() - 1].mFrames;
    2971             :         }
    2972             :       } else {
    2973             :         // We may have just finished a run of consecutive preserve-3d transforms,
    2974             :         // so flush these into the destination array before processing our frame list.
    2975           0 :         FlushFramesArray(temp, aOutFrames);
    2976             :       }
    2977             : 
    2978           0 :       for (uint32_t j = 0; j < outFrames.Length(); j++) {
    2979           0 :         nsIFrame *f = outFrames.ElementAt(j);
    2980             :         // Filter out some frames depending on the type of hittest
    2981             :         // we are doing. For visibility tests, pass through all frames.
    2982             :         // For pointer tests, only pass through frames that are styled
    2983             :         // to receive pointer events.
    2984           0 :         if (aBuilder->HitTestIsForVisibility() ||
    2985           0 :             (!GetMouseThrough(f) && IsFrameReceivingPointerEvents(f))) {
    2986           0 :           writeFrames->AppendElement(f);
    2987             :         }
    2988             :       }
    2989             : 
    2990           0 :       if (aBuilder->HitTestIsForVisibility() &&
    2991           0 :           item->GetOpaqueRegion(aBuilder, &snap).Contains(aRect)) {
    2992             :         // We're exiting early, so pop the remaining items off the buffer.
    2993           0 :         aState->mItemBuffer.SetLength(itemBufferStart);
    2994           0 :         break;
    2995             :       }
    2996             :     }
    2997             :   }
    2998             :   // Clear any remaining preserve-3d transforms.
    2999           0 :   FlushFramesArray(temp, aOutFrames);
    3000           0 :   NS_ASSERTION(aState->mItemBuffer.Length() == uint32_t(itemBufferStart),
    3001             :                "How did we forget to pop some elements?");
    3002             : }
    3003             : 
    3004           0 : static nsIContent* FindContentInDocument(nsDisplayItem* aItem, nsIDocument* aDoc) {
    3005           0 :   nsIFrame* f = aItem->Frame();
    3006           0 :   while (f) {
    3007           0 :     nsPresContext* pc = f->PresContext();
    3008           0 :     if (pc->Document() == aDoc) {
    3009           0 :       return f->GetContent();
    3010             :     }
    3011           0 :     f = nsLayoutUtils::GetCrossDocParentFrame(pc->PresShell()->GetRootFrame());
    3012             :   }
    3013             :   return nullptr;
    3014             : }
    3015             : 
    3016             : struct ZSortItem {
    3017             :   nsDisplayItem* item;
    3018             :   int32_t zIndex;
    3019             : 
    3020          74 :   explicit ZSortItem(nsDisplayItem* aItem)
    3021           0 :     : item(aItem), zIndex(aItem->ZIndex()) {}
    3022             : 
    3023             :   operator nsDisplayItem*() {
    3024             :     return item;
    3025             :   }
    3026             : };
    3027             : 
    3028             : struct ZOrderComparator {
    3029             :   bool operator()(const ZSortItem& aLeft, const ZSortItem& aRight) const {
    3030             :     // Note that we can't just take the difference of the two
    3031             :     // z-indices here, because that might overflow a 32-bit int.
    3032         168 :     return aLeft.zIndex < aRight.zIndex;
    3033             :   }
    3034             : };
    3035             : 
    3036           0 : void nsDisplayList::SortByZOrder() {
    3037           0 :   Sort<ZSortItem>(ZOrderComparator());
    3038         110 : }
    3039             : 
    3040             : struct ContentComparator {
    3041             :   nsIContent* mCommonAncestor;
    3042             : 
    3043             :   explicit ContentComparator(nsIContent* aCommonAncestor)
    3044           0 :     : mCommonAncestor(aCommonAncestor) {}
    3045             : 
    3046           0 :   bool operator()(nsDisplayItem* aLeft, nsDisplayItem* aRight) const {
    3047             :     // It's possible that the nsIContent for aItem1 or aItem2 is in a subdocument
    3048             :     // of commonAncestor, because display items for subdocuments have been
    3049             :     // mixed into the same list. Ensure that we're looking at content
    3050             :     // in commonAncestor's document.
    3051           0 :     nsIDocument* commonAncestorDoc = mCommonAncestor->OwnerDoc();
    3052           0 :     nsIContent* content1 = FindContentInDocument(aLeft, commonAncestorDoc);
    3053           0 :     nsIContent* content2 = FindContentInDocument(aRight, commonAncestorDoc);
    3054           0 :     if (!content1 || !content2) {
    3055           0 :       NS_ERROR("Document trees are mixed up!");
    3056             :       // Something weird going on
    3057           0 :       return true;
    3058             :     }
    3059           0 :     return nsLayoutUtils::CompareTreePosition(content1, content2, mCommonAncestor) < 0;
    3060             :   }
    3061             : };
    3062             : 
    3063         110 : void nsDisplayList::SortByContentOrder(nsIContent* aCommonAncestor) {
    3064         110 :   Sort<nsDisplayItem*>(ContentComparator(aCommonAncestor));
    3065         110 : }
    3066             : 
    3067         410 : nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
    3068             :  : nsDisplayItem(aBuilder, aFrame,
    3069           0 :                  aBuilder->CurrentActiveScrolledRoot())
    3070         410 : {}
    3071             : 
    3072         546 : nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    3073             :                              const ActiveScrolledRoot* aActiveScrolledRoot,
    3074           0 :                              bool aAnonymous)
    3075             :   : mFrame(aFrame)
    3076             :   , mActiveScrolledRoot(aActiveScrolledRoot)
    3077             :   , mAnimatedGeometryRoot(nullptr)
    3078         546 :   , mForceNotVisible(aBuilder->IsBuildingInvisibleItems())
    3079             :   , mDisableSubpixelAA(false)
    3080             :   , mReusedItem(false)
    3081           0 :   , mBackfaceHidden(mFrame->In3DContextAndBackfaceIsHidden())
    3082             :   , mPaintRectValid(false)
    3083             : #ifdef MOZ_DUMP_PAINTING
    3084        5460 :   , mPainted(false)
    3085             : #endif
    3086             : {
    3087         546 :   MOZ_COUNT_CTOR(nsDisplayItem);
    3088           0 :   if (aBuilder->IsRetainingDisplayList() && !aAnonymous) {
    3089           0 :     mFrame->AddDisplayItem(this);
    3090             :   }
    3091           0 :   mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame, &mToReferenceFrame);
    3092             :   // This can return the wrong result if the item override ShouldFixToViewport(),
    3093             :   // the item needs to set it again in its constructor.
    3094           1 :   mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(aFrame);
    3095         546 :   MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(aBuilder->RootReferenceFrame(),
    3096             :                                                     *mAnimatedGeometryRoot), "Bad");
    3097         546 :   NS_ASSERTION(aBuilder->GetVisibleRect().width >= 0 ||
    3098             :                !aBuilder->IsForPainting(), "visible rect not set");
    3099             : 
    3100           0 :   SetClipChain(aBuilder->ClipState().GetCurrentCombinedClipChain(aBuilder), true);
    3101             : 
    3102             :   // The visible rect is for mCurrentFrame, so we have to use
    3103             :   // mCurrentOffsetToReferenceFrame
    3104             :   nsRect visible = aBuilder->GetVisibleRect() +
    3105        1638 :     aBuilder->GetCurrentFrameOffsetToReferenceFrame();
    3106           0 :   SetBuildingRect(visible);
    3107           0 : }
    3108             : 
    3109             : /* static */ bool
    3110         248 : nsDisplayItem::ForceActiveLayers()
    3111             : {
    3112             :   static bool sForce = false;
    3113             :   static bool sForceCached = false;
    3114             : 
    3115           0 :   if (!sForceCached) {
    3116           1 :     Preferences::AddBoolVarCache(&sForce, "layers.force-active", false);
    3117           1 :     sForceCached = true;
    3118             :   }
    3119             : 
    3120         248 :   return sForce;
    3121             : }
    3122             : 
    3123          92 : static int32_t ZIndexForFrame(nsIFrame* aFrame)
    3124             : {
    3125           0 :   if (!aFrame->IsAbsPosContainingBlock() && !aFrame->IsFlexOrGridItem())
    3126             :     return 0;
    3127             : 
    3128           0 :   const nsStylePosition* position = aFrame->StylePosition();
    3129          76 :   if (position->mZIndex.GetUnit() == eStyleUnit_Integer)
    3130          24 :     return position->mZIndex.GetIntValue();
    3131             : 
    3132             :   // sort the auto and 0 elements together
    3133             :   return 0;
    3134             : }
    3135             : 
    3136             : int32_t
    3137           0 : nsDisplayItem::ZIndex() const
    3138             : {
    3139          92 :   return ZIndexForFrame(mFrame);
    3140             : }
    3141             : 
    3142             : bool
    3143           0 : nsDisplayItem::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    3144             :                                  nsRegion* aVisibleRegion)
    3145             : {
    3146         401 :   return !GetPaintRect().IsEmpty() &&
    3147           0 :     !IsInvisibleInRect(aVisibleRegion->GetBounds());
    3148             : }
    3149             : 
    3150             : bool
    3151         136 : nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
    3152             :                                    nsRegion* aVisibleRegion,
    3153             :                                    bool aUseClipBounds) {
    3154           0 :   if (mForceNotVisible && !GetSameCoordinateSystemChildren()) {
    3155             :     // mForceNotVisible wants to ensure that this display item doesn't render
    3156             :     // anything itself. If this item has contents, then we obviously want to
    3157             :     // render those, so we don't need this check in that case.
    3158           0 :     NS_ASSERTION(GetBuildingRect().IsEmpty(),
    3159             :       "invisible items without children should have empty vis rect");
    3160           0 :     SetPaintRect(nsRect());
    3161             :   } else {
    3162           0 :     nsRect bounds;
    3163         136 :     if (aUseClipBounds) {
    3164         136 :       bounds = GetClippedBounds(aBuilder);
    3165             :     } else {
    3166             :       bool snap;
    3167           0 :       bounds = GetBounds(aBuilder, &snap);
    3168             :     }
    3169             : 
    3170         272 :     nsRegion itemVisible;
    3171         136 :     itemVisible.And(*aVisibleRegion, bounds);
    3172         272 :     SetPaintRect(itemVisible.GetBounds());
    3173             :   }
    3174             : 
    3175             :   // When we recompute visibility within layers we don't need to
    3176             :   // expand the visible region for content behind plugins (the plugin
    3177             :   // is not in the layer).
    3178         136 :   if (!ComputeVisibility(aBuilder, aVisibleRegion)) {
    3179         118 :     SetPaintRect(nsRect());
    3180           0 :     return false;
    3181             :   }
    3182             : 
    3183           0 :   nsRegion opaque = TreatAsOpaque(this, aBuilder);
    3184           0 :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
    3185             :   return true;
    3186             : }
    3187             : 
    3188             : void
    3189         671 : nsDisplayItem::SetClipChain(const DisplayItemClipChain* aClipChain,
    3190             :                             bool aStore)
    3191             : {
    3192        1342 :   mClipChain = aClipChain;
    3193        1342 :   mClip = DisplayItemClipChain::ClipForASR(aClipChain, mActiveScrolledRoot);
    3194             : 
    3195           1 :   if (aStore) {
    3196         557 :     mState.mClipChain = mClipChain;
    3197           1 :     mState.mClip = mClip;
    3198             :   }
    3199           0 : }
    3200             : 
    3201             : Maybe<nsRect>
    3202           0 : nsDisplayItem::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
    3203             :                                        const ActiveScrolledRoot* aASR) const
    3204             : {
    3205           0 :   if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
    3206           0 :     return Some(clip->GetClipRect());
    3207             :   }
    3208             : #ifdef DEBUG
    3209           0 :   if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
    3210           0 :     MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
    3211             :   }
    3212             : #endif
    3213             :   return Nothing();
    3214             : }
    3215             : 
    3216             : void
    3217           0 : nsDisplayItem::FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
    3218             :                                  const ActiveScrolledRoot* aASR)
    3219             : {
    3220           0 :   const DisplayItemClipChain* sc = mClipChain;
    3221           0 :   DisplayItemClip mergedClip;
    3222          57 :   while (sc && ActiveScrolledRoot::PickDescendant(aASR, sc->mASR) == sc->mASR) {
    3223          11 :     mergedClip.IntersectWith(sc->mClip);
    3224          22 :     sc = sc->mParent;
    3225             :   }
    3226           0 :   if (mergedClip.HasClip()) {
    3227          22 :     mClipChain = aBuilder->AllocateDisplayItemClipChain(mergedClip, aASR, sc);
    3228          11 :     mClip = &mClipChain->mClip;
    3229             :   } else {
    3230           0 :     mClipChain = nullptr;
    3231          24 :     mClip = nullptr;
    3232             :   }
    3233           0 : }
    3234             : 
    3235             : bool
    3236           0 : nsDisplayItem::ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const
    3237             : {
    3238          56 :   return CanUseAdvancedLayer(aManager) ? aFunc() : false;
    3239             : }
    3240             : 
    3241             : bool
    3242           0 : nsDisplayItem::CanUseAdvancedLayer(LayerManager* aManager) const
    3243             : {
    3244         112 :   return gfxPrefs::LayersAdvancedBasicLayerEnabled() ||
    3245         112 :     !aManager ||
    3246           1 :     aManager->GetBackendType() == layers::LayersBackend::LAYERS_WR;
    3247             : }
    3248             : 
    3249             : static const DisplayItemClipChain*
    3250           0 : FindCommonAncestorClipForIntersection(const DisplayItemClipChain* aOne,
    3251             :                                       const DisplayItemClipChain* aTwo)
    3252             : {
    3253           0 :   for (const ActiveScrolledRoot* asr =
    3254           0 :          ActiveScrolledRoot::PickDescendant(aOne->mASR, aTwo->mASR);
    3255           0 :        asr;
    3256           0 :        asr = asr->mParent) {
    3257           0 :     if (aOne == aTwo) {
    3258             :       return aOne;
    3259             :     }
    3260           0 :     if (aOne->mASR == asr) {
    3261           0 :       aOne = aOne->mParent;
    3262             :     }
    3263           0 :     if (aTwo->mASR == asr) {
    3264           0 :       aTwo = aTwo->mParent;
    3265             :     }
    3266           0 :     if (!aOne) {
    3267             :       return aTwo;
    3268             :     }
    3269           0 :     if (!aTwo) {
    3270             :       return aOne;
    3271             :     }
    3272             :   }
    3273             :   return nullptr;
    3274             : }
    3275             : 
    3276             : void
    3277           8 : nsDisplayItem::IntersectClip(nsDisplayListBuilder* aBuilder,
    3278             :                              const DisplayItemClipChain* aOther,
    3279             :                              bool aStore)
    3280             : {
    3281           0 :   if (!aOther || mClipChain == aOther) {
    3282             :     return;
    3283             :   }
    3284             : 
    3285             :   // aOther might be a reference to a clip on the stack. We need to make sure
    3286             :   // that CreateClipChainIntersection will allocate the actual intersected
    3287             :   // clip in the builder's arena, so for the mClipChain == nullptr case,
    3288             :   // we supply nullptr as the common ancestor so that CreateClipChainIntersection
    3289             :   // clones the whole chain.
    3290             :   const DisplayItemClipChain* ancestorClip =
    3291           0 :     mClipChain ? FindCommonAncestorClipForIntersection(mClipChain, aOther) : nullptr;
    3292             : 
    3293           0 :   SetClipChain(aBuilder->CreateClipChainIntersection(ancestorClip, mClipChain, aOther),
    3294           0 :                aStore);
    3295             : }
    3296             : 
    3297             : nsRect
    3298           0 : nsDisplayItem::GetClippedBounds(nsDisplayListBuilder* aBuilder) const
    3299             : {
    3300             :   bool snap;
    3301           0 :   nsRect r = GetBounds(aBuilder, &snap);
    3302        1548 :   return GetClip().ApplyNonRoundedIntersection(r);
    3303             : }
    3304             : 
    3305             : nsRect
    3306           0 : nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder,
    3307             :                                bool* aSnap) const
    3308             : {
    3309          46 :   *aSnap = true;
    3310          46 :   return mBounds;
    3311             : }
    3312             : 
    3313             : LayerState
    3314           0 : nsDisplaySolidColor::GetLayerState(nsDisplayListBuilder* aBuilder,
    3315             :                                    LayerManager* aManager,
    3316             :                                    const ContainerLayerParameters& aParameters)
    3317             : {
    3318           0 :   if (ForceActiveLayers()) {
    3319             :     return LAYER_ACTIVE;
    3320             :   }
    3321           8 :   return LAYER_NONE;
    3322             : }
    3323             : 
    3324             : already_AddRefed<Layer>
    3325           0 : nsDisplaySolidColor::BuildLayer(nsDisplayListBuilder* aBuilder,
    3326             :                                 LayerManager* aManager,
    3327             :                                 const ContainerLayerParameters& aContainerParameters)
    3328             : {
    3329             :   RefPtr<ColorLayer> layer = static_cast<ColorLayer*>
    3330           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
    3331           0 :   if (!layer) {
    3332           0 :     layer = aManager->CreateColorLayer();
    3333           0 :     if (!layer) {
    3334             :       return nullptr;
    3335             :     }
    3336             :   }
    3337           0 :   layer->SetColor(gfx::Color::FromABGR(mColor));
    3338             : 
    3339           0 :   const int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    3340           0 :   layer->SetBounds(mBounds.ToNearestPixels(appUnitsPerDevPixel));
    3341           0 :   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
    3342           0 :                                                       aContainerParameters.mOffset.y, 0));
    3343             : 
    3344           0 :   return layer.forget();
    3345             : }
    3346             : 
    3347             : void
    3348           2 : nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
    3349             :                            gfxContext* aCtx)
    3350             : {
    3351           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    3352           2 :   DrawTarget* drawTarget = aCtx->GetDrawTarget();
    3353             :   Rect rect =
    3354           4 :     NSRectToSnappedRect(GetPaintRect(), appUnitsPerDevPixel, *drawTarget);
    3355           0 :   drawTarget->FillRect(rect, ColorPattern(ToDeviceColor(mColor)));
    3356           2 : }
    3357             : 
    3358             : void
    3359           0 : nsDisplaySolidColor::WriteDebugInfo(std::stringstream& aStream)
    3360             : {
    3361           0 :   aStream << " (rgba "
    3362           0 :           << (int)NS_GET_R(mColor) << ","
    3363           0 :           << (int)NS_GET_G(mColor) << ","
    3364           0 :           << (int)NS_GET_B(mColor) << ","
    3365           0 :           << (int)NS_GET_A(mColor) << ")";
    3366           0 : }
    3367             : 
    3368             : bool
    3369           0 : nsDisplaySolidColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    3370             :                                              mozilla::wr::IpcResourceUpdateQueue& aResources,
    3371             :                                              const StackingContextHelper& aSc,
    3372             :                                              mozilla::layers::WebRenderLayerManager* aManager,
    3373             :                                              nsDisplayListBuilder* aDisplayListBuilder)
    3374             : {
    3375             :   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
    3376           0 :         GetPaintRect(), mFrame->PresContext()->AppUnitsPerDevPixel());
    3377           0 :   wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(bounds);
    3378             : 
    3379           0 :   aBuilder.PushRect(roundedRect,
    3380             :                     roundedRect,
    3381           0 :                     !BackfaceIsHidden(),
    3382           0 :                     wr::ToColorF(ToDeviceColor(mColor)));
    3383             : 
    3384           0 :   return true;
    3385             : }
    3386             : 
    3387             : nsRect
    3388           0 : nsDisplaySolidColorRegion::GetBounds(nsDisplayListBuilder* aBuilder,
    3389             :                                      bool* aSnap) const
    3390             : {
    3391           0 :   *aSnap = true;
    3392           0 :   return mRegion.GetBounds();
    3393             : }
    3394             : 
    3395             : void
    3396           0 : nsDisplaySolidColorRegion::Paint(nsDisplayListBuilder* aBuilder,
    3397             :                                  gfxContext* aCtx)
    3398             : {
    3399           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    3400           0 :   DrawTarget* drawTarget = aCtx->GetDrawTarget();
    3401           0 :   ColorPattern color(mColor);
    3402           0 :   for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
    3403             :     Rect rect =
    3404           0 :       NSRectToSnappedRect(iter.Get(), appUnitsPerDevPixel, *drawTarget);
    3405           0 :     drawTarget->FillRect(rect, color);
    3406             :   }
    3407           0 : }
    3408             : 
    3409             : void
    3410           0 : nsDisplaySolidColorRegion::WriteDebugInfo(std::stringstream& aStream)
    3411             : {
    3412           0 :   aStream << " (rgba "
    3413           0 :           << int(mColor.r * 255) << ","
    3414           0 :           << int(mColor.g * 255) << ","
    3415           0 :           << int(mColor.b * 255) << ","
    3416           0 :           << mColor.a << ")";
    3417           0 : }
    3418             : 
    3419             : bool
    3420           0 : nsDisplaySolidColorRegion::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    3421             :                                                    mozilla::wr::IpcResourceUpdateQueue& aResources,
    3422             :                                                    const StackingContextHelper& aSc,
    3423             :                                                    mozilla::layers::WebRenderLayerManager* aManager,
    3424             :                                                    nsDisplayListBuilder* aDisplayListBuilder)
    3425             : {
    3426           0 :   for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
    3427           0 :     nsRect rect = iter.Get();
    3428             :     LayoutDeviceRect layerRects = LayoutDeviceRect::FromAppUnits(
    3429           0 :       rect, mFrame->PresContext()->AppUnitsPerDevPixel());
    3430           0 :     wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(layerRects);
    3431           0 :     aBuilder.PushRect(roundedRect,
    3432             :                       roundedRect,
    3433           0 :                       !BackfaceIsHidden(),
    3434           0 :                       wr::ToColorF(ToDeviceColor(mColor)));
    3435             :   }
    3436             : 
    3437           0 :   return true;
    3438             : }
    3439             : 
    3440             : static void
    3441           0 : RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
    3442             :                       nsIFrame* aFrame, nsITheme::ThemeGeometryType aType)
    3443             : {
    3444           0 :   if (aBuilder->IsInChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
    3445           0 :     nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
    3446           0 :     nsPoint offset = aBuilder->IsInSubdocument() ? aBuilder->ToReferenceFrame(aFrame)
    3447           0 :                                                  : aFrame->GetOffsetTo(displayRoot);
    3448           0 :     nsRect borderBox = nsRect(offset, aFrame->GetSize());
    3449           0 :     aBuilder->RegisterThemeGeometry(aType, aItem,
    3450           0 :       LayoutDeviceIntRect::FromUnknownRect(
    3451           0 :         borderBox.ToNearestPixels(
    3452           0 :           aFrame->PresContext()->AppUnitsPerDevPixel())));
    3453             :   }
    3454           0 : }
    3455             : 
    3456             : // Return the bounds of the viewport relative to |aFrame|'s reference frame.
    3457             : // Returns Nothing() if transforming into |aFrame|'s coordinate space fails.
    3458             : static Maybe<nsRect>
    3459           0 : GetViewportRectRelativeToReferenceFrame(nsDisplayListBuilder* aBuilder,
    3460             :                                         nsIFrame* aFrame)
    3461             : {
    3462           0 :   nsIFrame* rootFrame = aFrame->PresShell()->GetRootFrame();
    3463           0 :   nsRect rootRect = rootFrame->GetRectRelativeToSelf();
    3464           0 :   if (nsLayoutUtils::TransformRect(rootFrame, aFrame, rootRect) == nsLayoutUtils::TRANSFORM_SUCCEEDED) {
    3465           0 :     return Some(rootRect + aBuilder->ToReferenceFrame(aFrame));
    3466             :   }
    3467             :   return Nothing();
    3468             : }
    3469             : 
    3470             : /* static */ nsDisplayBackgroundImage::InitData
    3471           1 : nsDisplayBackgroundImage::GetInitData(nsDisplayListBuilder* aBuilder,
    3472             :                                       nsIFrame* aFrame,
    3473             :                                       uint32_t aLayer,
    3474             :                                       const nsRect& aBackgroundRect,
    3475             :                                       ComputedStyle* aBackgroundStyle)
    3476             : {
    3477          16 :   nsPresContext* presContext = aFrame->PresContext();
    3478           1 :   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
    3479          32 :   const nsStyleImageLayers::Layer &layer = aBackgroundStyle->StyleBackground()->mImage.mLayers[aLayer];
    3480             : 
    3481             :   bool isTransformedFixed;
    3482             :   nsBackgroundLayerState state =
    3483             :     nsCSSRendering::PrepareImageLayer(presContext, aFrame, flags,
    3484             :                                       aBackgroundRect, aBackgroundRect, layer,
    3485           1 :                                       &isTransformedFixed);
    3486             : 
    3487             :   // background-attachment:fixed is treated as background-attachment:scroll
    3488             :   // if it's affected by a transform.
    3489             :   // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=17521.
    3490             :   bool shouldTreatAsFixed =
    3491           1 :     layer.mAttachment == StyleImageLayerAttachment::Fixed && !isTransformedFixed;
    3492             : 
    3493          16 :   bool shouldFixToViewport = shouldTreatAsFixed && !layer.mImage.IsEmpty();
    3494          16 :   bool isRasterImage = state.mImageRenderer.IsRasterImage();
    3495          32 :   nsCOMPtr<imgIContainer> image;
    3496           0 :   if (isRasterImage) {
    3497           0 :     image = state.mImageRenderer.GetImage();
    3498             :   }
    3499             :   return InitData{
    3500             :     aBuilder, aFrame, aBackgroundStyle, image, aBackgroundRect,
    3501             :     state.mFillArea, state.mDestArea, aLayer, isRasterImage,
    3502             :     shouldFixToViewport
    3503          32 :   };
    3504             : }
    3505             : 
    3506          16 : nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder,
    3507             :                                                    const InitData& aInitData,
    3508           0 :                                                    nsIFrame* aFrameForBounds)
    3509          16 :   : nsDisplayImageContainer(aBuilder, aInitData.frame)
    3510          16 :   , mBackgroundStyle(aInitData.backgroundStyle)
    3511             :   , mImage(aInitData.image)
    3512             :   , mDependentFrame(nullptr)
    3513             :   , mBackgroundRect(aInitData.backgroundRect)
    3514             :   , mFillRect(aInitData.fillArea)
    3515             :   , mDestRect(aInitData.destArea)
    3516           0 :   , mLayer(aInitData.layer)
    3517          16 :   , mIsRasterImage(aInitData.isRasterImage)
    3518          16 :   , mShouldFixToViewport(aInitData.shouldFixToViewport)
    3519          80 :   , mImageFlags(0)
    3520             : {
    3521          16 :   MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
    3522             : 
    3523          16 :   mBounds = GetBoundsInternal(aInitData.builder, aFrameForBounds);
    3524          16 :   if (mShouldFixToViewport) {
    3525           0 :     mAnimatedGeometryRoot = aInitData.builder->FindAnimatedGeometryRootFor(this);
    3526             : 
    3527             :     // Expand the item's visible rect to cover the entire bounds, limited to the
    3528             :     // viewport rect. This is necessary because the background's clip can move
    3529             :     // asynchronously.
    3530           0 :     if (Maybe<nsRect> viewportRect = GetViewportRectRelativeToReferenceFrame(aInitData.builder, mFrame)) {
    3531           0 :       SetBuildingRect(mBounds.Intersect(*viewportRect));
    3532             :     }
    3533             :   }
    3534           0 : }
    3535             : 
    3536          32 : nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
    3537             : {
    3538             : #ifdef NS_BUILD_REFCNT_LOGGING
    3539          16 :   MOZ_COUNT_DTOR(nsDisplayBackgroundImage);
    3540             : #endif
    3541          16 :   if (mDependentFrame) {
    3542           0 :     mDependentFrame->RemoveDisplayItem(this);
    3543             :   }
    3544          16 : }
    3545             : 
    3546           0 : static nsIFrame* GetBackgroundComputedStyleFrame(nsIFrame* aFrame)
    3547             : {
    3548             :   nsIFrame* f;
    3549          56 :   if (!nsCSSRendering::FindBackgroundFrame(aFrame, &f)) {
    3550             :     // We don't want to bail out if moz-appearance is set on a root
    3551             :     // node. If it has a parent content node, bail because it's not
    3552             :     // a root, other wise keep going in order to let the theme stuff
    3553             :     // draw the background. The canvas really should be drawing the
    3554             :     // bg, but there's no way to hook that up via css.
    3555           0 :     if (!aFrame->StyleDisplay()->mAppearance) {
    3556             :       return nullptr;
    3557             :     }
    3558             : 
    3559           0 :     nsIContent* content = aFrame->GetContent();
    3560           0 :     if (!content || content->GetParent()) {
    3561             :       return nullptr;
    3562             :     }
    3563             : 
    3564           0 :     f = aFrame;
    3565             :   }
    3566          56 :   return f;
    3567             : }
    3568             : 
    3569             : static void
    3570          16 : SetBackgroundClipRegion(DisplayListClipState::AutoSaveRestore& aClipState,
    3571             :                         nsIFrame* aFrame, const nsPoint& aToReferenceFrame,
    3572             :                         const nsStyleImageLayers::Layer& aLayer,
    3573             :                         const nsRect& aBackgroundRect,
    3574             :                         bool aWillPaintBorder)
    3575             : {
    3576           0 :   nsCSSRendering::ImageLayerClipState clip;
    3577          16 :   nsCSSRendering::GetImageLayerClip(aLayer, aFrame, *aFrame->StyleBorder(),
    3578             :                                     aBackgroundRect, aBackgroundRect, aWillPaintBorder,
    3579             :                                     aFrame->PresContext()->AppUnitsPerDevPixel(),
    3580          16 :                                     &clip);
    3581             : 
    3582          16 :   if (clip.mHasAdditionalBGClipArea) {
    3583           0 :     aClipState.ClipContentDescendants(clip.mAdditionalBGClipArea, clip.mBGClipArea,
    3584           0 :                                       clip.mHasRoundedCorners ? clip.mRadii : nullptr);
    3585             :   } else {
    3586           0 :     aClipState.ClipContentDescendants(clip.mBGClipArea, clip.mHasRoundedCorners ? clip.mRadii : nullptr);
    3587             :   }
    3588          16 : }
    3589             : 
    3590             : /**
    3591             :  * This is used for the find bar highlighter overlay. It's only accessible
    3592             :  * through the AnonymousContent API, so it's not exposed to general web pages.
    3593             :  */
    3594             : static bool
    3595          72 : SpecialCutoutRegionCase(nsDisplayListBuilder* aBuilder,
    3596             :                         nsIFrame* aFrame,
    3597             :                         const nsRect& aBackgroundRect,
    3598             :                         nsDisplayList* aList,
    3599             :                         nscolor aColor)
    3600             : {
    3601           1 :   nsIContent* content = aFrame->GetContent();
    3602          72 :   if (!content) {
    3603             :     return false;
    3604             :   }
    3605             : 
    3606          72 :   void* cutoutRegion = content->GetProperty(nsGkAtoms::cutoutregion);
    3607           0 :   if (!cutoutRegion) {
    3608             :     return false;
    3609             :   }
    3610             : 
    3611           0 :   if (NS_GET_A(aColor) == 0) {
    3612             :     return true;
    3613             :   }
    3614             : 
    3615           0 :   nsRegion region;
    3616           0 :   region.Sub(aBackgroundRect, *static_cast<nsRegion*>(cutoutRegion));
    3617           0 :   region.MoveBy(aBuilder->ToReferenceFrame(aFrame));
    3618             :   aList->AppendToTop(
    3619           0 :     MakeDisplayItem<nsDisplaySolidColorRegion>(aBuilder, aFrame, region, aColor));
    3620             : 
    3621             :   return true;
    3622             : }
    3623             : 
    3624             : 
    3625             : /*static*/ bool
    3626          72 : nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
    3627             :                                                      nsIFrame* aFrame,
    3628             :                                                      const nsRect& aBackgroundRect,
    3629             :                                                      nsDisplayList* aList,
    3630             :                                                      bool aAllowWillPaintBorderOptimization,
    3631             :                                                      ComputedStyle* aComputedStyle,
    3632             :                                                      const nsRect& aBackgroundOriginRect,
    3633             :                                                      nsIFrame* aSecondaryReferenceFrame)
    3634             : {
    3635          72 :   ComputedStyle* bgSC = aComputedStyle;
    3636          72 :   const nsStyleBackground* bg = nullptr;
    3637         144 :   nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
    3638           0 :   nsRect bgOriginRect = bgRect;
    3639           0 :   if (!aBackgroundOriginRect.IsEmpty()) {
    3640           0 :     bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
    3641             :   }
    3642         144 :   nsPresContext* presContext = aFrame->PresContext();
    3643           0 :   bool isThemed = aFrame->IsThemed();
    3644           0 :   nsIFrame* dependentFrame = nullptr;
    3645          72 :   if (!isThemed) {
    3646          56 :     if (!bgSC) {
    3647          56 :       dependentFrame = GetBackgroundComputedStyleFrame(aFrame);
    3648           1 :       if (dependentFrame) {
    3649          56 :         bgSC = dependentFrame->Style();
    3650          56 :         if (dependentFrame == aFrame) {
    3651          48 :           dependentFrame = nullptr;
    3652             :         }
    3653             :       }
    3654             :     }
    3655          56 :     if (bgSC) {
    3656           1 :       bg = bgSC->StyleBackground();
    3657             :     }
    3658             :   }
    3659             : 
    3660          72 :   bool drawBackgroundColor = false;
    3661             :   // Dummy initialisation to keep Valgrind/Memcheck happy.
    3662             :   // See bug 1122375 comment 1.
    3663           0 :   nscolor color = NS_RGBA(0,0,0,0);
    3664          72 :   if (!nsCSSRendering::IsCanvasFrame(aFrame) && bg) {
    3665             :     bool drawBackgroundImage;
    3666             :     color =
    3667          48 :       nsCSSRendering::DetermineBackgroundColor(presContext, bgSC, aFrame,
    3668          48 :                                                drawBackgroundImage, drawBackgroundColor);
    3669             :   }
    3670             : 
    3671          72 :   if (SpecialCutoutRegionCase(aBuilder, aFrame, aBackgroundRect, aList, color)) {
    3672             :     return false;
    3673             :   }
    3674             : 
    3675           0 :   const nsStyleBorder* borderStyle = aFrame->StyleBorder();
    3676           0 :   const nsStyleEffects* effectsStyle = aFrame->StyleEffects();
    3677           0 :   bool hasInsetShadow = effectsStyle->mBoxShadow &&
    3678         232 :                         effectsStyle->mBoxShadow->HasShadowWithInset(true);
    3679           0 :   bool willPaintBorder = aAllowWillPaintBorderOptimization &&
    3680           0 :                          !isThemed && !hasInsetShadow &&
    3681           0 :                          borderStyle->HasBorder();
    3682             : 
    3683           0 :   nsPoint toRef = aBuilder->ToReferenceFrame(aFrame);
    3684             : 
    3685             :   // An auxiliary list is necessary in case we have background blending; if that
    3686             :   // is the case, background items need to be wrapped by a blend container to
    3687             :   // isolate blending to the background
    3688           0 :   nsDisplayList bgItemList;
    3689             :   // Even if we don't actually have a background color to paint, we may still need
    3690             :   // to create an item for hit testing.
    3691          96 :   if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) ||
    3692           0 :       aBuilder->IsForEventDelivery()) {
    3693           0 :     Maybe<DisplayListClipState::AutoSaveRestore> clipState;
    3694          96 :     nsRect bgColorRect = bgRect;
    3695          48 :     if (bg && !aBuilder->IsForEventDelivery()) {
    3696             :       // Disable the will-paint-border optimization for background
    3697             :       // colors with no border-radius. Enabling it for background colors
    3698             :       // doesn't help much (there are no tiling issues) and clipping the
    3699             :       // background breaks detection of the element's border-box being
    3700             :       // opaque. For nonzero border-radius we still need it because we
    3701             :       // want to inset the background if possible to avoid antialiasing
    3702             :       // artifacts along the rounded corners.
    3703          72 :       bool useWillPaintBorderOptimization = willPaintBorder &&
    3704           0 :           nsLayoutUtils::HasNonZeroCorner(borderStyle->mBorderRadius);
    3705             : 
    3706          96 :       nsCSSRendering::ImageLayerClipState clip;
    3707         144 :       nsCSSRendering::GetImageLayerClip(bg->BottomLayer(), aFrame, *aFrame->StyleBorder(),
    3708             :                                         bgRect, bgRect, useWillPaintBorderOptimization,
    3709             :                                         aFrame->PresContext()->AppUnitsPerDevPixel(),
    3710          96 :                                         &clip);
    3711             : 
    3712           0 :       bgColorRect = bgColorRect.Intersect(clip.mBGClipArea);
    3713           0 :       if (clip.mHasAdditionalBGClipArea) {
    3714           0 :         bgColorRect = bgColorRect.Intersect(clip.mAdditionalBGClipArea);
    3715             :       }
    3716           0 :       if (clip.mHasRoundedCorners) {
    3717           0 :         clipState.emplace(aBuilder);
    3718           0 :         clipState->ClipContentDescendants(clip.mBGClipArea, clip.mRadii);
    3719             :       }
    3720             :     }
    3721             :     nsDisplayBackgroundColor *bgItem;
    3722          48 :     if (aSecondaryReferenceFrame) {
    3723             :       bgItem =
    3724           0 :           MakeDisplayItem<nsDisplayTableBackgroundColor>(aBuilder, aSecondaryReferenceFrame, bgColorRect, bgSC,
    3725           0 :                                                        drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0),
    3726           0 :                                                        aFrame);
    3727             :     } else {
    3728             :       bgItem =
    3729           0 :           MakeDisplayItem<nsDisplayBackgroundColor>(aBuilder, aFrame, bgColorRect, bgSC,
    3730           0 :                                                   drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0));
    3731             :     }
    3732           0 :     bgItem->SetDependentFrame(aBuilder, dependentFrame);
    3733          48 :     bgItemList.AppendToTop(bgItem);
    3734             :   }
    3735             : 
    3736          72 :   if (isThemed) {
    3737          16 :     nsITheme* theme = presContext->GetTheme();
    3738          32 :     if (theme->NeedToClearBackgroundBehindWidget(aFrame, aFrame->StyleDisplay()->mAppearance) &&
    3739          16 :         aBuilder->IsInChromeDocumentOrPopup() && !aBuilder->IsInTransform()) {
    3740           0 :       bgItemList.AppendToTop(
    3741           0 :         MakeDisplayItem<nsDisplayClearBackground>(aBuilder, aFrame));
    3742             :     }
    3743           0 :     if (aSecondaryReferenceFrame) {
    3744             :       nsDisplayTableThemedBackground* bgItem =
    3745           0 :         MakeDisplayItem<nsDisplayTableThemedBackground>(aBuilder,
    3746             :                                                       aSecondaryReferenceFrame,
    3747             :                                                       bgRect,
    3748           0 :                                                       aFrame);
    3749           0 :       bgItem->Init(aBuilder);
    3750           0 :       bgItemList.AppendToTop(bgItem);
    3751             :     } else {
    3752             :       nsDisplayThemedBackground* bgItem =
    3753           0 :         MakeDisplayItem<nsDisplayThemedBackground>(aBuilder, aFrame, bgRect);
    3754           0 :       bgItem->Init(aBuilder);
    3755           0 :       bgItemList.AppendToTop(bgItem);
    3756             :     }
    3757          16 :     aList->AppendToTop(&bgItemList);
    3758          16 :     return true;
    3759             :   }
    3760             : 
    3761           0 :   if (!bg) {
    3762           0 :     aList->AppendToTop(&bgItemList);
    3763           0 :     return false;
    3764             :   }
    3765             : 
    3766             :   const ActiveScrolledRoot* asr =
    3767           0 :     aBuilder->CurrentActiveScrolledRoot();
    3768             : 
    3769           0 :   bool needBlendContainer = false;
    3770             : 
    3771             :   // Passing bg == nullptr in this macro will result in one iteration with
    3772             :   // i = 0.
    3773           0 :   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, bg->mImage) {
    3774           0 :     if (bg->mImage.mLayers[i].mImage.IsEmpty()) {
    3775           0 :       continue;
    3776             :     }
    3777             : 
    3778           1 :     if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
    3779           0 :       needBlendContainer = true;
    3780             :     }
    3781             : 
    3782           0 :     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
    3783          16 :     if (!aBuilder->IsForEventDelivery()) {
    3784          16 :       const nsStyleImageLayers::Layer& layer = bg->mImage.mLayers[i];
    3785           0 :       SetBackgroundClipRegion(clipState, aFrame, toRef,
    3786           0 :                               layer, bgRect, willPaintBorder);
    3787             :     }
    3788             : 
    3789          32 :     nsDisplayList thisItemList;
    3790             :     nsDisplayBackgroundImage::InitData bgData =
    3791           0 :       nsDisplayBackgroundImage::GetInitData(aBuilder, aFrame, i, bgOriginRect, bgSC);
    3792             : 
    3793          16 :     if (bgData.shouldFixToViewport) {
    3794             : 
    3795           0 :       auto* displayData = aBuilder->GetCurrentFixedBackgroundDisplayData();
    3796             :       nsDisplayListBuilder::AutoBuildingDisplayList
    3797           0 :         buildingDisplayList(aBuilder, aFrame, aBuilder->GetVisibleRect(), aBuilder->GetDirtyRect(), false);
    3798             : 
    3799           0 :       nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter asrSetter(aBuilder);
    3800           0 :       if (displayData) {
    3801           0 :         asrSetter.SetCurrentActiveScrolledRoot(
    3802           0 :           displayData->mContainingBlockActiveScrolledRoot);
    3803           0 :         if (nsLayoutUtils::UsesAsyncScrolling(aFrame)) {
    3804             :           // Override the dirty rect on the builder to be the dirty rect of
    3805             :           // the viewport.
    3806             :           // displayData->mDirtyRect is relative to the presshell's viewport
    3807             :           // frame (the root frame), and we need it to be relative to aFrame.
    3808           0 :           nsIFrame* rootFrame = aBuilder->CurrentPresShellState()->mPresShell->GetRootFrame();
    3809             :           // There cannot be any transforms between aFrame and rootFrame
    3810             :           // because then bgData.shouldFixToViewport would have been false.
    3811           0 :           nsRect visibleRect = displayData->mVisibleRect + aFrame->GetOffsetTo(rootFrame);
    3812           0 :           aBuilder->SetVisibleRect(visibleRect);
    3813           0 :           nsRect dirtyRect = displayData->mDirtyRect + aFrame->GetOffsetTo(rootFrame);
    3814           0 :           aBuilder->SetDirtyRect(dirtyRect);
    3815             :         }
    3816             :       }
    3817           0 :       nsDisplayBackgroundImage* bgItem = nullptr;
    3818             :       {
    3819             :         // The clip is captured by the nsDisplayFixedPosition, so clear the
    3820             :         // clip for the nsDisplayBackgroundImage inside.
    3821           0 :         DisplayListClipState::AutoSaveRestore bgImageClip(aBuilder);
    3822           0 :         bgImageClip.Clear();
    3823           0 :         if (aSecondaryReferenceFrame) {
    3824           0 :           nsDisplayBackgroundImage::InitData tableData = bgData;
    3825           0 :           nsIFrame* styleFrame = tableData.frame;
    3826           0 :           tableData.frame = aSecondaryReferenceFrame;
    3827           0 :           bgItem = MakeDisplayItem<nsDisplayTableBackgroundImage>(aBuilder, tableData, styleFrame);
    3828             :         } else {
    3829           0 :           bgItem = MakeDisplayItem<nsDisplayBackgroundImage>(aBuilder, bgData);
    3830             :         }
    3831             :       }
    3832           0 :       bgItem->SetDependentFrame(aBuilder, dependentFrame);
    3833           0 :       if (aSecondaryReferenceFrame) {
    3834           0 :         thisItemList.AppendToTop(
    3835           0 :           nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder,
    3836             :                                                                 aSecondaryReferenceFrame,
    3837             :                                                                 bgItem,
    3838             :                                                                 i,
    3839           0 :                                                                 aFrame));
    3840             :       } else {
    3841           0 :         thisItemList.AppendToTop(
    3842           0 :           nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
    3843             :       }
    3844             : 
    3845             :     } else {
    3846             :       nsDisplayBackgroundImage* bgItem;
    3847          16 :       if (aSecondaryReferenceFrame) {
    3848           0 :         nsDisplayBackgroundImage::InitData tableData = bgData;
    3849           0 :         nsIFrame* styleFrame = tableData.frame;
    3850           0 :         tableData.frame = aSecondaryReferenceFrame;
    3851             : 
    3852           0 :         bgItem = MakeDisplayItem<nsDisplayTableBackgroundImage>(aBuilder, tableData, styleFrame);
    3853             :       } else {
    3854           0 :         bgItem = MakeDisplayItem<nsDisplayBackgroundImage>(aBuilder, bgData);
    3855             :       }
    3856          16 :       bgItem->SetDependentFrame(aBuilder, dependentFrame);
    3857          16 :       thisItemList.AppendToTop(bgItem);
    3858             :     }
    3859             : 
    3860           0 :     if (bg->mImage.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
    3861           0 :       DisplayListClipState::AutoSaveRestore blendClip(aBuilder);
    3862             :       // asr is scrolled. Even if we wrap a fixed background layer, that's
    3863             :       // fine, because the item will have a scrolled clip that limits the
    3864             :       // item with respect to asr.
    3865           0 :       if (aSecondaryReferenceFrame) {
    3866           0 :         thisItemList.AppendToTop(
    3867           0 :           MakeDisplayItem<nsDisplayTableBlendMode>(aBuilder, aSecondaryReferenceFrame, &thisItemList,
    3868           0 :                                                  bg->mImage.mLayers[i].mBlendMode,
    3869           0 :                                                  asr, i + 1, aFrame));
    3870             :       } else {
    3871           0 :         thisItemList.AppendToTop(
    3872           0 :           MakeDisplayItem<nsDisplayBlendMode>(aBuilder, aFrame, &thisItemList,
    3873           0 :                                             bg->mImage.mLayers[i].mBlendMode,
    3874           0 :                                             asr, i + 1));
    3875             :       }
    3876             :     }
    3877          16 :     bgItemList.AppendToTop(&thisItemList);
    3878             :   }
    3879             : 
    3880          56 :   if (needBlendContainer) {
    3881           0 :     DisplayListClipState::AutoSaveRestore blendContainerClip(aBuilder);
    3882           0 :     if (aSecondaryReferenceFrame) {
    3883           0 :       bgItemList.AppendToTop(
    3884           0 :         nsDisplayTableBlendContainer::CreateForBackgroundBlendMode(aBuilder, aSecondaryReferenceFrame,
    3885           0 :                                                                    &bgItemList, asr, aFrame));
    3886             :     } else {
    3887           0 :       bgItemList.AppendToTop(
    3888           0 :         nsDisplayBlendContainer::CreateForBackgroundBlendMode(aBuilder, aFrame, &bgItemList, asr));
    3889             :     }
    3890             :   }
    3891             : 
    3892          56 :   aList->AppendToTop(&bgItemList);
    3893           0 :   return false;
    3894             : }
    3895             : 
    3896             : // Check that the rounded border of aFrame, added to aToReferenceFrame,
    3897             : // intersects aRect.  Assumes that the unrounded border has already
    3898             : // been checked for intersection.
    3899             : static bool
    3900           0 : RoundedBorderIntersectsRect(nsIFrame* aFrame,
    3901             :                             const nsPoint& aFrameToReferenceFrame,
    3902             :                             const nsRect& aTestRect)
    3903             : {
    3904           0 :   if (!nsRect(aFrameToReferenceFrame, aFrame->GetSize()).Intersects(aTestRect))
    3905             :     return false;
    3906             : 
    3907             :   nscoord radii[8];
    3908           0 :   return !aFrame->GetBorderRadii(radii) ||
    3909           0 :          nsLayoutUtils::RoundedRectIntersectsRect(nsRect(aFrameToReferenceFrame,
    3910           0 :                                                   aFrame->GetSize()),
    3911           0 :                                                   radii, aTestRect);
    3912             : }
    3913             : 
    3914             : // Returns TRUE if aContainedRect is guaranteed to be contained in
    3915             : // the rounded rect defined by aRoundedRect and aRadii. Complex cases are
    3916             : // handled conservatively by returning FALSE in some situations where
    3917             : // a more thorough analysis could return TRUE.
    3918             : //
    3919             : // See also RoundedRectIntersectsRect.
    3920           0 : static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
    3921             :                                     const nscoord aRadii[8],
    3922             :                                     const nsRect& aContainedRect) {
    3923           0 :   nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(aRoundedRect, aRadii, aContainedRect);
    3924           0 :   return rgn.Contains(aContainedRect);
    3925             : }
    3926             : 
    3927             : bool
    3928           0 : nsDisplayBackgroundImage::CanOptimizeToImageLayer(LayerManager* aManager,
    3929             :                                                   nsDisplayListBuilder* aBuilder)
    3930             : {
    3931           0 :   if (!mBackgroundStyle) {
    3932             :     return false;
    3933             :   }
    3934             : 
    3935             :   // We currently can't handle tiled backgrounds.
    3936           0 :   if (!mDestRect.Contains(mFillRect)) {
    3937             :     return false;
    3938             :   }
    3939             : 
    3940             :   // For 'contain' and 'cover', we allow any pixel of the image to be sampled
    3941             :   // because there isn't going to be any spriting/atlasing going on.
    3942           0 :   const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
    3943             :   bool allowPartialImages =
    3944           0 :     (layer.mSize.mWidthType == nsStyleImageLayers::Size::eContain ||
    3945           0 :      layer.mSize.mWidthType == nsStyleImageLayers::Size::eCover);
    3946           0 :   if (!allowPartialImages && !mFillRect.Contains(mDestRect)) {
    3947             :     return false;
    3948             :   }
    3949             : 
    3950           0 :   return nsDisplayImageContainer::CanOptimizeToImageLayer(aManager, aBuilder);
    3951             : }
    3952             : 
    3953             : nsRect
    3954           2 : nsDisplayBackgroundImage::GetDestRect() const
    3955             : {
    3956           2 :   return mDestRect;
    3957             : }
    3958             : 
    3959             : already_AddRefed<imgIContainer>
    3960           0 : nsDisplayBackgroundImage::GetImage()
    3961             : {
    3962           0 :   nsCOMPtr<imgIContainer> image = mImage;
    3963           0 :   return image.forget();
    3964             : }
    3965             : 
    3966             : nsDisplayBackgroundImage::ImageLayerization
    3967          16 : nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
    3968             :                                                LayerManager* aManager)
    3969             : {
    3970          16 :   if (ForceActiveLayers()) {
    3971             :     return WHENEVER_POSSIBLE;
    3972             :   }
    3973             : 
    3974          16 :   nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(StyleFrame());
    3975          16 :   if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder,
    3976             :                                                        backgroundStyleFrame)) {
    3977             :     return WHENEVER_POSSIBLE;
    3978             :   }
    3979             : 
    3980          16 :   if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
    3981           0 :     const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
    3982           0 :     const nsStyleImage* image = &layer.mImage;
    3983           0 :     if (image->GetType() == eStyleImageType_Image) {
    3984           0 :       imgIRequest* imgreq = image->GetImageData();
    3985           0 :       nsCOMPtr<imgIContainer> image;
    3986           0 :       if (imgreq &&
    3987           0 :           NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) &&
    3988           0 :           image) {
    3989           0 :         bool animated = false;
    3990           0 :         if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
    3991           0 :           return WHENEVER_POSSIBLE;
    3992             :         }
    3993             :       }
    3994             :     }
    3995             :   }
    3996             : 
    3997           0 :   if (nsLayoutUtils::GPUImageScalingEnabled() &&
    3998           0 :       aManager->IsCompositingCheap()) {
    3999             :     return ONLY_FOR_SCALING;
    4000             :   }
    4001             : 
    4002          16 :   return NO_LAYER_NEEDED;
    4003             : }
    4004             : 
    4005          16 : static void CheckForBorderItem(nsDisplayItem *aItem, uint32_t& aFlags)
    4006             : {
    4007           0 :   nsDisplayItem* nextItem = aItem->GetAbove();
    4008          16 :   while (nextItem && nextItem->GetType() == DisplayItemType::TYPE_BACKGROUND) {
    4009           0 :     nextItem = nextItem->GetAbove();
    4010             :   }
    4011           0 :   if (nextItem &&
    4012           0 :       nextItem->Frame() == aItem->Frame() &&
    4013           8 :       nextItem->GetType() == DisplayItemType::TYPE_BORDER) {
    4014           8 :     aFlags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
    4015             :   }
    4016          16 : }
    4017             : 
    4018             : LayerState
    4019           1 : nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
    4020             :                                         LayerManager* aManager,
    4021             :                                         const ContainerLayerParameters& aParameters)
    4022             : {
    4023           1 :   mImageFlags = aBuilder->GetBackgroundPaintFlags();
    4024           1 :   CheckForBorderItem(this, mImageFlags);
    4025             : 
    4026           1 :   ImageLayerization shouldLayerize = ShouldCreateOwnLayer(aBuilder, aManager);
    4027           1 :   if (shouldLayerize == NO_LAYER_NEEDED) {
    4028             :     // We can skip the call to CanOptimizeToImageLayer if we don't want a
    4029             :     // layer anyway.
    4030             :     return LAYER_NONE;
    4031             :   }
    4032             : 
    4033           0 :   if (CanOptimizeToImageLayer(aManager, aBuilder)) {
    4034           0 :     if (shouldLayerize == WHENEVER_POSSIBLE) {
    4035           0 :       return LAYER_ACTIVE;
    4036             :     }
    4037             : 
    4038           0 :     MOZ_ASSERT(shouldLayerize == ONLY_FOR_SCALING, "unhandled ImageLayerization value?");
    4039             : 
    4040           0 :     MOZ_ASSERT(mImage);
    4041             :     int32_t imageWidth;
    4042             :     int32_t imageHeight;
    4043           0 :     mImage->GetWidth(&imageWidth);
    4044           0 :     mImage->GetHeight(&imageHeight);
    4045           0 :     NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
    4046             : 
    4047           0 :     int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    4048           0 :     LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(GetDestRect(), appUnitsPerDevPixel);
    4049             : 
    4050           0 :     const LayerRect destLayerRect = destRect * aParameters.Scale();
    4051             : 
    4052             :     // Calculate the scaling factor for the frame.
    4053           0 :     const gfxSize scale = gfxSize(destLayerRect.width / imageWidth,
    4054           0 :                                   destLayerRect.height / imageHeight);
    4055             : 
    4056           0 :     if ((scale.width != 1.0f || scale.height != 1.0f) &&
    4057           0 :         (destLayerRect.width * destLayerRect.height >= 64 * 64)) {
    4058             :       // Separate this image into a layer.
    4059             :       // There's no point in doing this if we are not scaling at all or if the
    4060             :       // target size is pretty small.
    4061             :       return LAYER_ACTIVE;
    4062             :     }
    4063             :   }
    4064             : 
    4065             :   return LAYER_NONE;
    4066             : }
    4067             : 
    4068             : already_AddRefed<Layer>
    4069           0 : nsDisplayBackgroundImage::BuildLayer(nsDisplayListBuilder* aBuilder,
    4070             :                                      LayerManager* aManager,
    4071             :                                      const ContainerLayerParameters& aParameters)
    4072             : {
    4073             :   RefPtr<ImageLayer> layer = static_cast<ImageLayer*>
    4074           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
    4075           0 :   if (!layer) {
    4076           0 :     layer = aManager->CreateImageLayer();
    4077           0 :     if (!layer)
    4078             :       return nullptr;
    4079             :   }
    4080           0 :   RefPtr<ImageContainer> imageContainer = GetContainer(aManager, aBuilder);
    4081           0 :   layer->SetContainer(imageContainer);
    4082           0 :   ConfigureLayer(layer, aParameters);
    4083           0 :   return layer.forget();
    4084             : }
    4085             : 
    4086             : bool
    4087           0 : nsDisplayBackgroundImage::CanBuildWebRenderDisplayItems(LayerManager* aManager, nsDisplayListBuilder* aDisplayListBuilder)
    4088             : {
    4089           0 :   if (aDisplayListBuilder) {
    4090           0 :     mImageFlags = aDisplayListBuilder->GetBackgroundPaintFlags();
    4091             :   }
    4092             : 
    4093           0 :   return mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mClip != StyleGeometryBox::Text &&
    4094           0 :          nsCSSRendering::CanBuildWebRenderDisplayItemsForStyleImageLayer(aManager,
    4095           0 :                                                                          *StyleFrame()->PresContext(),
    4096           0 :                                                                          StyleFrame(),
    4097             :                                                                          mBackgroundStyle->StyleBackground(),
    4098           0 :                                                                          mLayer,
    4099           0 :                                                                          mImageFlags);
    4100             : }
    4101             : 
    4102             : bool
    4103           0 : nsDisplayBackgroundImage::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    4104             :                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
    4105             :                                                   const StackingContextHelper& aSc,
    4106             :                                                   WebRenderLayerManager* aManager,
    4107             :                                                   nsDisplayListBuilder* aDisplayListBuilder)
    4108             : {
    4109           0 :   ContainerLayerParameters parameter;
    4110           0 :   if (!CanBuildWebRenderDisplayItems(aManager, aDisplayListBuilder)) {
    4111             :     return false;
    4112             :   }
    4113             : 
    4114           0 :   CheckForBorderItem(this, mImageFlags);
    4115             :   nsCSSRendering::PaintBGParams params =
    4116           0 :     nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(),
    4117             :                                                   GetPaintRect(), mBackgroundRect,
    4118           0 :                                                   StyleFrame(), mImageFlags, mLayer,
    4119           0 :                                                   CompositionOp::OP_OVER);
    4120           0 :   params.bgClipRect = &mBounds;
    4121             :   ImgDrawResult result =
    4122           0 :     nsCSSRendering::BuildWebRenderDisplayItemsForStyleImageLayer(params, aBuilder, aResources, aSc, aManager, this);
    4123           0 :   nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
    4124             : 
    4125             :   return true;
    4126             : }
    4127             : 
    4128             : void
    4129           0 : nsDisplayBackgroundImage::HitTest(nsDisplayListBuilder* aBuilder,
    4130             :                                   const nsRect& aRect,
    4131             :                                   HitTestState* aState,
    4132             :                                   nsTArray<nsIFrame*> *aOutFrames)
    4133             : {
    4134           0 :   if (RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
    4135           0 :     aOutFrames->AppendElement(mFrame);
    4136             :   }
    4137           0 : }
    4138             : 
    4139             : bool
    4140           1 : nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    4141             :                                             nsRegion* aVisibleRegion)
    4142             : {
    4143           8 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
    4144             :     return false;
    4145             :   }
    4146             : 
    4147             :   // Return false if the background was propagated away from this
    4148             :   // frame. We don't want this display item to show up and confuse
    4149             :   // anything.
    4150           8 :   return mBackgroundStyle;
    4151             : }
    4152             : 
    4153             : /* static */ nsRegion
    4154          11 : nsDisplayBackgroundImage::GetInsideClipRegion(const nsDisplayItem* aItem,
    4155             :                                               StyleGeometryBox aClip,
    4156             :                                               const nsRect& aRect,
    4157             :                                               const nsRect& aBackgroundRect)
    4158             : {
    4159           1 :   nsRegion result;
    4160           1 :   if (aRect.IsEmpty())
    4161           0 :     return result;
    4162             : 
    4163          11 :   nsIFrame *frame = aItem->Frame();
    4164             : 
    4165          22 :   nsRect clipRect = aBackgroundRect;
    4166           0 :   if (frame->IsCanvasFrame()) {
    4167           0 :     nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
    4168           0 :     clipRect = canvasFrame->CanvasArea() + aItem->ToReferenceFrame();
    4169          11 :   } else if (aClip == StyleGeometryBox::PaddingBox ||
    4170             :              aClip == StyleGeometryBox::ContentBox) {
    4171           0 :     nsMargin border = frame->GetUsedBorder();
    4172           0 :     if (aClip == StyleGeometryBox::ContentBox) {
    4173           4 :       border += frame->GetUsedPadding();
    4174             :     }
    4175           6 :     border.ApplySkipSides(frame->GetSkipSides());
    4176           6 :     clipRect.Deflate(border);
    4177             :   }
    4178             : 
    4179          11 :   return clipRect.Intersect(aRect);
    4180             : }
    4181             : 
    4182             : nsRegion
    4183           4 : nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    4184             :                                           bool* aSnap) const
    4185             : {
    4186           4 :   nsRegion result;
    4187           0 :   *aSnap = false;
    4188             : 
    4189           8 :   if (!mBackgroundStyle)
    4190             :     return result;
    4191             : 
    4192           4 :   *aSnap = true;
    4193             : 
    4194             :   // For StyleBoxDecorationBreak::Slice, don't try to optimize here, since
    4195             :   // this could easily lead to O(N^2) behavior inside InlineBackgroundData,
    4196             :   // which expects frames to be sent to it in content order, not reverse
    4197             :   // content order which we'll produce here.
    4198             :   // Of course, if there's only one frame in the flow, it doesn't matter.
    4199           8 :   if (mFrame->StyleBorder()->mBoxDecorationBreak ==
    4200           0 :         StyleBoxDecorationBreak::Clone ||
    4201           8 :       (!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
    4202           0 :     const nsStyleImageLayers::Layer& layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
    4203           0 :     if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
    4204           0 :         layer.mRepeat.mXRepeat != StyleImageLayerRepeat::Space &&
    4205           0 :         layer.mRepeat.mYRepeat != StyleImageLayerRepeat::Space &&
    4206           0 :         layer.mClip != StyleGeometryBox::Text) {
    4207           0 :       result = GetInsideClipRegion(this, layer.mClip, mBounds, mBackgroundRect);
    4208             :     }
    4209             :   }
    4210             : 
    4211             :   return result;
    4212             : }
    4213             : 
    4214             : Maybe<nscolor>
    4215           0 : nsDisplayBackgroundImage::IsUniform(nsDisplayListBuilder* aBuilder) const
    4216             : {
    4217           0 :   if (!mBackgroundStyle) {
    4218           0 :     return Some(NS_RGBA(0,0,0,0));
    4219             :   }
    4220             :   return Nothing();
    4221             : }
    4222             : 
    4223             : nsRect
    4224           0 : nsDisplayBackgroundImage::GetPositioningArea() const
    4225             : {
    4226           0 :   if (!mBackgroundStyle) {
    4227           0 :     return nsRect();
    4228             :   }
    4229             :   nsIFrame* attachedToFrame;
    4230             :   bool transformedFixed;
    4231          64 :   return nsCSSRendering::ComputeImageLayerPositioningArea(
    4232          16 :       mFrame->PresContext(), mFrame,
    4233             :       mBackgroundRect,
    4234          48 :       mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer],
    4235             :       &attachedToFrame,
    4236           0 :       &transformedFixed) + ToReferenceFrame();
    4237             : }
    4238             : 
    4239             : bool
    4240           0 : nsDisplayBackgroundImage::RenderingMightDependOnPositioningAreaSizeChange() const
    4241             : {
    4242           0 :   if (!mBackgroundStyle)
    4243             :     return false;
    4244             : 
    4245             :   nscoord radii[8];
    4246           0 :   if (mFrame->GetBorderRadii(radii)) {
    4247             :     // A change in the size of the positioning area might change the position
    4248             :     // of the rounded corners.
    4249             :     return true;
    4250             :   }
    4251             : 
    4252           0 :   const nsStyleImageLayers::Layer &layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
    4253           0 :   if (layer.RenderingMightDependOnPositioningAreaSizeChange()) {
    4254             :     return true;
    4255             :   }
    4256           0 :   return false;
    4257             : }
    4258             : 
    4259             : void
    4260           4 : nsDisplayBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
    4261             :                                 gfxContext* aCtx) {
    4262           8 :   PaintInternal(aBuilder, aCtx, GetPaintRect(), &mBounds);
    4263           0 : }
    4264             : 
    4265             : void
    4266           4 : nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
    4267             :                                         gfxContext* aCtx, const nsRect& aBounds,
    4268             :                                         nsRect* aClipRect) {
    4269           0 :   gfxContext* ctx = aCtx;
    4270           8 :   StyleGeometryBox clip = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mClip;
    4271             : 
    4272           4 :   if (clip == StyleGeometryBox::Text) {
    4273           0 :     if (!GenerateAndPushTextMask(StyleFrame(), aCtx, mBackgroundRect, aBuilder)) {
    4274           0 :       return;
    4275             :     }
    4276             :   }
    4277             : 
    4278             :   nsCSSRendering::PaintBGParams params =
    4279           0 :     nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(),
    4280             :                                                   aBounds, mBackgroundRect,
    4281           8 :                                                   StyleFrame(), mImageFlags, mLayer,
    4282          16 :                                                   CompositionOp::OP_OVER);
    4283           0 :   params.bgClipRect = aClipRect;
    4284           4 :   ImgDrawResult result = nsCSSRendering::PaintStyleImageLayer(params, *aCtx);
    4285             : 
    4286           4 :   if (clip == StyleGeometryBox::Text) {
    4287           0 :     ctx->PopGroupAndBlend();
    4288             :   }
    4289             : 
    4290           0 :   nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
    4291             : }
    4292             : 
    4293             : void
    4294          14 : nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    4295             :                                                     const nsDisplayItemGeometry* aGeometry,
    4296             :                                                     nsRegion* aInvalidRegion) const
    4297             : {
    4298          28 :   if (!mBackgroundStyle) {
    4299           0 :     return;
    4300             :   }
    4301             : 
    4302          14 :   const nsDisplayBackgroundGeometry* geometry = static_cast<const nsDisplayBackgroundGeometry*>(aGeometry);
    4303             : 
    4304             :   bool snap;
    4305          28 :   nsRect bounds = GetBounds(aBuilder, &snap);
    4306           0 :   nsRect positioningArea = GetPositioningArea();
    4307           0 :   if (positioningArea.TopLeft() != geometry->mPositioningArea.TopLeft() ||
    4308          42 :       (positioningArea.Size() != geometry->mPositioningArea.Size() &&
    4309           0 :        RenderingMightDependOnPositioningAreaSizeChange())) {
    4310             :     // Positioning area changed in a way that could cause everything to change,
    4311             :     // so invalidate everything (both old and new painting areas).
    4312           0 :     aInvalidRegion->Or(bounds, geometry->mBounds);
    4313           0 :     return;
    4314             :   }
    4315          14 :   if (!mDestRect.IsEqualInterior(geometry->mDestRect)) {
    4316             :     // Dest area changed in a way that could cause everything to change,
    4317             :     // so invalidate everything (both old and new painting areas).
    4318           0 :     aInvalidRegion->Or(bounds, geometry->mBounds);
    4319           0 :     return;
    4320             :   }
    4321           0 :   if (aBuilder->ShouldSyncDecodeImages()) {
    4322           0 :     const nsStyleImage& image = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer].mImage;
    4323           0 :     if (image.GetType() == eStyleImageType_Image &&
    4324           0 :         geometry->ShouldInvalidateToSyncDecodeImages()) {
    4325           0 :       aInvalidRegion->Or(*aInvalidRegion, bounds);
    4326             :     }
    4327             :   }
    4328          14 :   if (!bounds.IsEqualInterior(geometry->mBounds)) {
    4329             :     // Positioning area is unchanged, so invalidate just the change in the
    4330             :     // painting area.
    4331           0 :     aInvalidRegion->Xor(bounds, geometry->mBounds);
    4332             :   }
    4333             : }
    4334             : 
    4335             : nsRect
    4336           0 : nsDisplayBackgroundImage::GetBounds(nsDisplayListBuilder* aBuilder,
    4337             :                                     bool* aSnap) const
    4338             : {
    4339           0 :   *aSnap = true;
    4340          56 :   return mBounds;
    4341             : }
    4342             : 
    4343             : nsRect
    4344           0 : nsDisplayBackgroundImage::GetBoundsInternal(nsDisplayListBuilder* aBuilder,
    4345             :                                             nsIFrame* aFrameForBounds)
    4346             : {
    4347             :   // This allows nsDisplayTableBackgroundImage to change the frame used for
    4348             :   // bounds calculation.
    4349           0 :   nsIFrame* frame = aFrameForBounds ? aFrameForBounds : mFrame;
    4350             : 
    4351          16 :   nsPresContext* presContext = frame->PresContext();
    4352             : 
    4353          32 :   if (!mBackgroundStyle) {
    4354           0 :     return nsRect();
    4355             :   }
    4356             : 
    4357          32 :   nsRect clipRect = mBackgroundRect;
    4358           0 :   if (frame->IsCanvasFrame()) {
    4359           0 :     nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
    4360           0 :     clipRect = canvasFrame->CanvasArea() + ToReferenceFrame();
    4361             :   }
    4362           0 :   const nsStyleImageLayers::Layer& layer = mBackgroundStyle->StyleBackground()->mImage.mLayers[mLayer];
    4363             :   return nsCSSRendering::GetBackgroundLayerRect(presContext, frame,
    4364             :                                                 mBackgroundRect, clipRect, layer,
    4365           0 :                                                 aBuilder->GetBackgroundPaintFlags());
    4366             : }
    4367             : 
    4368           0 : nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder,
    4369             :                                                              const InitData& aData,
    4370           0 :                                                              nsIFrame* aCellFrame)
    4371             :   : nsDisplayBackgroundImage(aBuilder, aData, aCellFrame)
    4372             :   , mStyleFrame(aCellFrame)
    4373           0 :   , mTableType(GetTableTypeFromFrame(mStyleFrame))
    4374             : {
    4375           0 :   if (aBuilder->IsRetainingDisplayList()) {
    4376           0 :     mStyleFrame->AddDisplayItem(this);
    4377             :   }
    4378           0 : }
    4379             : 
    4380           0 : nsDisplayTableBackgroundImage::~nsDisplayTableBackgroundImage()
    4381             : {
    4382           0 :   if (mStyleFrame) {
    4383           0 :     mStyleFrame->RemoveDisplayItem(this);
    4384             :   }
    4385           0 : }
    4386             : 
    4387             : bool
    4388           0 : nsDisplayTableBackgroundImage::IsInvalid(nsRect& aRect) const
    4389             : {
    4390           0 :   bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false;
    4391           0 :   aRect += ToReferenceFrame();
    4392           0 :   return result;
    4393             : }
    4394             : 
    4395           0 : nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
    4396             :                                                      nsIFrame* aFrame,
    4397           0 :                                                      const nsRect& aBackgroundRect)
    4398             :   : nsDisplayItem(aBuilder, aFrame)
    4399           0 :   , mBackgroundRect(aBackgroundRect)
    4400             : {
    4401          16 :   MOZ_COUNT_CTOR(nsDisplayThemedBackground);
    4402           0 : }
    4403             : 
    4404          32 : nsDisplayThemedBackground::~nsDisplayThemedBackground()
    4405             : {
    4406             : #ifdef NS_BUILD_REFCNT_LOGGING
    4407           0 :   MOZ_COUNT_DTOR(nsDisplayThemedBackground);
    4408             : #endif
    4409          16 : }
    4410             : 
    4411             : void
    4412           0 : nsDisplayThemedBackground::Init(nsDisplayListBuilder* aBuilder)
    4413             : {
    4414          16 :   const nsStyleDisplay* disp = StyleFrame()->StyleDisplay();
    4415           0 :   mAppearance = disp->mAppearance;
    4416          16 :   StyleFrame()->IsThemed(disp, &mThemeTransparency);
    4417             : 
    4418             :   // Perform necessary RegisterThemeGeometry
    4419           0 :   nsITheme* theme = StyleFrame()->PresContext()->GetTheme();
    4420             :   nsITheme::ThemeGeometryType type =
    4421          16 :     theme->ThemeGeometryTypeForWidget(StyleFrame(), disp->mAppearance);
    4422           0 :   if (type != nsITheme::eThemeGeometryTypeUnknown) {
    4423           0 :     RegisterThemeGeometry(aBuilder, this, StyleFrame(), type);
    4424             :   }
    4425             : 
    4426          16 :   if (disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
    4427             :       disp->mAppearance == NS_THEME_WIN_GLASS) {
    4428           0 :     aBuilder->SetGlassDisplayItem(this);
    4429             :   }
    4430             : 
    4431          16 :   mBounds = GetBoundsInternal();
    4432           0 : }
    4433             : 
    4434             : void
    4435           0 : nsDisplayThemedBackground::WriteDebugInfo(std::stringstream& aStream)
    4436             : {
    4437           0 :   aStream << " (themed, appearance:" << (int)mAppearance << ")";
    4438           0 : }
    4439             : 
    4440             : void
    4441           0 : nsDisplayThemedBackground::HitTest(nsDisplayListBuilder* aBuilder,
    4442             :                                   const nsRect& aRect,
    4443             :                                   HitTestState* aState,
    4444             :                                   nsTArray<nsIFrame*> *aOutFrames)
    4445             : {
    4446             :   // Assume that any point in our background rect is a hit.
    4447           0 :   if (mBackgroundRect.Intersects(aRect)) {
    4448           0 :     aOutFrames->AppendElement(mFrame);
    4449             :   }
    4450           0 : }
    4451             : 
    4452             : nsRegion
    4453           0 : nsDisplayThemedBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    4454             :                                            bool* aSnap) const
    4455             : {
    4456           0 :   nsRegion result;
    4457          12 :   *aSnap = false;
    4458             : 
    4459           0 :   if (mThemeTransparency == nsITheme::eOpaque) {
    4460           0 :     result = mBackgroundRect;
    4461             :   }
    4462          12 :   return result;
    4463             : }
    4464             : 
    4465             : Maybe<nscolor>
    4466           8 : nsDisplayThemedBackground::IsUniform(nsDisplayListBuilder* aBuilder) const
    4467             : {
    4468           0 :   if (mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
    4469             :       mAppearance == NS_THEME_WIN_GLASS) {
    4470           0 :     return Some(NS_RGBA(0,0,0,0));
    4471             :   }
    4472             :   return Nothing();
    4473             : }
    4474             : 
    4475             : nsRect
    4476           0 : nsDisplayThemedBackground::GetPositioningArea() const
    4477             : {
    4478           0 :   return mBackgroundRect;
    4479             : }
    4480             : 
    4481             : void
    4482           4 : nsDisplayThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
    4483             :                                  gfxContext* aCtx)
    4484             : {
    4485           0 :   PaintInternal(aBuilder, aCtx, GetPaintRect(), nullptr);
    4486           4 : }
    4487             : 
    4488             : 
    4489             : void
    4490           0 : nsDisplayThemedBackground::PaintInternal(nsDisplayListBuilder* aBuilder,
    4491             :                                          gfxContext* aCtx, const nsRect& aBounds,
    4492             :                                          nsRect* aClipRect)
    4493             : {
    4494             :   // XXXzw this ignores aClipRect.
    4495           8 :   nsPresContext* presContext = StyleFrame()->PresContext();
    4496           0 :   nsITheme *theme = presContext->GetTheme();
    4497           0 :   nsRect drawing(mBackgroundRect);
    4498           8 :   theme->GetWidgetOverflow(presContext->DeviceContext(), StyleFrame(), mAppearance,
    4499           0 :                            &drawing);
    4500           4 :   drawing.IntersectRect(drawing, aBounds);
    4501           4 :   theme->DrawWidgetBackground(aCtx, StyleFrame(), mAppearance, mBackgroundRect, drawing);
    4502           4 : }
    4503             : 
    4504             : 
    4505             : bool
    4506           0 : nsDisplayThemedBackground::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    4507             :                                                    mozilla::wr::IpcResourceUpdateQueue& aResources,
    4508             :                                                    const StackingContextHelper& aSc,
    4509             :                                                    mozilla::layers::WebRenderLayerManager* aManager,
    4510             :                                                    nsDisplayListBuilder* aDisplayListBuilder)
    4511             : {
    4512           0 :   nsITheme *theme = StyleFrame()->PresContext()->GetTheme();
    4513           0 :   return theme->CreateWebRenderCommandsForWidget(aBuilder, aResources, aSc, aManager,
    4514           0 :                                                  StyleFrame(), mAppearance, mBackgroundRect);
    4515             : }
    4516             : 
    4517             : bool
    4518           2 : nsDisplayThemedBackground::IsWindowActive() const
    4519             : {
    4520           4 :   EventStates docState = mFrame->GetContent()->OwnerDoc()->GetDocumentState();
    4521           2 :   return !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
    4522             : }
    4523             : 
    4524             : void
    4525          14 : nsDisplayThemedBackground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    4526             :                                                      const nsDisplayItemGeometry* aGeometry,
    4527             :                                                      nsRegion* aInvalidRegion) const
    4528             : {
    4529          14 :   const nsDisplayThemedBackgroundGeometry* geometry = static_cast<const nsDisplayThemedBackgroundGeometry*>(aGeometry);
    4530             : 
    4531             :   bool snap;
    4532           0 :   nsRect bounds = GetBounds(aBuilder, &snap);
    4533           0 :   nsRect positioningArea = GetPositioningArea();
    4534           0 :   if (!positioningArea.IsEqualInterior(geometry->mPositioningArea)) {
    4535             :     // Invalidate everything (both old and new painting areas).
    4536           0 :     aInvalidRegion->Or(bounds, geometry->mBounds);
    4537           0 :     return;
    4538             :   }
    4539           0 :   if (!bounds.IsEqualInterior(geometry->mBounds)) {
    4540             :     // Positioning area is unchanged, so invalidate just the change in the
    4541             :     // painting area.
    4542           0 :     aInvalidRegion->Xor(bounds, geometry->mBounds);
    4543             :   }
    4544          28 :   nsITheme* theme = StyleFrame()->PresContext()->GetTheme();
    4545          14 :   if (theme->WidgetAppearanceDependsOnWindowFocus(mAppearance) &&
    4546           0 :       IsWindowActive() != geometry->mWindowIsActive) {
    4547           0 :     aInvalidRegion->Or(*aInvalidRegion, bounds);
    4548             :   }
    4549             : }
    4550             : 
    4551             : nsRect
    4552          56 : nsDisplayThemedBackground::GetBounds(nsDisplayListBuilder* aBuilder,
    4553             :                                      bool* aSnap) const
    4554             : {
    4555           0 :   *aSnap = true;
    4556          56 :   return mBounds;
    4557             : }
    4558             : 
    4559             : nsRect
    4560          16 : nsDisplayThemedBackground::GetBoundsInternal() {
    4561          32 :   nsPresContext* presContext = mFrame->PresContext();
    4562             : 
    4563          32 :   nsRect r = mBackgroundRect - ToReferenceFrame();
    4564          16 :   presContext->GetTheme()->
    4565          32 :       GetWidgetOverflow(presContext->DeviceContext(), mFrame,
    4566           0 :                         mFrame->StyleDisplay()->mAppearance, &r);
    4567          32 :   return r + ToReferenceFrame();
    4568             : }
    4569             : 
    4570             : void
    4571           0 : nsDisplayImageContainer::ConfigureLayer(ImageLayer* aLayer,
    4572             :                                         const ContainerLayerParameters& aParameters)
    4573             : {
    4574           0 :   aLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(mFrame));
    4575             : 
    4576           0 :   nsCOMPtr<imgIContainer> image = GetImage();
    4577           0 :   MOZ_ASSERT(image);
    4578             :   int32_t imageWidth;
    4579             :   int32_t imageHeight;
    4580           0 :   image->GetWidth(&imageWidth);
    4581           0 :   image->GetHeight(&imageHeight);
    4582           0 :   NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
    4583             : 
    4584           0 :   if (imageWidth > 0 && imageHeight > 0) {
    4585             :     // We're actually using the ImageContainer. Let our frame know that it
    4586             :     // should consider itself to have painted successfully.
    4587           0 :     UpdateDrawResult(ImgDrawResult::SUCCESS);
    4588             :   }
    4589             : 
    4590             :   // XXX(seth): Right now we ignore aParameters.Scale() and
    4591             :   // aParameters.Offset(), because FrameLayerBuilder already applies
    4592             :   // aParameters.Scale() via the layer's post-transform, and
    4593             :   // aParameters.Offset() is always zero.
    4594           0 :   MOZ_ASSERT(aParameters.Offset() == LayerIntPoint(0,0));
    4595             : 
    4596             :   // It's possible (for example, due to downscale-during-decode) that the
    4597             :   // ImageContainer this ImageLayer is holding has a different size from the
    4598             :   // intrinsic size of the image. For this reason we compute the transform using
    4599             :   // the ImageContainer's size rather than the image's intrinsic size.
    4600             :   // XXX(seth): In reality, since the size of the ImageContainer may change
    4601             :   // asynchronously, this is not enough. Bug 1183378 will provide a more
    4602             :   // complete fix, but this solution is safe in more cases than simply relying
    4603             :   // on the intrinsic size.
    4604           0 :   IntSize containerSize = aLayer->GetContainer()
    4605           0 :                         ? aLayer->GetContainer()->GetCurrentSize()
    4606           0 :                         : IntSize(imageWidth, imageHeight);
    4607             : 
    4608           0 :   const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    4609             :   const LayoutDeviceRect destRect(
    4610           0 :     LayoutDeviceIntRect::FromAppUnitsToNearest(GetDestRect(), factor));
    4611             : 
    4612           0 :   const LayoutDevicePoint p = destRect.TopLeft();
    4613           0 :   Matrix transform = Matrix::Translation(p.x, p.y);
    4614           0 :   transform.PreScale(destRect.width / containerSize.width,
    4615           0 :                      destRect.height / containerSize.height);
    4616           0 :   aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
    4617           0 : }
    4618             : 
    4619             : already_AddRefed<ImageContainer>
    4620           0 : nsDisplayImageContainer::GetContainer(LayerManager* aManager,
    4621             :                                       nsDisplayListBuilder *aBuilder)
    4622             : {
    4623           0 :   nsCOMPtr<imgIContainer> image = GetImage();
    4624           0 :   if (!image) {
    4625           0 :     MOZ_ASSERT_UNREACHABLE("Must call CanOptimizeToImage() and get true "
    4626             :                            "before calling GetContainer()");
    4627             :     return nullptr;
    4628             :   }
    4629             : 
    4630           0 :   uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY;
    4631           0 :   if (aBuilder->ShouldSyncDecodeImages()) {
    4632           0 :     flags |= imgIContainer::FLAG_SYNC_DECODE;
    4633             :   }
    4634             : 
    4635           0 :   RefPtr<ImageContainer> container = image->GetImageContainer(aManager, flags);
    4636           0 :   if (!container || !container->HasCurrentImage()) {
    4637             :     return nullptr;
    4638             :   }
    4639             : 
    4640             :   return container.forget();
    4641             : }
    4642             : 
    4643             : bool
    4644           0 : nsDisplayImageContainer::CanOptimizeToImageLayer(LayerManager* aManager,
    4645             :                                                  nsDisplayListBuilder* aBuilder)
    4646             : {
    4647           0 :   uint32_t flags = aBuilder->ShouldSyncDecodeImages()
    4648           0 :                  ? imgIContainer::FLAG_SYNC_DECODE
    4649           0 :                  : imgIContainer::FLAG_NONE;
    4650             : 
    4651           0 :   nsCOMPtr<imgIContainer> image = GetImage();
    4652           0 :   if (!image) {
    4653             :     return false;
    4654             :   }
    4655             : 
    4656           0 :   if (!image->IsImageContainerAvailable(aManager, flags)) {
    4657             :     return false;
    4658             :   }
    4659             : 
    4660             :   int32_t imageWidth;
    4661             :   int32_t imageHeight;
    4662           0 :   image->GetWidth(&imageWidth);
    4663           0 :   image->GetHeight(&imageHeight);
    4664             : 
    4665           0 :   if (imageWidth == 0 || imageHeight == 0) {
    4666           0 :     NS_ASSERTION(false, "invalid image size");
    4667           0 :     return false;
    4668             :   }
    4669             : 
    4670           0 :   const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    4671             :   const LayoutDeviceRect destRect(
    4672           0 :     LayoutDeviceIntRect::FromAppUnitsToNearest(GetDestRect(), factor));
    4673             : 
    4674             :   // Calculate the scaling factor for the frame.
    4675           0 :   const gfxSize scale = gfxSize(destRect.width / imageWidth,
    4676           0 :                                 destRect.height / imageHeight);
    4677             : 
    4678           0 :   if (scale.width < 0.34 || scale.height < 0.34) {
    4679             :     // This would look awful as long as we can't use high-quality downscaling
    4680             :     // for image layers (bug 803703), so don't turn this into an image layer.
    4681             :     return false;
    4682             :   }
    4683             : 
    4684           0 :   if (mFrame->IsImageFrame()) {
    4685             :     // Image layer doesn't support draw focus ring for image map.
    4686           0 :     nsImageFrame* f = static_cast<nsImageFrame*>(mFrame);
    4687           0 :     if (f->HasImageMap()) {
    4688             :       return false;
    4689             :     }
    4690             :   }
    4691             : 
    4692             :   return true;
    4693             : }
    4694             : 
    4695             : void
    4696           0 : nsDisplayBackgroundColor::ApplyOpacity(nsDisplayListBuilder* aBuilder,
    4697             :                                        float aOpacity,
    4698             :                                        const DisplayItemClipChain* aClip)
    4699             : {
    4700           0 :   NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
    4701           0 :   mColor.a = mColor.a * aOpacity;
    4702           0 :   IntersectClip(aBuilder, aClip, false);
    4703           0 : }
    4704             : 
    4705             : bool
    4706           8 : nsDisplayBackgroundColor::CanApplyOpacity() const
    4707             : {
    4708           8 :   return true;
    4709             : }
    4710             : 
    4711             : LayerState
    4712           0 : nsDisplayBackgroundColor::GetLayerState(nsDisplayListBuilder* aBuilder,
    4713             :                                         LayerManager* aManager,
    4714             :                                         const ContainerLayerParameters& aParameters)
    4715             : {
    4716         112 :   StyleGeometryBox clip = mBackgroundStyle->StyleBackground()->mImage.mLayers[0].mClip;
    4717          56 :   if (ForceActiveLayers() && clip != StyleGeometryBox::Text) {
    4718             :     return LAYER_ACTIVE;
    4719             :   }
    4720          56 :   return LAYER_NONE;
    4721             : }
    4722             : 
    4723             : already_AddRefed<Layer>
    4724           0 : nsDisplayBackgroundColor::BuildLayer(nsDisplayListBuilder* aBuilder,
    4725             :                                      LayerManager* aManager,
    4726             :                                      const ContainerLayerParameters& aContainerParameters)
    4727             : {
    4728           0 :   if (mColor == Color()) {
    4729             :     return nullptr;
    4730             :   }
    4731             : 
    4732             :   RefPtr<ColorLayer> layer = static_cast<ColorLayer*>
    4733           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
    4734           0 :   if (!layer) {
    4735           0 :     layer = aManager->CreateColorLayer();
    4736           0 :     if (!layer)
    4737             :       return nullptr;
    4738             :   }
    4739           0 :   layer->SetColor(mColor);
    4740             : 
    4741           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    4742           0 :   layer->SetBounds(mBackgroundRect.ToNearestPixels(appUnitsPerDevPixel));
    4743           0 :   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
    4744           0 :                                                       aContainerParameters.mOffset.y, 0));
    4745             : 
    4746           0 :   return layer.forget();
    4747             : }
    4748             : 
    4749             : bool
    4750           0 : nsDisplayBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    4751             :                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
    4752             :                                                   const StackingContextHelper& aSc,
    4753             :                                                   mozilla::layers::WebRenderLayerManager* aManager,
    4754             :                                                   nsDisplayListBuilder* aDisplayListBuilder)
    4755             : {
    4756           0 :   if (mColor == Color()) {
    4757             :     return true;
    4758             :   }
    4759             : 
    4760           0 :   StyleGeometryBox clip = mBackgroundStyle->StyleBackground()->mImage.mLayers[0].mClip;
    4761           0 :   if (clip == StyleGeometryBox::Text) {
    4762             :     return false;
    4763             :   }
    4764             : 
    4765             :   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
    4766           0 :         mBackgroundRect, mFrame->PresContext()->AppUnitsPerDevPixel());
    4767           0 :   wr::LayoutRect roundedRect = wr::ToRoundedLayoutRect(bounds);
    4768             : 
    4769           0 :   aBuilder.PushRect(roundedRect,
    4770             :                     roundedRect,
    4771           0 :                     !BackfaceIsHidden(),
    4772           0 :                     wr::ToColorF(ToDeviceColor(mColor)));
    4773             : 
    4774           0 :   return true;
    4775             : }
    4776             : 
    4777             : void
    4778           0 : nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
    4779             :                                 gfxContext* aCtx)
    4780             : {
    4781           0 :   if (mColor == Color()) {
    4782           0 :     return;
    4783             :   }
    4784             : 
    4785             : #if 0
    4786             :   // See https://bugzilla.mozilla.org/show_bug.cgi?id=1148418#c21 for why this
    4787             :   // results in a precision induced rounding issue that makes the rect one
    4788             :   // pixel shorter in rare cases. Disabled in favor of the old code for now.
    4789             :   // Note that the pref layout.css.devPixelsPerPx needs to be set to 1 to
    4790             :   // reproduce the bug.
    4791             :   //
    4792             :   // TODO:
    4793             :   // This new path does not include support for background-clip:text; need to
    4794             :   // be fixed if/when we switch to this new code path.
    4795             : 
    4796             :   DrawTarget& aDrawTarget = *aCtx->GetDrawTarget();
    4797             : 
    4798             :   Rect rect = NSRectToSnappedRect(mBackgroundRect,
    4799             :                                   mFrame->PresContext()->AppUnitsPerDevPixel(),
    4800             :                                   aDrawTarget);
    4801             :   ColorPattern color(ToDeviceColor(mColor));
    4802             :   aDrawTarget.FillRect(rect, color);
    4803             : #else
    4804           1 :   gfxContext* ctx = aCtx;
    4805             :   gfxRect bounds =
    4806             :     nsLayoutUtils::RectToGfxRect(mBackgroundRect,
    4807          26 :                                  mFrame->PresContext()->AppUnitsPerDevPixel());
    4808             : 
    4809           1 :   StyleGeometryBox clip = mBackgroundStyle->StyleBackground()->mImage.mLayers[0].mClip;
    4810          13 :   if (clip == StyleGeometryBox::Text) {
    4811           0 :     if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
    4812             :       return;
    4813             :     }
    4814             : 
    4815           0 :     ctx->SetColor(mColor);
    4816           0 :     ctx->NewPath();
    4817           0 :     ctx->Rectangle(bounds, true);
    4818           0 :     ctx->Fill();
    4819           0 :     ctx->PopGroupAndBlend();
    4820           0 :     return;
    4821             :   }
    4822             : 
    4823          13 :   ctx->SetColor(mColor);
    4824          13 :   ctx->NewPath();
    4825          13 :   ctx->Rectangle(bounds, true);
    4826          13 :   ctx->Fill();
    4827             : #endif
    4828             : }
    4829             : 
    4830             : nsRegion
    4831          13 : nsDisplayBackgroundColor::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    4832             :                                           bool* aSnap) const
    4833             : {
    4834          13 :   *aSnap = false;
    4835             : 
    4836          13 :   if (mColor.a != 1) {
    4837           2 :     return nsRegion();
    4838             :   }
    4839             : 
    4840          22 :   if (!mBackgroundStyle)
    4841           0 :     return nsRegion();
    4842             : 
    4843             : 
    4844           0 :   const nsStyleImageLayers::Layer& bottomLayer = mBackgroundStyle->StyleBackground()->BottomLayer();
    4845          11 :   if (bottomLayer.mClip == StyleGeometryBox::Text) {
    4846           0 :     return nsRegion();
    4847             :   }
    4848             : 
    4849          11 :   *aSnap = true;
    4850          11 :   return nsDisplayBackgroundImage::GetInsideClipRegion(this, bottomLayer.mClip,
    4851          22 :                                                        mBackgroundRect, mBackgroundRect);
    4852             : }
    4853             : 
    4854             : Maybe<nscolor>
    4855           0 : nsDisplayBackgroundColor::IsUniform(nsDisplayListBuilder* aBuilder) const
    4856             : {
    4857           0 :   return Some(mColor.ToABGR());
    4858             : }
    4859             : 
    4860             : void
    4861           0 : nsDisplayBackgroundColor::HitTest(nsDisplayListBuilder* aBuilder,
    4862             :                                   const nsRect& aRect,
    4863             :                                   HitTestState* aState,
    4864             :                                   nsTArray<nsIFrame*> *aOutFrames)
    4865             : {
    4866           0 :   if (!RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
    4867             :     // aRect doesn't intersect our border-radius curve.
    4868             :     return;
    4869             :   }
    4870             : 
    4871           0 :   aOutFrames->AppendElement(mFrame);
    4872             : }
    4873             : 
    4874             : void
    4875           0 : nsDisplayBackgroundColor::WriteDebugInfo(std::stringstream& aStream)
    4876             : {
    4877           0 :   aStream << " (rgba " << mColor.r << "," << mColor.g << ","
    4878           0 :           << mColor.b << "," << mColor.a << ")";
    4879           0 : }
    4880             : 
    4881             : already_AddRefed<Layer>
    4882           0 : nsDisplayClearBackground::BuildLayer(nsDisplayListBuilder* aBuilder,
    4883             :                                      LayerManager* aManager,
    4884             :                                      const ContainerLayerParameters& aParameters)
    4885             : {
    4886             :   RefPtr<ColorLayer> layer = static_cast<ColorLayer*>
    4887           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
    4888           0 :   if (!layer) {
    4889           0 :     layer = aManager->CreateColorLayer();
    4890           0 :     if (!layer)
    4891             :       return nullptr;
    4892             :   }
    4893           0 :   layer->SetColor(Color());
    4894           0 :   layer->SetMixBlendMode(gfx::CompositionOp::OP_SOURCE);
    4895             : 
    4896             :   bool snap;
    4897           0 :   nsRect bounds = GetBounds(aBuilder, &snap);
    4898           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    4899           0 :   layer->SetBounds(bounds.ToNearestPixels(appUnitsPerDevPixel)); // XXX Do we need to respect the parent layer's scale here?
    4900             : 
    4901           0 :   return layer.forget();
    4902             : }
    4903             : 
    4904             : bool
    4905           0 : nsDisplayClearBackground::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    4906             :                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
    4907             :                                                   const StackingContextHelper& aSc,
    4908             :                                                   mozilla::layers::WebRenderLayerManager* aManager,
    4909             :                                                   nsDisplayListBuilder* aDisplayListBuilder)
    4910             : {
    4911             :   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
    4912           0 :     nsRect(ToReferenceFrame(), mFrame->GetSize()),
    4913           0 :     mFrame->PresContext()->AppUnitsPerDevPixel());
    4914             : 
    4915           0 :   aBuilder.PushClearRect(wr::ToRoundedLayoutRect(bounds));
    4916             : 
    4917           0 :   return true;
    4918             : }
    4919             : 
    4920             : nsRect
    4921           0 : nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder,
    4922             :                             bool* aSnap) const
    4923             : {
    4924           0 :   *aSnap = false;
    4925           0 :   return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
    4926             : }
    4927             : 
    4928             : void
    4929           0 : nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
    4930             :                         gfxContext* aCtx) {
    4931             :   // TODO join outlines together
    4932           0 :   MOZ_ASSERT(mFrame->StyleOutline()->ShouldPaintOutline(),
    4933             :              "Should have not created a nsDisplayOutline!");
    4934             : 
    4935           0 :   nsPoint offset = ToReferenceFrame();
    4936           0 :   nsCSSRendering::PaintOutline(mFrame->PresContext(), *aCtx, mFrame,
    4937             :                                GetPaintRect(),
    4938           0 :                                nsRect(offset, mFrame->GetSize()),
    4939           0 :                                mFrame->Style());
    4940           0 : }
    4941             : 
    4942             : bool
    4943           0 : nsDisplayOutline::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    4944             :                                           mozilla::wr::IpcResourceUpdateQueue& aResources,
    4945             :                                           const StackingContextHelper& aSc,
    4946             :                                           mozilla::layers::WebRenderLayerManager* aManager,
    4947             :                                           nsDisplayListBuilder* aDisplayListBuilder)
    4948             : {
    4949           0 :   ContainerLayerParameters parameter;
    4950             : 
    4951           0 :   uint8_t outlineStyle = mFrame->Style()->StyleOutline()->mOutlineStyle;
    4952           0 :   if (outlineStyle == NS_STYLE_BORDER_STYLE_AUTO && nsLayoutUtils::IsOutlineStyleAutoEnabled()) {
    4953           0 :       nsITheme* theme = mFrame->PresContext()->GetTheme();
    4954           0 :       if (theme && theme->ThemeSupportsWidget(mFrame->PresContext(), mFrame,
    4955           0 :                                               NS_THEME_FOCUS_OUTLINE)) {
    4956             :         return false;
    4957             :       }
    4958             :   }
    4959             : 
    4960           0 :   nsPoint offset = ToReferenceFrame();
    4961             : 
    4962             :   mozilla::Maybe<nsCSSBorderRenderer> borderRenderer =
    4963           0 :     nsCSSRendering::CreateBorderRendererForOutline(mFrame->PresContext(),
    4964             :                                                    nullptr, mFrame,
    4965             :                                                    GetPaintRect(),
    4966           0 :                                                    nsRect(offset, mFrame->GetSize()),
    4967           0 :                                                    mFrame->Style());
    4968             : 
    4969           0 :   if (!borderRenderer) {
    4970             :     // No border renderer means "there is no outline".
    4971             :     // Paint nothing and return success.
    4972             :     return true;
    4973             :   }
    4974             : 
    4975           0 :   borderRenderer->CreateWebRenderCommands(this, aBuilder, aResources, aSc);
    4976           0 :   return true;
    4977             : }
    4978             : 
    4979             : bool
    4980           0 : nsDisplayOutline::IsInvisibleInRect(const nsRect& aRect) const
    4981             : {
    4982           0 :   const nsStyleOutline* outline = mFrame->StyleOutline();
    4983           0 :   nsRect borderBox(ToReferenceFrame(), mFrame->GetSize());
    4984           0 :   if (borderBox.Contains(aRect) &&
    4985           0 :       !nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) {
    4986           0 :     if (outline->mOutlineOffset >= 0) {
    4987             :       // aRect is entirely inside the border-rect, and the outline isn't
    4988             :       // rendered inside the border-rect, so the outline is not visible.
    4989             :       return true;
    4990             :     }
    4991             :   }
    4992             : 
    4993           0 :   return false;
    4994             : }
    4995             : 
    4996             : void
    4997           0 : nsDisplayEventReceiver::HitTest(nsDisplayListBuilder* aBuilder,
    4998             :                                 const nsRect& aRect,
    4999             :                                 HitTestState* aState,
    5000             :                                 nsTArray<nsIFrame*> *aOutFrames)
    5001             : {
    5002           0 :   if (!RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
    5003             :     // aRect doesn't intersect our border-radius curve.
    5004             :     return;
    5005             :   }
    5006             : 
    5007           0 :   aOutFrames->AppendElement(mFrame);
    5008             : }
    5009             : 
    5010             : bool
    5011           0 : nsDisplayEventReceiver::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5012             :                                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
    5013             :                                                 const StackingContextHelper& aSc,
    5014             :                                                 mozilla::layers::WebRenderLayerManager* aManager,
    5015             :                                                 nsDisplayListBuilder* aDisplayListBuilder)
    5016             : {
    5017             :   // This display item should never be getting created when building a display
    5018             :   // list for WebRender consumption, so this function should never get called.
    5019           0 :   MOZ_ASSERT(false);
    5020             :   return true;
    5021             : }
    5022             : 
    5023         114 : nsDisplayCompositorHitTestInfo::nsDisplayCompositorHitTestInfo(nsDisplayListBuilder* aBuilder,
    5024             :                                                                nsIFrame* aFrame,
    5025             :                                                                mozilla::gfx::CompositorHitTestInfo aHitTestInfo,
    5026             :                                                                uint32_t aIndex,
    5027           0 :                                                                const mozilla::Maybe<nsRect>& aArea)
    5028             :   : nsDisplayEventReceiver(aBuilder, aFrame)
    5029             :   , mHitTestInfo(aHitTestInfo)
    5030             :   , mIndex(aIndex)
    5031           0 :   , mAppUnitsPerDevPixel(mFrame->PresContext()->AppUnitsPerDevPixel())
    5032             : {
    5033         114 :   MOZ_COUNT_CTOR(nsDisplayCompositorHitTestInfo);
    5034             :   // We should never even create this display item if we're not building
    5035             :   // compositor hit-test info or if the computed hit info indicated the
    5036             :   // frame is invisible to hit-testing
    5037         114 :   MOZ_ASSERT(aBuilder->BuildCompositorHitTestInfo());
    5038         114 :   MOZ_ASSERT(mHitTestInfo != mozilla::gfx::CompositorHitTestInfo::eInvisibleToHitTest);
    5039             : 
    5040         228 :   if (aBuilder->GetCurrentScrollbarDirection().isSome()) {
    5041             :     // In the case of scrollbar frames, we use the scrollbar's target scrollframe
    5042             :     // instead of the scrollframe with which the scrollbar actually moves.
    5043           0 :     MOZ_ASSERT(mHitTestInfo & CompositorHitTestInfo::eScrollbar);
    5044           0 :     mScrollTarget = Some(aBuilder->GetCurrentScrollbarTarget());
    5045             :   }
    5046             : 
    5047         114 :   if (aArea.isSome()) {
    5048           0 :     mArea = *aArea;
    5049             :   } else {
    5050         114 :     mArea = GetFrameArea(aBuilder, aFrame);
    5051             :   }
    5052         114 : }
    5053             : 
    5054             : bool
    5055           0 : nsDisplayCompositorHitTestInfo::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5056             :                                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
    5057             :                                                         const StackingContextHelper& aSc,
    5058             :                                                         mozilla::layers::WebRenderLayerManager* aManager,
    5059             :                                                         nsDisplayListBuilder* aDisplayListBuilder)
    5060             : {
    5061           0 :   if (mArea.IsEmpty()) {
    5062             :     return true;
    5063             :   }
    5064             : 
    5065             :   // XXX: eventually this scrollId computation and the SetHitTestInfo
    5066             :   // call will get moved out into the WR display item iteration code so that
    5067             :   // we don't need to do it as often, and so that we can do it for other
    5068             :   // display item types as well (reducing the need for as many instances of
    5069             :   // this display item).
    5070           0 :   FrameMetrics::ViewID scrollId = mScrollTarget.valueOrFrom(
    5071           0 :       [&]() -> FrameMetrics::ViewID {
    5072           0 :           const ActiveScrolledRoot* asr = GetActiveScrolledRoot();
    5073             :           Maybe<FrameMetrics::ViewID> fixedTarget =
    5074           0 :               aBuilder.GetContainingFixedPosScrollTarget(asr);
    5075           0 :           if (fixedTarget) {
    5076           0 :             return *fixedTarget;
    5077             :           }
    5078           0 :           if (asr) {
    5079           0 :             return asr->GetViewId();
    5080             :           }
    5081           0 :           return FrameMetrics::NULL_SCROLL_ID;
    5082           0 :       });
    5083             : 
    5084             :   // Insert a transparent rectangle with the hit-test info
    5085           0 :   aBuilder.SetHitTestInfo(scrollId, mHitTestInfo);
    5086             : 
    5087             :   const LayoutDeviceRect devRect =
    5088           0 :     LayoutDeviceRect::FromAppUnits(mArea, mAppUnitsPerDevPixel);
    5089             : 
    5090           0 :   const wr::LayoutRect rect = wr::ToRoundedLayoutRect(devRect);
    5091             : 
    5092           0 :   aBuilder.PushRect(rect, rect, !BackfaceIsHidden(), wr::ToColorF(gfx::Color()));
    5093           0 :   aBuilder.ClearHitTestInfo();
    5094             : 
    5095           0 :   return true;
    5096             : }
    5097             : 
    5098             : void
    5099           0 : nsDisplayCompositorHitTestInfo::WriteDebugInfo(std::stringstream& aStream)
    5100             : {
    5101           0 :   aStream << nsPrintfCString(" (hitTestInfo 0x%x)", (int)mHitTestInfo).get();
    5102           0 :   AppendToString(aStream, mArea, " hitTestArea");
    5103           0 : }
    5104             : 
    5105             : uint32_t
    5106           1 : nsDisplayCompositorHitTestInfo::GetPerFrameKey() const
    5107             : {
    5108          68 :   return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
    5109             : }
    5110             : 
    5111             : int32_t
    5112           0 : nsDisplayCompositorHitTestInfo::ZIndex() const
    5113             : {
    5114           0 :   return mOverrideZIndex ? *mOverrideZIndex : nsDisplayItem::ZIndex();
    5115             : }
    5116             : 
    5117             : void
    5118           0 : nsDisplayCompositorHitTestInfo::SetOverrideZIndex(int32_t aZIndex)
    5119             : {
    5120           0 :   mOverrideZIndex = Some(aZIndex);
    5121           0 : }
    5122             : 
    5123           1 : nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder,
    5124           5 :                                nsIFrame* aCaretFrame)
    5125             :   : nsDisplayItem(aBuilder, aCaretFrame)
    5126             :   , mCaret(aBuilder->GetCaret())
    5127           1 :   , mBounds(aBuilder->GetCaretRect() + ToReferenceFrame())
    5128             : {
    5129           1 :   MOZ_COUNT_CTOR(nsDisplayCaret);
    5130           1 : }
    5131             : 
    5132             : #ifdef NS_BUILD_REFCNT_LOGGING
    5133          10 : nsDisplayCaret::~nsDisplayCaret()
    5134             : {
    5135           5 :   MOZ_COUNT_DTOR(nsDisplayCaret);
    5136           0 : }
    5137             : #endif
    5138             : 
    5139             : nsRect
    5140           0 : nsDisplayCaret::GetBounds(nsDisplayListBuilder* aBuilder,
    5141             :                           bool* aSnap) const
    5142             : {
    5143          18 :   *aSnap = true;
    5144             :   // The caret returns a rect in the coordinates of mFrame.
    5145          18 :   return mBounds;
    5146             : }
    5147             : 
    5148             : void
    5149           0 : nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
    5150             :                       gfxContext* aCtx) {
    5151             :   // Note: Because we exist, we know that the caret is visible, so we don't
    5152             :   // need to check for the caret's visibility.
    5153           4 :   mCaret->PaintCaret(*aCtx->GetDrawTarget(), mFrame, ToReferenceFrame());
    5154           2 : }
    5155             : 
    5156             : bool
    5157           0 : nsDisplayCaret::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5158             :                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
    5159             :                                         const StackingContextHelper& aSc,
    5160             :                                         mozilla::layers::WebRenderLayerManager* aManager,
    5161             :                                         nsDisplayListBuilder* aDisplayListBuilder)
    5162             : {
    5163             :   using namespace mozilla::layers;
    5164             :   int32_t contentOffset;
    5165           0 :   nsIFrame* frame = mCaret->GetFrame(&contentOffset);
    5166           0 :   if (!frame) {
    5167             :     return true;
    5168             :   }
    5169           0 :   NS_ASSERTION(frame == mFrame, "We're referring different frame");
    5170             : 
    5171           0 :   int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
    5172             : 
    5173           0 :   nsRect caretRect;
    5174           0 :   nsRect hookRect;
    5175           0 :   mCaret->ComputeCaretRects(frame, contentOffset, &caretRect, &hookRect);
    5176             : 
    5177           0 :   gfx::Color color = ToDeviceColor(frame->GetCaretColorAt(contentOffset));
    5178             :   LayoutDeviceRect devCaretRect = LayoutDeviceRect::FromAppUnits(
    5179           0 :     caretRect + ToReferenceFrame(), appUnitsPerDevPixel);
    5180             :   LayoutDeviceRect devHookRect = LayoutDeviceRect::FromAppUnits(
    5181           0 :     hookRect + ToReferenceFrame(), appUnitsPerDevPixel);
    5182             : 
    5183           0 :   wr::LayoutRect caret = wr::ToRoundedLayoutRect(devCaretRect);
    5184           0 :   wr::LayoutRect hook = wr::ToRoundedLayoutRect(devHookRect);
    5185             : 
    5186             :   // Note, WR will pixel snap anything that is layout aligned.
    5187           0 :   aBuilder.PushRect(caret,
    5188             :                     caret,
    5189           0 :                     !BackfaceIsHidden(),
    5190           0 :                     wr::ToColorF(color));
    5191             : 
    5192           0 :   if (!devHookRect.IsEmpty()) {
    5193           0 :     aBuilder.PushRect(hook,
    5194             :                       hook,
    5195           0 :                       !BackfaceIsHidden(),
    5196           0 :                       wr::ToColorF(color));
    5197             :   }
    5198             :   return true;
    5199             : }
    5200             : 
    5201          48 : nsDisplayBorder::nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
    5202             :   : nsDisplayItem(aBuilder, aFrame)
    5203         288 :   , mBorderIsEmpty(false)
    5204             : {
    5205           1 :   MOZ_COUNT_CTOR(nsDisplayBorder);
    5206             : 
    5207          48 :   mBounds = CalculateBounds<nsRect>(*mFrame->StyleBorder());
    5208          48 : }
    5209             : 
    5210             : bool
    5211           1 : nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect) const
    5212             : {
    5213          36 :   nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
    5214           1 :     ToReferenceFrame();
    5215             :   const nsStyleBorder *styleBorder;
    5216           1 :   if (paddingRect.Contains(aRect) &&
    5217          16 :       !(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded() &&
    5218           2 :       !nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
    5219             :     // aRect is entirely inside the content rect, and no part
    5220             :     // of the border is rendered inside the content rect, so we are not
    5221             :     // visible
    5222             :     // Skip this if there's a border-image (which draws a background
    5223             :     // too) or if there is a border-radius (which makes the border draw
    5224             :     // further in).
    5225             :     return true;
    5226             :   }
    5227             : 
    5228          12 :   return false;
    5229             : }
    5230             : 
    5231             : nsDisplayItemGeometry*
    5232           7 : nsDisplayBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
    5233             : {
    5234           7 :   return new nsDisplayBorderGeometry(this, aBuilder);
    5235             : }
    5236             : 
    5237             : void
    5238           1 : nsDisplayBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    5239             :                                            const nsDisplayItemGeometry* aGeometry,
    5240             :                                            nsRegion* aInvalidRegion) const
    5241             : {
    5242           1 :   const nsDisplayBorderGeometry* geometry = static_cast<const nsDisplayBorderGeometry*>(aGeometry);
    5243             :   bool snap;
    5244             : 
    5245          41 :   if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap))) {
    5246             :     // We can probably get away with only invalidating the difference
    5247             :     // between the border and padding rects, but the XUL ui at least
    5248             :     // is apparently painting a background with this?
    5249           0 :     aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
    5250             :   }
    5251             : 
    5252           1 :   if (aBuilder->ShouldSyncDecodeImages() &&
    5253           0 :       geometry->ShouldInvalidateToSyncDecodeImages()) {
    5254           0 :     aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
    5255             :   }
    5256           1 : }
    5257             : 
    5258             : LayerState
    5259           1 : nsDisplayBorder::GetLayerState(nsDisplayListBuilder* aBuilder,
    5260             :                                LayerManager* aManager,
    5261             :                                const ContainerLayerParameters& aParameters)
    5262             : {
    5263          56 :   if (!ShouldUseAdvancedLayer(aManager, gfxPrefs::LayersAllowBorderLayers)) {
    5264             :     return LAYER_NONE;
    5265             :   }
    5266             : 
    5267           0 :   mBorderIsEmpty = false;
    5268           0 :   nsPoint offset = ToReferenceFrame();
    5269             :   Maybe<nsCSSBorderRenderer> br =
    5270           0 :     nsCSSRendering::CreateBorderRenderer(mFrame->PresContext(),
    5271             :                                          nullptr,
    5272             :                                          mFrame,
    5273           0 :                                          nsRect(),
    5274           0 :                                          nsRect(offset, mFrame->GetSize()),
    5275           0 :                                          mFrame->Style(),
    5276             :                                          &mBorderIsEmpty,
    5277           0 :                                          mFrame->GetSkipSides());
    5278             : 
    5279           0 :   mBorderRenderer = Nothing();
    5280           0 :   mBorderImageRenderer = Nothing();
    5281           0 :   if (!br) {
    5282           0 :     if (mBorderIsEmpty) {
    5283             :       return LAYER_ACTIVE;
    5284             :     }
    5285           0 :     return LAYER_NONE;
    5286             :   }
    5287             : 
    5288           0 :   if (!br->AllBordersSolid()) {
    5289             :     return LAYER_NONE;
    5290             :   }
    5291             : 
    5292             :   // We don't support this yet as we don't copy the values to
    5293             :   // the layer, and BasicBorderLayer doesn't support it yet.
    5294           0 :   if (!br->mNoBorderRadius) {
    5295             :     return LAYER_NONE;
    5296             :   }
    5297             : 
    5298             :   // We copy these values correctly to the layer, but BasicBorderLayer
    5299             :   // won't render them
    5300           0 :   if (!br->AreBorderSideFinalStylesSame(eSideBitsAll) ||
    5301           0 :       !br->AllBordersSameWidth()) {
    5302             :     return LAYER_NONE;
    5303             :   }
    5304             : 
    5305           0 :   NS_FOR_CSS_SIDES(i) {
    5306           0 :     if (br->mBorderStyles[i] == NS_STYLE_BORDER_STYLE_SOLID) {
    5307           0 :       mColors[i] = ToDeviceColor(br->mBorderColors[i]);
    5308           0 :       mWidths[i] = br->mBorderWidths[i];
    5309           0 :       mBorderStyles[i] = br->mBorderStyles[i];
    5310             :     } else {
    5311           0 :       mWidths[i] = 0;
    5312             :     }
    5313             :   }
    5314           0 :   NS_FOR_CSS_FULL_CORNERS(corner) {
    5315           0 :     mCorners[corner] = LayerSize(br->mBorderRadii[corner].width, br->mBorderRadii[corner].height);
    5316             :   }
    5317             : 
    5318           0 :   mRect = ViewAs<LayerPixel>(br->mOuterRect);
    5319           0 :   return LAYER_ACTIVE;
    5320             : }
    5321             : 
    5322             : already_AddRefed<Layer>
    5323           0 : nsDisplayBorder::BuildLayer(nsDisplayListBuilder* aBuilder,
    5324             :                             LayerManager* aManager,
    5325             :                             const ContainerLayerParameters& aContainerParameters)
    5326             : {
    5327           0 :   if (mBorderIsEmpty) {
    5328             :     return nullptr;
    5329             :   }
    5330             : 
    5331             :   RefPtr<BorderLayer> layer = static_cast<BorderLayer*>
    5332           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
    5333           0 :   if (!layer) {
    5334           0 :     layer = aManager->CreateBorderLayer();
    5335           0 :     if (!layer)
    5336             :       return nullptr;
    5337             :   }
    5338           0 :   layer->SetRect(mRect);
    5339           0 :   layer->SetCornerRadii(mCorners);
    5340           0 :   layer->SetColors(mColors);
    5341           0 :   layer->SetWidths(mWidths);
    5342           0 :   layer->SetStyles(mBorderStyles);
    5343           0 :   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
    5344           0 :                                                       aContainerParameters.mOffset.y, 0));
    5345           0 :   return layer.forget();
    5346             : }
    5347             : 
    5348             : bool
    5349           0 : nsDisplayBorder::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5350             :                                          mozilla::wr::IpcResourceUpdateQueue& aResources,
    5351             :                                          const StackingContextHelper& aSc,
    5352             :                                          mozilla::layers::WebRenderLayerManager* aManager,
    5353             :                                          nsDisplayListBuilder* aDisplayListBuilder)
    5354             : {
    5355           0 :   nsRect rect = nsRect(ToReferenceFrame(), mFrame->GetSize());
    5356             : 
    5357           0 :   return nsCSSRendering::CreateWebRenderCommandsForBorder(this,
    5358             :                                                           mFrame,
    5359             :                                                           rect,
    5360             :                                                           aBuilder,
    5361             :                                                           aResources,
    5362             :                                                           aSc,
    5363             :                                                           aManager,
    5364           0 :                                                           aDisplayListBuilder);
    5365             : };
    5366             : 
    5367             : void
    5368           0 : nsDisplayBorder::CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5369             :                                                     mozilla::wr::IpcResourceUpdateQueue& aResources,
    5370             :                                                     const StackingContextHelper& aSc,
    5371             :                                                     mozilla::layers::WebRenderLayerManager* aManager,
    5372             :                                                     nsDisplayListBuilder* aDisplayListBuilder)
    5373             : {
    5374           0 :   MOZ_ASSERT(mBorderImageRenderer);
    5375           0 :   if (!mBorderImageRenderer->mImageRenderer.IsReady()) {
    5376           0 :     return;
    5377             :   }
    5378             : 
    5379             :   float widths[4];
    5380             :   float slice[4];
    5381             :   float outset[4];
    5382           0 :   const int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    5383           0 :   NS_FOR_CSS_SIDES(i) {
    5384           0 :     slice[i] = (float)(mBorderImageRenderer->mSlice.Side(i)) / appUnitsPerDevPixel;
    5385           0 :     widths[i] = (float)(mBorderImageRenderer->mWidths.Side(i)) / appUnitsPerDevPixel;
    5386           0 :     outset[i] = (float)(mBorderImageRenderer->mImageOutset.Side(i)) / appUnitsPerDevPixel;
    5387             :   }
    5388             : 
    5389             :   LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(
    5390           0 :     mBorderImageRenderer->mArea, appUnitsPerDevPixel);
    5391           0 :   wr::LayoutRect dest = wr::ToRoundedLayoutRect(destRect);
    5392             : 
    5393           0 :   wr::LayoutRect clip = dest;
    5394           0 :   if (!mBorderImageRenderer->mClip.IsEmpty()) {
    5395             :     LayoutDeviceRect clipRect = LayoutDeviceRect::FromAppUnits(
    5396           0 :       mBorderImageRenderer->mClip, appUnitsPerDevPixel);
    5397           0 :     clip = wr::ToRoundedLayoutRect(clipRect);
    5398             :   }
    5399             : 
    5400           0 :   switch (mBorderImageRenderer->mImageRenderer.GetType()) {
    5401             :     case eStyleImageType_Image:
    5402             :     {
    5403           0 :       uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY;
    5404           0 :       if (aDisplayListBuilder->IsPaintingToWindow()) {
    5405           0 :         flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
    5406             :       }
    5407           0 :       if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
    5408           0 :         flags |= imgIContainer::FLAG_SYNC_DECODE;
    5409             :       }
    5410             : 
    5411           0 :       RefPtr<imgIContainer> img = mBorderImageRenderer->mImageRenderer.GetImage();
    5412           0 :       Maybe<SVGImageContext> svgContext;
    5413             :       gfx::IntSize decodeSize =
    5414             :         nsLayoutUtils::ComputeImageContainerDrawingParameters(img, mFrame, destRect,
    5415           0 :                                                               aSc, flags, svgContext);
    5416             :       RefPtr<layers::ImageContainer> container =
    5417           0 :         img->GetImageContainerAtSize(aManager, decodeSize, svgContext, flags);
    5418           0 :       if (!container) {
    5419           0 :         return;
    5420             :       }
    5421             : 
    5422           0 :       gfx::IntSize size;
    5423           0 :       Maybe<wr::ImageKey> key = aManager->CommandBuilder().CreateImageKey(this, container, aBuilder,
    5424           0 :                                                                           aResources, aSc, size, Nothing());
    5425           0 :       if (key.isNothing()) {
    5426             :         return;
    5427             :       }
    5428             : 
    5429           0 :       aBuilder.PushBorderImage(dest,
    5430             :                                clip,
    5431           0 :                                !BackfaceIsHidden(),
    5432           0 :                                wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
    5433             :                                key.value(),
    5434           0 :                                (float)(mBorderImageRenderer->mImageSize.width) / appUnitsPerDevPixel,
    5435           0 :                                (float)(mBorderImageRenderer->mImageSize.height) / appUnitsPerDevPixel,
    5436           0 :                                wr::ToSideOffsets2D_u32(slice[0], slice[1], slice[2], slice[3]),
    5437           0 :                                wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]),
    5438           0 :                                wr::ToRepeatMode(mBorderImageRenderer->mRepeatModeHorizontal),
    5439           0 :                                wr::ToRepeatMode(mBorderImageRenderer->mRepeatModeVertical));
    5440           0 :       break;
    5441             :     }
    5442             :     case eStyleImageType_Gradient:
    5443             :     {
    5444           0 :       RefPtr<nsStyleGradient> gradientData = mBorderImageRenderer->mImageRenderer.GetGradientData();
    5445             :       nsCSSGradientRenderer renderer =
    5446           0 :         nsCSSGradientRenderer::Create(mFrame->PresContext(), mFrame->Style(),
    5447           0 :                                       gradientData, mBorderImageRenderer->mImageSize);
    5448             : 
    5449             :       wr::ExtendMode extendMode;
    5450           0 :       nsTArray<wr::GradientStop> stops;
    5451           0 :       LayoutDevicePoint lineStart;
    5452           0 :       LayoutDevicePoint lineEnd;
    5453           0 :       LayoutDeviceSize gradientRadius;
    5454           0 :       renderer.BuildWebRenderParameters(1.0, extendMode, stops, lineStart, lineEnd, gradientRadius);
    5455             : 
    5456           0 :       if (gradientData->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
    5457           0 :         LayoutDevicePoint startPoint = LayoutDevicePoint(dest.origin.x, dest.origin.y) + lineStart;
    5458           0 :         LayoutDevicePoint endPoint = LayoutDevicePoint(dest.origin.x, dest.origin.y) + lineEnd;
    5459             : 
    5460           0 :         aBuilder.PushBorderGradient(dest,
    5461             :                                     clip,
    5462           0 :                                     !BackfaceIsHidden(),
    5463           0 :                                     wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
    5464           0 :                                     wr::ToLayoutPoint(startPoint),
    5465           0 :                                     wr::ToLayoutPoint(endPoint),
    5466             :                                     stops,
    5467             :                                     extendMode,
    5468           0 :                                     wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]));
    5469             :       } else {
    5470           0 :         aBuilder.PushBorderRadialGradient(dest,
    5471             :                                           clip,
    5472           0 :                                           !BackfaceIsHidden(),
    5473           0 :                                           wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
    5474           0 :                                           wr::ToLayoutPoint(lineStart),
    5475           0 :                                           wr::ToLayoutSize(gradientRadius),
    5476             :                                           stops,
    5477             :                                           extendMode,
    5478           0 :                                           wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]));
    5479             :       }
    5480             :       break;
    5481             :     }
    5482             :     default:
    5483           0 :       MOZ_ASSERT_UNREACHABLE("Unsupport border image type");
    5484             :   }
    5485             : }
    5486             : 
    5487             : void
    5488           0 : nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
    5489             :                        gfxContext* aCtx) {
    5490          24 :   nsPoint offset = ToReferenceFrame();
    5491             : 
    5492           1 :   PaintBorderFlags flags = aBuilder->ShouldSyncDecodeImages()
    5493           1 :                          ? PaintBorderFlags::SYNC_DECODE_IMAGES
    5494          12 :                          : PaintBorderFlags();
    5495             : 
    5496             :   ImgDrawResult result =
    5497          60 :     nsCSSRendering::PaintBorder(mFrame->PresContext(), *aCtx, mFrame,
    5498             :                                 GetPaintRect(),
    5499           1 :                                 nsRect(offset, mFrame->GetSize()),
    5500           1 :                                 mFrame->Style(),
    5501             :                                 flags,
    5502           1 :                                 mFrame->GetSkipSides());
    5503             : 
    5504           1 :   nsDisplayBorderGeometry::UpdateDrawResult(this, result);
    5505           1 : }
    5506             : 
    5507             : nsRect
    5508         172 : nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder,
    5509             :                            bool* aSnap) const
    5510             : {
    5511         172 :   *aSnap = true;
    5512         172 :   return mBounds;
    5513             : }
    5514             : 
    5515             : // Given a region, compute a conservative approximation to it as a list
    5516             : // of rectangles that aren't vertically adjacent (i.e., vertically
    5517             : // adjacent or overlapping rectangles are combined).
    5518             : // Right now this is only approximate, some vertically overlapping rectangles
    5519             : // aren't guaranteed to be combined.
    5520             : static void
    5521           4 : ComputeDisjointRectangles(const nsRegion& aRegion,
    5522             :                           nsTArray<nsRect>* aRects) {
    5523           4 :   nscoord accumulationMargin = nsPresContext::CSSPixelsToAppUnits(25);
    5524           8 :   nsRect accumulated;
    5525             : 
    5526           1 :   for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
    5527          20 :     const nsRect& r = iter.Get();
    5528          24 :     if (accumulated.IsEmpty()) {
    5529           4 :       accumulated = r;
    5530           1 :       continue;
    5531             :     }
    5532             : 
    5533           1 :     if (accumulated.YMost() >= r.y - accumulationMargin) {
    5534           1 :       accumulated.UnionRect(accumulated, r);
    5535             :     } else {
    5536           0 :       aRects->AppendElement(accumulated);
    5537           0 :       accumulated = r;
    5538             :     }
    5539             :   }
    5540             : 
    5541             :   // Finish the in-flight rectangle, if there is one.
    5542           8 :   if (!accumulated.IsEmpty()) {
    5543           1 :     aRects->AppendElement(accumulated);
    5544             :   }
    5545           4 : }
    5546             : 
    5547             : void
    5548           1 : nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
    5549             :                                gfxContext* aCtx) {
    5550           8 :   nsPoint offset = ToReferenceFrame();
    5551           8 :   nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
    5552           1 :   nsPresContext* presContext = mFrame->PresContext();
    5553           8 :   AutoTArray<nsRect,10> rects;
    5554           4 :   ComputeDisjointRectangles(mVisibleRegion, &rects);
    5555             : 
    5556           8 :   AUTO_PROFILER_LABEL("nsDisplayBoxShadowOuter::Paint", GRAPHICS);
    5557             : 
    5558           1 :   for (uint32_t i = 0; i < rects.Length(); ++i) {
    5559           1 :     nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
    5560           1 :                                         borderRect, rects[i], mOpacity);
    5561             :   }
    5562           4 : }
    5563             : 
    5564             : nsRect
    5565           1 : nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
    5566             :                                    bool* aSnap) const
    5567             : {
    5568           1 :   *aSnap = false;
    5569           1 :   return mBounds;
    5570             : }
    5571             : 
    5572             : nsRect
    5573          16 : nsDisplayBoxShadowOuter::GetBoundsInternal() {
    5574           1 :   return nsLayoutUtils::GetBoxShadowRectForFrame(mFrame, mFrame->GetSize()) +
    5575          48 :          ToReferenceFrame();
    5576             : }
    5577             : 
    5578             : bool
    5579           4 : nsDisplayBoxShadowOuter::IsInvisibleInRect(const nsRect& aRect) const
    5580             : {
    5581           8 :   nsPoint origin = ToReferenceFrame();
    5582           1 :   nsRect frameRect(origin, mFrame->GetSize());
    5583           4 :   if (!frameRect.Contains(aRect))
    5584             :     return false;
    5585             : 
    5586             :   // the visible region is entirely inside the border-rect, and box shadows
    5587             :   // never render within the border-rect (unless there's a border radius).
    5588             :   nscoord twipsRadii[8];
    5589           0 :   bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii);
    5590           0 :   if (!hasBorderRadii)
    5591             :     return true;
    5592             : 
    5593           0 :   return RoundedRectContainsRect(frameRect, twipsRadii, aRect);
    5594             : }
    5595             : 
    5596             : bool
    5597           8 : nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    5598             :                                            nsRegion* aVisibleRegion) {
    5599           1 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
    5600             :     return false;
    5601             :   }
    5602             : 
    5603           8 :   mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
    5604           4 :   return true;
    5605             : }
    5606             : 
    5607             : bool
    5608           0 : nsDisplayBoxShadowOuter::CanBuildWebRenderDisplayItems()
    5609             : {
    5610           0 :   nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
    5611           0 :   if (!shadows) {
    5612             :     return false;
    5613             :   }
    5614             : 
    5615             :   bool hasBorderRadius;
    5616             :   bool nativeTheme =
    5617           0 :       nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius);
    5618             : 
    5619             :   // We don't support native themed things yet like box shadows around
    5620             :   // input buttons.
    5621           0 :   if (nativeTheme) {
    5622             :     return false;
    5623             :   }
    5624             : 
    5625           0 :   return true;
    5626             : }
    5627             : 
    5628             : bool
    5629           0 : nsDisplayBoxShadowOuter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5630             :                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
    5631             :                                                  const StackingContextHelper& aSc,
    5632             :                                                  mozilla::layers::WebRenderLayerManager* aManager,
    5633             :                                                  nsDisplayListBuilder* aDisplayListBuilder)
    5634             : {
    5635           0 :   if (!CanBuildWebRenderDisplayItems()) {
    5636             :     return false;
    5637             :   }
    5638             : 
    5639           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    5640           0 :   nsPoint offset = ToReferenceFrame();
    5641           0 :   nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
    5642           0 :   AutoTArray<nsRect,10> rects;
    5643             :   bool snap;
    5644           0 :   nsRect bounds = GetBounds(aDisplayListBuilder, &snap);
    5645           0 :   ComputeDisjointRectangles(bounds, &rects);
    5646             : 
    5647             :   bool hasBorderRadius;
    5648           0 :   bool nativeTheme = nsCSSRendering::HasBoxShadowNativeTheme(mFrame,
    5649           0 :                                                              hasBorderRadius);
    5650             : 
    5651             :   // Don't need the full size of the shadow rect like we do in
    5652             :   // nsCSSRendering since WR takes care of calculations for blur
    5653             :   // and spread radius.
    5654             :   nsRect frameRect = nsCSSRendering::GetShadowRect(borderRect,
    5655             :                                                     nativeTheme,
    5656           0 :                                                     mFrame);
    5657             : 
    5658           0 :   RectCornerRadii borderRadii;
    5659           0 :   if (hasBorderRadius) {
    5660           0 :     hasBorderRadius = nsCSSRendering::GetBorderRadii(frameRect,
    5661             :                                                      borderRect,
    5662             :                                                      mFrame,
    5663             :                                                      borderRadii);
    5664             :   }
    5665             : 
    5666             :   // Everything here is in app units, change to device units.
    5667           0 :   for (uint32_t i = 0; i < rects.Length(); ++i) {
    5668             :     LayoutDeviceRect clipRect = LayoutDeviceRect::FromAppUnits(
    5669           0 :         rects[i], appUnitsPerDevPixel);
    5670           0 :     nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
    5671           0 :     MOZ_ASSERT(shadows);
    5672             : 
    5673           0 :     for (uint32_t j = shadows->Length(); j  > 0; j--) {
    5674           0 :       nsCSSShadowItem* shadow = shadows->ShadowAt(j - 1);
    5675           0 :       if (shadow->mInset) {
    5676           0 :         continue;
    5677             :       }
    5678             : 
    5679           0 :       float blurRadius = float(shadow->mRadius) / float(appUnitsPerDevPixel);
    5680             :       gfx::Color shadowColor = nsCSSRendering::GetShadowColor(shadow,
    5681             :                                                               mFrame,
    5682           0 :                                                               mOpacity);
    5683             : 
    5684             :       // We don't move the shadow rect here since WR does it for us
    5685             :       // Now translate everything to device pixels.
    5686           0 :       nsRect shadowRect = frameRect;
    5687             :       LayoutDevicePoint shadowOffset = LayoutDevicePoint::FromAppUnits(
    5688           0 :           nsPoint(shadow->mXOffset, shadow->mYOffset),
    5689           0 :           appUnitsPerDevPixel);
    5690             : 
    5691             :       LayoutDeviceRect deviceBox = LayoutDeviceRect::FromAppUnits(
    5692           0 :           shadowRect, appUnitsPerDevPixel);
    5693           0 :       wr::LayoutRect deviceBoxRect = wr::ToRoundedLayoutRect(deviceBox);
    5694           0 :       wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
    5695             : 
    5696           0 :       LayoutDeviceSize zeroSize;
    5697             :       wr::BorderRadius borderRadius = wr::ToBorderRadius(zeroSize, zeroSize,
    5698           0 :                                                          zeroSize, zeroSize);
    5699           0 :       if (hasBorderRadius) {
    5700             :         borderRadius = wr::ToBorderRadius(
    5701           0 :           LayoutDeviceSize::FromUnknownSize(borderRadii.TopLeft()),
    5702           0 :           LayoutDeviceSize::FromUnknownSize(borderRadii.TopRight()),
    5703           0 :           LayoutDeviceSize::FromUnknownSize(borderRadii.BottomLeft()),
    5704           0 :           LayoutDeviceSize::FromUnknownSize(borderRadii.BottomRight()));
    5705             :       }
    5706             : 
    5707           0 :       float spreadRadius = float(shadow->mSpread) / float(appUnitsPerDevPixel);
    5708             : 
    5709           0 :       aBuilder.PushBoxShadow(deviceBoxRect,
    5710             :                              deviceClipRect,
    5711           0 :                              !BackfaceIsHidden(),
    5712             :                              deviceBoxRect,
    5713           0 :                              wr::ToLayoutVector2D(shadowOffset),
    5714           0 :                              wr::ToColorF(shadowColor),
    5715             :                              blurRadius,
    5716             :                              spreadRadius,
    5717             :                              borderRadius,
    5718           0 :                              wr::BoxShadowClipMode::Outset);
    5719             :     }
    5720             :   }
    5721             : 
    5722             :   return true;
    5723             : }
    5724             : 
    5725             : void
    5726          14 : nsDisplayBoxShadowOuter::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    5727             :                                                    const nsDisplayItemGeometry* aGeometry,
    5728             :                                                    nsRegion* aInvalidRegion) const
    5729             : {
    5730             :   const nsDisplayBoxShadowOuterGeometry* geometry =
    5731          14 :     static_cast<const nsDisplayBoxShadowOuterGeometry*>(aGeometry);
    5732             :   bool snap;
    5733           0 :   if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
    5734          42 :       !geometry->mBorderRect.IsEqualInterior(GetBorderRect()) ||
    5735          14 :       mOpacity != geometry->mOpacity) {
    5736           0 :     nsRegion oldShadow, newShadow;
    5737             :     nscoord dontCare[8];
    5738           0 :     bool hasBorderRadius = mFrame->GetBorderRadii(dontCare);
    5739           0 :     if (hasBorderRadius) {
    5740             :       // If we have rounded corners then we need to invalidate the frame area
    5741             :       // too since we paint into it.
    5742           0 :       oldShadow = geometry->mBounds;
    5743           0 :       newShadow = GetBounds(aBuilder, &snap);
    5744             :     } else {
    5745           0 :       oldShadow.Sub(geometry->mBounds, geometry->mBorderRect);
    5746           0 :       newShadow.Sub(GetBounds(aBuilder, &snap), GetBorderRect());
    5747             :     }
    5748           0 :     aInvalidRegion->Or(oldShadow, newShadow);
    5749             :   }
    5750          14 : }
    5751             : 
    5752             : 
    5753             : void
    5754           0 : nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
    5755             :                                gfxContext* aCtx) {
    5756           0 :   nsPoint offset = ToReferenceFrame();
    5757           0 :   nsRect borderRect = nsRect(offset, mFrame->GetSize());
    5758           0 :   nsPresContext* presContext = mFrame->PresContext();
    5759           0 :   AutoTArray<nsRect,10> rects;
    5760           0 :   ComputeDisjointRectangles(mVisibleRegion, &rects);
    5761             : 
    5762           0 :   AUTO_PROFILER_LABEL("nsDisplayBoxShadowInner::Paint", GRAPHICS);
    5763             : 
    5764           0 :   DrawTarget* drawTarget = aCtx->GetDrawTarget();
    5765           0 :   gfxContext* gfx = aCtx;
    5766           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    5767             : 
    5768           0 :   for (uint32_t i = 0; i < rects.Length(); ++i) {
    5769           0 :     gfx->Save();
    5770           0 :     gfx->Clip(NSRectToSnappedRect(rects[i], appUnitsPerDevPixel, *drawTarget));
    5771           0 :     nsCSSRendering::PaintBoxShadowInner(presContext, *aCtx, mFrame, borderRect);
    5772           0 :     gfx->Restore();
    5773             :   }
    5774           0 : }
    5775             : 
    5776             : bool
    5777           0 : nsDisplayBoxShadowInner::CanCreateWebRenderCommands(nsDisplayListBuilder* aBuilder,
    5778             :                                                     nsIFrame* aFrame,
    5779             :                                                     nsPoint aReferenceOffset)
    5780             : {
    5781           0 :   nsCSSShadowArray *shadows = aFrame->StyleEffects()->mBoxShadow;
    5782           0 :   if (!shadows) {
    5783             :     // Means we don't have to paint anything
    5784             :     return true;
    5785             :   }
    5786             : 
    5787             :   bool hasBorderRadius;
    5788             :   bool nativeTheme =
    5789           0 :     nsCSSRendering::HasBoxShadowNativeTheme(aFrame, hasBorderRadius);
    5790             : 
    5791             :   // We don't support native themed things yet like box shadows around
    5792             :   // input buttons.
    5793           0 :   if (nativeTheme) {
    5794             :     return false;
    5795             :   }
    5796             : 
    5797           0 :   return true;
    5798             : }
    5799             : 
    5800             : /* static */ void
    5801           0 : nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5802             :                                                                const StackingContextHelper& aSc,
    5803             :                                                                nsRegion& aVisibleRegion,
    5804             :                                                                nsIFrame* aFrame,
    5805             :                                                                const nsRect aBorderRect)
    5806             : {
    5807           0 :   if (!nsCSSRendering::ShouldPaintBoxShadowInner(aFrame)) {
    5808           0 :     return;
    5809             :   }
    5810             : 
    5811           0 :   int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
    5812             : 
    5813           0 :   AutoTArray<nsRect,10> rects;
    5814           0 :   ComputeDisjointRectangles(aVisibleRegion, &rects);
    5815             : 
    5816           0 :   nsCSSShadowArray* shadows = aFrame->StyleEffects()->mBoxShadow;
    5817             : 
    5818           0 :   for (uint32_t i = 0; i < rects.Length(); ++i) {
    5819             :     LayoutDeviceRect clipRect = LayoutDeviceRect::FromAppUnits(
    5820           0 :         rects[i], appUnitsPerDevPixel);
    5821             : 
    5822           0 :     for (uint32_t i = shadows->Length(); i > 0; --i) {
    5823           0 :       nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
    5824           0 :       if (!shadowItem->mInset) {
    5825           0 :         continue;
    5826             :       }
    5827             : 
    5828             :       nsRect shadowRect =
    5829           0 :         nsCSSRendering::GetBoxShadowInnerPaddingRect(aFrame, aBorderRect);
    5830           0 :       RectCornerRadii innerRadii;
    5831           0 :       nsCSSRendering::GetShadowInnerRadii(aFrame, aBorderRect, innerRadii);
    5832             : 
    5833             :       // Now translate everything to device pixels.
    5834             :       LayoutDeviceRect deviceBoxRect = LayoutDeviceRect::FromAppUnits(
    5835           0 :           shadowRect, appUnitsPerDevPixel);
    5836           0 :       wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
    5837           0 :       Color shadowColor = nsCSSRendering::GetShadowColor(shadowItem, aFrame, 1.0);
    5838             : 
    5839             :       LayoutDevicePoint shadowOffset = LayoutDevicePoint::FromAppUnits(
    5840           0 :           nsPoint(shadowItem->mXOffset, shadowItem->mYOffset),
    5841           0 :           appUnitsPerDevPixel);
    5842             : 
    5843           0 :       float blurRadius = float(shadowItem->mRadius) / float(appUnitsPerDevPixel);
    5844             : 
    5845             :       wr::BorderRadius borderRadius = wr::ToBorderRadius(
    5846           0 :         LayoutDeviceSize::FromUnknownSize(innerRadii.TopLeft()),
    5847           0 :         LayoutDeviceSize::FromUnknownSize(innerRadii.TopRight()),
    5848           0 :         LayoutDeviceSize::FromUnknownSize(innerRadii.BottomLeft()),
    5849           0 :         LayoutDeviceSize::FromUnknownSize(innerRadii.BottomRight()));
    5850             :       // NOTE: Any spread radius > 0 will render nothing. WR Bug.
    5851           0 :       float spreadRadius = float(shadowItem->mSpread) / float(appUnitsPerDevPixel);
    5852             : 
    5853           0 :       aBuilder.PushBoxShadow(wr::ToLayoutRect(deviceBoxRect),
    5854             :                              deviceClipRect,
    5855           0 :                              !aFrame->BackfaceIsHidden(),
    5856           0 :                              wr::ToLayoutRect(deviceBoxRect),
    5857           0 :                              wr::ToLayoutVector2D(shadowOffset),
    5858           0 :                              wr::ToColorF(shadowColor),
    5859             :                              blurRadius,
    5860             :                              spreadRadius,
    5861             :                              borderRadius,
    5862             :                              wr::BoxShadowClipMode::Inset
    5863           0 :                              );
    5864             :     }
    5865             :   }
    5866             : }
    5867             : 
    5868             : bool
    5869           0 : nsDisplayBoxShadowInner::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    5870             :                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
    5871             :                                                  const StackingContextHelper& aSc,
    5872             :                                                  mozilla::layers::WebRenderLayerManager* aManager,
    5873             :                                                  nsDisplayListBuilder* aDisplayListBuilder)
    5874             : {
    5875           0 :   if (!CanCreateWebRenderCommands(aDisplayListBuilder, mFrame, ToReferenceFrame())) {
    5876             :     return false;
    5877             :   }
    5878             : 
    5879             :   bool snap;
    5880           0 :   nsRegion visible = GetBounds(aDisplayListBuilder, &snap);
    5881           0 :   nsPoint offset = ToReferenceFrame();
    5882           0 :   nsRect borderRect = nsRect(offset, mFrame->GetSize());
    5883           0 :   nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(aBuilder, aSc, visible,
    5884           0 :                                                                  mFrame, borderRect);
    5885             : 
    5886             :   return true;
    5887             : }
    5888             : 
    5889             : bool
    5890           0 : nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    5891             :                                            nsRegion* aVisibleRegion) {
    5892           0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
    5893             :     return false;
    5894             :   }
    5895             : 
    5896           0 :   mVisibleRegion.And(*aVisibleRegion, GetPaintRect());
    5897           0 :   return true;
    5898             : }
    5899             : 
    5900           1 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    5901           1 :                                      nsIFrame* aFrame, nsDisplayList* aList, bool aAnonymous)
    5902             :   : nsDisplayWrapList(aBuilder, aFrame, aList,
    5903          22 :                       aBuilder->CurrentActiveScrolledRoot(), false, 0, aAnonymous)
    5904           1 : {}
    5905             : 
    5906         136 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    5907             :                                      nsIFrame* aFrame, nsDisplayList* aList,
    5908             :                                      const ActiveScrolledRoot* aActiveScrolledRoot,
    5909             :                                      bool aClearClipChain,
    5910             :                                      uint32_t aIndex,
    5911           1 :                                      bool aAnonymous)
    5912             :   : nsDisplayItem(aBuilder, aFrame, aActiveScrolledRoot, aAnonymous)
    5913             :   , mFrameActiveScrolledRoot(aBuilder->CurrentActiveScrolledRoot())
    5914             :   , mOverrideZIndex(0)
    5915             :   , mIndex(aIndex)
    5916             :   , mHasZIndexOverride(false)
    5917           1 :   , mClearingClipChain(aClearClipChain)
    5918             : {
    5919           1 :   MOZ_COUNT_CTOR(nsDisplayWrapList);
    5920             : 
    5921           1 :   mBaseBuildingRect = GetBuildingRect();
    5922             : 
    5923           1 :   mListPtr = &mList;
    5924           1 :   mListPtr->AppendToTop(aList);
    5925         136 :   UpdateBounds(aBuilder);
    5926             : 
    5927           1 :   if (!aFrame || !aFrame->IsTransformed()) {
    5928           1 :     return;
    5929             :   }
    5930             : 
    5931             :   // If we're a transformed frame, then we need to find out if we're inside
    5932             :   // the nsDisplayTransform or outside of it. Frames inside the transform
    5933             :   // need mReferenceFrame == mFrame, outside needs the next ancestor
    5934             :   // reference frame.
    5935             :   // If we're inside the transform, then the nsDisplayItem constructor
    5936             :   // will have done the right thing.
    5937             :   // If we're outside the transform, then we should have only one child
    5938             :   // (since nsDisplayTransform wraps all actual content), and that child
    5939             :   // will have the correct reference frame set (since nsDisplayTransform
    5940             :   // handles this explictly).
    5941          22 :   nsDisplayItem *i = mListPtr->GetBottom();
    5942          42 :   if (i && (!i->GetAbove() || i->GetType() == DisplayItemType::TYPE_TRANSFORM) &&
    5943           1 :       i->Frame() == mFrame) {
    5944          11 :     mReferenceFrame = i->ReferenceFrame();
    5945          11 :     mToReferenceFrame = i->ToReferenceFrame();
    5946             :   }
    5947             : 
    5948             :   nsRect visible = aBuilder->GetVisibleRect() +
    5949          66 :     aBuilder->GetCurrentFrameOffsetToReferenceFrame();
    5950             : 
    5951           0 :   SetBuildingRect(visible);
    5952             : }
    5953             : 
    5954           0 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    5955           0 :                                      nsIFrame* aFrame, nsDisplayItem* aItem, bool aAnonymous)
    5956             :   : nsDisplayItem(aBuilder, aFrame, aBuilder->CurrentActiveScrolledRoot(), aAnonymous)
    5957             :   , mOverrideZIndex(0)
    5958             :   , mIndex(0)
    5959           0 :   , mHasZIndexOverride(false)
    5960             : {
    5961           0 :   MOZ_COUNT_CTOR(nsDisplayWrapList);
    5962             : 
    5963           0 :   mBaseBuildingRect = GetBuildingRect();
    5964             : 
    5965           0 :   mListPtr = &mList;
    5966           0 :   mListPtr->AppendToTop(aItem);
    5967           0 :   UpdateBounds(aBuilder);
    5968             : 
    5969           0 :   if (!aFrame || !aFrame->IsTransformed()) {
    5970           0 :     return;
    5971             :   }
    5972             : 
    5973             :   // See the previous nsDisplayWrapList constructor
    5974           0 :   if (aItem->Frame() == aFrame) {
    5975           0 :     mReferenceFrame = aItem->ReferenceFrame();
    5976           0 :     mToReferenceFrame = aItem->ToReferenceFrame();
    5977             :   }
    5978             : 
    5979             :   nsRect visible = aBuilder->GetVisibleRect() +
    5980           0 :     aBuilder->GetCurrentFrameOffsetToReferenceFrame();
    5981             : 
    5982           0 :   SetBuildingRect(visible);
    5983             : }
    5984             : 
    5985           0 : nsDisplayWrapList::~nsDisplayWrapList() {
    5986         136 :   MOZ_COUNT_DTOR(nsDisplayWrapList);
    5987           0 : }
    5988             : 
    5989             : void
    5990           0 : nsDisplayWrapList::MergeDisplayListFromItem(nsDisplayListBuilder* aBuilder,
    5991             :                                             const nsDisplayItem* aItem)
    5992             : {
    5993           0 :   const nsDisplayWrapList* wrappedItem = aItem->AsDisplayWrapList();
    5994           0 :   MOZ_ASSERT(wrappedItem);
    5995             : 
    5996             :   // Create a new nsDisplayWrapList using a copy-constructor. This is done
    5997             :   // to preserve the information about bounds.
    5998           0 :   nsDisplayWrapList* wrapper = MakeDisplayItem<nsDisplayWrapList>(aBuilder, *wrappedItem);
    5999             : 
    6000             :   // Set the display list pointer of the new wrapper item to the display list
    6001             :   // of the wrapped item.
    6002           0 :   wrapper->mListPtr = wrappedItem->mListPtr;
    6003             : 
    6004           0 :   mListPtr->AppendToBottom(wrapper);
    6005           0 : }
    6006             : 
    6007             : void
    6008           0 : nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    6009             :                            HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
    6010           0 :   mListPtr->HitTest(aBuilder, aRect, aState, aOutFrames);
    6011           0 : }
    6012             : 
    6013             : nsRect
    6014           1 : nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder,
    6015             :                              bool* aSnap) const
    6016             : {
    6017         232 :   *aSnap = false;
    6018           1 :   return mBounds;
    6019             : }
    6020             : 
    6021             : bool
    6022           1 : nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    6023             :                                      nsRegion* aVisibleRegion) {
    6024             :   // Convert the passed in visible region to our appunits.
    6025          32 :   nsRegion visibleRegion;
    6026             :   // mVisibleRect has been clipped to GetClippedBounds
    6027          32 :   visibleRegion.And(*aVisibleRegion, GetPaintRect());
    6028          32 :   nsRegion originalVisibleRegion = visibleRegion;
    6029             : 
    6030             :   bool retval =
    6031          16 :     mListPtr->ComputeVisibilityForSublist(aBuilder,
    6032             :                                           &visibleRegion,
    6033           1 :                                           GetPaintRect());
    6034          32 :   nsRegion removed;
    6035             :   // removed = originalVisibleRegion - visibleRegion
    6036           1 :   removed.Sub(originalVisibleRegion, visibleRegion);
    6037             :   // aVisibleRegion = aVisibleRegion - removed (modulo any simplifications
    6038             :   // SubtractFromVisibleRegion does)
    6039           1 :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
    6040             : 
    6041           1 :   return retval;
    6042             : }
    6043             : 
    6044             : nsRegion
    6045           0 : nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    6046             :                                    bool* aSnap) const
    6047             : {
    6048           0 :   *aSnap = false;
    6049           0 :   nsRegion result;
    6050           0 :   if (mListPtr->IsOpaque()) {
    6051             :     // Everything within GetBounds that's visible is opaque.
    6052           0 :     result = GetBounds(aBuilder, aSnap);
    6053           0 :   } else if (aBuilder->HitTestIsForVisibility()) {
    6054             :     // If we care about an accurate opaque region, iterate the display list
    6055             :     // and build up a region of opaque bounds.
    6056           0 :     nsDisplayItem* item = mList.GetBottom();
    6057           0 :     while (item) {
    6058           0 :       result.OrWith(item->GetOpaqueRegion(aBuilder, aSnap));
    6059           0 :       item = item->GetAbove();
    6060             :     }
    6061             :   }
    6062           0 :   *aSnap = false;
    6063           0 :   return result;
    6064             : }
    6065             : 
    6066             : Maybe<nscolor>
    6067           0 : nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder) const
    6068             : {
    6069             :   // We could try to do something but let's conservatively just return Nothing.
    6070           0 :   return Nothing();
    6071             : }
    6072             : 
    6073           0 : void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
    6074             :                               gfxContext* aCtx) {
    6075           0 :   NS_ERROR("nsDisplayWrapList should have been flattened away for painting");
    6076           0 : }
    6077             : 
    6078             : /**
    6079             :  * Returns true if all descendant display items can be placed in the same
    6080             :  * PaintedLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
    6081             :  * and they all have the expected animated geometry root.
    6082             :  */
    6083             : static LayerState
    6084          54 : RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
    6085             :                               LayerManager* aManager,
    6086             :                               const ContainerLayerParameters& aParameters,
    6087             :                               const nsDisplayList& aList,
    6088             :                               AnimatedGeometryRoot* aExpectedAnimatedGeometryRootForChildren)
    6089             : {
    6090          54 :   LayerState result = LAYER_INACTIVE;
    6091         158 :   for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
    6092         208 :     if (result == LAYER_INACTIVE &&
    6093         104 :         i->GetAnimatedGeometryRoot() != aExpectedAnimatedGeometryRootForChildren) {
    6094           0 :       result = LAYER_ACTIVE;
    6095             :     }
    6096             : 
    6097         104 :     LayerState state = i->GetLayerState(aBuilder, aManager, aParameters);
    6098         208 :     if (state == LAYER_ACTIVE &&
    6099           0 :         (i->GetType() == DisplayItemType::TYPE_BLEND_MODE ||
    6100           0 :          i->GetType() == DisplayItemType::TYPE_TABLE_BLEND_MODE)) {
    6101             :       // nsDisplayBlendMode always returns LAYER_ACTIVE to ensure that the
    6102             :       // blending operation happens in the intermediate surface of its parent
    6103             :       // display item (usually an nsDisplayBlendContainer). But this does not
    6104             :       // mean that it needs all its ancestor display items to become active.
    6105             :       // So we ignore its layer state and look at its children instead.
    6106           0 :       state = RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
    6107           0 :         *i->GetSameCoordinateSystemChildren(), i->GetAnimatedGeometryRoot());
    6108             :     }
    6109           1 :     if ((state == LAYER_ACTIVE || state == LAYER_ACTIVE_FORCE) &&
    6110           0 :         state > result) {
    6111           0 :       result = state;
    6112             :     }
    6113         104 :     if (state == LAYER_ACTIVE_EMPTY && state > result) {
    6114           0 :       result = LAYER_ACTIVE_FORCE;
    6115             :     }
    6116         104 :     if (state == LAYER_NONE) {
    6117           0 :       nsDisplayList* list = i->GetSameCoordinateSystemChildren();
    6118         104 :       if (list) {
    6119             :         LayerState childState =
    6120             :           RequiredLayerStateForChildren(aBuilder, aManager, aParameters, *list,
    6121           0 :               aExpectedAnimatedGeometryRootForChildren);
    6122           0 :         if (childState > result) {
    6123           0 :           result = childState;
    6124             :         }
    6125             :       }
    6126             :     }
    6127             :   }
    6128           0 :   return result;
    6129             : }
    6130             : 
    6131           0 : nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const
    6132             : {
    6133          32 :   nsRect bounds;
    6134         112 :   for (nsDisplayItem* i = mListPtr->GetBottom(); i; i = i->GetAbove()) {
    6135          80 :     bounds.UnionRect(bounds, i->GetComponentAlphaBounds(aBuilder));
    6136             :   }
    6137          32 :   return bounds;
    6138             : }
    6139             : 
    6140             : void
    6141           0 : nsDisplayWrapList::SetReferenceFrame(const nsIFrame* aFrame)
    6142             : {
    6143           0 :   mReferenceFrame = aFrame;
    6144           0 :   mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
    6145           0 : }
    6146             : 
    6147             : bool
    6148           0 : nsDisplayWrapList::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    6149             :                                            mozilla::wr::IpcResourceUpdateQueue& aResources,
    6150             :                                            const StackingContextHelper& aSc,
    6151             :                                            mozilla::layers::WebRenderLayerManager* aManager,
    6152             :                                            nsDisplayListBuilder* aDisplayListBuilder)
    6153             : {
    6154           0 :   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(GetChildren(),
    6155             :                                                                     this,
    6156             :                                                                     aDisplayListBuilder,
    6157             :                                                                     aSc,
    6158             :                                                                     aBuilder,
    6159           0 :                                                                     aResources);
    6160           0 :   return true;
    6161             : }
    6162             : 
    6163             : static nsresult
    6164           0 : WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    6165             :                 nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
    6166           0 :   if (!aList->GetTop())
    6167             :     return NS_OK;
    6168           0 :   nsDisplayItem* item = aWrapper->WrapList(aBuilder, aFrame, aList);
    6169           0 :   if (!item)
    6170             :     return NS_ERROR_OUT_OF_MEMORY;
    6171             :   // aList was emptied
    6172           0 :   aList->AppendToTop(item);
    6173           0 :   return NS_OK;
    6174             : }
    6175             : 
    6176             : static nsresult
    6177           0 : WrapEachDisplayItem(nsDisplayListBuilder* aBuilder,
    6178             :                     nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
    6179           0 :   nsDisplayList newList;
    6180             :   nsDisplayItem* item;
    6181           0 :   while ((item = aList->RemoveBottom())) {
    6182           0 :     item = aWrapper->WrapItem(aBuilder, item);
    6183           0 :     if (!item)
    6184             :       return NS_ERROR_OUT_OF_MEMORY;
    6185           0 :     newList.AppendToTop(item);
    6186             :   }
    6187             :   // aList was emptied
    6188           0 :   aList->AppendToTop(&newList);
    6189           0 :   return NS_OK;
    6190             : }
    6191             : 
    6192           0 : nsresult nsDisplayWrapper::WrapLists(nsDisplayListBuilder* aBuilder,
    6193             :     nsIFrame* aFrame, const nsDisplayListSet& aIn, const nsDisplayListSet& aOut)
    6194             : {
    6195           0 :   nsresult rv = WrapListsInPlace(aBuilder, aFrame, aIn);
    6196           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6197             : 
    6198           0 :   if (&aOut == &aIn)
    6199             :     return NS_OK;
    6200           0 :   aOut.BorderBackground()->AppendToTop(aIn.BorderBackground());
    6201           0 :   aOut.BlockBorderBackgrounds()->AppendToTop(aIn.BlockBorderBackgrounds());
    6202           0 :   aOut.Floats()->AppendToTop(aIn.Floats());
    6203           0 :   aOut.Content()->AppendToTop(aIn.Content());
    6204           0 :   aOut.PositionedDescendants()->AppendToTop(aIn.PositionedDescendants());
    6205           0 :   aOut.Outlines()->AppendToTop(aIn.Outlines());
    6206           0 :   return NS_OK;
    6207             : }
    6208             : 
    6209           0 : nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
    6210             :     nsIFrame* aFrame, const nsDisplayListSet& aLists)
    6211             : {
    6212             :   nsresult rv;
    6213           0 :   if (WrapBorderBackground()) {
    6214             :     // Our border-backgrounds are in-flow
    6215           0 :     rv = WrapDisplayList(aBuilder, aFrame, aLists.BorderBackground(), this);
    6216           0 :     NS_ENSURE_SUCCESS(rv, rv);
    6217             :   }
    6218             :   // Our block border-backgrounds are in-flow
    6219           0 :   rv = WrapDisplayList(aBuilder, aFrame, aLists.BlockBorderBackgrounds(), this);
    6220           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6221             :   // The floats are not in flow
    6222           0 :   rv = WrapEachDisplayItem(aBuilder, aLists.Floats(), this);
    6223           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6224             :   // Our child content is in flow
    6225           0 :   rv = WrapDisplayList(aBuilder, aFrame, aLists.Content(), this);
    6226           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6227             :   // The positioned descendants may not be in-flow
    6228           0 :   rv = WrapEachDisplayItem(aBuilder, aLists.PositionedDescendants(), this);
    6229           0 :   NS_ENSURE_SUCCESS(rv, rv);
    6230             :   // The outlines may not be in-flow
    6231           0 :   return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
    6232             : }
    6233             : 
    6234          32 : nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
    6235             :                                    nsIFrame* aFrame, nsDisplayList* aList,
    6236             :                                    const ActiveScrolledRoot* aActiveScrolledRoot,
    6237          32 :                                    bool aForEventsAndPluginsOnly)
    6238             :     : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
    6239           0 :     , mOpacity(aFrame->StyleEffects()->mOpacity)
    6240             :     , mForEventsAndPluginsOnly(aForEventsAndPluginsOnly)
    6241          64 :     , mOpacityAppliedToChildren(false)
    6242             : {
    6243           0 :   MOZ_COUNT_CTOR(nsDisplayOpacity);
    6244          32 :   mState.mOpacity = mOpacity;
    6245          32 : }
    6246             : 
    6247             : #ifdef NS_BUILD_REFCNT_LOGGING
    6248          64 : nsDisplayOpacity::~nsDisplayOpacity() {
    6249          32 :   MOZ_COUNT_DTOR(nsDisplayOpacity);
    6250           0 : }
    6251             : #endif
    6252             : 
    6253           0 : nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    6254             :                                            bool* aSnap) const
    6255             : {
    6256           0 :   *aSnap = false;
    6257             :   // The only time where mOpacity == 1.0 should be when we have will-change.
    6258             :   // We could report this as opaque then but when the will-change value starts
    6259             :   // animating the element would become non opaque and could cause repaints.
    6260           6 :   return nsRegion();
    6261             : }
    6262             : 
    6263             : // nsDisplayOpacity uses layers for rendering
    6264             : already_AddRefed<Layer>
    6265           0 : nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
    6266             :                              LayerManager* aManager,
    6267             :                              const ContainerLayerParameters& aContainerParameters) {
    6268           0 :   ContainerLayerParameters params = aContainerParameters;
    6269           0 :   params.mForEventsAndPluginsOnly = mForEventsAndPluginsOnly;
    6270             :   RefPtr<Layer> container = aManager->GetLayerBuilder()->
    6271           0 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    6272             :                            params, nullptr,
    6273           0 :                            FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR);
    6274           0 :   if (!container)
    6275             :     return nullptr;
    6276             : 
    6277           0 :   container->SetOpacity(mOpacity);
    6278           0 :   nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
    6279             :                                                            this, mFrame,
    6280           0 :                                                            eCSSProperty_opacity);
    6281             :   return container.forget();
    6282             : }
    6283             : 
    6284             : /**
    6285             :  * This doesn't take into account layer scaling --- the layer may be
    6286             :  * rendered at a higher (or lower) resolution, affecting the retained layer
    6287             :  * size --- but this should be good enough.
    6288             :  */
    6289             : static bool
    6290           0 : IsItemTooSmallForActiveLayer(nsIFrame* aFrame)
    6291             : {
    6292           0 :   nsIntRect visibleDevPixels = aFrame->GetVisualOverflowRectRelativeToSelf().ToOutsidePixels(
    6293           0 :           aFrame->PresContext()->AppUnitsPerDevPixel());
    6294           0 :   return visibleDevPixels.Size() <
    6295           0 :     nsIntSize(gfxPrefs::LayoutMinActiveLayerSize(),
    6296           0 :               gfxPrefs::LayoutMinActiveLayerSize());
    6297             : }
    6298             : 
    6299             : /* static */ bool
    6300           1 : nsDisplayOpacity::NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
    6301             : {
    6302         112 :   if (EffectCompositor::HasAnimationsForCompositor(aFrame,
    6303         112 :                                                    eCSSProperty_opacity) ||
    6304          56 :       (ActiveLayerTracker::IsStyleAnimated(aBuilder, aFrame,
    6305           0 :                                            eCSSProperty_opacity) &&
    6306           0 :        !IsItemTooSmallForActiveLayer(aFrame))) {
    6307             :     return true;
    6308             :   }
    6309           0 :   return false;
    6310             : }
    6311             : 
    6312             : void
    6313           0 : nsDisplayOpacity::ApplyOpacity(nsDisplayListBuilder* aBuilder,
    6314             :                              float aOpacity,
    6315           0 :                              const DisplayItemClipChain* aClip)
    6316             : {
    6317             :   NS_ASSERTION(CanApplyOpacity(), "ApplyOpacity should be allowed");
    6318             :   mOpacity = mOpacity * aOpacity;
    6319           0 :   IntersectClip(aBuilder, aClip, false);
    6320             : }
    6321             : 
    6322             : bool
    6323           0 : nsDisplayOpacity::CanApplyOpacity() const
    6324           0 : {
    6325           0 :   return !EffectCompositor::HasAnimationsForCompositor(mFrame,
    6326           0 :                                                        eCSSProperty_opacity);
    6327             : }
    6328             : 
    6329           0 : /**
    6330             :  * Recursively iterates through |aList| and collects at most |aMaxChildCount|
    6331           0 :  * display item pointers to items that return true for CanApplyOpacity().
    6332           0 :  * The item pointers are added to |aArray|.
    6333             :  *
    6334             :  * LayerEventRegions and WrapList items are ignored.
    6335             :  *
    6336             :  * We need to do this recursively, because the child display items might contain
    6337             :  * nested nsDisplayWrapLists.
    6338             :  *
    6339             :  * Returns false if there are more than |aMaxChildCount| items, or if an item
    6340             :  * that returns false for CanApplyOpacity() is encountered.
    6341             :  * Otherwise returns true.
    6342             :  */
    6343             : static bool
    6344             : CollectItemsWithOpacity(nsDisplayList* aList,
    6345             :                      nsTArray<nsDisplayItem*>& aArray,
    6346             :                      const size_t aMaxChildCount)
    6347             : {
    6348             :   for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) {
    6349             :     DisplayItemType type = i->GetType();
    6350          32 :     nsDisplayList* children = i->GetChildren();
    6351             : 
    6352             :     // Descend only into wraplists.
    6353             :     if (type == DisplayItemType::TYPE_WRAP_LIST && children) {
    6354          72 :       // The current display item has children, process them first.
    6355          64 :       if (!CollectItemsWithOpacity(children, aArray, aMaxChildCount)) {
    6356           0 :         return false;
    6357             :       }
    6358             :     }
    6359           0 : 
    6360             :     if (type == DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO ||
    6361           0 :         type == DisplayItemType::TYPE_WRAP_LIST) {
    6362           0 :       continue;
    6363             :     }
    6364             : 
    6365             :     if (!i->CanApplyOpacity() || aArray.Length() == aMaxChildCount) {
    6366           1 :       return false;
    6367             :     }
    6368             : 
    6369             :     aArray.AppendElement(i);
    6370             :   }
    6371          56 : 
    6372             :   return true;
    6373             : }
    6374             : 
    6375          16 : bool
    6376             : nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
    6377             : {
    6378           8 :   // Only try folding our opacity down if we have at most kMaxChildCount
    6379             :   // children that don't overlap and can all apply the opacity to themselves.
    6380             :   static const size_t kMaxChildCount = 3;
    6381             : 
    6382          32 :   // Iterate through the child display list and copy at most kMaxChildCount
    6383             :   // child display item pointers to a temporary list.
    6384             :   AutoTArray<nsDisplayItem*, kMaxChildCount> items;
    6385             :   if (!CollectItemsWithOpacity(&mList, items, kMaxChildCount)) {
    6386             :     return false;
    6387             :   }
    6388             : 
    6389             :   struct {
    6390          64 :     nsDisplayItem* item;
    6391           0 :     nsRect bounds;
    6392             :   } children[kMaxChildCount];
    6393             : 
    6394             :   bool snap;
    6395          48 :   size_t childCount = 0;
    6396             :   for (nsDisplayItem* item : items) {
    6397             :     children[childCount].item = item;
    6398           0 :     children[childCount].bounds = item->GetBounds(aBuilder, &snap);
    6399             :     childCount++;
    6400             :   }
    6401           8 : 
    6402           0 :   for (size_t i = 0; i < childCount; i++) {
    6403           8 :     for (size_t j = i+1; j < childCount; j++) {
    6404           0 :       if (children[i].bounds.Intersects(children[j].bounds)) {
    6405           8 :         return false;
    6406             :       }
    6407             :     }
    6408           0 :   }
    6409           8 : 
    6410           0 :   for (uint32_t i = 0; i < childCount; i++) {
    6411             :     children[i].item->ApplyOpacity(aBuilder, mOpacity, mClipChain);
    6412             :   }
    6413             : 
    6414             :   mOpacityAppliedToChildren = true;
    6415             :   return true;
    6416          24 : }
    6417           0 : 
    6418             : bool
    6419             : nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
    6420           0 : {
    6421           0 :   // ShouldFlattenAway() should be called only once during painting.
    6422             :   MOZ_ASSERT(!mOpacityAppliedToChildren);
    6423             : 
    6424             :   if (mFrame->GetPrevContinuation() || mFrame->GetNextContinuation() ||
    6425           0 :       mFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
    6426             :     // If we've been split, then we might need to merge, so
    6427             :     // don't flatten us away.
    6428           0 :     return false;
    6429             :   }
    6430           0 : 
    6431           0 :   if (NeedsActiveLayer(aBuilder, mFrame) || mOpacity == 0.0) {
    6432             :     // If our opacity is zero then we'll discard all descendant display items
    6433             :     // except for layer event regions, so there's no point in doing this
    6434             :     // optimization (and if we do do it, then invalidations of those descendants
    6435             :     // might trigger repainting).
    6436             :     return false;
    6437          32 :   }
    6438             : 
    6439             :   if (mList.IsEmpty()) {
    6440             :     return false;
    6441             :   }
    6442             : 
    6443             :   // Return true if we successfully applied opacity to child items, or if
    6444             :   // WebRender is not in use. In the latter case, the opacity gets flattened and
    6445           0 :   // applied during layer building.
    6446             :   return ApplyOpacityToChildren(aBuilder) || !gfxVars::UseWebRender();
    6447             : }
    6448             : 
    6449             : nsDisplayItem::LayerState
    6450             : nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
    6451             :                                 LayerManager* aManager,
    6452          32 :                                 const ContainerLayerParameters& aParameters) {
    6453             :   // If we only created this item so that we'd get correct nsDisplayEventRegions for child
    6454             :   // frames, then force us to inactive to avoid unnecessary layerization changes for content
    6455             :   // that won't ever be painted.
    6456           0 :   if (mForEventsAndPluginsOnly) {
    6457             :     MOZ_ASSERT(mOpacity == 0);
    6458             :     return LAYER_INACTIVE;
    6459             :   }
    6460             : 
    6461             :   if (NeedsActiveLayer(aBuilder, mFrame)) {
    6462           0 :     // Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
    6463           0 :     // animations.
    6464             :     return LAYER_ACTIVE_FORCE;
    6465             :   }
    6466             : 
    6467          24 :   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
    6468             : }
    6469             : 
    6470             : bool
    6471             : nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    6472             :                                     nsRegion* aVisibleRegion) {
    6473           0 :   // Our children are translucent so we should not allow them to subtract
    6474             :   // area from aVisibleRegion. We do need to find out what is visible under
    6475             :   // our children in the temporary compositing buffer, because if our children
    6476             :   // paint our entire bounds opaquely then we don't need an alpha channel in
    6477          12 :   // the temporary compositing buffer.
    6478             :   nsRect bounds = GetClippedBounds(aBuilder);
    6479             :   nsRegion visibleUnderChildren;
    6480             :   visibleUnderChildren.And(*aVisibleRegion, bounds);
    6481             :   return
    6482             :     nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren);
    6483             : }
    6484          24 : 
    6485           0 : void
    6486          12 : nsDisplayOpacity::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    6487             :                                             const nsDisplayItemGeometry* aGeometry,
    6488          24 :                                             nsRegion* aInvalidRegion) const
    6489             : {
    6490             :   const nsDisplayOpacityGeometry* geometry =
    6491             :     static_cast<const nsDisplayOpacityGeometry*>(aGeometry);
    6492          19 : 
    6493             :   bool snap;
    6494             :   if (mOpacity != geometry->mOpacity) {
    6495             :     aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
    6496             :   }
    6497          19 : }
    6498             : 
    6499             : void
    6500          19 : nsDisplayOpacity::WriteDebugInfo(std::stringstream& aStream)
    6501           0 : {
    6502             :   aStream << " (opacity " << mOpacity << ")";
    6503           0 : }
    6504             : 
    6505             : bool
    6506           0 : nsDisplayOpacity::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    6507             :                                           mozilla::wr::IpcResourceUpdateQueue& aResources,
    6508           0 :                                           const StackingContextHelper& aSc,
    6509           0 :                                           mozilla::layers::WebRenderLayerManager* aManager,
    6510             :                                           nsDisplayListBuilder* aDisplayListBuilder)
    6511             : {
    6512           0 :   float* opacityForSC = &mOpacity;
    6513             : 
    6514             :   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
    6515             :   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
    6516             :   AddAnimationsForProperty(Frame(), aDisplayListBuilder,
    6517             :                            this, eCSSProperty_opacity,
    6518           0 :                            animationInfo, false, true);
    6519             :   animationInfo.StartPendingAnimations(aManager->GetAnimationReadyTime());
    6520           0 : 
    6521           0 :   // Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
    6522           0 :   // are no active animations.
    6523             :   uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
    6524           0 :   wr::WrAnimationProperty prop;
    6525           0 : 
    6526             :   if (!animationInfo.GetAnimations().IsEmpty()) {
    6527             :     prop.id = animationsId;
    6528             :     prop.effect_type = wr::WrAnimationType::Opacity;
    6529           0 : 
    6530             : 
    6531             :     OpAddCompositorAnimations
    6532           0 :       anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId));
    6533           0 :     aManager->WrBridge()->AddWebRenderParentCommand(anim);
    6534           0 :     aManager->AddActiveCompositorAnimationId(animationsId);
    6535             :   } else if (animationsId) {
    6536             :     aManager->AddCompositorAnimationsIdForDiscard(animationsId);
    6537             :     animationsId = 0;
    6538           0 :   }
    6539           0 : 
    6540           0 :   nsTArray<mozilla::wr::WrFilterOp> filters;
    6541           0 :   StackingContextHelper sc(aSc, aBuilder, filters, LayoutDeviceRect(), nullptr,
    6542           0 :                            animationsId ? &prop : nullptr,
    6543           0 :                            opacityForSC);
    6544             : 
    6545             :   aManager->CommandBuilder().CreateWebRenderCommandsFromDisplayList(&mList,
    6546           0 :                                                                     this,
    6547           0 :                                                                     aDisplayListBuilder,
    6548             :                                                                     sc,
    6549           0 :                                                                     aBuilder,
    6550             :                                                                     aResources);
    6551           0 :   return true;
    6552             : }
    6553             : 
    6554             : nsDisplayBlendMode::nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
    6555             :                                              nsIFrame* aFrame, nsDisplayList* aList,
    6556           0 :                                              uint8_t aBlendMode,
    6557           0 :                                              const ActiveScrolledRoot* aActiveScrolledRoot,
    6558             :                                              uint32_t aIndex)
    6559             :   : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
    6560           0 :   , mBlendMode(aBlendMode)
    6561             :   , mIndex(aIndex)
    6562             : {
    6563             :   MOZ_COUNT_CTOR(nsDisplayBlendMode);
    6564           0 : }
    6565             : 
    6566             : #ifdef NS_BUILD_REFCNT_LOGGING
    6567           0 : nsDisplayBlendMode::~nsDisplayBlendMode() {
    6568             :   MOZ_COUNT_DTOR(nsDisplayBlendMode);
    6569           0 : }
    6570           0 : #endif
    6571             : 
    6572             : nsRegion nsDisplayBlendMode::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    6573           0 :                                                 bool* aSnap) const
    6574           0 : {
    6575           0 :   *aSnap = false;
    6576             :   // We are never considered opaque
    6577             :   return nsRegion();
    6578           0 : }
    6579             : 
    6580             : LayerState
    6581           0 : nsDisplayBlendMode::GetLayerState(nsDisplayListBuilder* aBuilder,
    6582             :                                      LayerManager* aManager,
    6583           0 :                                      const ContainerLayerParameters& aParameters)
    6584             : {
    6585             :   return LAYER_ACTIVE;
    6586             : }
    6587           0 : 
    6588             : bool
    6589             : nsDisplayBlendMode::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    6590             :                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
    6591           0 :                                             const StackingContextHelper& aSc,
    6592             :                                             mozilla::layers::WebRenderLayerManager* aManager,
    6593             :                                             nsDisplayListBuilder* aDisplayListBuilder)
    6594             : {
    6595           0 :   nsTArray<mozilla::wr::WrFilterOp> filters;
    6596             :   StackingContextHelper sc(aSc, aBuilder, filters, LayoutDeviceRect(), nullptr,
    6597             :                            nullptr, nullptr, nullptr, nullptr,
    6598             :                            nsCSSRendering::GetGFXBlendMode(mBlendMode));
    6599             : 
    6600             :   return nsDisplayWrapList::CreateWebRenderCommands(aBuilder,aResources, sc,
    6601           0 :                                                     aManager, aDisplayListBuilder);
    6602           0 : }
    6603             : 
    6604           0 : // nsDisplayBlendMode uses layers for rendering
    6605             : already_AddRefed<Layer>
    6606           0 : nsDisplayBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
    6607           0 :                                   LayerManager* aManager,
    6608             :                                   const ContainerLayerParameters& aContainerParameters) {
    6609             :   ContainerLayerParameters newContainerParameters = aContainerParameters;
    6610             :   newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
    6611             : 
    6612           0 :   RefPtr<Layer> container = aManager->GetLayerBuilder()->
    6613             :   BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    6614             :                          newContainerParameters, nullptr);
    6615           0 :   if (!container) {
    6616           0 :     return nullptr;
    6617             :   }
    6618             : 
    6619           0 :   container->SetMixBlendMode(nsCSSRendering::GetGFXBlendMode(mBlendMode));
    6620           0 : 
    6621           0 :   return container.forget();
    6622             : }
    6623             : 
    6624             : mozilla::gfx::CompositionOp
    6625           0 : nsDisplayBlendMode::BlendMode()
    6626             : {
    6627             :   return nsCSSRendering::GetGFXBlendMode(mBlendMode);
    6628             : }
    6629             : 
    6630             : bool
    6631           0 : nsDisplayBlendMode::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    6632             :                                               nsRegion* aVisibleRegion) {
    6633           0 :   // Our children are need their backdrop so we should not allow them to subtract
    6634             :   // area from aVisibleRegion. We do need to find out what is visible under
    6635             :   // our children in the temporary compositing buffer, because if our children
    6636             :   // paint our entire bounds opaquely then we don't need an alpha channel in
    6637           0 :   // the temporary compositing buffer.
    6638             :   nsRect bounds = GetClippedBounds(aBuilder);
    6639             :   nsRegion visibleUnderChildren;
    6640             :   visibleUnderChildren.And(*aVisibleRegion, bounds);
    6641             :   return nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren);
    6642             : }
    6643             : 
    6644           0 : bool
    6645           0 : nsDisplayBlendMode::CanMerge(const nsDisplayItem* aItem) const
    6646           0 : {
    6647           0 :   // Items for the same content element should be merged into a single
    6648             :   // compositing group.
    6649             :   if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
    6650             :     return false;
    6651           0 :   }
    6652             : 
    6653             :   const nsDisplayBlendMode* item =
    6654             :     static_cast<const nsDisplayBlendMode*>(aItem);
    6655           0 : 
    6656             :   if (item->mIndex != 0 || mIndex != 0) {
    6657             :     // Don't merge background-blend-mode items
    6658             :     return false;
    6659             :   }
    6660           0 : 
    6661             :   return true;
    6662           0 : }
    6663             : 
    6664             : /* static */ nsDisplayBlendContainer*
    6665             : nsDisplayBlendContainer::CreateForMixBlendMode(nsDisplayListBuilder* aBuilder,
    6666             :                                                nsIFrame* aFrame, nsDisplayList* aList,
    6667           0 :                                                const ActiveScrolledRoot* aActiveScrolledRoot)
    6668             : {
    6669             :   return MakeDisplayItem<nsDisplayBlendContainer>(aBuilder, aFrame, aList, aActiveScrolledRoot, false);
    6670             : }
    6671           0 : 
    6672             : /* static */ nsDisplayBlendContainer*
    6673             : nsDisplayBlendContainer::CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder,
    6674             :                                                       nsIFrame* aFrame, nsDisplayList* aList,
    6675           0 :                                                       const ActiveScrolledRoot* aActiveScrolledRoot)
    6676             : {
    6677             :   return MakeDisplayItem<nsDisplayBlendContainer>(aBuilder, aFrame, aList, aActiveScrolledRoot, true);
    6678             : }
    6679           0 : 
    6680             : nsDisplayBlendContainer::nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder,
    6681             :                                                  nsIFrame* aFrame, nsDisplayList* aList,
    6682             :                                                  const ActiveScrolledRoot* aActiveScrolledRoot,
    6683           0 :                                                  bool aIsForBackground)
    6684             :     : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
    6685             :     , mIsForBackground(aIsForBackground)
    6686           0 : {
    6687             :   MOZ_COUNT_CTOR(nsDisplayBlendContainer);
    6688             : }
    6689           0 : 
    6690             : #ifdef NS_BUILD_REFCNT_LOGGING
    6691           0 : nsDisplayBlendContainer::~nsDisplayBlendContainer() {
    6692             :   MOZ_COUNT_DTOR(nsDisplayBlendContainer);
    6693           0 : }
    6694           0 : #endif
    6695             : 
    6696             : // nsDisplayBlendContainer uses layers for rendering
    6697           0 : already_AddRefed<Layer>
    6698           0 : nsDisplayBlendContainer::BuildLayer(nsDisplayListBuilder* aBuilder,
    6699           0 :                                     LayerManager* aManager,
    6700             :                                     const ContainerLayerParameters& aContainerParameters) {
    6701             :   // turn off anti-aliasing in the parent stacking context because it changes
    6702             :   // how the group is initialized.
    6703             :   ContainerLayerParameters newContainerParameters = aContainerParameters;
    6704           0 :   newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
    6705             : 
    6706             :   RefPtr<Layer> container = aManager->GetLayerBuilder()->
    6707             :   BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    6708             :                          newContainerParameters, nullptr);
    6709           0 :   if (!container) {
    6710           0 :     return nullptr;
    6711             :   }
    6712             : 
    6713           0 :   container->SetForceIsolatedGroup(true);
    6714           0 :   return container.forget();
    6715           0 : }
    6716             : 
    6717             : LayerState
    6718             : nsDisplayBlendContainer::GetLayerState(nsDisplayListBuilder* aBuilder,
    6719           0 :                                        LayerManager* aManager,
    6720             :                                        const ContainerLayerParameters& aParameters)
    6721             : {
    6722             :   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
    6723             : }
    6724           0 : 
    6725             : bool
    6726             : nsDisplayBlendContainer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    6727             :                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
    6728           0 :                                                  const StackingContextHelper& aSc,
    6729             :                                                  mozilla::layers::WebRenderLayerManager* aManager,
    6730             :                                                  nsDisplayListBuilder* aDisplayListBuilder)
    6731             : {
    6732           0 :   StackingContextHelper sc(aSc, aBuilder);
    6733             : 
    6734             :   return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
    6735             :                                                     aManager, aDisplayListBuilder);
    6736             : }
    6737             : 
    6738           0 : /* static */ nsDisplayTableBlendContainer*
    6739             : nsDisplayTableBlendContainer::CreateForBackgroundBlendMode(nsDisplayListBuilder* aBuilder,
    6740           0 :                                                            nsIFrame* aFrame, nsDisplayList* aList,
    6741           0 :                                                            const ActiveScrolledRoot* aActiveScrolledRoot,
    6742             :                                                            nsIFrame* aAncestorFrame)
    6743             : {
    6744             :   return MakeDisplayItem<nsDisplayTableBlendContainer>(aBuilder, aFrame, aList, aActiveScrolledRoot, true, aAncestorFrame);
    6745           0 : }
    6746             : 
    6747             : nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
    6748             :                                      nsIFrame* aFrame, nsDisplayList* aList,
    6749             :                                      const ActiveScrolledRoot* aActiveScrolledRoot,
    6750           0 :                                      nsDisplayOwnLayerFlags aFlags,
    6751             :                                      const ScrollbarData& aScrollbarData,
    6752             :                                      bool aForceActive,
    6753           0 :                                      bool aClearClipChain)
    6754             :     : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, aClearClipChain)
    6755             :     , mFlags(aFlags)
    6756             :     , mScrollbarData(aScrollbarData)
    6757             :     , mForceActive(aForceActive)
    6758             :     , mWrAnimationId(0)
    6759           0 : {
    6760             :   MOZ_COUNT_CTOR(nsDisplayOwnLayer);
    6761             : 
    6762             :   // For scroll thumb layers, override the AGR to be the thumb's AGR rather
    6763             :   // than the AGR for mFrame (which is the slider frame).
    6764           0 :   if (IsScrollThumbLayer()) {
    6765             :     if (nsIFrame* thumbFrame = nsBox::GetChildXULBox(mFrame)) {
    6766           0 :       mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(thumbFrame);
    6767             :     }
    6768             :   }
    6769             : }
    6770           0 : 
    6771           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    6772           0 : nsDisplayOwnLayer::~nsDisplayOwnLayer() {
    6773             :   MOZ_COUNT_DTOR(nsDisplayOwnLayer);
    6774             : }
    6775           0 : #endif
    6776             : 
    6777             : LayerState
    6778           0 : nsDisplayOwnLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
    6779           0 :                                  LayerManager* aManager,
    6780           0 :                                  const ContainerLayerParameters& aParameters)
    6781             : {
    6782             :   if (mForceActive) {
    6783             :     return mozilla::LAYER_ACTIVE_FORCE;
    6784           0 :   }
    6785             : 
    6786             :   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, mAnimatedGeometryRoot);
    6787             : }
    6788           0 : 
    6789             : bool
    6790             : nsDisplayOwnLayer::IsScrollThumbLayer() const
    6791             : {
    6792           0 :   return mScrollbarData.mScrollbarLayerType == layers::ScrollbarLayerType::Thumb;
    6793             : }
    6794             : 
    6795             : bool
    6796           0 : nsDisplayOwnLayer::IsScrollbarContainer() const
    6797             : {
    6798           0 :   return mScrollbarData.mScrollbarLayerType == layers::ScrollbarLayerType::Container;
    6799             : }
    6800             : 
    6801             : bool
    6802           0 : nsDisplayOwnLayer::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const
    6803             : {
    6804           0 :   // Render scroll thumb layers even if they are invisible, because async
    6805             :   // scrolling might bring them into view.
    6806             :   return IsScrollThumbLayer();
    6807             : }
    6808           0 : 
    6809             : // nsDisplayOpacity uses layers for rendering
    6810             : already_AddRefed<Layer>
    6811             : nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
    6812           0 :                               LayerManager* aManager,
    6813             :                               const ContainerLayerParameters& aContainerParameters)
    6814             : {
    6815             :   RefPtr<ContainerLayer> layer = aManager->GetLayerBuilder()->
    6816             :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    6817           0 :                            aContainerParameters, nullptr,
    6818             :                            FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR);
    6819             : 
    6820             :   if (IsScrollThumbLayer() || IsScrollbarContainer()) {
    6821             :     layer->SetScrollbarData(mScrollbarData);
    6822           0 :   }
    6823             : 
    6824           0 :   if (mFlags & nsDisplayOwnLayerFlags::eGenerateSubdocInvalidations) {
    6825             :     mFrame->PresContext()->SetNotifySubDocInvalidationData(layer);
    6826           0 :   }
    6827           0 :   return layer.forget();
    6828             : }
    6829             : 
    6830           0 : bool
    6831           0 : nsDisplayOwnLayer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    6832             :                                            mozilla::wr::IpcResourceUpdateQueue& aResources,
    6833           0 :                                            const StackingContextHelper& aSc,
    6834             :                                            WebRenderLayerManager* aManager,
    6835             :                                            nsDisplayListBuilder* aDisplayListBuilder)
    6836             : {
    6837           0 :   if (!aManager->AsyncPanZoomEnabled() || !IsScrollThumbLayer()) {
    6838             :     return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, aSc,
    6839             :                                                       aManager, aDisplayListBuilder);
    6840             :   }
    6841             : 
    6842             :   // APZ is enabled and this is a scroll thumb, so we need to create and
    6843           0 :   // set an animation id. That way APZ can move this scrollthumb around as
    6844           0 :   // needed.
    6845           0 :   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
    6846             :   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
    6847             :   animationInfo.EnsureAnimationsId();
    6848             :   mWrAnimationId = animationInfo.GetCompositorAnimationsId();
    6849             : 
    6850             : 
    6851           0 :   wr::WrAnimationProperty prop;
    6852           0 :   prop.id = mWrAnimationId;
    6853           0 :   prop.effect_type = wr::WrAnimationType::Transform;
    6854           0 : 
    6855             :   StackingContextHelper sc(aSc, aBuilder, nsTArray<wr::WrFilterOp>(),
    6856             :                            LayoutDeviceRect(), nullptr, &prop);
    6857             : 
    6858           0 :   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
    6859           0 :                                              aManager, aDisplayListBuilder);
    6860             :   return true;
    6861           0 : }
    6862           0 : 
    6863             : bool
    6864           0 : nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
    6865           0 :                                     mozilla::layers::WebRenderLayerScrollData* aLayerData)
    6866             : {
    6867             :   bool ret = false;
    6868             : 
    6869             :   if (IsScrollThumbLayer() || IsScrollbarContainer()) {
    6870           0 :     ret = true;
    6871             :     if (aLayerData) {
    6872             :       aLayerData->SetScrollbarData(mScrollbarData);
    6873           0 :       if (IsScrollThumbLayer()) {
    6874             :         aLayerData->SetScrollbarAnimationId(mWrAnimationId);
    6875           0 :       }
    6876           0 :     }
    6877           0 :   }
    6878           0 :   return ret;
    6879           0 : }
    6880           0 : 
    6881             : void
    6882             : nsDisplayOwnLayer::WriteDebugInfo(std::stringstream& aStream)
    6883             : {
    6884           0 :   aStream << nsPrintfCString(" (flags 0x%x) (scrolltarget %" PRIu64 ")", (int)mFlags, mScrollbarData.mTargetViewId).get();
    6885             : }
    6886             : 
    6887             : nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
    6888           0 :                                            nsIFrame* aFrame,
    6889             :                                            nsSubDocumentFrame* aSubDocFrame,
    6890           0 :                                            nsDisplayList* aList,
    6891           0 :                                            nsDisplayOwnLayerFlags aFlags)
    6892             :     : nsDisplayOwnLayer(aBuilder, aFrame, aList, aBuilder->CurrentActiveScrolledRoot(), aFlags)
    6893           0 :     , mScrollParentId(aBuilder->GetCurrentScrollParentId())
    6894             :     , mShouldFlatten(false)
    6895             :     , mSubDocFrame(aSubDocFrame)
    6896             : {
    6897           0 :   MOZ_COUNT_CTOR(nsDisplaySubDocument);
    6898             : 
    6899           0 :   // The SubDocument display item is conceptually outside the viewport frame,
    6900             :   // so in cases where the viewport frame is an AGR, the SubDocument's AGR
    6901           0 :   // should be not the viewport frame itself, but its parent AGR.
    6902             :   if (*mAnimatedGeometryRoot == mFrame && mAnimatedGeometryRoot->mParentAGR) {
    6903           0 :     mAnimatedGeometryRoot = mAnimatedGeometryRoot->mParentAGR;
    6904             :   }
    6905             : 
    6906             :   if (mSubDocFrame && mSubDocFrame != mFrame) {
    6907             :     mSubDocFrame->AddDisplayItem(this);
    6908           0 :   }
    6909           0 : }
    6910             : 
    6911             : nsDisplaySubDocument::~nsDisplaySubDocument() {
    6912           0 :   MOZ_COUNT_DTOR(nsDisplaySubDocument);
    6913           0 :   if (mSubDocFrame) {
    6914             :     mSubDocFrame->RemoveDisplayItem(this);
    6915           0 :   }
    6916             : }
    6917           0 : 
    6918           0 : nsIFrame*
    6919           0 : nsDisplaySubDocument::FrameForInvalidation() const
    6920           0 : {
    6921             :   return mSubDocFrame ? mSubDocFrame : mFrame;
    6922           0 : }
    6923             : 
    6924             : bool
    6925           0 : nsDisplaySubDocument::HasDeletedFrame() const
    6926             : {
    6927           0 :   return !mSubDocFrame || nsDisplayItem::HasDeletedFrame();
    6928             : }
    6929             : 
    6930             : void
    6931           0 : nsDisplaySubDocument::RemoveFrame(nsIFrame* aFrame)
    6932             : {
    6933           0 :   if (aFrame == mSubDocFrame) {
    6934             :     mSubDocFrame = nullptr;
    6935             :   }
    6936             :   nsDisplayItem::RemoveFrame(aFrame);
    6937           0 : }
    6938             : 
    6939           0 : void
    6940           0 : nsDisplaySubDocument::Disown()
    6941             : {
    6942           0 :   if (mFrame) {
    6943           0 :     mFrame->RemoveDisplayItem(this);
    6944             :     mFrame = nullptr;
    6945             :   }
    6946           0 :   if (mSubDocFrame) {
    6947             :     mSubDocFrame->RemoveDisplayItem(this);
    6948             :     mSubDocFrame = nullptr;
    6949           0 :   }
    6950             : }
    6951             : 
    6952             : UniquePtr<ScrollMetadata>
    6953           0 : nsDisplaySubDocument::ComputeScrollMetadata(LayerManager* aLayerManager,
    6954           0 :                                             const ContainerLayerParameters& aContainerParameters)
    6955           0 : {
    6956           0 :   if (!(mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer)) {
    6957             :     return UniquePtr<ScrollMetadata>(nullptr);
    6958           0 :   }
    6959           0 : 
    6960           0 :   nsPresContext* presContext = mFrame->PresContext();
    6961             :   nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
    6962           0 :   bool isRootContentDocument = presContext->IsRootContentDocument();
    6963           0 :   nsIPresShell* presShell = presContext->PresShell();
    6964           0 :   ContainerLayerParameters params(
    6965             :       aContainerParameters.mXScale * presShell->GetResolution(),
    6966             :       aContainerParameters.mYScale * presShell->GetResolution(),
    6967           0 :       nsIntPoint(), aContainerParameters);
    6968             : 
    6969             :   nsRect viewport = mFrame->GetRect() -
    6970           0 :                     mFrame->GetPosition() +
    6971             :                     mFrame->GetOffsetToCrossDoc(ReferenceFrame());
    6972             : 
    6973             :   return MakeUnique<ScrollMetadata>(
    6974           0 :     nsLayoutUtils::ComputeScrollMetadata(
    6975             :       mFrame, rootScrollFrame, rootScrollFrame->GetContent(), ReferenceFrame(),
    6976           0 :       aLayerManager, mScrollParentId, viewport, Nothing(),
    6977           0 :       isRootContentDocument, params));
    6978             : }
    6979             : 
    6980             : static bool
    6981           0 : UseDisplayPortForViewport(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
    6982             : {
    6983             :   return aBuilder->IsPaintingToWindow() &&
    6984           0 :       nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext());
    6985             : }
    6986           0 : 
    6987           0 : nsRect
    6988           0 : nsDisplaySubDocument::GetBounds(nsDisplayListBuilder* aBuilder,
    6989             :                                 bool* aSnap) const
    6990             : {
    6991           0 :   bool usingDisplayPort = UseDisplayPortForViewport(aBuilder, mFrame);
    6992             : 
    6993             :   if ((mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer) && usingDisplayPort) {
    6994             :     *aSnap = false;
    6995           0 :     return mFrame->GetRect() + aBuilder->ToReferenceFrame(mFrame);
    6996             :   }
    6997             : 
    6998           0 :   return nsDisplayOwnLayer::GetBounds(aBuilder, aSnap);
    6999             : }
    7000           0 : 
    7001           0 : bool
    7002             : nsDisplaySubDocument::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    7003             :                                         nsRegion* aVisibleRegion)
    7004           0 : {
    7005           0 :   bool usingDisplayPort = UseDisplayPortForViewport(aBuilder, mFrame);
    7006           0 : 
    7007           0 :   if (!(mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer) || !usingDisplayPort) {
    7008             :     return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion);
    7009             :   }
    7010           0 : 
    7011             :   nsRect displayport;
    7012             :   nsIFrame* rootScrollFrame = mFrame->PresShell()->GetRootScrollFrame();
    7013             :   MOZ_ASSERT(rootScrollFrame);
    7014           0 :   Unused << nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), &displayport,
    7015             :     RelativeTo::ScrollFrame);
    7016             : 
    7017           0 :   nsRegion childVisibleRegion;
    7018           0 :   // The visible region for the children may be much bigger than the hole we
    7019             :   // are viewing the children from, so that the compositor process has enough
    7020           0 :   // content to asynchronously pan while content is being refreshed.
    7021             :   childVisibleRegion = displayport + mFrame->GetOffsetToCrossDoc(ReferenceFrame());
    7022             : 
    7023             :   nsRect boundedRect =
    7024             :     childVisibleRegion.GetBounds().Intersect(
    7025           0 :       mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot));
    7026             :   bool visible = mList.ComputeVisibilityForSublist(
    7027           0 :     aBuilder, &childVisibleRegion, boundedRect);
    7028           0 : 
    7029           0 :   // If APZ is enabled then don't allow this computation to influence
    7030             :   // aVisibleRegion, on the assumption that the layer can be asynchronously
    7031           0 :   // scrolled so we'll definitely need all the content under it.
    7032             :   if (!nsLayoutUtils::UsesAsyncScrolling(mFrame)) {
    7033             :     bool snap;
    7034             :     nsRect bounds = GetBounds(aBuilder, &snap);
    7035             :     nsRegion removed;
    7036             :     removed.Sub(bounds, childVisibleRegion);
    7037             : 
    7038           0 :     aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
    7039             :   }
    7040           0 : 
    7041             :   return visible;
    7042           0 : }
    7043             : 
    7044             : bool
    7045             : nsDisplaySubDocument::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const
    7046           0 : {
    7047             :   bool usingDisplayPort = UseDisplayPortForViewport(aBuilder, mFrame);
    7048             : 
    7049             :   if ((mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer) && usingDisplayPort) {
    7050           0 :     return true;
    7051             :   }
    7052             : 
    7053           0 :   return nsDisplayOwnLayer::ShouldBuildLayerEvenIfInvisible(aBuilder);
    7054             : }
    7055           0 : 
    7056           0 : nsRegion
    7057           0 : nsDisplaySubDocument::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    7058             :                                       bool* aSnap) const
    7059             : {
    7060           0 :   bool usingDisplayPort = UseDisplayPortForViewport(aBuilder, mFrame);
    7061             : 
    7062             :   if ((mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer) && usingDisplayPort) {
    7063           0 :     *aSnap = false;
    7064             :     return nsRegion();
    7065           0 :   }
    7066           0 : 
    7067           0 :   return nsDisplayOwnLayer::GetOpaqueRegion(aBuilder, aSnap);
    7068           0 : }
    7069             : 
    7070             : nsDisplayResolution::nsDisplayResolution(nsDisplayListBuilder* aBuilder,
    7071           0 :                                          nsIFrame* aFrame, nsDisplayList* aList,
    7072           0 :                                          nsDisplayOwnLayerFlags aFlags)
    7073           0 :     : nsDisplaySubDocument(aBuilder, aFrame, nullptr, aList, aFlags) {
    7074             :   MOZ_COUNT_CTOR(nsDisplayResolution);
    7075             : }
    7076             : 
    7077           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    7078             : nsDisplayResolution::~nsDisplayResolution() {
    7079             :   MOZ_COUNT_DTOR(nsDisplayResolution);
    7080             : }
    7081             : #endif
    7082           0 : 
    7083           0 : void
    7084           0 : nsDisplayResolution::HitTest(nsDisplayListBuilder* aBuilder,
    7085           0 :                              const nsRect& aRect,
    7086             :                              HitTestState* aState,
    7087             :                              nsTArray<nsIFrame*> *aOutFrames)
    7088           0 : {
    7089             :   nsIPresShell* presShell = mFrame->PresShell();
    7090             :   nsRect rect = aRect.RemoveResolution(presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f);
    7091           0 :   mList.HitTest(aBuilder, rect, aState, aOutFrames);
    7092             : }
    7093           0 : 
    7094           0 : already_AddRefed<Layer>
    7095             : nsDisplayResolution::BuildLayer(nsDisplayListBuilder* aBuilder,
    7096           0 :                                 LayerManager* aManager,
    7097           0 :                                 const ContainerLayerParameters& aContainerParameters) {
    7098           0 :   nsIPresShell* presShell = mFrame->PresShell();
    7099           0 :   ContainerLayerParameters containerParameters(
    7100           0 :     presShell->GetResolution(), presShell->GetResolution(), nsIntPoint(),
    7101           0 :     aContainerParameters);
    7102           0 : 
    7103             :   RefPtr<Layer> layer = nsDisplaySubDocument::BuildLayer(
    7104             :     aBuilder, aManager, containerParameters);
    7105           0 :   layer->SetPostScale(1.0f / presShell->GetResolution(),
    7106             :                       1.0f / presShell->GetResolution());
    7107             :   layer->AsContainerLayer()->SetScaleToResolution(
    7108             :       presShell->ScaleToResolution(), presShell->GetResolution());
    7109           0 :   return layer.forget();
    7110             : }
    7111             : 
    7112             : nsDisplayFixedPosition::nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
    7113           0 :                                                nsIFrame* aFrame,
    7114             :                                                nsDisplayList* aList,
    7115           0 :                                                const ActiveScrolledRoot* aActiveScrolledRoot,
    7116           0 :                                                const ActiveScrolledRoot* aContainerASR)
    7117           0 :   : nsDisplayOwnLayer(aBuilder, aFrame, aList, aActiveScrolledRoot)
    7118             :   , mIndex(0)
    7119           0 :   , mIsFixedBackground(false)
    7120             :   , mContainerASR(aContainerASR)
    7121             : {
    7122           0 :   MOZ_COUNT_CTOR(nsDisplayFixedPosition);
    7123             :   Init(aBuilder);
    7124             : }
    7125             : 
    7126           0 : nsDisplayFixedPosition::nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder,
    7127             :                                                nsIFrame* aFrame,
    7128           0 :                                                nsDisplayList* aList,
    7129           0 :                                                uint32_t aIndex)
    7130           0 :   : nsDisplayOwnLayer(aBuilder, aFrame, aList, aBuilder->CurrentActiveScrolledRoot())
    7131             :   , mIndex(aIndex)
    7132             :   , mIsFixedBackground(true)
    7133           0 :   , mContainerASR(nullptr) // XXX maybe this should be something?
    7134             : {
    7135           0 :   MOZ_COUNT_CTOR(nsDisplayFixedPosition);
    7136           0 :   Init(aBuilder);
    7137           0 : }
    7138             : 
    7139           0 : void
    7140             : nsDisplayFixedPosition::Init(nsDisplayListBuilder* aBuilder)
    7141             : {
    7142           0 :   mAnimatedGeometryRootForScrollMetadata = mAnimatedGeometryRoot;
    7143             :   if (ShouldFixToViewport(aBuilder)) {
    7144             :     mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this);
    7145             :   }
    7146             : }
    7147           0 : 
    7148           0 : /* static */ nsDisplayFixedPosition*
    7149             : nsDisplayFixedPosition::CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
    7150           0 :                                                  nsIFrame* aFrame,
    7151             :                                                  nsDisplayBackgroundImage* aImage,
    7152             :                                                  uint32_t aIndex)
    7153             : {
    7154             :   nsDisplayList temp;
    7155           0 :   temp.AppendToTop(aImage);
    7156           0 : 
    7157           0 :   return MakeDisplayItem<nsDisplayFixedPosition>(aBuilder, aFrame, &temp, aIndex + 1);
    7158             : }
    7159             : 
    7160             : 
    7161           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    7162             : nsDisplayFixedPosition::~nsDisplayFixedPosition() {
    7163             :   MOZ_COUNT_DTOR(nsDisplayFixedPosition);
    7164             : }
    7165           0 : #endif
    7166             : 
    7167           0 : already_AddRefed<Layer>
    7168             : nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
    7169           0 :                                    LayerManager* aManager,
    7170           0 :                                    const ContainerLayerParameters& aContainerParameters) {
    7171             :   RefPtr<Layer> layer =
    7172           0 :     nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
    7173             : 
    7174             :   layer->SetIsFixedPosition(true);
    7175           0 : 
    7176           0 :   nsPresContext* presContext = mFrame->PresContext();
    7177             :   nsIFrame* fixedFrame = mIsFixedBackground ? presContext->PresShell()->GetRootFrame() : mFrame;
    7178             : 
    7179           0 :   const nsIFrame* viewportFrame = fixedFrame->GetParent();
    7180           0 :   // anchorRect will be in the container's coordinate system (aLayer's parent layer).
    7181             :   // This is the same as the display items' reference frame.
    7182           0 :   nsRect anchorRect;
    7183             :   if (viewportFrame) {
    7184             :     // Fixed position frames are reflowed into the scroll-port size if one has
    7185             :     // been set.
    7186             :     if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
    7187             :       anchorRect.SizeTo(presContext->PresShell()->GetScrollPositionClampingScrollPortSize());
    7188             :     } else {
    7189             :       anchorRect.SizeTo(viewportFrame->GetSize());
    7190             :     }
    7191           0 :   } else {
    7192             :     // A display item directly attached to the viewport.
    7193           0 :     // For background-attachment:fixed items, the anchor point is always the
    7194           0 :     // top-left of the viewport currently.
    7195             :     viewportFrame = fixedFrame;
    7196           0 :   }
    7197             :   // The anchorRect top-left is always the viewport top-left.
    7198             :   anchorRect.MoveTo(viewportFrame->GetOffsetToCrossDoc(ReferenceFrame()));
    7199             : 
    7200           0 :   nsLayoutUtils::SetFixedPositionLayerData(layer,
    7201             :       viewportFrame, anchorRect, fixedFrame, presContext, aContainerParameters);
    7202           0 : 
    7203           0 :   return layer.forget();
    7204             : }
    7205           0 : 
    7206             : ViewID
    7207             : nsDisplayFixedPosition::GetScrollTargetId()
    7208             : {
    7209           0 :   if (mContainerASR && !nsLayoutUtils::IsReallyFixedPos(mFrame)) {
    7210             :     return mContainerASR->GetViewId();
    7211             :   }
    7212             :   return nsLayoutUtils::ScrollIdForRootScrollFrame(mFrame->PresContext());
    7213             : }
    7214             : 
    7215             : bool
    7216             : nsDisplayFixedPosition::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    7217             :                                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
    7218             :                                                 const StackingContextHelper& aSc,
    7219             :                                                 mozilla::layers::WebRenderLayerManager* aManager,
    7220             :                                                 nsDisplayListBuilder* aDisplayListBuilder)
    7221             : {
    7222           0 :   // We install this RAII scrolltarget tracker so that any
    7223           0 :   // nsDisplayCompositorHitTestInfo items inside this fixed-pos item (and that
    7224           0 :   // share the same ASR as this item) use the correct scroll target. That way
    7225             :   // attempts to scroll on those items will scroll the root scroll frame.
    7226             :   mozilla::wr::DisplayListBuilder::FixedPosScrollTargetTracker tracker(
    7227             :       aBuilder,
    7228           0 :       GetActiveScrolledRoot(),
    7229             :       GetScrollTargetId());
    7230             :   return nsDisplayOwnLayer::CreateWebRenderCommands(aBuilder, aResources, aSc,
    7231           0 :       aManager, aDisplayListBuilder);
    7232           0 : }
    7233             : 
    7234           0 : bool
    7235             : nsDisplayFixedPosition::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
    7236             :                                          mozilla::layers::WebRenderLayerScrollData* aLayerData)
    7237             : {
    7238           0 :   if (aLayerData) {
    7239             :     aLayerData->SetFixedPositionScrollContainerId(GetScrollTargetId());
    7240           0 :   }
    7241           0 :   return nsDisplayOwnLayer::UpdateScrollData(aData, aLayerData) | true;
    7242           0 : }
    7243           0 : 
    7244             : void
    7245             : nsDisplayFixedPosition::WriteDebugInfo(std::stringstream& aStream)
    7246           0 : {
    7247             :   aStream << nsPrintfCString(" (containerASR %s) (scrolltarget %" PRIu64 ")",
    7248           0 :       ActiveScrolledRoot::ToString(mContainerASR).get(),
    7249             :       GetScrollTargetId()).get();
    7250             : }
    7251             : 
    7252           0 : TableType
    7253             : GetTableTypeFromFrame(nsIFrame* aFrame)
    7254             : {
    7255             :   if (aFrame->IsTableFrame()) {
    7256           0 :     return TableType::TABLE;
    7257             :   }
    7258             : 
    7259             :   if (aFrame->IsTableColFrame()) {
    7260           0 :     return TableType::TABLE_COL;
    7261             :   }
    7262             : 
    7263             :   if (aFrame->IsTableColGroupFrame()) {
    7264           0 :     return TableType::TABLE_COL_GROUP;
    7265             :   }
    7266             : 
    7267             :   if (aFrame->IsTableRowFrame()) {
    7268           0 :     return TableType::TABLE_ROW;
    7269             :   }
    7270             : 
    7271             :   if (aFrame->IsTableRowGroupFrame()) {
    7272           0 :     return TableType::TABLE_ROW_GROUP;
    7273             :   }
    7274             : 
    7275             :   if (aFrame->IsTableCellFrame()) {
    7276           0 :     return TableType::TABLE_CELL;
    7277             :   }
    7278             : 
    7279             :   MOZ_ASSERT_UNREACHABLE("Invalid frame.");
    7280           0 :   return TableType::TABLE;
    7281             : }
    7282             : 
    7283           0 : nsDisplayTableFixedPosition::nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder,
    7284             :                                                          nsIFrame* aFrame,
    7285           0 :                                                          nsDisplayList* aList,
    7286           0 :                                                          uint32_t aIndex,
    7287             :                                                          nsIFrame* aAncestorFrame)
    7288           0 :   : nsDisplayFixedPosition(aBuilder, aFrame, aList, aIndex)
    7289             :   , mAncestorFrame(aAncestorFrame)
    7290             :   , mTableType(GetTableTypeFromFrame(aAncestorFrame))
    7291           0 : {
    7292             :   if (aBuilder->IsRetainingDisplayList()) {
    7293             :     mAncestorFrame->AddDisplayItem(this);
    7294             :   }
    7295             : }
    7296             : 
    7297           0 : /* static */ nsDisplayTableFixedPosition*
    7298           0 : nsDisplayTableFixedPosition::CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
    7299             :                                                       nsIFrame* aFrame,
    7300           0 :                                                       nsDisplayBackgroundImage* aImage,
    7301             :                                                       uint32_t aIndex,
    7302             :                                                       nsIFrame* aAncestorFrame)
    7303           0 : {
    7304             :   nsDisplayList temp;
    7305             :   temp.AppendToTop(aImage);
    7306             : 
    7307           0 :   return MakeDisplayItem<nsDisplayTableFixedPosition>(aBuilder, aFrame, &temp, aIndex + 1, aAncestorFrame);
    7308             : }
    7309           0 : 
    7310             : nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
    7311           0 :                                                  nsIFrame* aFrame,
    7312           0 :                                                  nsDisplayList* aList,
    7313             :                                                  const ActiveScrolledRoot* aActiveScrolledRoot,
    7314             :                                                  const ActiveScrolledRoot* aContainerASR)
    7315           0 :   : nsDisplayOwnLayer(aBuilder, aFrame, aList, aActiveScrolledRoot)
    7316             :   , mContainerASR(aContainerASR)
    7317             : {
    7318           0 :   MOZ_COUNT_CTOR(nsDisplayStickyPosition);
    7319           0 : }
    7320             : 
    7321             : void
    7322             : nsDisplayStickyPosition::SetClipChain(const DisplayItemClipChain* aClipChain,
    7323           0 :                                       bool aStore)
    7324           0 : {
    7325           0 :   mClipChain = aClipChain;
    7326             :   mClip = nullptr;
    7327           0 : 
    7328             :   MOZ_ASSERT(!mClip, "There should never be a clip on this item because no clip moves with it.");
    7329             : 
    7330           0 :   if (aStore) {
    7331           0 :     mState.mClipChain = aClipChain;
    7332           0 :     mState.mClip = mClip;
    7333             :   }
    7334             : }
    7335             : 
    7336           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    7337             : nsDisplayStickyPosition::~nsDisplayStickyPosition() {
    7338             :   MOZ_COUNT_DTOR(nsDisplayStickyPosition);
    7339             : }
    7340           0 : #endif
    7341             : 
    7342             : already_AddRefed<Layer>
    7343           0 : nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
    7344           0 :                                     LayerManager* aManager,
    7345             :                                     const ContainerLayerParameters& aContainerParameters) {
    7346             :   RefPtr<Layer> layer =
    7347             :     nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
    7348           0 : 
    7349           0 :   StickyScrollContainer* stickyScrollContainer = StickyScrollContainer::
    7350             :     GetStickyScrollContainerForFrame(mFrame);
    7351             :   if (!stickyScrollContainer) {
    7352             :     return layer.forget();
    7353           0 :   }
    7354           0 : 
    7355           0 :   nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame());
    7356             :   nsPresContext* presContext = scrollFrame->PresContext();
    7357           0 : 
    7358             :   // Sticky position frames whose scroll frame is the root scroll frame are
    7359             :   // reflowed into the scroll-port size if one has been set.
    7360           0 :   nsSize scrollFrameSize = scrollFrame->GetSize();
    7361           0 :   if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() &&
    7362           0 :       presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
    7363             :     scrollFrameSize = presContext->PresShell()->
    7364           0 :       GetScrollPositionClampingScrollPortSize();
    7365           0 :   }
    7366             : 
    7367           0 :   nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame,
    7368           0 :     nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize),
    7369           0 :     mFrame, presContext, aContainerParameters);
    7370           0 : 
    7371           0 :   ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor(
    7372             :     stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent());
    7373           0 : 
    7374             :   float factor = presContext->AppUnitsPerDevPixel();
    7375           0 :   nsRectAbsolute outer;
    7376           0 :   nsRectAbsolute inner;
    7377           0 :   stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
    7378           0 :   LayerRectAbsolute stickyOuter(NSAppUnitsToFloatPixels(outer.X(), factor) *
    7379           0 :                           aContainerParameters.mXScale,
    7380             :                         NSAppUnitsToFloatPixels(outer.Y(), factor) *
    7381           0 :                           aContainerParameters.mYScale,
    7382             :                         NSAppUnitsToFloatPixels(outer.XMost(), factor) *
    7383           0 :                           aContainerParameters.mXScale,
    7384             :                         NSAppUnitsToFloatPixels(outer.YMost(), factor) *
    7385           0 :                           aContainerParameters.mYScale);
    7386           0 :   LayerRectAbsolute stickyInner(NSAppUnitsToFloatPixels(inner.X(), factor) *
    7387           0 :                           aContainerParameters.mXScale,
    7388             :                         NSAppUnitsToFloatPixels(inner.Y(), factor) *
    7389             :                           aContainerParameters.mYScale,
    7390             :                         NSAppUnitsToFloatPixels(inner.XMost(), factor) *
    7391             :                           aContainerParameters.mXScale,
    7392             :                         NSAppUnitsToFloatPixels(inner.YMost(), factor) *
    7393             :                           aContainerParameters.mYScale);
    7394           0 :   layer->SetStickyPositionData(scrollId, stickyOuter, stickyInner);
    7395           0 : 
    7396           0 :   return layer.forget();
    7397             : }
    7398             : 
    7399           0 : // Returns the smallest distance from "0" to the range [min, max] where
    7400             : // min <= max.
    7401             : static nscoord DistanceToRange(nscoord min, nscoord max) {
    7402             :   MOZ_ASSERT(min <= max);
    7403             :   if (max < 0) {
    7404             :     return max;
    7405             :   }
    7406             :   if (min > 0) {
    7407           0 :     return min;
    7408             :   }
    7409             :   MOZ_ASSERT(min <= 0 && max >= 0);
    7410             :   return 0;
    7411             : }
    7412             : 
    7413           0 : bool
    7414           0 : nsDisplayStickyPosition::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    7415             :                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
    7416             :                                                  const StackingContextHelper& aSc,
    7417             :                                                  WebRenderLayerManager* aManager,
    7418             :                                                  nsDisplayListBuilder* aDisplayListBuilder)
    7419             : {
    7420             :   StickyScrollContainer* stickyScrollContainer = StickyScrollContainer::GetStickyScrollContainerForFrame(mFrame);
    7421             :   if (stickyScrollContainer) {
    7422             :     // If there's no ASR for the scrollframe that this sticky item is attached
    7423             :     // to, then don't create a WR sticky item for it either. Trying to do so
    7424             :     // will end in sadness because WR will interpret some coordinates as
    7425             :     // relative to the nearest enclosing scrollframe, which will correspond
    7426           0 :     // to the nearest ancestor ASR on the gecko side. That ASR will not be the
    7427           0 :     // same as the scrollframe this sticky item is actually supposed to be
    7428             :     // attached to, thus the sadness.
    7429             :     // Not sending WR the sticky item is ok, because the enclosing scrollframe
    7430             :     // will never be asynchronously scrolled. Instead we will always position
    7431           0 :     // the sticky items correctly on the gecko side and WR will never need to
    7432           0 :     // adjust their position itself.
    7433             :     if (!stickyScrollContainer->ScrollFrame()->IsMaybeAsynchronouslyScrolled()) {
    7434             :       stickyScrollContainer = nullptr;
    7435           0 :     }
    7436             :   }
    7437           0 : 
    7438           0 :   if (stickyScrollContainer) {
    7439           0 :     float auPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    7440           0 : 
    7441           0 :     bool snap;
    7442           0 :     nsRect itemBounds = GetBounds(aDisplayListBuilder, &snap);
    7443           0 : 
    7444             :     Maybe<float> topMargin;
    7445           0 :     Maybe<float> rightMargin;
    7446           0 :     Maybe<float> bottomMargin;
    7447           0 :     Maybe<float> leftMargin;
    7448             :     wr::StickyOffsetBounds vBounds = { 0.0, 0.0 };
    7449           0 :     wr::StickyOffsetBounds hBounds = { 0.0, 0.0 };
    7450           0 :     nsPoint appliedOffset;
    7451             : 
    7452             :     nsRectAbsolute outer;
    7453             :     nsRectAbsolute inner;
    7454           0 :     stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
    7455           0 : 
    7456             :     nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame());
    7457             :     nsPoint offset = scrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
    7458             : 
    7459             :     // Adjust the scrollPort coordinates to be relative to the reference frame,
    7460             :     // so that it is in the same space as everything else.
    7461           0 :     nsRect scrollPort = stickyScrollContainer->ScrollFrame()->GetScrollPortRect();
    7462             :     scrollPort += offset;
    7463             : 
    7464             :     // The following computations make more sense upon understanding the
    7465             :     // semantics of "inner" and "outer", which is explained in the comment on
    7466             :     // SetStickyPositionData in Layers.h.
    7467             : 
    7468             :     if (outer.YMost() != inner.YMost()) {
    7469             :       // Question: How far will itemBounds.y be from the top of the scrollport
    7470             :       // when we have scrolled from the current scroll position of "0" to
    7471             :       // reach the range [inner.YMost(), outer.YMost()] where the item gets
    7472             :       // stuck?
    7473             :       // Answer: the current distance is "itemBounds.y - scrollPort.y". That
    7474             :       // needs to be adjusted by the distance to the range. If the distance is
    7475             :       // negative (i.e. inner.YMost() <= outer.YMost() < 0) then we would be
    7476             :       // scrolling upwards (decreasing scroll offset) to reach that range,
    7477           0 :       // which would increase itemBounds.y and make it farther away from the
    7478           0 :       // top of the scrollport. So in that case the adjustment is -distance.
    7479             :       // If the distance is positive (0 < inner.YMost() <= outer.YMost()) then
    7480             :       // we would be scrolling downwards, itemBounds.y would decrease, and we
    7481             :       // again need to adjust by -distance. If we are already in the range
    7482             :       // then no adjustment is needed and distance is 0 so again using
    7483             :       // -distance works.
    7484             :       nscoord distance = DistanceToRange(inner.YMost(), outer.YMost());
    7485           0 :       topMargin = Some(NSAppUnitsToFloatPixels(itemBounds.y - scrollPort.y - distance, auPerDevPixel));
    7486             :       // Question: What is the maximum positive ("downward") offset that WR
    7487             :       // will have to apply to this item in order to prevent the item from
    7488             :       // visually moving?
    7489             :       // Answer: Since the item is "sticky" in the range [inner.YMost(), outer.YMost()],
    7490             :       // the maximum offset will be the size of the range, which is
    7491             :       // outer.YMost() - inner.YMost().
    7492             :       vBounds.max = NSAppUnitsToFloatPixels(outer.YMost() - inner.YMost(), auPerDevPixel);
    7493           0 :       // Question: how much of an offset has layout already applied to the item?
    7494           0 :       // Answer: if we are
    7495           0 :       // (a) inside the sticky range (inner.YMost() < 0 <= outer.YMost()), or
    7496             :       // (b) past the sticky range (inner.YMost() < outer.YMost() < 0)
    7497             :       // then layout has already applied some offset to the position of the
    7498           0 :       // item. The amount of the adjustment is |0 - inner.YMost()| in case (a)
    7499             :       // and |outer.YMost() - inner.YMost()| in case (b).
    7500             :       if (inner.YMost() < 0) {
    7501           0 :         appliedOffset.y = std::min(0, outer.YMost()) - inner.YMost();
    7502           0 :         MOZ_ASSERT(appliedOffset.y > 0);
    7503             :       }
    7504             :     }
    7505           0 :     if (outer.Y() != inner.Y()) {
    7506             :       // Similar logic as in the previous section, but this time we care about
    7507             :       // the distance from itemBounds.YMost() to scrollPort.YMost().
    7508             :       nscoord distance = DistanceToRange(outer.Y(), inner.Y());
    7509           0 :       bottomMargin = Some(NSAppUnitsToFloatPixels(scrollPort.YMost() - itemBounds.YMost() + distance, auPerDevPixel));
    7510           0 :       // And here WR will be moving the item upwards rather than downwards so
    7511           0 :       // again things are inverted from the previous block.
    7512             :       vBounds.min = NSAppUnitsToFloatPixels(outer.Y() - inner.Y(), auPerDevPixel);
    7513             :       // We can't have appliedOffset be both positive and negative, and the top
    7514             :       // adjustment takes priority. So here we only update appliedOffset.y if
    7515           0 :       // it wasn't set by the top-sticky case above.
    7516           0 :       if (appliedOffset.y == 0 && inner.Y() > 0) {
    7517           0 :         appliedOffset.y = std::max(0, outer.Y()) - inner.Y();
    7518           0 :         MOZ_ASSERT(appliedOffset.y < 0);
    7519           0 :       }
    7520           0 :     }
    7521           0 :     // Same as above, but for the x-axis
    7522             :     if (outer.XMost() != inner.XMost()) {
    7523             :       nscoord distance = DistanceToRange(inner.XMost(), outer.XMost());
    7524           0 :       leftMargin = Some(NSAppUnitsToFloatPixels(itemBounds.x - scrollPort.x - distance, auPerDevPixel));
    7525           0 :       hBounds.max = NSAppUnitsToFloatPixels(outer.XMost() - inner.XMost(), auPerDevPixel);
    7526           0 :       if (inner.XMost() < 0) {
    7527           0 :         appliedOffset.x = std::min(0, outer.XMost()) - inner.XMost();
    7528           0 :         MOZ_ASSERT(appliedOffset.x > 0);
    7529           0 :       }
    7530           0 :     }
    7531             :     if (outer.X() != inner.X()) {
    7532             :       nscoord distance = DistanceToRange(outer.X(), inner.X());
    7533             :       rightMargin = Some(NSAppUnitsToFloatPixels(scrollPort.XMost() - itemBounds.XMost() + distance, auPerDevPixel));
    7534           0 :       hBounds.min = NSAppUnitsToFloatPixels(outer.X() - inner.X(), auPerDevPixel);
    7535             :       if (appliedOffset.x == 0 && inner.X() > 0) {
    7536           0 :         appliedOffset.x = std::max(0, outer.X()) - inner.X();
    7537           0 :         MOZ_ASSERT(appliedOffset.x < 0);
    7538           0 :       }
    7539           0 :     }
    7540           0 : 
    7541           0 :     LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(itemBounds, auPerDevPixel);
    7542           0 :     wr::LayoutVector2D applied = {
    7543             :       NSAppUnitsToFloatPixels(appliedOffset.x, auPerDevPixel),
    7544           0 :       NSAppUnitsToFloatPixels(appliedOffset.y, auPerDevPixel)
    7545           0 :     };
    7546             :     wr::WrClipId id = aBuilder.DefineStickyFrame(wr::ToRoundedLayoutRect(bounds),
    7547             :         topMargin.ptrOr(nullptr), rightMargin.ptrOr(nullptr),
    7548           0 :         bottomMargin.ptrOr(nullptr), leftMargin.ptrOr(nullptr),
    7549           0 :         vBounds, hBounds, applied);
    7550             : 
    7551           0 :     aBuilder.PushClip(id);
    7552           0 :     aManager->CommandBuilder().PushOverrideForASR(mContainerASR, Some(id));
    7553           0 :   }
    7554             : 
    7555             :   nsDisplayOwnLayer::CreateWebRenderCommands(aBuilder, aResources, aSc,
    7556           0 :       aManager, aDisplayListBuilder);
    7557             : 
    7558             :   if (stickyScrollContainer) {
    7559           0 :     aManager->CommandBuilder().PopOverrideForASR(mContainerASR);
    7560             :     aBuilder.PopClip();
    7561             :   }
    7562           0 : 
    7563             :   return true;
    7564             : }
    7565             : 
    7566           0 : nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
    7567             :   nsDisplayListBuilder* aBuilder,
    7568             :   nsIFrame* aScrolledFrame,
    7569           0 :   nsIFrame* aScrollFrame)
    7570             :   : nsDisplayWrapList(aBuilder, aScrollFrame)
    7571           0 :   , mScrollFrame(aScrollFrame)
    7572             :   , mScrolledFrame(aScrolledFrame)
    7573             :   , mScrollParentId(aBuilder->GetCurrentScrollParentId())
    7574           0 : {
    7575             : #ifdef NS_BUILD_REFCNT_LOGGING
    7576           0 :   MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer);
    7577           0 : #endif
    7578             : }
    7579             : 
    7580             : #ifdef NS_BUILD_REFCNT_LOGGING
    7581           0 : nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer()
    7582             : {
    7583             :   MOZ_COUNT_DTOR(nsDisplayScrollInfoLayer);
    7584             : }
    7585             : #endif
    7586             : 
    7587             : already_AddRefed<Layer>
    7588             : nsDisplayScrollInfoLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
    7589             :                                      LayerManager* aManager,
    7590             :                                      const ContainerLayerParameters& aContainerParameters)
    7591           0 : {
    7592             :   // In general for APZ with event-regions we no longer have a need for
    7593           0 :   // scrollinfo layers. However, in some cases, there might be content that
    7594             :   // cannot be layerized, and so needs to scroll synchronously. To handle those
    7595             :   // cases, we still want to generate scrollinfo layers.
    7596             : 
    7597           0 :   return aManager->GetLayerBuilder()->
    7598             :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    7599             :                            aContainerParameters, nullptr,
    7600             :                            FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR);
    7601           0 : }
    7602             : 
    7603             : LayerState
    7604             : nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
    7605           0 :                                     LayerManager* aManager,
    7606             :                                     const ContainerLayerParameters& aParameters)
    7607             : {
    7608           0 :   return LAYER_ACTIVE_EMPTY;
    7609           0 : }
    7610           0 : 
    7611             : UniquePtr<ScrollMetadata>
    7612             : nsDisplayScrollInfoLayer::ComputeScrollMetadata(LayerManager* aLayerManager,
    7613           0 :                                                 const ContainerLayerParameters& aContainerParameters)
    7614             : {
    7615           0 :   nsRect viewport = mScrollFrame->GetRect() -
    7616           0 :                     mScrollFrame->GetPosition() +
    7617             :                     mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
    7618           0 : 
    7619             :   ScrollMetadata metadata = nsLayoutUtils::ComputeScrollMetadata(
    7620             :       mScrolledFrame, mScrollFrame, mScrollFrame->GetContent(),
    7621             :       ReferenceFrame(), aLayerManager,
    7622           0 :       mScrollParentId, viewport, Nothing(), false, aContainerParameters);
    7623             :   metadata.GetMetrics().SetIsScrollInfoLayer(true);
    7624             : 
    7625           0 :   return UniquePtr<ScrollMetadata>(new ScrollMetadata(metadata));
    7626             : }
    7627           0 : 
    7628           0 : bool
    7629           0 : nsDisplayScrollInfoLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
    7630           0 :                                            mozilla::layers::WebRenderLayerScrollData* aLayerData)
    7631             : {
    7632           0 :   if (aLayerData) {
    7633             :     UniquePtr<ScrollMetadata> metadata =
    7634             :       ComputeScrollMetadata(aData->GetManager(), ContainerLayerParameters());
    7635             :     MOZ_ASSERT(aData);
    7636           0 :     MOZ_ASSERT(metadata);
    7637             :     aLayerData->AppendScrollMetadata(*aData, *metadata);
    7638           0 :   }
    7639           0 :   return true;
    7640           0 : }
    7641             : 
    7642           0 : void
    7643             : nsDisplayScrollInfoLayer::WriteDebugInfo(std::stringstream& aStream)
    7644             : {
    7645           0 :   aStream << " (scrollframe " << mScrollFrame
    7646             :           << " scrolledFrame " << mScrolledFrame << ")";
    7647           0 : }
    7648           0 : 
    7649           0 : nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
    7650             :                              nsIFrame* aFrame, nsDisplayList* aList,
    7651             :                              int32_t aAPD, int32_t aParentAPD,
    7652           0 :                              nsDisplayOwnLayerFlags aFlags)
    7653           0 :     : nsDisplaySubDocument(aBuilder, aFrame, nullptr, aList, aFlags)
    7654           0 :     , mAPD(aAPD), mParentAPD(aParentAPD) {
    7655             :   MOZ_COUNT_CTOR(nsDisplayZoom);
    7656             : }
    7657           0 : 
    7658             : #ifdef NS_BUILD_REFCNT_LOGGING
    7659             : nsDisplayZoom::~nsDisplayZoom() {
    7660           0 :   MOZ_COUNT_DTOR(nsDisplayZoom);
    7661           0 : }
    7662           0 : #endif
    7663             : 
    7664             : nsRect nsDisplayZoom::GetBounds(nsDisplayListBuilder* aBuilder,
    7665           0 :                                 bool* aSnap) const
    7666             : {
    7667             :   nsRect bounds = nsDisplaySubDocument::GetBounds(aBuilder, aSnap);
    7668             :   *aSnap = false;
    7669             :   return bounds.ScaleToOtherAppUnitsRoundOut(mAPD, mParentAPD);
    7670           0 : }
    7671             : 
    7672             : void nsDisplayZoom::HitTest(nsDisplayListBuilder *aBuilder,
    7673           0 :                             const nsRect& aRect,
    7674           0 :                             HitTestState *aState,
    7675           0 :                             nsTArray<nsIFrame*> *aOutFrames)
    7676             : {
    7677           0 :   nsRect rect;
    7678             :   // A 1x1 rect indicates we are just hit testing a point, so pass down a 1x1
    7679           0 :   // rect as well instead of possibly rounding the width or height to zero.
    7680           0 :   if (aRect.width == 1 && aRect.height == 1) {
    7681             :     rect.MoveTo(aRect.TopLeft().ScaleToOtherAppUnits(mParentAPD, mAPD));
    7682           0 :     rect.width = rect.height = 1;
    7683             :   } else {
    7684             :     rect = aRect.ScaleToOtherAppUnitsRoundOut(mParentAPD, mAPD);
    7685             :   }
    7686           0 :   mList.HitTest(aBuilder, rect, aState, aOutFrames);
    7687             : }
    7688           0 : 
    7689           0 : bool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder,
    7690           0 :                                       nsRegion *aVisibleRegion)
    7691             : {
    7692             :   // Convert the passed in visible region to our appunits.
    7693           0 :   nsRegion visibleRegion;
    7694             :   // mVisibleRect has been clipped to GetClippedBounds
    7695             :   visibleRegion.And(*aVisibleRegion, GetPaintRect());
    7696             :   visibleRegion = visibleRegion.ScaleToOtherAppUnitsRoundOut(mParentAPD, mAPD);
    7697             :   nsRegion originalVisibleRegion = visibleRegion;
    7698           0 : 
    7699           0 :   nsRect transformedVisibleRect =
    7700             :     GetPaintRect().ScaleToOtherAppUnitsRoundOut(mParentAPD, mAPD);
    7701           0 :   bool retval;
    7702           0 :   // If we are to generate a scrollable layer we call
    7703             :   // nsDisplaySubDocument::ComputeVisibility to make the necessary adjustments
    7704             :   // for ComputeVisibility, it does all it's calculations in the child APD.
    7705           0 :   bool usingDisplayPort = UseDisplayPortForViewport(aBuilder, mFrame);
    7706             :   if (!(mFlags & nsDisplayOwnLayerFlags::eGenerateScrollableLayer) || !usingDisplayPort) {
    7707             :     retval =
    7708           0 :       mList.ComputeVisibilityForSublist(aBuilder, &visibleRegion,
    7709             :                                         transformedVisibleRect);
    7710           0 :   } else {
    7711             :     retval =
    7712           0 :       nsDisplaySubDocument::ComputeVisibility(aBuilder, &visibleRegion);
    7713             :   }
    7714             : 
    7715           0 :   nsRegion removed;
    7716             :   // removed = originalVisibleRegion - visibleRegion
    7717           0 :   removed.Sub(originalVisibleRegion, visibleRegion);
    7718             :   // Convert removed region to parent appunits.
    7719             :   removed = removed.ScaleToOtherAppUnitsRoundIn(mAPD, mParentAPD);
    7720             :   // aVisibleRegion = aVisibleRegion - removed (modulo any simplifications
    7721             :   // SubtractFromVisibleRegion does)
    7722             :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
    7723             : 
    7724             :   return retval;
    7725             : }
    7726             : 
    7727             : ///////////////////////////////////////////////////
    7728             : // nsDisplayTransform Implementation
    7729             : //
    7730             : 
    7731             : // Write #define UNIFIED_CONTINUATIONS here and in
    7732             : // TransformReferenceBox::Initialize to have the transform property try
    7733             : // to transform content with continuations as one unified block instead of
    7734             : // several smaller ones.  This is currently disabled because it doesn't work
    7735             : // correctly, since when the frames are initially being reflowed, their
    7736           0 : // continuations all compute their bounding rects independently of each other
    7737             : // and consequently get the wrong value.  Write #define DEBUG_HIT here to have
    7738             : // the nsDisplayTransform class dump out a bunch of information about hit
    7739             : // detection.
    7740           0 : #undef  UNIFIED_CONTINUATIONS
    7741             : #undef  DEBUG_HIT
    7742             : 
    7743             : nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
    7744             :                                        nsIFrame *aFrame, nsDisplayList *aList,
    7745             :                                        const nsRect& aChildrenBuildingRect,
    7746             :                                        ComputeTransformFunction aTransformGetter,
    7747             :                                        uint32_t aIndex)
    7748             :   : nsDisplayItem(aBuilder, aFrame)
    7749             :   , mStoredList(aBuilder, aFrame, aList)
    7750             :   , mTransformGetter(aTransformGetter)
    7751           0 :   , mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
    7752             :   , mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
    7753           0 :   , mChildrenBuildingRect(aChildrenBuildingRect)
    7754           0 :   , mIndex(aIndex)
    7755           0 :   , mNoExtendContext(false)
    7756           0 :   , mIsTransformSeparator(false)
    7757             :   , mTransformPreserves3DInited(false)
    7758             :   , mAllowAsyncAnimation(false)
    7759          11 : {
    7760             :   MOZ_COUNT_CTOR(nsDisplayTransform);
    7761          11 :   MOZ_ASSERT(aFrame, "Must have a frame!");
    7762             :   Init(aBuilder);
    7763             : }
    7764          11 : 
    7765           0 : void
    7766           0 : nsDisplayTransform::SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder)
    7767          11 : {
    7768          11 :   if (mFrame == aBuilder->RootReferenceFrame()) {
    7769             :     return;
    7770             :   }
    7771             :   nsIFrame *outerFrame = nsLayoutUtils::GetCrossDocParentFrame(mFrame);
    7772             :   mReferenceFrame =
    7773             :     aBuilder->FindReferenceFrameFor(outerFrame);
    7774           0 :   mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
    7775          11 :   if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(mFrame)) {
    7776           0 :     // This is an odd special case. If we are both IsFixedPosFrameInDisplayPort
    7777             :     // and transformed that we are our own AGR parent.
    7778             :     // We want our frame to be our AGR because FrameLayerBuilder uses our AGR to
    7779             :     // determine if we are inside a fixed pos subtree. If we use the outer AGR
    7780           0 :     // from outside the fixed pos subtree FLB can't tell that we are fixed pos.
    7781          22 :     mAnimatedGeometryRoot = mAnimatedGeometryRootForChildren;
    7782           0 :   } else if (mFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY &&
    7783           0 :              IsStickyFrameActive(aBuilder, mFrame, nullptr)) {
    7784             :     // Similar to the IsFixedPosFrameInDisplayPort case we are our own AGR.
    7785             :     // We are inside the sticky position, so our AGR is the sticky positioned
    7786             :     // frame, which is our AGR, not the parent AGR.
    7787             :     mAnimatedGeometryRoot = mAnimatedGeometryRootForChildren;
    7788             :   } else if (mAnimatedGeometryRoot->mParentAGR) {
    7789           0 :     mAnimatedGeometryRootForScrollMetadata = mAnimatedGeometryRoot->mParentAGR;
    7790             :     if (!MayBeAnimated(aBuilder)) {
    7791             :       // If we're an animated transform then we want the same AGR as our children
    7792             :       // so that FrameLayerBuilder knows that this layer moves with the transform
    7793          22 :       // and won't compute occlusions. If we're not animated then use our parent
    7794             :       // AGR so that inactive transform layers can go in the same PaintedLayer as
    7795             :       // surrounding content.
    7796             :       mAnimatedGeometryRoot = mAnimatedGeometryRoot->mParentAGR;
    7797           0 :     }
    7798             :   }
    7799           0 : 
    7800          11 :   SetBuildingRect(aBuilder->GetVisibleRect() + mToReferenceFrame);
    7801          11 : }
    7802           0 : 
    7803             : void
    7804           0 : nsDisplayTransform::Init(nsDisplayListBuilder* aBuilder)
    7805             : {
    7806             :   mHasBounds = false;
    7807             :   mStoredList.SetClipChain(nullptr, true);
    7808          11 :   mStoredList.SetBuildingRect(mChildrenBuildingRect);
    7809             : }
    7810             : 
    7811             : nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
    7812             :                                        nsIFrame *aFrame, nsDisplayList *aList,
    7813             :                                        const nsRect& aChildrenBuildingRect,
    7814             :                                        uint32_t aIndex,
    7815             :                                        bool aAllowAsyncAnimation)
    7816             :   : nsDisplayItem(aBuilder, aFrame)
    7817             :   , mStoredList(aBuilder, aFrame, aList)
    7818             :   , mTransformGetter(nullptr)
    7819           1 :   , mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
    7820             :   , mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
    7821           1 :   , mChildrenBuildingRect(aChildrenBuildingRect)
    7822          11 :   , mIndex(aIndex)
    7823          11 :   , mNoExtendContext(false)
    7824          11 :   , mIsTransformSeparator(false)
    7825           1 :   , mTransformPreserves3DInited(false)
    7826          11 :   , mAllowAsyncAnimation(aAllowAsyncAnimation)
    7827             : {
    7828           0 :   MOZ_COUNT_CTOR(nsDisplayTransform);
    7829             :   MOZ_ASSERT(aFrame, "Must have a frame!");
    7830             :   SetReferenceFrameToAncestor(aBuilder);
    7831             :   Init(aBuilder);
    7832           0 :   UpdateBoundsFor3D(aBuilder);
    7833             : }
    7834             : 
    7835           0 : nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder,
    7836             :                                        nsIFrame *aFrame, nsDisplayList *aList,
    7837             :                                        const nsRect& aChildrenBuildingRect,
    7838             :                                        const Matrix4x4& aTransform,
    7839             :                                        uint32_t aIndex)
    7840             :   : nsDisplayItem(aBuilder, aFrame)
    7841             :   , mStoredList(aBuilder, aFrame, aList)
    7842             :   , mTransform(Some(aTransform))
    7843             :   , mTransformGetter(nullptr)
    7844           0 :   , mAnimatedGeometryRootForChildren(mAnimatedGeometryRoot)
    7845             :   , mAnimatedGeometryRootForScrollMetadata(mAnimatedGeometryRoot)
    7846           0 :   , mChildrenBuildingRect(aChildrenBuildingRect)
    7847           0 :   , mIndex(aIndex)
    7848           0 :   , mNoExtendContext(false)
    7849           0 :   , mIsTransformSeparator(true)
    7850           0 :   , mTransformPreserves3DInited(false)
    7851             :   , mAllowAsyncAnimation(false)
    7852             : {
    7853             :   MOZ_COUNT_CTOR(nsDisplayTransform);
    7854             :   MOZ_ASSERT(aFrame, "Must have a frame!");
    7855             :   Init(aBuilder);
    7856             :   UpdateBoundsFor3D(aBuilder);
    7857             : }
    7858          95 : 
    7859             : /* Returns the delta specified by the transform-origin property.
    7860             :  * This is a positive delta, meaning that it indicates the direction to move
    7861             :  * to get from (0, 0) of the frame to the transform origin.  This function is
    7862           0 :  * called off the main thread.
    7863           0 :  */
    7864             : /* static */ Point3D
    7865             : nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame,
    7866             :                                               float aAppUnitsPerPixel,
    7867             :                                               const nsRect* aBoundsOverride)
    7868           0 : {
    7869           0 :   MOZ_ASSERT(aFrame, "Can't get delta for a null frame!");
    7870             :   MOZ_ASSERT(aFrame->IsTransformed() ||
    7871             :              aFrame->BackfaceIsHidden() ||
    7872             :              aFrame->Combines3DTransformWithAncestors(),
    7873             :              "Shouldn't get a delta for an untransformed frame!");
    7874             : 
    7875             :   if (!aFrame->IsTransformed()) {
    7876          95 :     return Point3D();
    7877             :   }
    7878             : 
    7879             :   /* For both of the coordinates, if the value of transform is a
    7880          95 :    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    7881          95 :    * a distance, it's already computed for us!
    7882           0 :    */
    7883           0 :   const nsStyleDisplay* display = aFrame->StyleDisplay();
    7884             :   // We don't use aBoundsOverride for SVG since we need to account for
    7885          95 :   // refBox.X/Y(). This happens to work because ReflowSVG sets the frame's
    7886             :   // mRect before calling FinishAndStoreOverflow so we don't need the override.
    7887             :   TransformReferenceBox refBox;
    7888             :   if (aBoundsOverride &&
    7889             :       !(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
    7890             :     refBox.Init(aBoundsOverride->Size());
    7891           0 :   } else {
    7892             :     refBox.Init(aFrame);
    7893          95 :   }
    7894             : 
    7895         285 :   /* Allows us to access dimension getters by index. */
    7896             :   float transformOrigin[2];
    7897             :   TransformReferenceBox::DimensionGetter dimensionGetter[] =
    7898             :     { &TransformReferenceBox::Width, &TransformReferenceBox::Height };
    7899           0 :   TransformReferenceBox::DimensionGetter offsetGetter[] =
    7900         190 :     { &TransformReferenceBox::X, &TransformReferenceBox::Y };
    7901           0 : 
    7902           0 :   for (uint8_t index = 0; index < 2; ++index) {
    7903           0 :     /* If the transform-origin specifies a percentage, take the percentage
    7904           0 :      * of the size of the box.
    7905           0 :      */
    7906           0 :     const nsStyleCoord& originValue  = display->mTransformOrigin[index];
    7907         190 :     if (originValue.GetUnit() == eStyleUnit_Calc) {
    7908         570 :       const nsStyleCoord::Calc *calc = originValue.GetCalcValue();
    7909         190 :       transformOrigin[index] =
    7910             :         NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(), aAppUnitsPerPixel) *
    7911           0 :           calc->mPercent +
    7912             :         NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
    7913           0 :     } else if (originValue.GetUnit() == eStyleUnit_Percent) {
    7914           0 :       transformOrigin[index] =
    7915             :         NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(), aAppUnitsPerPixel) *
    7916             :         originValue.GetPercentValue();
    7917             :     } else {
    7918         380 :       MOZ_ASSERT(originValue.GetUnit() == eStyleUnit_Coord,
    7919             :                  "unexpected unit");
    7920             :       transformOrigin[index] =
    7921             :         NSAppUnitsToFloatPixels(originValue.GetCoordValue(),
    7922         162 :                                 aAppUnitsPerPixel);
    7923         324 :     }
    7924             : 
    7925             :     if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
    7926             :       // SVG frames (unlike other frames) have a reference box that can be (and
    7927         285 :       // typically is) offset from the TopLeft() of the frame. We need to
    7928             :       // account for that here.
    7929           0 :       transformOrigin[index] +=
    7930             :         NSAppUnitsToFloatPixels((refBox.*offsetGetter[index])(), aAppUnitsPerPixel);
    7931             :     }
    7932             :   }
    7933          95 : 
    7934             :   return Point3D(transformOrigin[0], transformOrigin[1],
    7935             :                  NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
    7936             :                                          aAppUnitsPerPixel));
    7937          95 : }
    7938          95 : 
    7939             : /* static */ bool
    7940             : nsDisplayTransform::ComputePerspectiveMatrix(const nsIFrame* aFrame,
    7941             :                                              float aAppUnitsPerPixel,
    7942           0 :                                              Matrix4x4& aOutMatrix)
    7943             : {
    7944           0 :   MOZ_ASSERT(aFrame, "Can't get delta for a null frame!");
    7945             :   MOZ_ASSERT(aFrame->IsTransformed() ||
    7946             :              aFrame->BackfaceIsHidden() ||
    7947             :              aFrame->Combines3DTransformWithAncestors(),
    7948             :              "Shouldn't get a delta for an untransformed frame!");
    7949             :   MOZ_ASSERT(aOutMatrix.IsIdentity(), "Must have a blank output matrix");
    7950             : 
    7951             :   if (!aFrame->IsTransformed()) {
    7952             :     return false;
    7953             :   }
    7954           0 : 
    7955           0 :   /* Find our containing block, which is the element that provides the
    7956             :    * value for perspective we need to use
    7957             :    */
    7958             : 
    7959             :   //TODO: Is it possible that the cbFrame's bounds haven't been set correctly yet
    7960             :   // (similar to the aBoundsOverride case for GetResultingTransformMatrix)?
    7961          95 :   nsIFrame* cbFrame = aFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME);
    7962          95 :   if (!cbFrame) {
    7963             :     return false;
    7964             :   }
    7965           0 : 
    7966           0 :   /* Grab the values for perspective and perspective-origin (if present) */
    7967             : 
    7968             :   const nsStyleDisplay* cbDisplay = cbFrame->StyleDisplay();
    7969             :   if (cbDisplay->mChildPerspective.GetUnit() != eStyleUnit_Coord) {
    7970           0 :     return false;
    7971             :   }
    7972             :   nscoord perspective = cbDisplay->mChildPerspective.GetCoordValue();
    7973             :   if (perspective < std::numeric_limits<Float>::epsilon()) {
    7974           0 :     return true;
    7975             :   }
    7976             : 
    7977             :   TransformReferenceBox refBox(cbFrame);
    7978             : 
    7979             :   Point perspectiveOrigin =
    7980           0 :     nsStyleTransformMatrix::Convert2DPosition(cbDisplay->mPerspectiveOrigin,
    7981             :                                               refBox, aAppUnitsPerPixel);
    7982             : 
    7983           0 :   /* GetOffsetTo computes the offset required to move from 0,0 in cbFrame to 0,0
    7984             :    * in aFrame. Although we actually want the inverse of this, it's faster to
    7985             :    * compute this way.
    7986             :    */
    7987             :   nsPoint frameToCbOffset = -aFrame->GetOffsetTo(cbFrame);
    7988           0 :   Point frameToCbGfxOffset(
    7989             :             NSAppUnitsToFloatPixels(frameToCbOffset.x, aAppUnitsPerPixel),
    7990           0 :             NSAppUnitsToFloatPixels(frameToCbOffset.y, aAppUnitsPerPixel));
    7991           0 : 
    7992             :   /* Move the perspective origin to be relative to aFrame, instead of relative
    7993           0 :    * to the containing block which is how it was specified in the style system.
    7994           0 :    */
    7995             :   perspectiveOrigin += frameToCbGfxOffset;
    7996             : 
    7997           0 :   aOutMatrix._34 =
    7998             :     -1.0 / NSAppUnitsToFloatPixels(perspective, aAppUnitsPerPixel);
    7999          95 : 
    8000             :   aOutMatrix.ChangeBasis(Point3D(perspectiveOrigin.x, perspectiveOrigin.y, 0));
    8001         190 :   return true;
    8002         380 : }
    8003             : 
    8004          95 : nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame,
    8005             :                                                                        float aAppUnitsPerPixel,
    8006             :                                                                        const nsRect* aBoundsOverride)
    8007             :   : mFrame(aFrame)
    8008             :   , mTransformList(aFrame->StyleDisplay()->GetCombinedTransform())
    8009             :   , mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
    8010             : {
    8011           0 : }
    8012             : 
    8013             : /* Wraps up the transform matrix in a change-of-basis matrix pair that
    8014             :  * translates from local coordinate space to transform coordinate space, then
    8015             :  * hands it back.
    8016             :  */
    8017             : Matrix4x4
    8018           0 : nsDisplayTransform::GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
    8019             :                                                 const nsPoint& aOrigin,
    8020             :                                                 float aAppUnitsPerPixel,
    8021             :                                                 uint32_t aFlags,
    8022          95 :                                                 const nsRect* aBoundsOverride)
    8023             : {
    8024             :   return GetResultingTransformMatrixInternal(aProperties, aOrigin, aAppUnitsPerPixel,
    8025             :                                              aFlags, aBoundsOverride);
    8026             : }
    8027             : 
    8028             : Matrix4x4
    8029             : nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
    8030         190 :                                                 const nsPoint& aOrigin,
    8031             :                                                 float aAppUnitsPerPixel,
    8032             :                                                 uint32_t aFlags,
    8033           1 :                                                 const nsRect* aBoundsOverride)
    8034             : {
    8035             :   FrameTransformProperties props(aFrame,
    8036             :                                  aAppUnitsPerPixel,
    8037           1 :                                  aBoundsOverride);
    8038             : 
    8039             :   return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel,
    8040             :                                              aFlags, aBoundsOverride);
    8041             : }
    8042             : 
    8043           0 : Matrix4x4
    8044          95 : nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
    8045             :                                                         const nsPoint& aOrigin,
    8046             :                                                         float aAppUnitsPerPixel,
    8047             :                                                         uint32_t aFlags,
    8048             :                                                         const nsRect* aBoundsOverride)
    8049             : {
    8050             :   const nsIFrame *frame = aProperties.mFrame;
    8051          95 :   NS_ASSERTION(frame || !(aFlags & INCLUDE_PERSPECTIVE), "Must have a frame to compute perspective!");
    8052         190 : 
    8053           0 :   // Get the underlying transform matrix:
    8054           0 : 
    8055             :   // We don't use aBoundsOverride for SVG since we need to account for
    8056          95 :   // refBox.X/Y(). This happens to work because ReflowSVG sets the frame's
    8057             :   // mRect before calling FinishAndStoreOverflow so we don't need the override.
    8058             :   TransformReferenceBox refBox;
    8059             :   if (aBoundsOverride &&
    8060             :       (!frame || !(frame->GetStateBits() & NS_FRAME_SVG_LAYOUT))) {
    8061           0 :     refBox.Init(aBoundsOverride->Size());
    8062             :   } else {
    8063             :     refBox.Init(frame);
    8064             :   }
    8065          95 : 
    8066             :   /* Get the matrix, then change its basis to factor in the origin. */
    8067         190 :   bool dummyBool;
    8068         190 :   Matrix4x4 result;
    8069             :   // Call IsSVGTransformed() regardless of the value of
    8070         190 :   // disp->mSpecifiedTransform, since we still need any
    8071          14 :   // parentsChildrenOnlyTransform.
    8072             :   Matrix svgTransform, parentsChildrenOnlyTransform;
    8073             :   bool hasSVGTransforms =
    8074           0 :     frame && frame->IsSVGTransformed(&svgTransform,
    8075             :                                      &parentsChildrenOnlyTransform);
    8076          81 :   /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
    8077          81 :   if (aProperties.mTransformList) {
    8078          81 :     result = nsStyleTransformMatrix::ReadTransforms(aProperties.mTransformList->mHead,
    8079           0 :                                                     refBox, aAppUnitsPerPixel,
    8080           0 :                                                     &dummyBool);
    8081             :   } else if (hasSVGTransforms) {
    8082             :     // Correct the translation components for zoom:
    8083             :     float pixelsPerCSSPx = frame->PresContext()->AppUnitsPerCSSPixel() /
    8084          95 :                              aAppUnitsPerPixel;
    8085             :     svgTransform._31 *= pixelsPerCSSPx;
    8086             :     svgTransform._32 *= pixelsPerCSSPx;
    8087             :     result = Matrix4x4::From2D(svgTransform);
    8088             :   }
    8089          95 : 
    8090             :   // Apply any translation due to 'transform-origin' and/or 'transform-box':
    8091           0 :   result.ChangeBasis(aProperties.mToTransformOrigin);
    8092             : 
    8093           0 :   // See the comment for nsSVGContainerFrame::HasChildrenOnlyTransform for
    8094           0 :   // an explanation of what children-only transforms are.
    8095           0 :   bool parentHasChildrenOnlyTransform =
    8096             :     hasSVGTransforms && !parentsChildrenOnlyTransform.IsIdentity();
    8097             : 
    8098           0 :   if (parentHasChildrenOnlyTransform) {
    8099           0 :     float pixelsPerCSSPx =
    8100           0 :       frame->PresContext()->AppUnitsPerCSSPixel() / aAppUnitsPerPixel;
    8101             :     parentsChildrenOnlyTransform._31 *= pixelsPerCSSPx;
    8102           0 :     parentsChildrenOnlyTransform._32 *= pixelsPerCSSPx;
    8103             : 
    8104           0 :     Point3D frameOffset(
    8105             :       NSAppUnitsToFloatPixels(-frame->GetPosition().x, aAppUnitsPerPixel),
    8106             :       NSAppUnitsToFloatPixels(-frame->GetPosition().y, aAppUnitsPerPixel),
    8107          95 :       0);
    8108          95 :     Matrix4x4 parentsChildrenOnlyTransform3D =
    8109          95 :       Matrix4x4::From2D(parentsChildrenOnlyTransform).ChangeBasis(frameOffset);
    8110           0 : 
    8111           0 :     result *= parentsChildrenOnlyTransform3D;
    8112             :   }
    8113             : 
    8114             :   Matrix4x4 perspectiveMatrix;
    8115           0 :   bool hasPerspective = aFlags & INCLUDE_PERSPECTIVE;
    8116           0 :   if (hasPerspective) {
    8117             :     if (ComputePerspectiveMatrix(frame, aAppUnitsPerPixel, perspectiveMatrix)) {
    8118           0 :       result *= perspectiveMatrix;
    8119           0 :     }
    8120             :   }
    8121             : 
    8122             :   if ((aFlags & INCLUDE_PRESERVE3D_ANCESTORS) &&
    8123             :       frame && frame->Combines3DTransformWithAncestors()) {
    8124           0 :     // Include the transform set on our parent
    8125             :     nsIFrame* parentFrame = frame->GetInFlowParent();
    8126           0 :     NS_ASSERTION(parentFrame && parentFrame->IsTransformed() &&
    8127             :                  parentFrame->Extend3DContext(),
    8128             :                  "Preserve3D mismatch!");
    8129             :     FrameTransformProperties props(parentFrame,
    8130             :                                    aAppUnitsPerPixel,
    8131             :                                    nullptr);
    8132           0 : 
    8133           0 :     uint32_t flags = aFlags & (INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE);
    8134             : 
    8135             :     // If this frame isn't transformed (but we exist for backface-visibility),
    8136             :     // then we're not a reference frame so no offset to origin will be added.
    8137           0 :     // Otherwise we need to manually translate into our parent's coordinate
    8138             :     // space.
    8139           0 :     if (frame->IsTransformed()) {
    8140           0 :       nsLayoutUtils::PostTranslate(result, frame->GetPosition(), aAppUnitsPerPixel, !hasSVGTransforms);
    8141             :     }
    8142             :     Matrix4x4 parent =
    8143          95 :       GetResultingTransformMatrixInternal(props,
    8144           0 :                                           nsPoint(0, 0),
    8145             :                                           aAppUnitsPerPixel, flags,
    8146             :                                           nullptr);
    8147          95 :     result = result * parent;
    8148             :   }
    8149             : 
    8150             :   if (aFlags & OFFSET_BY_ORIGIN) {
    8151           0 :     nsLayoutUtils::PostTranslate(result, aOrigin, aAppUnitsPerPixel, !hasSVGTransforms);
    8152             :   }
    8153           0 : 
    8154             :   return result;
    8155             : }
    8156             : 
    8157             : bool
    8158           0 : nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
    8159           0 : {
    8160           0 :   if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_opacity)) {
    8161             :     return true;
    8162           0 :   }
    8163             : 
    8164             :   EffectCompositor::SetPerformanceWarning(
    8165             :     mFrame, eCSSProperty_opacity,
    8166           0 :     AnimationPerformanceWarning(
    8167             :       AnimationPerformanceWarning::Type::OpacityFrameInactive));
    8168           0 : 
    8169             :   return false;
    8170             : }
    8171             : 
    8172           0 : bool
    8173             : nsDisplayTransform::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder)
    8174             : {
    8175             :   return mAllowAsyncAnimation;
    8176             : }
    8177             : 
    8178             : /* static */ auto
    8179             : nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
    8180          22 :                                                       nsIFrame* aFrame,
    8181           0 :                                                       nsRect* aDirtyRect) -> PrerenderDecision
    8182             : {
    8183             :   // Elements whose transform has been modified recently, or which
    8184             :   // have a compositor-animated transform, can be prerendered. An element
    8185           0 :   // might have only just had its transform animated in which case
    8186          11 :   // the ActiveLayerManager may not have been notified yet.
    8187             :   if (!ActiveLayerTracker::IsStyleMaybeAnimated(aFrame, eCSSProperty_transform) &&
    8188          11 :       !EffectCompositor::HasAnimationsForCompositor(aFrame,
    8189             :                                                     eCSSProperty_transform)) {
    8190             :     EffectCompositor::SetPerformanceWarning(
    8191             :       aFrame, eCSSProperty_transform,
    8192             :       AnimationPerformanceWarning(
    8193             :         AnimationPerformanceWarning::Type::TransformFrameInactive));
    8194             : 
    8195             :     return NoPrerender;
    8196             :   }
    8197             : 
    8198             :   // We should not allow prerender if any ancestor container element has
    8199             :   // mask/clip-path effects.
    8200             :   //
    8201             :   // With prerender and async transform animation, we do not need to restyle an
    8202             :   // animated element to respect position changes, since that transform is done
    8203             :   // by layer animation. As a result, the container element is not aware of
    8204             :   // position change of that containing element and loses the chance to update
    8205             :   // the content of mask/clip-path.
    8206             :   //
    8207             :   // Why do we need to update a mask? This is relative to how we generate a
    8208             :   // mask layer in ContainerState::SetupMaskLayerForCSSMask. While creating a
    8209           0 :   // mask layer, to reduce memory usage, we did not choose the size of the
    8210           0 :   // masked element as mask size. Instead, we read the union of bounds of all
    8211           0 :   // children display items by nsDisplayWrapList::GetBounds, which is smaller
    8212           0 :   // than or equal to the masked element's boundary, and use it as the position
    8213             :   // size of the mask layer. That union bounds is actually affected by the
    8214             :   // geometry of the animated element. To keep the content of mask up to date,
    8215             :   // forbidding of prerender is required.
    8216             :   for (nsIFrame* container = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
    8217             :        container; container = nsLayoutUtils::GetCrossDocParentFrame(container)) {
    8218             :     const nsStyleSVGReset *svgReset = container->StyleSVGReset();
    8219           0 :     if (svgReset->HasMask() || svgReset->HasClipPath()) {
    8220           0 :       return NoPrerender;
    8221             :     }
    8222             :   }
    8223             : 
    8224           0 :   // If the incoming dirty rect already contains the entire overflow area,
    8225           0 :   // we are already rendering the entire content.
    8226           0 :   nsRect overflow = aFrame->GetVisualOverflowRectRelativeToSelf();
    8227           0 :   if (aDirtyRect->Contains(overflow)) {
    8228           0 :     return FullPrerender;
    8229             :   }
    8230             : 
    8231             :   float viewportRatioX = gfxPrefs::AnimationPrerenderViewportRatioLimitX();
    8232           0 :   float viewportRatioY = gfxPrefs::AnimationPrerenderViewportRatioLimitY();
    8233           0 :   uint32_t absoluteLimitX = gfxPrefs::AnimationPrerenderAbsoluteLimitX();
    8234             :   uint32_t absoluteLimitY = gfxPrefs::AnimationPrerenderAbsoluteLimitY();
    8235           0 :   nsSize refSize = aBuilder->RootReferenceFrame()->GetSize();
    8236           0 :   // Only prerender if the transformed frame's size is <= a multiple of the
    8237             :   // reference frame size (~viewport), and less than an absolute limit.
    8238             :   // Both the ratio and the absolute limit are configurable.
    8239           0 :   nsSize relativeLimit(nscoord(refSize.width * viewportRatioX),
    8240             :                        nscoord(refSize.height * viewportRatioY));
    8241           0 :   nsSize absoluteLimit(aFrame->PresContext()->DevPixelsToAppUnits(absoluteLimitX),
    8242           0 :                        aFrame->PresContext()->DevPixelsToAppUnits(absoluteLimitY));
    8243           0 :   nsSize maxSize = Min(relativeLimit, absoluteLimit);
    8244             : 
    8245           0 :   const auto transform = nsLayoutUtils::GetTransformToAncestor(aFrame,
    8246           0 :     nsLayoutUtils::GetDisplayRootFrame(aFrame));
    8247           0 :   const gfxRect transformedBounds = transform.TransformAndClipBounds(
    8248           0 :     gfxRect(overflow.x, overflow.y, overflow.width, overflow.height),
    8249           0 :     gfxRect::MaxIntRect());
    8250           0 :   const nsSize frameSize = nsSize(transformedBounds.width, transformedBounds.height);
    8251           0 : 
    8252           0 :   uint64_t maxLimitArea = uint64_t(maxSize.width) * maxSize.height;
    8253             :   uint64_t frameArea = uint64_t(frameSize.width) * frameSize.height;
    8254             :   if (frameArea <= maxLimitArea && frameSize <= absoluteLimit) {
    8255           0 :     *aDirtyRect = overflow;
    8256           0 :     return FullPrerender;
    8257             :   } else if (gfxPrefs::PartiallyPrerenderAnimatedContent()) {
    8258             :     *aDirtyRect = nsLayoutUtils::ComputePartialPrerenderArea(*aDirtyRect, overflow, maxSize);
    8259           0 :     return PartialPrerender;
    8260             :   }
    8261             : 
    8262           0 :   if (frameArea > maxLimitArea) {
    8263           0 :     uint64_t appUnitsPerPixel = nsPresContext::AppUnitsPerCSSPixel();
    8264           0 :     EffectCompositor::SetPerformanceWarning(
    8265             :       aFrame, eCSSProperty_transform,
    8266             :       AnimationPerformanceWarning(
    8267             :         AnimationPerformanceWarning::Type::ContentTooLargeArea,
    8268           0 :         {
    8269             :           int(frameArea / (appUnitsPerPixel * appUnitsPerPixel)),
    8270             :           int(maxLimitArea / (appUnitsPerPixel * appUnitsPerPixel)),
    8271           0 :         }));
    8272           0 :   } else {
    8273           0 :     EffectCompositor::SetPerformanceWarning(
    8274           0 :       aFrame, eCSSProperty_transform,
    8275           0 :       AnimationPerformanceWarning(
    8276           0 :         AnimationPerformanceWarning::Type::ContentTooLarge,
    8277           0 :         {
    8278             :           nsPresContext::AppUnitsToIntCSSPixels(frameSize.width),
    8279             :           nsPresContext::AppUnitsToIntCSSPixels(frameSize.height),
    8280             :           nsPresContext::AppUnitsToIntCSSPixels(relativeLimit.width),
    8281             :           nsPresContext::AppUnitsToIntCSSPixels(relativeLimit.height),
    8282             :           nsPresContext::AppUnitsToIntCSSPixels(absoluteLimit.width),
    8283             :           nsPresContext::AppUnitsToIntCSSPixels(absoluteLimit.height),
    8284           0 :         }));
    8285             :   }
    8286           0 : 
    8287             :   return NoPrerender;
    8288             : }
    8289           0 : 
    8290             : /* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
    8291             : static bool IsFrameVisible(nsIFrame* aFrame, const Matrix4x4& aMatrix)
    8292           0 : {
    8293             :   if (aMatrix.IsSingular()) {
    8294             :     return false;
    8295             :   }
    8296          33 :   if (aFrame->BackfaceIsHidden() && aMatrix.IsBackfaceVisible()) {
    8297             :     return false;
    8298          66 :   }
    8299          22 :   return true;
    8300             : }
    8301             : 
    8302           0 : const Matrix4x4Flagged&
    8303             : nsDisplayTransform::GetTransform() const
    8304           0 : {
    8305           0 :   if (mTransform) {
    8306             :     return *mTransform;
    8307           0 :   }
    8308           0 : 
    8309           0 :   float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
    8310           0 : 
    8311           0 :   if (mTransformGetter) {
    8312             :     mTransform.emplace(mTransformGetter(mFrame, scale));
    8313           0 :     Point3D newOrigin =
    8314          33 :       Point3D(NSAppUnitsToFloatPixels(mToReferenceFrame.x, scale),
    8315           0 :               NSAppUnitsToFloatPixels(mToReferenceFrame.y, scale),
    8316          11 :               0.0f);
    8317          22 :     mTransform->ChangeBasis(newOrigin.x, newOrigin.y, newOrigin.z);
    8318           0 :   } else if (!mIsTransformSeparator) {
    8319             :     DebugOnly<bool> isReference =
    8320             :       mFrame->IsTransformed() ||
    8321           0 :       mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext();
    8322             :     MOZ_ASSERT(isReference);
    8323             :     mTransform.emplace(
    8324          11 :       GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
    8325             :                                   scale, INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN));
    8326             :   } else {
    8327             :     // Use identity matrix
    8328           0 :     mTransform.emplace();
    8329             :   }
    8330           0 : 
    8331           0 :   return *mTransform;
    8332             : }
    8333             : 
    8334           0 : const Matrix4x4Flagged&
    8335             : nsDisplayTransform::GetInverseTransform() const
    8336           0 : {
    8337             :   if (mInverseTransform) {
    8338           0 :     return *mInverseTransform;
    8339             :   }
    8340             : 
    8341             :   MOZ_ASSERT(!GetTransform().IsSingular());
    8342          11 : 
    8343             :   mInverseTransform.emplace(GetTransform().Inverse());
    8344           0 : 
    8345          11 :   return *mInverseTransform;
    8346             : }
    8347             : 
    8348             : Matrix4x4
    8349             : nsDisplayTransform::GetTransformForRendering(LayoutDevicePoint* aOutOrigin)
    8350           0 : {
    8351           0 :   if (!mFrame->HasPerspective() || mTransformGetter || mIsTransformSeparator) {
    8352           0 :     if (!mTransformGetter && !mIsTransformSeparator && aOutOrigin) {
    8353             :       // If aOutOrigin is provided, put the offset to origin into it, because
    8354           0 :       // we need to keep it separate for webrender. The combination of
    8355             :       // *aOutOrigin and the returned matrix here should always be equivalent
    8356           0 :       // to what GetTransform() would have returned.
    8357             :       float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
    8358           0 :       *aOutOrigin = LayoutDevicePoint::FromAppUnits(ToReferenceFrame(), scale);
    8359             :       return GetResultingTransformMatrix(mFrame, nsPoint(0, 0), scale, INCLUDE_PERSPECTIVE);
    8360             :     }
    8361           0 :     return GetTransform().GetMatrix();
    8362             :   }
    8363             :   MOZ_ASSERT(!mTransformGetter);
    8364             : 
    8365           0 :   float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
    8366             :   // Don't include perspective transform, or the offset to origin, since
    8367           0 :   // nsDisplayPerspective will handle both of those.
    8368             :   return GetResultingTransformMatrix(mFrame, ToReferenceFrame(), scale, 0);
    8369           0 : }
    8370           0 : 
    8371           0 : const Matrix4x4&
    8372           0 : nsDisplayTransform::GetAccumulatedPreserved3DTransform(nsDisplayListBuilder* aBuilder)
    8373           0 : {
    8374             :   MOZ_ASSERT(!mFrame->Extend3DContext() || IsLeafOf3DContext());
    8375             :   // XXX: should go back to fix mTransformGetter.
    8376             :   if (!mTransformPreserves3DInited) {
    8377           0 :     mTransformPreserves3DInited = true;
    8378           0 :     if (!IsLeafOf3DContext()) {
    8379             :       mTransformPreserves3D = GetTransform().GetMatrix();
    8380             :       return mTransformPreserves3D;
    8381             :     }
    8382           0 : 
    8383             :     const nsIFrame* establisher; // Establisher of the 3D rendering context.
    8384           0 :     for (establisher = mFrame;
    8385           0 :          establisher && establisher->Combines3DTransformWithAncestors();
    8386           0 :          establisher = establisher->GetInFlowParent()) {
    8387           0 :     }
    8388           0 :     const nsIFrame* establisherReference =
    8389             :       aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetCrossDocParentFrame(establisher));
    8390           0 : 
    8391             :     nsPoint offset = establisher->GetOffsetToCrossDoc(establisherReference);
    8392             :     float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
    8393             :     uint32_t flags = INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN;
    8394           0 :     mTransformPreserves3D =
    8395             :       GetResultingTransformMatrix(mFrame, offset, scale, flags);
    8396             :   }
    8397             :   return mTransformPreserves3D;
    8398             : }
    8399           0 : 
    8400             : bool
    8401             : nsDisplayTransform::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const
    8402             : {
    8403           0 :   // The visible rect of a Preserves-3D frame is just an intermediate
    8404             :   // result.  It should always build a layer to make sure it is
    8405             :   // rendering correctly.
    8406             :   return MayBeAnimated(aBuilder) || mFrame->Combines3DTransformWithAncestors();
    8407             : }
    8408             : 
    8409             : bool
    8410             : nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    8411             :                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
    8412             :                                             const StackingContextHelper& aSc,
    8413             :                                             WebRenderLayerManager* aManager,
    8414           0 :                                             nsDisplayListBuilder* aDisplayListBuilder)
    8415           0 : {
    8416             :   // We want to make sure we don't pollute the transform property in the WR
    8417           0 :   // stacking context by including the position of this frame (relative to the
    8418           0 :   // parent reference frame). We need to keep those separate; the position of
    8419             :   // this frame goes into the stacking context bounds while the transform goes
    8420             :   // into the transform.
    8421             :   LayoutDevicePoint position;
    8422           0 :   Matrix4x4 newTransformMatrix = GetTransformForRendering(&position);
    8423             : 
    8424             :   gfx::Matrix4x4* transformForSC = &newTransformMatrix;
    8425           0 :   if (newTransformMatrix.IsIdentity()) {
    8426             :     // If the transform is an identity transform, strip it out so that WR
    8427           0 :     // doesn't turn this stacking context into a reference frame, as it
    8428           0 :     // affects positioning. Bug 1345577 tracks a better fix.
    8429             :     transformForSC = nullptr;
    8430           0 :   }
    8431           0 : 
    8432             :   RefPtr<WebRenderAnimationData> animationData = aManager->CommandBuilder().CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
    8433             : 
    8434             :   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
    8435           0 :   AddAnimationsForProperty(Frame(), aDisplayListBuilder,
    8436             :                            this, eCSSProperty_transform,
    8437           0 :                            animationInfo, false, true);
    8438           0 :   animationInfo.StartPendingAnimations(aManager->GetAnimationReadyTime());
    8439           0 : 
    8440             :   // Note that animationsId can be 0 (uninitialized in AnimationInfo) if there
    8441             :   // are no active animations.
    8442           0 :   uint64_t animationsId = animationInfo.GetCompositorAnimationsId();
    8443           0 :   wr::WrAnimationProperty prop;
    8444           0 :   if (!animationInfo.GetAnimations().IsEmpty()) {
    8445           0 :     prop.id = animationsId;
    8446           0 :     prop.effect_type = wr::WrAnimationType::Transform;
    8447           0 : 
    8448             :     OpAddCompositorAnimations
    8449             :       anim(CompositorAnimations(animationInfo.GetAnimations(), animationsId));
    8450           0 :     aManager->WrBridge()->AddWebRenderParentCommand(anim);
    8451           0 :     aManager->AddActiveCompositorAnimationId(animationsId);
    8452           0 :   } else if (animationsId) {
    8453             :     aManager->AddCompositorAnimationsIdForDiscard(animationsId);
    8454             :     animationsId = 0;
    8455             :   }
    8456             : 
    8457             :   nsTArray<mozilla::wr::WrFilterOp> filters;
    8458           0 :   Maybe<nsDisplayTransform*> deferredTransformItem;
    8459             :   if (!mFrame->HasPerspective()) {
    8460             :     // If it has perspective, we create a new scroll data via the
    8461             :     // UpdateScrollData call because that scenario is more complex. Otherwise
    8462             :     // we can just stash the transform on the StackingContextHelper and
    8463           0 :     // apply it to any scroll data that are created inside this
    8464           0 :     // nsDisplayTransform.
    8465             :     deferredTransformItem = Some(this);
    8466             :   }
    8467             : 
    8468             :   // If it looks like we're animated, we should rasterize in local space
    8469           0 :   // (disabling subpixel-aa and global pixel snapping)
    8470             :   bool rasterizeLocally = ActiveLayerTracker::IsStyleMaybeAnimated(
    8471             :     Frame(), eCSSProperty_transform);
    8472             : 
    8473             :   StackingContextHelper sc(aSc,
    8474             :                            aBuilder,
    8475             :                            filters,
    8476           0 :                            LayoutDeviceRect(position, LayoutDeviceSize()),
    8477           0 :                            &newTransformMatrix,
    8478             :                            animationsId ? &prop : nullptr,
    8479             :                            nullptr,
    8480           0 :                            transformForSC,
    8481             :                            nullptr,
    8482           0 :                            gfx::CompositionOp::OP_OVER,
    8483           0 :                            !BackfaceIsHidden(),
    8484             :                            mFrame->Extend3DContext() && !mNoExtendContext,
    8485             :                            deferredTransformItem,
    8486             :                            nullptr,
    8487           0 :                            rasterizeLocally);
    8488             : 
    8489             :   return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc,
    8490           0 :                                              aManager, aDisplayListBuilder);
    8491             : }
    8492             : 
    8493             : bool
    8494             : nsDisplayTransform::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
    8495           0 :                                      mozilla::layers::WebRenderLayerScrollData* aLayerData)
    8496           0 : {
    8497             :   if (!mFrame->HasPerspective()) {
    8498             :     // This case is handled in CreateWebRenderCommands by stashing the transform
    8499             :     // on the stacking context.
    8500             :     return false;
    8501             :   }
    8502          11 :   if (aLayerData) {
    8503             :     aLayerData->SetTransform(GetTransform().GetMatrix());
    8504             :     aLayerData->SetTransformIsPerspective(true);
    8505             :   }
    8506             :   return true;
    8507             : }
    8508             : 
    8509           0 : already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
    8510           0 :                                                        LayerManager *aManager,
    8511             :                                                        const ContainerLayerParameters& aContainerParameters)
    8512             : {
    8513             :   // While generating a glyph mask, the transform vector of the root frame had
    8514             :   // been applied into the target context, so stop applying it again here.
    8515             :   const bool shouldSkipTransform =
    8516             :     (aBuilder->RootReferenceFrame() == mFrame) &&
    8517           0 :     (aBuilder->IsForGenerateGlyphMask() || aBuilder->IsForPaintingSelectionBG());
    8518             : 
    8519          11 :   /* For frames without transform, it would not be removed for
    8520             :    * backface hidden here.  But, it would be removed by the init
    8521           0 :    * function of nsDisplayTransform.
    8522           0 :    */
    8523             :   const Matrix4x4 newTransformMatrix =
    8524           0 :     shouldSkipTransform ? Matrix4x4(): GetTransformForRendering();
    8525             : 
    8526             :   uint32_t flags = FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR;
    8527             :   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
    8528             :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mStoredList.GetChildren(),
    8529             :                            aContainerParameters, &newTransformMatrix, flags);
    8530          11 : 
    8531           0 :   if (!container) {
    8532             :     return nullptr;
    8533          22 :   }
    8534             : 
    8535             :   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
    8536          11 :   // so we never need to explicitely unset this flag.
    8537           0 :   if (mFrame->Extend3DContext() && !mNoExtendContext) {
    8538             :     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT);
    8539             :   } else {
    8540           1 :     container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT);
    8541             :   }
    8542           1 : 
    8543          11 :   if (mAllowAsyncAnimation) {
    8544             :     mFrame->SetProperty(nsIFrame::RefusedAsyncAnimationProperty(), false);
    8545             :   }
    8546             : 
    8547           0 :   nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder,
    8548           0 :                                                            this, mFrame,
    8549           0 :                                                            eCSSProperty_transform);
    8550             :   if (mAllowAsyncAnimation && MayBeAnimated(aBuilder)) {
    8551           0 :     // Only allow async updates to the transform if we're an animated layer, since that's what
    8552          22 :     // triggers us to set the correct AGR in the constructor and makes sure FrameLayerBuilder
    8553             :     // won't compute occlusions for this layer.
    8554          22 :     container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
    8555             :                            /*the value is irrelevant*/nullptr);
    8556             :     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_MAY_CHANGE_TRANSFORM);
    8557             :   } else {
    8558          22 :     container->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
    8559             :     container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_MAY_CHANGE_TRANSFORM);
    8560             :   }
    8561             :   return container.forget();
    8562             : }
    8563             : 
    8564             : bool
    8565             : nsDisplayTransform::MayBeAnimated(nsDisplayListBuilder* aBuilder) const
    8566             : {
    8567           0 :   // If EffectCompositor::HasAnimationsForCompositor() is true then we can
    8568           0 :   // completely bypass the main thread for this animation, so it is always
    8569          22 :   // worthwhile.
    8570          22 :   // For ActiveLayerTracker::IsStyleAnimated() cases the main thread is
    8571           0 :   // already involved so there is less to be gained.
    8572           0 :   // Therefore we check that the *post-transform* bounds of this item are
    8573             :   // big enough to justify an active layer.
    8574             :   if (EffectCompositor::HasAnimationsForCompositor(mFrame,
    8575           0 :                                                    eCSSProperty_transform) ||
    8576             :       (ActiveLayerTracker::IsStyleAnimated(aBuilder,
    8577             :                                            mFrame,
    8578             :                                            eCSSProperty_transform) &&
    8579          11 :        !IsItemTooSmallForActiveLayer(mFrame))) {
    8580             :     return true;
    8581             :   }
    8582             :   return false;
    8583             : }
    8584             : 
    8585             : nsDisplayItem::LayerState
    8586             : nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
    8587          44 :                                   LayerManager* aManager,
    8588          33 :                                   const ContainerLayerParameters& aParameters) {
    8589             :   // If the transform is 3d, the layer takes part in preserve-3d
    8590             :   // sorting, or the layer is a separator then we *always* want this
    8591             :   // to be an active layer.
    8592          11 :   // Checking HasPerspective() is needed to handle perspective value 0 when
    8593             :   // the transform is 2D.
    8594             :   if (!GetTransform().Is2D() || mFrame->Combines3DTransformWithAncestors() ||
    8595             :       mIsTransformSeparator || mFrame->HasPerspective()) {
    8596             :     return LAYER_ACTIVE_FORCE;
    8597             :   }
    8598             : 
    8599             :   if (MayBeAnimated(aBuilder)) {
    8600             :     // Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
    8601             :     // animations.
    8602          33 :     return LAYER_ACTIVE_FORCE;
    8603          33 :   }
    8604             : 
    8605             :   // Expect the child display items to have this frame as their animated
    8606           0 :   // geometry root (since it will be their reference frame). If they have a
    8607             :   // different animated geometry root, we'll make this an active layer so the
    8608             :   // animation can be accelerated.
    8609             :   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
    8610             :     *mStoredList.GetChildren(), mAnimatedGeometryRootForChildren);
    8611             : }
    8612             : 
    8613           0 : bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
    8614             :                                              nsRegion *aVisibleRegion)
    8615             : {
    8616             :   // nsDisplayTransform::GetBounds() returns an empty rect in nested 3d context.
    8617             :   // Calling mStoredList.RecomputeVisibility below for such transform causes the
    8618             :   // child display items to end up with empty visible rect.
    8619             :   // We avoid this by bailing out always if we are dealing with a 3d context.
    8620             :   if (mFrame->Extend3DContext() || mFrame->Combines3DTransformWithAncestors()) {
    8621           0 :     return true;
    8622           0 :   }
    8623             : 
    8624           0 :   /* As we do this, we need to be sure to
    8625             :    * untransform the visible rect, since we want everything that's painting to
    8626           0 :    * think that it's painting in its original rectangular coordinate space.
    8627             :    * If we can't untransform, take the entire overflow rect */
    8628             :   nsRect untransformedVisibleRect;
    8629             :   if (!UntransformPaintRect(aBuilder, &untransformedVisibleRect))
    8630           0 :   {
    8631             :     untransformedVisibleRect = mFrame->GetVisualOverflowRectRelativeToSelf();
    8632             :   }
    8633             :   nsRegion untransformedVisible = untransformedVisibleRect;
    8634             :   // Call RecomputeVisiblity instead of ComputeVisibility since
    8635             :   // nsDisplayItem::ComputeVisibility should only be called from
    8636             :   // nsDisplayList::ComputeVisibility (which sets mVisibleRect on the item)
    8637             :   mStoredList.RecomputeVisibility(aBuilder, &untransformedVisible);
    8638             :   return true;
    8639           0 : }
    8640             : 
    8641             : #ifdef DEBUG_HIT
    8642             : #include <time.h>
    8643             : #endif
    8644           0 : 
    8645           0 : /* HitTest does some fun stuff with matrix transforms to obtain the answer. */
    8646           0 : void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
    8647             :                                  const nsRect& aRect,
    8648             :                                  HitTestState *aState,
    8649             :                                  nsTArray<nsIFrame*> *aOutFrames)
    8650             : {
    8651             :   if (aState->mInPreserves3D) {
    8652             :     mStoredList.HitTest(aBuilder, aRect, aState, aOutFrames);
    8653             :     return;
    8654             :   }
    8655             : 
    8656             :   /* Here's how this works:
    8657           0 :    * 1. Get the matrix.  If it's singular, abort (clearly we didn't hit
    8658           0 :    *    anything).
    8659             :    * 2. Invert the matrix.
    8660           0 :    * 3. Use it to transform the rect into the correct space.
    8661             :    * 4. Pass that rect down through to the list's version of HitTest.
    8662             :    */
    8663             :   // GetTransform always operates in dev pixels.
    8664             :   float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    8665             :   Matrix4x4 matrix = GetAccumulatedPreserved3DTransform(aBuilder);
    8666             : 
    8667             :   if (!IsFrameVisible(mFrame, matrix)) {
    8668             :     return;
    8669             :   }
    8670           0 : 
    8671           0 :   /* We want to go from transformed-space to regular space.
    8672           0 :    * Thus we have to invert the matrix, which normally does
    8673             :    * the reverse operation (e.g. regular->transformed)
    8674           0 :    */
    8675           0 : 
    8676           0 :   /* Now, apply the transform and pass it down the channel. */
    8677           0 :   matrix.Invert();
    8678             :   nsRect resultingRect;
    8679             :   if (aRect.width == 1 && aRect.height == 1) {
    8680           0 :     // Magic width/height indicating we're hit testing a point, not a rect
    8681             :     Point4D point = matrix.ProjectPoint(Point(NSAppUnitsToFloatPixels(aRect.x, factor),
    8682           0 :                                               NSAppUnitsToFloatPixels(aRect.y, factor)));
    8683           0 :     if (!point.HasPositiveWCoord()) {
    8684           0 :       return;
    8685             :     }
    8686             : 
    8687           0 :     Point point2d = point.As2DPoint();
    8688           0 : 
    8689           0 :     resultingRect = nsRect(NSFloatPixelsToAppUnits(float(point2d.x), factor),
    8690           0 :                            NSFloatPixelsToAppUnits(float(point2d.y), factor),
    8691             :                            1, 1);
    8692             : 
    8693             :   } else {
    8694           0 :     Rect originalRect(NSAppUnitsToFloatPixels(aRect.x, factor),
    8695             :                       NSAppUnitsToFloatPixels(aRect.y, factor),
    8696             :                       NSAppUnitsToFloatPixels(aRect.width, factor),
    8697             :                       NSAppUnitsToFloatPixels(aRect.height, factor));
    8698           0 : 
    8699             : 
    8700           0 :     bool snap;
    8701             :     nsRect childBounds = mStoredList.GetBounds(aBuilder, &snap);
    8702           0 :     Rect childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
    8703             :                         NSAppUnitsToFloatPixels(childBounds.y, factor),
    8704             :                         NSAppUnitsToFloatPixels(childBounds.width, factor),
    8705             :                         NSAppUnitsToFloatPixels(childBounds.height, factor));
    8706             : 
    8707             :     Rect rect = matrix.ProjectRectBounds(originalRect, childGfxBounds);
    8708           0 : 
    8709             :     resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
    8710             :                            NSFloatPixelsToAppUnits(float(rect.Y()), factor),
    8711             :                            NSFloatPixelsToAppUnits(float(rect.Width()), factor),
    8712             :                            NSFloatPixelsToAppUnits(float(rect.Height()), factor));
    8713             :   }
    8714             : 
    8715             :   if (resultingRect.IsEmpty()) {
    8716             :     return;
    8717             :   }
    8718             : 
    8719           0 : 
    8720             : #ifdef DEBUG_HIT
    8721             :   printf("Frame: %p\n", dynamic_cast<void *>(mFrame));
    8722             :   printf("  Untransformed point: (%f, %f)\n", resultingRect.X(), resultingRect.Y());
    8723             :   uint32_t originalFrameCount = aOutFrames.Length();
    8724             : #endif
    8725             : 
    8726             :   mStoredList.HitTest(aBuilder, resultingRect, aState, aOutFrames);
    8727             : 
    8728             : #ifdef DEBUG_HIT
    8729             :   if (originalFrameCount != aOutFrames.Length())
    8730             :     printf("  Hit! Time: %f, first frame: %p\n", static_cast<double>(clock()),
    8731           0 :            dynamic_cast<void *>(aOutFrames.ElementAt(0)));
    8732             :   printf("=== end of hit test ===\n");
    8733             : #endif
    8734           0 : 
    8735           0 : }
    8736             : 
    8737           0 : float
    8738             : nsDisplayTransform::GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint)
    8739             : {
    8740           0 :   // GetTransform always operates in dev pixels.
    8741           0 :   float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    8742           0 :   Matrix4x4 matrix = GetAccumulatedPreserved3DTransform(aBuilder);
    8743           0 : 
    8744             :   NS_ASSERTION(IsFrameVisible(mFrame, matrix),
    8745           0 :                "We can't have hit a frame that isn't visible!");
    8746             : 
    8747           0 :   Matrix4x4 inverse = matrix;
    8748           0 :   inverse.Invert();
    8749             :   Point4D point = inverse.ProjectPoint(Point(NSAppUnitsToFloatPixels(aPoint.x, factor),
    8750             :                                              NSAppUnitsToFloatPixels(aPoint.y, factor)));
    8751             : 
    8752             :   Point point2d = point.As2DPoint();
    8753             : 
    8754             :   Point3D transformed = matrix.TransformPoint(Point3D(point2d.x, point2d.y, 0));
    8755           0 :   return transformed.z;
    8756             : }
    8757             : 
    8758           0 : /* The bounding rectangle for the object is the overflow rectangle translated
    8759             :  * by the reference point.
    8760          22 :  */
    8761           0 : nsRect
    8762             : nsDisplayTransform::GetBounds(nsDisplayListBuilder* aBuilder,
    8763             :                               bool* aSnap) const
    8764          11 : {
    8765           0 :   *aSnap = false;
    8766             : 
    8767             :   if (mHasBounds) {
    8768          33 :     return mBounds;
    8769             :   }
    8770          22 : 
    8771          11 :   if (mFrame->Extend3DContext() && !mIsTransformSeparator) {
    8772          11 :     return nsRect();
    8773             :   }
    8774           0 : 
    8775          11 :   nsRect untransformedBounds = mStoredList.GetBounds(aBuilder, aSnap);
    8776             :   // GetTransform always operates in dev pixels.
    8777             :   float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    8778             :   mBounds = nsLayoutUtils::MatrixTransformRect(untransformedBounds,
    8779           0 :                                                GetTransform(),
    8780             :                                                factor);
    8781           0 :   mHasBounds = true;
    8782             :   return mBounds;
    8783             : }
    8784             : 
    8785             : void
    8786             : nsDisplayTransform::ComputeBounds(nsDisplayListBuilder* aBuilder)
    8787             : {
    8788             :   MOZ_ASSERT(mFrame->Extend3DContext() || IsLeafOf3DContext());
    8789             : 
    8790             :   /* For some cases, the transform would make an empty bounds, but it
    8791           0 :    * may be turned back again to get a non-empty bounds.  We should
    8792             :    * not depend on transforming bounds level by level.
    8793           0 :    *
    8794             :    * Here, it applies accumulated transforms on the leaf frames of the
    8795           0 :    * 3d rendering context, and track and accmulate bounds at
    8796             :    * nsDisplayListBuilder.
    8797           0 :    */
    8798             :   nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder);
    8799             : 
    8800             :   accTransform.Accumulate(GetTransform().GetMatrix());
    8801             : 
    8802             :   if (!IsLeafOf3DContext()) {
    8803             :     // Do not dive into another 3D context.
    8804             :     mStoredList.DoUpdateBoundsPreserves3D(aBuilder);
    8805           0 :   }
    8806             : 
    8807           0 :   /* For Preserves3D, it is bounds of only children as leaf frames.
    8808             :    * For non-leaf frames, their bounds are accumulated and kept at
    8809             :    * nsDisplayListBuilder.
    8810           0 :    */
    8811           0 :   bool snap;
    8812             :   nsRect untransformedBounds = mStoredList.GetBounds(aBuilder, &snap);
    8813           0 :   // GetTransform always operates in dev pixels.
    8814           0 :   float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    8815             :   nsRect rect =
    8816             :     nsLayoutUtils::MatrixTransformRect(untransformedBounds,
    8817             :                                        accTransform.GetCurrentTransform(),
    8818             :                                        factor);
    8819             : 
    8820             :   aBuilder->AccumulateRect(rect);
    8821             : }
    8822             : 
    8823             : /* The transform is opaque iff the transform consists solely of scales and
    8824             :  * translations and if the underlying content is opaque.  Thus if the transform
    8825             :  * is of the form
    8826             :  *
    8827             :  * |a c e|
    8828             :  * |b d f|
    8829             :  * |0 0 1|
    8830             :  *
    8831             :  * We need b and c to be zero.
    8832             :  *
    8833           0 :  * We also need to check whether the underlying opaque content completely fills
    8834             :  * our visible rect. We use UntransformRect which expands to the axis-aligned
    8835             :  * bounding rect, but that's OK since if
    8836           0 :  * mStoredList.GetVisibleRect().Contains(untransformedVisible), then it
    8837           0 :  * certainly contains the actual (non-axis-aligned) untransformed rect.
    8838           0 :  */
    8839           0 : nsRegion
    8840             : nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
    8841             :                                              bool* aSnap) const
    8842           0 : {
    8843             :   *aSnap = false;
    8844           0 :   nsRect untransformedVisible;
    8845           0 :   if (!UntransformBuildingRect(aBuilder, &untransformedVisible)) {
    8846             :       return nsRegion();
    8847           0 :   }
    8848           0 : 
    8849           0 :   const Matrix4x4Flagged& matrix = GetTransform();
    8850           0 : 
    8851             :   nsRegion result;
    8852           0 :   Matrix matrix2d;
    8853             :   bool tmpSnap;
    8854             :   if (matrix.Is2D(&matrix2d) &&
    8855             :       matrix2d.PreservesAxisAlignedRectangles() &&
    8856             :       mStoredList.GetOpaqueRegion(aBuilder, &tmpSnap).Contains(untransformedVisible)) {
    8857             :     result = GetBuildingRect().Intersect(GetBounds(aBuilder, &tmpSnap));
    8858             :   }
    8859             :   return result;
    8860             : }
    8861             : 
    8862             : /* TransformRect takes in as parameters a rectangle (in app space) and returns
    8863             :  * the smallest rectangle (in app space) containing the transformed image of
    8864             :  * that rectangle.  That is, it takes the four corners of the rectangle,
    8865             :  * transforms them according to the matrix associated with the specified frame,
    8866             :  * then returns the smallest rectangle containing the four transformed points.
    8867             :  *
    8868             :  * @param aUntransformedBounds The rectangle (in app units) to transform.
    8869           0 :  * @param aFrame The frame whose transformation should be applied.
    8870             :  * @param aOrigin The delta from the frame origin to the coordinate space origin
    8871             :  * @param aBoundsOverride (optional) Force the frame bounds to be the
    8872             :  *        specified bounds.
    8873           0 :  * @return The smallest rectangle containing the image of the transformed
    8874             :  *         rectangle.
    8875           0 :  */
    8876             : nsRect nsDisplayTransform::TransformRect(const nsRect &aUntransformedBounds,
    8877          62 :                                          const nsIFrame* aFrame,
    8878             :                                          const nsRect* aBoundsOverride)
    8879             : {
    8880           0 :   MOZ_ASSERT(aFrame, "Can't take the transform based on a null frame!");
    8881         124 : 
    8882             :   float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
    8883             : 
    8884           0 :   uint32_t flags = INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN|INCLUDE_PRESERVE3D_ANCESTORS;
    8885             :   return nsLayoutUtils::MatrixTransformRect
    8886             :     (aUntransformedBounds,
    8887             :      GetResultingTransformMatrix(aFrame, nsPoint(0, 0), factor, flags, aBoundsOverride),
    8888             :      factor);
    8889          22 : }
    8890             : 
    8891          44 : bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds,
    8892             :                                          const nsRect &aChildBounds,
    8893          22 :                                          const nsIFrame* aFrame,
    8894             :                                          nsRect *aOutRect)
    8895          22 : {
    8896          22 :   MOZ_ASSERT(aFrame, "Can't take the transform based on a null frame!");
    8897             : 
    8898             :   float factor = aFrame->PresContext()->AppUnitsPerDevPixel();
    8899             : 
    8900          44 :   uint32_t flags = INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN|INCLUDE_PRESERVE3D_ANCESTORS;
    8901          44 : 
    8902          44 :   Matrix4x4 transform = GetResultingTransformMatrix(aFrame, nsPoint(0, 0), factor, flags);
    8903         132 :   if (transform.IsSingular()) {
    8904             :     return false;
    8905           0 :   }
    8906          44 : 
    8907          44 :   RectDouble result(NSAppUnitsToFloatPixels(aTransformedBounds.x, factor),
    8908         132 :                     NSAppUnitsToFloatPixels(aTransformedBounds.y, factor),
    8909             :                     NSAppUnitsToFloatPixels(aTransformedBounds.width, factor),
    8910          22 :                     NSAppUnitsToFloatPixels(aTransformedBounds.height, factor));
    8911          22 : 
    8912          22 :   RectDouble childGfxBounds(NSAppUnitsToFloatPixels(aChildBounds.x, factor),
    8913             :                             NSAppUnitsToFloatPixels(aChildBounds.y, factor),
    8914             :                             NSAppUnitsToFloatPixels(aChildBounds.width, factor),
    8915           0 :                             NSAppUnitsToFloatPixels(aChildBounds.height, factor));
    8916             : 
    8917             :   result = transform.Inverse().ProjectRectBounds(result, childGfxBounds);
    8918             :   *aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
    8919           0 :   return true;
    8920             : }
    8921             : 
    8922             : bool nsDisplayTransform::UntransformRect(nsDisplayListBuilder* aBuilder,
    8923             :                                          const nsRect& aRect,
    8924           0 :                                          nsRect *aOutRect) const
    8925           0 : {
    8926           0 :   if (GetTransform().IsSingular()) {
    8927           0 :     return false;
    8928           0 :   }
    8929             : 
    8930             :   // GetTransform always operates in dev pixels.
    8931           0 :   float factor = mFrame->PresContext()->AppUnitsPerDevPixel();
    8932           0 :   RectDouble result(NSAppUnitsToFloatPixels(aRect.x, factor),
    8933           0 :                     NSAppUnitsToFloatPixels(aRect.y, factor),
    8934           0 :                     NSAppUnitsToFloatPixels(aRect.width, factor),
    8935           0 :                     NSAppUnitsToFloatPixels(aRect.height, factor));
    8936             : 
    8937             :   bool snap;
    8938           0 :   nsRect childBounds = mStoredList.GetBounds(aBuilder, &snap);
    8939             :   RectDouble childGfxBounds(NSAppUnitsToFloatPixels(childBounds.x, factor),
    8940           0 :                             NSAppUnitsToFloatPixels(childBounds.y, factor),
    8941             :                             NSAppUnitsToFloatPixels(childBounds.width, factor),
    8942             :                             NSAppUnitsToFloatPixels(childBounds.height, factor));
    8943             : 
    8944             :   /* We want to untransform the matrix, so invert the transformation first! */
    8945             :   result = GetInverseTransform().ProjectRectBounds(result, childGfxBounds);
    8946           0 : 
    8947             :   *aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(ThebesRect(result), factor);
    8948           0 : 
    8949           0 :   return true;
    8950           0 : }
    8951             : 
    8952           0 : void
    8953           0 : nsDisplayTransform::WriteDebugInfo(std::stringstream& aStream)
    8954             : {
    8955           0 :   AppendToString(aStream, GetTransform().GetMatrix());
    8956           0 :   if (IsTransformSeparator()) {
    8957             :     aStream << " transform-separator";
    8958           0 :   }
    8959           0 :   if (IsLeafOf3DContext()) {
    8960             :     aStream << " 3d-context-leaf";
    8961           0 :   }
    8962             :   if (mFrame->Extend3DContext()) {
    8963           0 :     aStream << " extends-3d-context";
    8964             :   }
    8965           0 :   if (mFrame->Combines3DTransformWithAncestors()) {
    8966             :     aStream << " combines-3d-with-ancestors";
    8967           0 :   }
    8968             : }
    8969           0 : 
    8970           0 : nsDisplayPerspective::nsDisplayPerspective(nsDisplayListBuilder* aBuilder,
    8971           0 :                                            nsIFrame* aFrame,
    8972           0 :                                            nsDisplayList* aList)
    8973             :   : nsDisplayItem(aBuilder, aFrame)
    8974             :   , mList(aBuilder, aFrame, aList, true)
    8975           0 : {
    8976             :   MOZ_ASSERT(mList.GetChildren()->Count() == 1);
    8977             :   MOZ_ASSERT(mList.GetChildren()->GetTop()->GetType() == DisplayItemType::TYPE_TRANSFORM);
    8978             :   mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(mFrame->GetContainingBlock(nsIFrame::SKIP_SCROLLED_FRAME));
    8979           0 : }
    8980             : 
    8981           0 : already_AddRefed<Layer>
    8982             : nsDisplayPerspective::BuildLayer(nsDisplayListBuilder *aBuilder,
    8983           0 :                                  LayerManager *aManager,
    8984           0 :                                  const ContainerLayerParameters& aContainerParameters)
    8985           0 : {
    8986             :   float appUnitsPerPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    8987             : 
    8988             :   Matrix4x4 perspectiveMatrix;
    8989             :   DebugOnly<bool> hasPerspective =
    8990           0 :     nsDisplayTransform::ComputePerspectiveMatrix(mFrame, appUnitsPerPixel,
    8991             :                                                  perspectiveMatrix);
    8992             :   MOZ_ASSERT(hasPerspective, "Why did we create nsDisplayPerspective?");
    8993             : 
    8994             :   /*
    8995             :    * ClipListToRange can remove our child after we were created.
    8996             :    */
    8997             :   if (!mList.GetChildren()->GetTop()) {
    8998             :     return nullptr;
    8999           0 :   }
    9000             : 
    9001             :   /*
    9002           0 :    * The resulting matrix is still in the coordinate space of the transformed
    9003           0 :    * frame. Append a translation to the reference frame coordinates.
    9004           0 :    */
    9005           0 :   nsDisplayTransform* transform =
    9006           0 :     static_cast<nsDisplayTransform*>(mList.GetChildren()->GetTop());
    9007           0 : 
    9008             :   Point3D newOrigin =
    9009           0 :     Point3D(NSAppUnitsToFloatPixels(transform->ToReferenceFrame().x, appUnitsPerPixel),
    9010             :             NSAppUnitsToFloatPixels(transform->ToReferenceFrame().y, appUnitsPerPixel),
    9011             :             0.0f);
    9012           0 :   Point3D roundedOrigin(NS_round(newOrigin.x),
    9013           0 :                         NS_round(newOrigin.y),
    9014             :                         0);
    9015           0 : 
    9016             :   perspectiveMatrix.PostTranslate(roundedOrigin);
    9017             : 
    9018             :   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
    9019             :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList.GetChildren(),
    9020             :                            aContainerParameters, &perspectiveMatrix, 0);
    9021             : 
    9022           0 :   if (!container) {
    9023           0 :     return nullptr;
    9024             :   }
    9025           0 : 
    9026             :   // Sort of a lie, but we want to pretend that the perspective layer extends a 3d context
    9027             :   // so that it gets its transform combined with children. Might need a better name that reflects
    9028             :   // this use case and isn't specific to preserve-3d.
    9029           0 :   container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT);
    9030             :   container->SetTransformIsPerspective(true);
    9031             : 
    9032             :   return container.forget();
    9033           0 : }
    9034             : 
    9035             : LayerState
    9036             : nsDisplayPerspective::GetLayerState(nsDisplayListBuilder* aBuilder,
    9037           0 :                                     LayerManager* aManager,
    9038             :                                     const ContainerLayerParameters& aParameters)
    9039             : {
    9040             :   return LAYER_ACTIVE_FORCE;
    9041             : }
    9042             : 
    9043           0 : bool
    9044           0 : nsDisplayPerspective::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    9045             :                                               mozilla::wr::IpcResourceUpdateQueue& aResources,
    9046           0 :                                               const StackingContextHelper& aSc,
    9047           0 :                                               WebRenderLayerManager* aManager,
    9048           0 :                                               nsDisplayListBuilder* aDisplayListBuilder)
    9049             : {
    9050             :   float appUnitsPerPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    9051             :   Matrix4x4 perspectiveMatrix;
    9052             :   DebugOnly<bool> hasPerspective =
    9053           0 :     nsDisplayTransform::ComputePerspectiveMatrix(mFrame, appUnitsPerPixel,
    9054             :                                                  perspectiveMatrix);
    9055             :   MOZ_ASSERT(hasPerspective, "Why did we create nsDisplayPerspective?");
    9056             : 
    9057             :   /*
    9058             :    * ClipListToRange can remove our child after we were created.
    9059             :    */
    9060             :   if (!mList.GetChildren()->GetTop()) {
    9061             :     return false;
    9062           0 :   }
    9063             : 
    9064             :   /*
    9065           0 :    * The resulting matrix is still in the coordinate space of the transformed
    9066           0 :    * frame. Append a translation to the reference frame coordinates.
    9067           0 :    */
    9068           0 :   nsDisplayTransform* transform =
    9069           0 :     static_cast<nsDisplayTransform*>(mList.GetChildren()->GetTop());
    9070           0 : 
    9071             :   Point3D newOrigin =
    9072           0 :     Point3D(NSAppUnitsToFloatPixels(transform->ToReferenceFrame().x, appUnitsPerPixel),
    9073             :             NSAppUnitsToFloatPixels(transform->ToReferenceFrame().y, appUnitsPerPixel),
    9074           0 :             0.0f);
    9075             :   Point3D roundedOrigin(NS_round(newOrigin.x),
    9076             :                         NS_round(newOrigin.y),
    9077             :                         0);
    9078           0 : 
    9079             :   gfx::Matrix4x4 transformForSC = gfx::Matrix4x4::Translation(roundedOrigin);
    9080             : 
    9081             :   nsTArray<mozilla::wr::WrFilterOp> filters;
    9082             :   StackingContextHelper sc(aSc,
    9083             :                            aBuilder,
    9084             :                            filters,
    9085           0 :                            LayoutDeviceRect(),
    9086           0 :                            nullptr,
    9087             :                            nullptr,
    9088           0 :                            nullptr,
    9089           0 :                            &transformForSC,
    9090             :                            &perspectiveMatrix,
    9091             :                            gfx::CompositionOp::OP_OVER,
    9092             :                            !BackfaceIsHidden(),
    9093           0 :                            true);
    9094             : 
    9095           0 :   return mList.CreateWebRenderCommands(aBuilder, aResources, sc,
    9096             :                                        aManager, aDisplayListBuilder);
    9097             : }
    9098             : 
    9099           0 : nsDisplayItemGeometry*
    9100             : nsCharClipDisplayItem::AllocateGeometry(nsDisplayListBuilder* aBuilder)
    9101             : {
    9102             :   return new nsCharClipGeometry(this, aBuilder);
    9103           0 : }
    9104             : 
    9105             : void
    9106           0 : nsCharClipDisplayItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    9107           0 :                                          const nsDisplayItemGeometry* aGeometry,
    9108           0 :                                          nsRegion* aInvalidRegion) const
    9109           0 : {
    9110           0 :   const nsCharClipGeometry* geometry = static_cast<const nsCharClipGeometry*>(aGeometry);
    9111           0 : 
    9112           0 :   bool snap;
    9113             :   nsRect newRect = geometry->mBounds;
    9114           0 :   nsRect oldRect = GetBounds(aBuilder, &snap);
    9115             :   if (mVisIStartEdge != geometry->mVisIStartEdge ||
    9116           0 :       mVisIEndEdge != geometry->mVisIEndEdge ||
    9117             :       !oldRect.IsEqualInterior(newRect) ||
    9118             :       !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
    9119             :     aInvalidRegion->Or(oldRect, newRect);
    9120           0 :   }
    9121             : }
    9122           0 : 
    9123             : nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
    9124           0 :                                          nsIFrame* aFrame, nsDisplayList* aList,
    9125           0 :                                          bool aHandleOpacity,
    9126             :                                          const ActiveScrolledRoot* aActiveScrolledRoot,
    9127           0 :                                          bool aClearClipChain)
    9128             :   : nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, aClearClipChain)
    9129           0 :   , mHandleOpacity(aHandleOpacity)
    9130             : {
    9131           0 :   MOZ_COUNT_CTOR(nsDisplaySVGEffects);
    9132             : }
    9133           0 : 
    9134           0 : nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
    9135             :                                          nsIFrame* aFrame, nsDisplayList* aList,
    9136             :                                          bool aHandleOpacity)
    9137           0 :   : nsDisplayWrapList(aBuilder, aFrame, aList)
    9138             :   , mHandleOpacity(aHandleOpacity)
    9139           0 : {
    9140           0 :   MOZ_COUNT_CTOR(nsDisplaySVGEffects);
    9141             : }
    9142             : 
    9143           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    9144             : nsDisplaySVGEffects::~nsDisplaySVGEffects()
    9145             : {
    9146           0 :   MOZ_COUNT_DTOR(nsDisplaySVGEffects);
    9147           0 : }
    9148             : #endif
    9149             : 
    9150             : nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    9151           0 :                                               bool* aSnap) const
    9152             : {
    9153             :   *aSnap = false;
    9154           0 :   return nsRegion();
    9155           0 : }
    9156           0 : 
    9157           0 : void
    9158             : nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    9159           0 :                              HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    9160             : {
    9161             :   nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
    9162           0 :   if (nsSVGIntegrationUtils::HitTestFrameForEffects(mFrame,
    9163             :       rectCenter - ToReferenceFrame())) {
    9164           0 :     mList.HitTest(aBuilder, aRect, aState, aOutFrames);
    9165             :   }
    9166             : }
    9167             : 
    9168           0 : gfxRect
    9169             : nsDisplaySVGEffects::BBoxInUserSpace() const
    9170           0 : {
    9171             :   return nsSVGUtils::GetBBox(mFrame);
    9172             : }
    9173             : 
    9174           0 : gfxPoint
    9175             : nsDisplaySVGEffects::UserSpaceOffset() const
    9176             : {
    9177             :   return nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(mFrame);
    9178             : }
    9179           0 : 
    9180             : void
    9181           0 : nsDisplaySVGEffects::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    9182           0 :                                                const nsDisplayItemGeometry* aGeometry,
    9183           0 :                                                nsRegion* aInvalidRegion) const
    9184           0 : {
    9185             :   const nsDisplaySVGEffectGeometry* geometry =
    9186             :     static_cast<const nsDisplaySVGEffectGeometry*>(aGeometry);
    9187             :   bool snap;
    9188             :   nsRect bounds = GetBounds(aBuilder, &snap);
    9189             :   if (geometry->mFrameOffsetToReferenceFrame != ToReferenceFrame() ||
    9190             :       geometry->mUserSpaceOffset != UserSpaceOffset() ||
    9191           0 :       !geometry->mBBox.IsEqualInterior(BBoxInUserSpace())) {
    9192             :     // Filter and mask output can depend on the location of the frame's user
    9193           0 :     // space and on the frame's BBox. We need to invalidate if either of these
    9194             :     // change relative to the reference frame.
    9195           0 :     // Invalidations from our inactive layer manager are not enough to catch
    9196             :     // some of these cases because filters can produce output even if there's
    9197           0 :     // nothing in the filter input.
    9198           0 :     aInvalidRegion->Or(bounds, geometry->mBounds);
    9199           0 :   }
    9200           0 : }
    9201           0 : 
    9202           0 : bool nsDisplaySVGEffects::ValidateSVGFrame()
    9203           0 : {
    9204             :   const nsIContent* content = mFrame->GetContent();
    9205           0 :   bool hasSVGLayout = (mFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
    9206             :   if (hasSVGLayout) {
    9207             :     nsSVGDisplayableFrame* svgFrame = do_QueryFrame(mFrame);
    9208             :     if (!svgFrame || !mFrame->GetContent()->IsSVGElement()) {
    9209             :       NS_ASSERTION(false, "why?");
    9210             :       return false;
    9211             :     }
    9212             :     if (!static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
    9213             :       return false; // The SVG spec says not to draw filters for this
    9214           0 :     }
    9215             :   }
    9216             : 
    9217             :   return true;
    9218           0 : }
    9219           0 : 
    9220             : static IntRect
    9221           0 : ComputeClipExtsInDeviceSpace(gfxContext& aCtx)
    9222           0 : {
    9223           0 :   // Get the clip extents in device space.
    9224           0 :   gfxRect clippedFrameSurfaceRect =
    9225             :     aCtx.GetClipExtents(gfxContext::eDeviceSpace);
    9226             :   clippedFrameSurfaceRect.RoundOut();
    9227             : 
    9228             :   IntRect result;
    9229             :   ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
    9230           0 :   return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
    9231             :                                                                 : IntRect();
    9232             : }
    9233             : 
    9234             : typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
    9235           0 : 
    9236             : static void
    9237           0 : ComputeMaskGeometry(PaintFramesParams& aParams)
    9238             : {
    9239             :   // Properties are added lazily and may have been removed by a restyle, so
    9240           0 :   // make sure all applicable ones are set again.
    9241           0 :   nsIFrame* firstFrame =
    9242             :     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aParams.frame);
    9243           0 : 
    9244           0 :   const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
    9245             : 
    9246             :   SVGObserverUtils::EffectProperties effectProperties =
    9247           0 :     SVGObserverUtils::GetEffectProperties(firstFrame);
    9248           0 :   nsTArray<nsSVGMaskFrame *> maskFrames = effectProperties.GetMaskFrames();
    9249             : 
    9250             :   if (maskFrames.Length() == 0) {
    9251           0 :     return;
    9252             :   }
    9253             : 
    9254             :   gfxContext& ctx = aParams.ctx;
    9255           0 :   nsIFrame* frame = aParams.frame;
    9256             : 
    9257           0 :   nsPoint offsetToUserSpace =
    9258           0 :       nsLayoutUtils::ComputeOffsetToUserSpace(aParams.builder, aParams.frame);
    9259             : 
    9260             :   gfxPoint devPixelOffsetToUserSpace =
    9261           0 :     nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
    9262           0 :                                    frame->PresContext()->AppUnitsPerDevPixel());
    9263           0 : 
    9264             :   gfxContextMatrixAutoSaveRestore matSR(&ctx);
    9265             :   ctx.SetMatrixDouble(ctx.CurrentMatrixDouble().PreTranslate(devPixelOffsetToUserSpace));
    9266           0 : 
    9267           0 :   // Convert boaderArea and dirtyRect to user space.
    9268           0 :   int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
    9269           0 :   nsRect userSpaceBorderArea = aParams.borderArea - offsetToUserSpace;
    9270             :   nsRect userSpaceDirtyRect = aParams.dirtyRect - offsetToUserSpace;
    9271           0 : 
    9272           0 :   // Union all mask layer rectangles in user space.
    9273             :   gfxRect maskInUserSpace;
    9274           0 :   for (size_t i = 0; i < maskFrames.Length() ; i++) {
    9275           0 :     nsSVGMaskFrame* maskFrame = maskFrames[i];
    9276             :     gfxRect currentMaskSurfaceRect;
    9277           0 : 
    9278             :     if (maskFrame) {
    9279             :       currentMaskSurfaceRect = maskFrame->GetMaskArea(aParams.frame);
    9280             :     } else {
    9281             :       nsCSSRendering::ImageLayerClipState clipState;
    9282           0 :       nsCSSRendering::GetImageLayerClip(svgReset->mMask.mLayers[i],
    9283           0 :                                        frame,
    9284             :                                        *frame->StyleBorder(),
    9285             :                                        userSpaceBorderArea,
    9286           0 :                                        userSpaceDirtyRect,
    9287             :                                        false, /* aWillPaintBorder */
    9288             :                                        appUnitsPerDevPixel,
    9289           0 :                                        &clipState);
    9290             :       currentMaskSurfaceRect = clipState.mDirtyRectInDevPx;
    9291           0 :     }
    9292           0 : 
    9293           0 :     maskInUserSpace = maskInUserSpace.Union(currentMaskSurfaceRect);
    9294             :   }
    9295             : 
    9296           0 :   gfxContextAutoSaveRestore autoSR;
    9297           0 : 
    9298             :   if (!maskInUserSpace.IsEmpty()) {
    9299             :     autoSR.SetContext(&ctx);
    9300           0 :     ctx.Clip(maskInUserSpace);
    9301             :   }
    9302             : 
    9303           0 :   IntRect result = ComputeClipExtsInDeviceSpace(ctx);
    9304           0 :   aParams.maskRect = result;
    9305             : }
    9306           0 : 
    9307             : nsDisplayMask::nsDisplayMask(nsDisplayListBuilder* aBuilder,
    9308           0 :                              nsIFrame* aFrame, nsDisplayList* aList,
    9309           0 :                              bool aHandleOpacity,
    9310           0 :                              const ActiveScrolledRoot* aActiveScrolledRoot)
    9311           0 :   : nsDisplaySVGEffects(aBuilder, aFrame, aList, aHandleOpacity, aActiveScrolledRoot, true)
    9312           0 : {
    9313           0 :   MOZ_COUNT_CTOR(nsDisplayMask);
    9314           0 : 
    9315             :   nsPresContext* presContext = mFrame->PresContext();
    9316             :   uint32_t flags = aBuilder->GetBackgroundPaintFlags() |
    9317             :                    nsCSSRendering::PAINTBG_MASK_IMAGE;
    9318             :   const nsStyleSVGReset *svgReset = aFrame->StyleSVGReset();
    9319           0 :   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
    9320           0 :     if (!svgReset->mMask.mLayers[i].mImage.IsResolved()) {
    9321             :       continue;
    9322           0 :     }
    9323           0 :     bool isTransformedFixed;
    9324             :     nsBackgroundLayerState state =
    9325           0 :       nsCSSRendering::PrepareImageLayer(presContext, aFrame, flags,
    9326             :                                         mFrame->GetRectRelativeToSelf(),
    9327             :                                         mFrame->GetRectRelativeToSelf(),
    9328           0 :                                         svgReset->mMask.mLayers[i],
    9329             :                                         &isTransformedFixed);
    9330           0 :     mDestRects.AppendElement(state.mDestArea);
    9331           0 :   }
    9332             : }
    9333             : 
    9334             : #ifdef NS_BUILD_REFCNT_LOGGING
    9335           0 : nsDisplayMask::~nsDisplayMask()
    9336             : {
    9337             :   MOZ_COUNT_DTOR(nsDisplayMask);
    9338             : }
    9339           0 : #endif
    9340             : 
    9341             : static bool
    9342             : CanMergeDisplayMaskFrame(nsIFrame* aFrame)
    9343             : {
    9344             :   // Do not merge items for box-decoration-break:clone elements,
    9345             :   // since each box should have its own mask in that case.
    9346           0 :   if (aFrame->StyleBorder()->mBoxDecorationBreak ==
    9347             :         mozilla::StyleBoxDecorationBreak::Clone) {
    9348             :     return false;
    9349             :   }
    9350           0 : 
    9351             :   // Do not merge if either frame has a mask. Continuation frames should apply
    9352             :   // the mask independently (just like nsDisplayBackgroundImage).
    9353             :   if (aFrame->StyleSVGReset()->HasMask()) {
    9354           0 :     return false;
    9355             :   }
    9356             : 
    9357             :   return true;
    9358           0 : }
    9359             : 
    9360             : bool
    9361             : nsDisplayMask::CanMerge(const nsDisplayItem* aItem) const
    9362           0 : {
    9363           0 :   // Items for the same content element should be merged into a single
    9364             :   // compositing group.
    9365             :   if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
    9366             :     return false;
    9367           0 :   }
    9368             : 
    9369             :   return CanMergeDisplayMaskFrame(mFrame) &&
    9370             :          CanMergeDisplayMaskFrame(aItem->Frame());
    9371           0 : }
    9372             : 
    9373             : already_AddRefed<Layer>
    9374             : nsDisplayMask::BuildLayer(nsDisplayListBuilder* aBuilder,
    9375           0 :                           LayerManager* aManager,
    9376             :                           const ContainerLayerParameters& aContainerParameters)
    9377             : {
    9378             :   if (!ValidateSVGFrame()) {
    9379             :     return nullptr;
    9380           0 :   }
    9381             : 
    9382           0 :   if (mFrame->StyleEffects()->mOpacity == 0.0f && mHandleOpacity) {
    9383             :     return nullptr;
    9384           0 :   }
    9385           0 : 
    9386             :   nsIFrame* firstFrame =
    9387             :     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
    9388             :   SVGObserverUtils::EffectProperties effectProperties =
    9389             :     SVGObserverUtils::GetEffectProperties(firstFrame);
    9390           0 : 
    9391           0 :   if (effectProperties.HasInvalidClipPath() ||
    9392             :       effectProperties.HasInvalidMask()) {
    9393           0 :     return nullptr;
    9394             :   }
    9395             : 
    9396             :   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
    9397           0 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    9398             :                            aContainerParameters, nullptr);
    9399             : 
    9400           0 :   return container.forget();
    9401             : }
    9402           0 : 
    9403             : bool
    9404           0 : nsDisplayMask::PaintMask(nsDisplayListBuilder* aBuilder,
    9405           0 :                          gfxContext* aMaskContext)
    9406             : {
    9407             :   MOZ_ASSERT(aMaskContext->GetDrawTarget()->GetFormat() == SurfaceFormat::A8);
    9408             : 
    9409             :   imgDrawingParams imgParmas(aBuilder->ShouldSyncDecodeImages()
    9410           0 :                              ? imgIContainer::FLAG_SYNC_DECODE
    9411           0 :                              : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
    9412           0 :   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
    9413             :   nsSVGIntegrationUtils::PaintFramesParams params(*aMaskContext,
    9414           0 :                                                   mFrame,  GetBuildingRect(),
    9415             :                                                   borderArea, aBuilder,
    9416           0 :                                                   nullptr,
    9417             :                                                   mHandleOpacity, imgParmas);
    9418             :   ComputeMaskGeometry(params);
    9419             :   nsSVGIntegrationUtils::PaintMask(params);
    9420           0 : 
    9421             :   nsDisplayMaskGeometry::UpdateDrawResult(this, imgParmas.result);
    9422             : 
    9423             :   return imgParmas.result == mozilla::image::ImgDrawResult::SUCCESS;
    9424           0 : }
    9425           0 : 
    9426           0 : LayerState
    9427             : nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
    9428             :                              LayerManager* aManager,
    9429             :                              const ContainerLayerParameters& aParameters)
    9430             : {
    9431             :   if (CanPaintOnMaskLayer(aManager)) {
    9432           0 :     LayerState result = RequiredLayerStateForChildren(aBuilder, aManager,
    9433             :         aParameters, mList, GetAnimatedGeometryRoot());
    9434             :     // When we're not active, FrameLayerBuilder will call PaintAsLayer()
    9435             :     // on us during painting. In that case we don't want a mask layer to
    9436             :     // be created, because PaintAsLayer() takes care of applying the mask.
    9437             :     // So we return LAYER_SVG_EFFECTS instead of LAYER_INACTIVE so that
    9438           0 :     // FrameLayerBuilder doesn't set a mask layer on our layer.
    9439             :     return result == LAYER_INACTIVE ? LAYER_SVG_EFFECTS : result;
    9440           0 :   }
    9441             : 
    9442             :   return LAYER_SVG_EFFECTS;
    9443             : }
    9444           0 : 
    9445             : bool nsDisplayMask::CanPaintOnMaskLayer(LayerManager* aManager)
    9446             : {
    9447             :   if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
    9448           0 :     return false;
    9449             :   }
    9450             : 
    9451           0 :   if (gfxPrefs::DrawMaskLayer()) {
    9452             :     return false;
    9453             :   }
    9454             : 
    9455             :   return true;
    9456           0 : }
    9457           0 : 
    9458           0 : bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    9459           0 :                                       nsRegion* aVisibleRegion)
    9460             : {
    9461             :   // Our children may be made translucent or arbitrarily deformed so we should
    9462             :   // not allow them to subtract area from aVisibleRegion.
    9463           0 :   nsRegion childrenVisible(GetPaintRect());
    9464             :   nsRect r = GetPaintRect().Intersect(mList.GetBounds(aBuilder));
    9465             :   mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
    9466             :   return true;
    9467           0 : }
    9468           0 : 
    9469             : void
    9470             : nsDisplayMask::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    9471           0 :                                          const nsDisplayItemGeometry* aGeometry,
    9472             :                                          nsRegion* aInvalidRegion) const
    9473           0 : {
    9474             :   nsDisplaySVGEffects::ComputeInvalidationRegion(aBuilder, aGeometry,
    9475           0 :                                                  aInvalidRegion);
    9476           0 : 
    9477           0 :   const nsDisplayMaskGeometry* geometry =
    9478             :     static_cast<const nsDisplayMaskGeometry*>(aGeometry);
    9479             :   bool snap;
    9480           0 :   nsRect bounds = GetBounds(aBuilder, &snap);
    9481           0 : 
    9482             :   if (mFrame->StyleEffects()->mOpacity != geometry->mOpacity ||
    9483           0 :       mHandleOpacity != geometry->mHandleOpacity) {
    9484           0 :     aInvalidRegion->Or(*aInvalidRegion, bounds);
    9485           0 :   }
    9486           0 : 
    9487             :   if (mDestRects.Length() != geometry->mDestRects.Length()) {
    9488             :     aInvalidRegion->Or(bounds, geometry->mBounds);
    9489             :   } else {
    9490             :     for (size_t i = 0; i < mDestRects.Length(); i++) {
    9491           0 :       if (!mDestRects[i].IsEqualInterior(geometry->mDestRects[i])) {
    9492           0 :         aInvalidRegion->Or(bounds, geometry->mBounds);
    9493           0 :         break;
    9494           0 :       }
    9495           0 :     }
    9496           0 :   }
    9497           0 : 
    9498           0 :   if (aBuilder->ShouldSyncDecodeImages() &&
    9499             :       geometry->ShouldInvalidateToSyncDecodeImages()) {
    9500             :     const nsStyleSVGReset *svgReset = mFrame->StyleSVGReset();
    9501             :     NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, svgReset->mMask) {
    9502           0 :       const nsStyleImage& image = svgReset->mMask.mLayers[i].mImage;
    9503             :       if (image.GetType() == eStyleImageType_Image ) {
    9504             :         aInvalidRegion->Or(*aInvalidRegion, bounds);
    9505           0 :         break;
    9506             :       }
    9507             :     }
    9508             :   }
    9509             : }
    9510             : 
    9511           0 : void
    9512             : nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
    9513             :                             gfxContext* aCtx,
    9514           0 :                             LayerManager* aManager)
    9515           0 : {
    9516           0 :   // Clip the drawing target by mVisibleRect, which contains the visible
    9517             :   // region of the target frame and its out-of-flow and inflow descendants.
    9518           0 :   gfxContext* context = aCtx;
    9519             : 
    9520           0 :   Rect bounds =
    9521           0 :     NSRectToRect(GetPaintRect(), mFrame->PresContext()->AppUnitsPerDevPixel());
    9522             :   bounds.RoundOut();
    9523             :   context->Clip(bounds);
    9524             : 
    9525             :   imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
    9526           0 :                              ? imgIContainer::FLAG_SYNC_DECODE
    9527             :                              : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
    9528           0 :   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
    9529             :   nsSVGIntegrationUtils::PaintFramesParams params(*aCtx,
    9530           0 :                                                   mFrame,  GetPaintRect(),
    9531             :                                                   borderArea, aBuilder,
    9532           0 :                                                   aManager,
    9533             :                                                   mHandleOpacity, imgParams);
    9534           0 : 
    9535           0 :   ComputeMaskGeometry(params);
    9536             : 
    9537             :   nsSVGIntegrationUtils::PaintMaskAndClipPath(params);
    9538           0 : 
    9539             :   context->PopClip();
    9540             : 
    9541             :   nsDisplayMaskGeometry::UpdateDrawResult(this, imgParams.result);
    9542             : }
    9543             : 
    9544             : bool
    9545           0 : nsDisplayMask::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    9546           0 :                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
    9547           0 :                                        const StackingContextHelper& aSc,
    9548             :                                        mozilla::layers::WebRenderLayerManager* aManager,
    9549           0 :                                        nsDisplayListBuilder* aDisplayListBuilder)
    9550             : {
    9551           0 :   bool snap;
    9552           0 :   float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    9553           0 :   nsRect displayBound = GetBounds(aDisplayListBuilder, &snap);
    9554           0 :   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(displayBound, appUnitsPerDevPixel);
    9555           0 : 
    9556             :   Maybe<wr::WrImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(this, aBuilder, aResources,
    9557           0 :                                                                             aSc, aDisplayListBuilder,
    9558             :                                                                             bounds);
    9559             :   Maybe<StackingContextHelper> layer;
    9560             :   const StackingContextHelper* sc = &aSc;
    9561             :   if (mask) {
    9562             :     auto layoutBounds = wr::ToRoundedLayoutRect(bounds);
    9563           0 :     wr::WrClipId clipId = aBuilder.DefineClip(Nothing(),
    9564             :         layoutBounds, nullptr, mask.ptr());
    9565           0 : 
    9566             :     // Create a new stacking context to attach the mask to, ensuring the mask is
    9567           0 :     // applied to the aggregate, and not the individual elements.
    9568             : 
    9569             :     // The stacking context shouldn't have any offset.
    9570             :     bounds.MoveTo(0, 0);
    9571             : 
    9572             :     layer.emplace(aSc,
    9573             :                   aBuilder,
    9574             :                   /*aFilters: */ nsTArray<wr::WrFilterOp>(),
    9575             :                   /*aBounds: */ bounds,
    9576             :                   /*aBoundTransform: */ nullptr,
    9577             :                   /*aAnimation: */ nullptr,
    9578           0 :                   /*aOpacity: */ nullptr,
    9579           0 :                   /*aTransform: */ nullptr,
    9580           0 :                   /*aPerspective: */ nullptr,
    9581             :                   /*aMixBlendMode: */ gfx::CompositionOp::OP_OVER,
    9582             :                   /*aBackfaceVisible: */ true,
    9583           0 :                   /*aIsPreserve3D: */ false,
    9584             :                   /*aTransformForScrollData: */ Nothing(),
    9585           0 :                   /*aClipNodeId: */ &clipId);
    9586           0 :     sc = layer.ptr();
    9587             :     aManager->CommandBuilder().PushOverrideForASR(GetActiveScrolledRoot(), Some(clipId));
    9588             :   }
    9589           0 : 
    9590             :   nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, *sc, aManager, aDisplayListBuilder);
    9591             : 
    9592             :   if (mask) {
    9593           0 :     aManager->CommandBuilder().PopOverrideForASR(GetActiveScrolledRoot());
    9594             :   }
    9595             : 
    9596           0 :   return true;
    9597           0 : }
    9598             : 
    9599             : Maybe<nsRect>
    9600             : nsDisplayMask::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
    9601             :                                        const ActiveScrolledRoot* aASR) const
    9602           0 : {
    9603           0 :   if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
    9604           0 :     return Some(clip->GetClipRect());
    9605             :   }
    9606             :   // This item does not have a clip with respect to |aASR|. However, we
    9607           0 :   // might still have finite bounds with respect to |aASR|. Check our
    9608           0 :   // children.
    9609             :   nsDisplayList* childList = GetSameCoordinateSystemChildren();
    9610             :   if (childList) {
    9611             :     return Some(childList->GetClippedBoundsWithRespectToASR(aBuilder, aASR));
    9612             :   }
    9613             : #ifdef DEBUG
    9614             :   if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
    9615             :     MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
    9616             :   }
    9617             : #endif
    9618           0 :   return Nothing();
    9619             : }
    9620             : 
    9621           0 : 
    9622             : 
    9623           0 : #ifdef MOZ_DUMP_PAINTING
    9624           0 : void
    9625           0 : nsDisplayMask::PrintEffects(nsACString& aTo)
    9626           0 : {
    9627           0 :   nsIFrame* firstFrame =
    9628           0 :     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
    9629           0 :   SVGObserverUtils::EffectProperties effectProperties =
    9630             :     SVGObserverUtils::GetEffectProperties(firstFrame);
    9631           0 :   nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame();
    9632           0 :   bool first = true;
    9633           0 :   aTo += " effects=(";
    9634             :   if (mFrame->StyleEffects()->mOpacity != 1.0f && mHandleOpacity) {
    9635           0 :     first = false;
    9636           0 :     aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
    9637             :   }
    9638           0 :   if (clipPathFrame) {
    9639           0 :     if (!first) {
    9640           0 :       aTo += ", ";
    9641           0 :     }
    9642             :     aTo += nsPrintfCString("clip(%s)", clipPathFrame->IsTrivial() ? "trivial" : "non-trivial");
    9643           0 :     first = false;
    9644           0 :   }
    9645             :   const nsStyleSVGReset *style = mFrame->StyleSVGReset();
    9646             :   if (style->HasClipPath() && !clipPathFrame) {
    9647           0 :     if (!first) {
    9648           0 :       aTo += ", ";
    9649           0 :     }
    9650           0 :     aTo += "clip(basic-shape)";
    9651             :     first = false;
    9652           0 :   }
    9653             : 
    9654           0 :   nsTArray<nsSVGMaskFrame*> masks = effectProperties.GetMaskFrames();
    9655           0 :   if (!masks.IsEmpty() && masks[0]) {
    9656             :     if (!first) {
    9657             :       aTo += ", ";
    9658           0 :     }
    9659             :     aTo += "mask";
    9660           0 :   }
    9661             :   aTo += ")";
    9662           0 : }
    9663             : #endif
    9664           0 : 
    9665           0 : nsDisplayFilter::nsDisplayFilter(nsDisplayListBuilder* aBuilder,
    9666             :                                  nsIFrame* aFrame, nsDisplayList* aList,
    9667             :                                  bool aHandleOpacity)
    9668           0 :   : nsDisplaySVGEffects(aBuilder, aFrame, aList, aHandleOpacity),
    9669             :     mEffectsBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
    9670           0 : {
    9671           0 :   MOZ_COUNT_CTOR(nsDisplayFilter);
    9672             : }
    9673             : 
    9674             : #ifdef NS_BUILD_REFCNT_LOGGING
    9675           0 : nsDisplayFilter::~nsDisplayFilter()
    9676             : {
    9677             :   MOZ_COUNT_DTOR(nsDisplayFilter);
    9678             : }
    9679           0 : #endif
    9680             : 
    9681             : already_AddRefed<Layer>
    9682             : nsDisplayFilter::BuildLayer(nsDisplayListBuilder* aBuilder,
    9683           0 :                            LayerManager* aManager,
    9684             :                            const ContainerLayerParameters& aContainerParameters)
    9685             : {
    9686             :   if (!ValidateSVGFrame()) {
    9687             :     return nullptr;
    9688           0 :   }
    9689             : 
    9690           0 :   if (mFrame->StyleEffects()->mOpacity == 0.0f && mHandleOpacity) {
    9691             :     return nullptr;
    9692           0 :   }
    9693             : 
    9694             :   nsIFrame* firstFrame =
    9695             :     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
    9696           0 :   SVGObserverUtils::EffectProperties effectProperties =
    9697             :     SVGObserverUtils::GetEffectProperties(firstFrame);
    9698             : 
    9699           0 :   if (effectProperties.HasInvalidFilter()) {
    9700           0 :     return nullptr;
    9701             :   }
    9702             : 
    9703           0 :   MOZ_ASSERT(effectProperties.mFilter && mFrame->StyleEffects()->HasFilters(),
    9704           0 :              "By getting here, we must have valid CSS filters.");
    9705           0 : 
    9706             :   ContainerLayerParameters newContainerParameters = aContainerParameters;
    9707             :   newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
    9708             : 
    9709           0 :   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
    9710             :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    9711             :                            newContainerParameters, nullptr);
    9712             :   return container.forget();
    9713           0 : }
    9714             : 
    9715             : LayerState
    9716             : nsDisplayFilter::GetLayerState(nsDisplayListBuilder* aBuilder,
    9717           0 :                                LayerManager* aManager,
    9718             :                                const ContainerLayerParameters& aParameters)
    9719             : {
    9720           0 :   return LAYER_SVG_EFFECTS;
    9721             : }
    9722           0 : 
    9723           0 : bool
    9724           0 : nsDisplayFilter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    9725             :                                    nsRegion* aVisibleRegion)
    9726             : {
    9727             :   nsPoint offset = ToReferenceFrame();
    9728           0 :   nsRect dirtyRect =
    9729             :     nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mFrame,
    9730           0 :                                                            GetPaintRect() - offset) +
    9731           0 :     offset;
    9732           0 : 
    9733             :   // Our children may be made translucent or arbitrarily deformed so we should
    9734             :   // not allow them to subtract area from aVisibleRegion.
    9735             :   nsRegion childrenVisible(dirtyRect);
    9736           0 :   nsRect r = dirtyRect.Intersect(
    9737             :     mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot));
    9738             :   mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
    9739             :   return true;
    9740           0 : }
    9741           0 : 
    9742             : void
    9743             : nsDisplayFilter::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
    9744           0 :                                            const nsDisplayItemGeometry* aGeometry,
    9745             :                                            nsRegion* aInvalidRegion) const
    9746           0 : {
    9747           0 :   nsDisplaySVGEffects::ComputeInvalidationRegion(aBuilder, aGeometry,
    9748             :                                                  aInvalidRegion);
    9749           0 : 
    9750           0 :   const nsDisplayFilterGeometry* geometry =
    9751             :     static_cast<const nsDisplayFilterGeometry*>(aGeometry);
    9752           0 : 
    9753             :   if (aBuilder->ShouldSyncDecodeImages() &&
    9754             :       geometry->ShouldInvalidateToSyncDecodeImages()) {
    9755           0 :     bool snap;
    9756             :     nsRect bounds = GetBounds(aBuilder, &snap);
    9757             :     aInvalidRegion->Or(*aInvalidRegion, bounds);
    9758             :   }
    9759           0 : }
    9760             : 
    9761           0 : void
    9762           0 : nsDisplayFilter::PaintAsLayer(nsDisplayListBuilder* aBuilder,
    9763             :                               gfxContext* aCtx,
    9764             :                               LayerManager* aManager)
    9765             : {
    9766             :   imgDrawingParams imgParams(aBuilder->ShouldSyncDecodeImages()
    9767           0 :                              ? imgIContainer::FLAG_SYNC_DECODE
    9768           0 :                              : imgIContainer::FLAG_SYNC_DECODE_IF_FAST);
    9769           0 :   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
    9770           0 :   nsSVGIntegrationUtils::PaintFramesParams params(*aCtx,
    9771             :                                                   mFrame,  GetPaintRect(),
    9772             :                                                   borderArea, aBuilder,
    9773           0 :                                                   aManager,
    9774             :                                                   mHandleOpacity, imgParams);
    9775             :   nsSVGIntegrationUtils::PaintFilter(params);
    9776           0 :   nsDisplayFilterGeometry::UpdateDrawResult(this, imgParams.result);
    9777             : }
    9778             : 
    9779             : static float
    9780           0 : ClampStdDeviation(float aStdDeviation)
    9781             : {
    9782             :   // Cap software blur radius for performance reasons.
    9783             :   return std::min(std::max(0.0f, aStdDeviation), 100.0f);
    9784             : }
    9785             : 
    9786           0 : bool
    9787             : nsDisplayFilter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    9788             :                                          mozilla::wr::IpcResourceUpdateQueue& aResources,
    9789             :                                          const StackingContextHelper& aSc,
    9790             :                                          mozilla::layers::WebRenderLayerManager* aManager,
    9791             :                                          nsDisplayListBuilder* aDisplayListBuilder)
    9792             : {
    9793           0 :   if (mFrame->IsFrameOfType(nsIFrame::eSVG)) {
    9794           0 :     return false;
    9795           0 :   }
    9796           0 : 
    9797             :   // Due to differences in the way that WebRender filters operate
    9798             :   // only the brightness and contrast filters use that path. We
    9799             :   // can gradually enable more filters as WebRender bugs are fixed.
    9800             :   nsTArray<mozilla::wr::WrFilterOp> wrFilters;
    9801             :   const nsTArray<nsStyleFilter>& filters = mFrame->StyleEffects()->mFilters;
    9802             :   for (const nsStyleFilter& filter : filters) {
    9803             :     switch (filter.GetType()) {
    9804             :       case NS_STYLE_FILTER_BRIGHTNESS:
    9805           0 :       case NS_STYLE_FILTER_CONTRAST:
    9806           0 :       case NS_STYLE_FILTER_GRAYSCALE:
    9807           0 :       case NS_STYLE_FILTER_INVERT:
    9808           0 :       case NS_STYLE_FILTER_OPACITY:
    9809             :       case NS_STYLE_FILTER_SATURATE:
    9810             :       case NS_STYLE_FILTER_SEPIA: {
    9811             :         mozilla::wr::WrFilterOp filterOp = {
    9812             :           wr::ToWrFilterOpType(filter.GetType()),
    9813           0 :           filter.GetFilterParameter().GetFactorOrPercentValue(),
    9814           0 :         };
    9815           0 :         wrFilters.AppendElement(filterOp);
    9816           0 :         break;
    9817             :       }
    9818             :     case NS_STYLE_FILTER_HUE_ROTATE: {
    9819             :         mozilla::wr::WrFilterOp filterOp = {
    9820           0 :           wr::ToWrFilterOpType(filter.GetType()),
    9821             :           (float)filter.GetFilterParameter().GetAngleValueInDegrees(),
    9822           0 :         };
    9823           0 :         wrFilters.AppendElement(filterOp);
    9824             :         break;
    9825           0 :       }
    9826             :       case NS_STYLE_FILTER_BLUR: {
    9827           0 :         float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    9828           0 :         mozilla::wr::WrFilterOp filterOp = {
    9829             :           wr::ToWrFilterOpType(filter.GetType()),
    9830             :           ClampStdDeviation(
    9831             :             NSAppUnitsToFloatPixels(
    9832           0 :               filter.GetFilterParameter().GetCoordValue(),
    9833           0 :               appUnitsPerDevPixel)),
    9834           0 :         };
    9835           0 :         wrFilters.AppendElement(filterOp);
    9836           0 :         break;
    9837             :       }
    9838             :       case NS_STYLE_FILTER_DROP_SHADOW: {
    9839           0 :         float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
    9840           0 :         nsCSSShadowArray* shadows = filter.GetDropShadow();
    9841           0 :         if (!shadows || shadows->Length() != 1) {
    9842           0 :           NS_NOTREACHED("Exactly one drop shadow should have been parsed.");
    9843             :           return false;
    9844             :         }
    9845             : 
    9846           0 :         nsCSSShadowItem* shadow = shadows->ShadowAt(0);
    9847           0 :         nscolor color = shadow->mColor;
    9848             :         if (!shadow->mHasColor) {
    9849           0 :           color = mFrame->StyleColor()->mColor;
    9850           0 :         }
    9851             : 
    9852             :         mozilla::wr::WrFilterOp filterOp = {
    9853           0 :           wr::ToWrFilterOpType(filter.GetType()),
    9854           0 :           NSAppUnitsToFloatPixels(shadow->mRadius, appUnitsPerDevPixel),
    9855           0 :           {
    9856           0 :             NSAppUnitsToFloatPixels(shadow->mXOffset, appUnitsPerDevPixel),
    9857             :             NSAppUnitsToFloatPixels(shadow->mYOffset, appUnitsPerDevPixel),
    9858           0 :           },
    9859             :           {
    9860           0 :             NS_GET_R(color) / 255.0f,
    9861           0 :             NS_GET_G(color) / 255.0f,
    9862             :             NS_GET_B(color) / 255.0f,
    9863             :             NS_GET_A(color) / 255.0f,
    9864             :           }
    9865             :         };
    9866             : 
    9867             :         wrFilters.AppendElement(filterOp);
    9868           0 :         break;
    9869           0 :       }
    9870           0 :       default:
    9871             :         return false;
    9872           0 :     }
    9873             :   }
    9874             : 
    9875             :   float opacity = mFrame->StyleEffects()->mOpacity;
    9876             :   StackingContextHelper sc(aSc, aBuilder, wrFilters, LayoutDeviceRect(), nullptr,
    9877             :                            nullptr, opacity != 1.0f && mHandleOpacity ? &opacity : nullptr);
    9878           0 : 
    9879             :   nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, sc, aManager, aDisplayListBuilder);
    9880             :   return true;
    9881           0 : }
    9882             : 
    9883           0 : #ifdef MOZ_DUMP_PAINTING
    9884           0 : void
    9885           0 : nsDisplayFilter::PrintEffects(nsACString& aTo)
    9886           0 : {
    9887           0 :   nsIFrame* firstFrame =
    9888           0 :     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
    9889             :   SVGObserverUtils::EffectProperties effectProperties =
    9890           0 :     SVGObserverUtils::GetEffectProperties(firstFrame);
    9891           0 :   bool first = true;
    9892           0 :   aTo += " effects=(";
    9893             :   if (mFrame->StyleEffects()->mOpacity != 1.0f && mHandleOpacity) {
    9894           0 :     first = false;
    9895             :     aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
    9896           0 :   }
    9897           0 :   if (effectProperties.HasValidFilter()) {
    9898             :     if (!first) {
    9899             :       aTo += ", ";
    9900          11 :     }
    9901           0 :     aTo += "filter";
    9902          11 :   }
    9903             :   aTo += ")";
    9904          11 : }
    9905           0 : #endif
    9906             : 
    9907             : nsDisplaySVGWrapper::nsDisplaySVGWrapper(nsDisplayListBuilder* aBuilder,
    9908           0 :                                          nsIFrame* aFrame, nsDisplayList* aList)
    9909           0 :     : nsDisplayWrapList(aBuilder, aFrame, aList)
    9910          11 : {
    9911             :   MOZ_COUNT_CTOR(nsDisplaySVGWrapper);
    9912             : }
    9913             : 
    9914           0 : #ifdef NS_BUILD_REFCNT_LOGGING
    9915             : nsDisplaySVGWrapper::~nsDisplaySVGWrapper() {
    9916             :   MOZ_COUNT_DTOR(nsDisplaySVGWrapper);
    9917             : }
    9918           0 : #endif
    9919          11 : 
    9920             : LayerState
    9921             : nsDisplaySVGWrapper::GetLayerState(nsDisplayListBuilder* aBuilder,
    9922           0 :                                    LayerManager* aManager,
    9923             :                                    const ContainerLayerParameters& aParameters)
    9924             : {
    9925             :   RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager();
    9926           0 :   if (layerManager && layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
    9927             :     return LAYER_ACTIVE_FORCE;
    9928          22 :   }
    9929           0 :   return LAYER_NONE;
    9930             : }
    9931             : 
    9932           0 : bool
    9933             : nsDisplaySVGWrapper::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
    9934             : {
    9935             :   RefPtr<LayerManager> layerManager = aBuilder->GetWidgetLayerManager();
    9936           0 :   if (layerManager && layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
    9937             :     return false;
    9938             :   }
    9939             :   return true;
    9940           0 : }
    9941           0 : 
    9942             : already_AddRefed<Layer>
    9943             : nsDisplaySVGWrapper::BuildLayer(nsDisplayListBuilder* aBuilder,
    9944           0 :                                 LayerManager* aManager,
    9945           0 :                                 const ContainerLayerParameters& aContainerParameters)
    9946             : {
    9947           0 :   ContainerLayerParameters newContainerParameters = aContainerParameters;
    9948             :   newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true;
    9949             : 
    9950             :   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
    9951           0 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
    9952             :                            newContainerParameters, nullptr);
    9953             : 
    9954             :   return container.forget();
    9955             : }
    9956             : 
    9957           0 : bool
    9958           0 : nsDisplaySVGWrapper::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
    9959             :                                              mozilla::wr::IpcResourceUpdateQueue& aResources,
    9960             :                                              const StackingContextHelper& aSc,
    9961             :                                              mozilla::layers::WebRenderLayerManager* aManager,
    9962           0 :                                              nsDisplayListBuilder* aDisplayListBuilder)
    9963             : {
    9964             :   if (gfxPrefs::WebRenderBlobInvalidation()) {
    9965             :     return nsDisplayWrapList::CreateWebRenderCommands(aBuilder,
    9966             :                                              aResources,
    9967             :                                              aSc,
    9968             :                                              aManager,
    9969             :                                              aDisplayListBuilder);
    9970             :   } else {
    9971             :     return false;
    9972             :   }
    9973             : }
    9974             : 
    9975             : namespace mozilla {
    9976           0 : 
    9977             : uint32_t PaintTelemetry::sPaintLevel = 0;
    9978             : uint32_t PaintTelemetry::sMetricLevel = 0;
    9979           0 : EnumeratedArray<PaintTelemetry::Metric,
    9980             :                 PaintTelemetry::Metric::COUNT,
    9981             :                 double> PaintTelemetry::sMetrics;
    9982             : 
    9983             : PaintTelemetry::AutoRecordPaint::AutoRecordPaint()
    9984         147 : {
    9985           1 :   // Don't record nested paints.
    9986             :   if (sPaintLevel++ > 0) {
    9987          21 :     return;
    9988             :   }
    9989             : 
    9990          21 :   // Reset metrics for a new paint.
    9991             :   for (auto& metric : sMetrics) {
    9992          21 :     metric = 0.0;
    9993          21 :   }
    9994             :   mStart = TimeStamp::Now();
    9995             : }
    9996             : 
    9997             : PaintTelemetry::AutoRecordPaint::~AutoRecordPaint()
    9998             : {
    9999          21 :   MOZ_ASSERT(sPaintLevel != 0);
   10000             :   if (--sPaintLevel > 0) {
   10001             :     return;
   10002             :   }
   10003           0 : 
   10004             :   // If we're in multi-process mode, don't include paint times for the parent
   10005             :   // process.
   10006           0 :   if (gfxVars::BrowserTabsRemoteAutostart() && XRE_IsParentProcess()) {
   10007             :     return;
   10008             :   }
   10009           0 : 
   10010           0 :   double totalMs = (TimeStamp::Now() - mStart).ToMilliseconds();
   10011           0 : 
   10012           0 :   // Record the total time.
   10013           0 :   Telemetry::Accumulate(Telemetry::CONTENT_PAINT_TIME, static_cast<uint32_t>(totalMs));
   10014           0 : 
   10015           0 :   // Helpers for recording large/small paints.
   10016           0 :   auto recordLarge = [=](const nsCString& aKey, double aDurationMs) -> void {
   10017           0 :     MOZ_ASSERT(aDurationMs <= totalMs);
   10018           0 :     uint32_t amount = static_cast<int32_t>((aDurationMs / totalMs) * 100.0);
   10019             :     Telemetry::Accumulate(Telemetry::CONTENT_LARGE_PAINT_PHASE_WEIGHT, aKey, amount);
   10020           0 :   };
   10021           0 :   auto recordSmall = [=](const nsCString& aKey, double aDurationMs) -> void {
   10022           0 :     MOZ_ASSERT(aDurationMs <= totalMs);
   10023             :     uint32_t amount = static_cast<int32_t>((aDurationMs / totalMs) * 100.0);
   10024             :     Telemetry::Accumulate(Telemetry::CONTENT_SMALL_PAINT_PHASE_WEIGHT, aKey, amount);
   10025             :   };
   10026           0 : 
   10027           0 :   double dlMs = sMetrics[Metric::DisplayList];
   10028           0 :   double flbMs = sMetrics[Metric::Layerization];
   10029           0 :   double rMs = sMetrics[Metric::Rasterization];
   10030             : 
   10031           0 :   // If the total time was >= 16ms, then it's likely we missed a frame due to
   10032           0 :   // painting. We bucket these metrics separately.
   10033           0 :   if (totalMs >= 16.0) {
   10034             :     recordLarge(NS_LITERAL_CSTRING("dl"), dlMs);
   10035          21 :     recordLarge(NS_LITERAL_CSTRING("flb"), flbMs);
   10036             :     recordLarge(NS_LITERAL_CSTRING("r"), rMs);
   10037           1 :   } else {
   10038          92 :     recordSmall(NS_LITERAL_CSTRING("dl"), dlMs);
   10039             :     recordSmall(NS_LITERAL_CSTRING("flb"), flbMs);
   10040             :     recordSmall(NS_LITERAL_CSTRING("r"), rMs);
   10041           1 :   }
   10042             : }
   10043             : 
   10044             : PaintTelemetry::AutoRecord::AutoRecord(Metric aMetric)
   10045             :  : mMetric(aMetric)
   10046          24 : {
   10047             :   // Don't double-record anything nested.
   10048             :   if (sMetricLevel++ > 0) {
   10049             :     return;
   10050           1 :   }
   10051             : 
   10052             :   // Don't record inside nested paints, or outside of paints.
   10053          70 :   if (sPaintLevel != 1) {
   10054             :     return;
   10055           1 :   }
   10056             : 
   10057          46 :   mStart = TimeStamp::Now();
   10058           1 : }
   10059             : 
   10060             : PaintTelemetry::AutoRecord::~AutoRecord()
   10061             : {
   10062           1 :   MOZ_ASSERT(sMetricLevel != 0);
   10063           1 : 
   10064             :   sMetricLevel--;
   10065             :   if (mStart.IsNull()) {
   10066             :     return;
   10067             :   }
   10068             : 
   10069             :   sMetrics[mMetric] += (TimeStamp::Now() - mStart).ToMilliseconds();
   10070             : }
   10071             : 
   10072             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952