LCOV - code coverage report
Current view: top level - layout/painting - nsDisplayList.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1782 4227 42.2 %
Date: 2017-07-14 16:53:18 Functions: 210 414 50.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13