LCOV - code coverage report
Current view: top level - gfx/layers/basic - BasicLayerManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 229 461 49.7 %
Date: 2017-07-14 16:53:18 Functions: 23 34 67.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include <stdint.h>                     // for uint32_t
       7             : #include <stdlib.h>                     // for rand, RAND_MAX
       8             : #include <sys/types.h>                  // for int32_t
       9             : #include <stack>                        // for stack
      10             : #include "BasicContainerLayer.h"        // for BasicContainerLayer
      11             : #include "BasicLayersImpl.h"            // for ToData, BasicReadbackLayer, etc
      12             : #include "GeckoProfiler.h"              // for AUTO_PROFILER_LABEL
      13             : #include "ImageContainer.h"             // for ImageFactory
      14             : #include "Layers.h"                     // for Layer, ContainerLayer, etc
      15             : #include "ReadbackLayer.h"              // for ReadbackLayer
      16             : #include "ReadbackProcessor.h"          // for ReadbackProcessor
      17             : #include "RenderTrace.h"                // for RenderTraceLayers, etc
      18             : #include "basic/BasicImplData.h"        // for BasicImplData
      19             : #include "basic/BasicLayers.h"          // for BasicLayerManager, etc
      20             : #include "gfxASurface.h"                // for gfxASurface, etc
      21             : #include "gfxContext.h"                 // for gfxContext, etc
      22             : #include "gfxImageSurface.h"            // for gfxImageSurface
      23             : #include "gfxMatrix.h"                  // for gfxMatrix
      24             : #include "gfxPlatform.h"                // for gfxPlatform
      25             : #include "gfxPrefs.h"                   // for gfxPrefs
      26             : #include "gfxPoint.h"                   // for IntSize, gfxPoint
      27             : #include "gfxRect.h"                    // for gfxRect
      28             : #include "gfxUtils.h"                   // for gfxUtils
      29             : #include "gfx2DGlue.h"                  // for thebes --> moz2d transition
      30             : #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
      31             : #include "mozilla/WidgetUtils.h"        // for ScreenRotation
      32             : #include "mozilla/gfx/2D.h"             // for DrawTarget
      33             : #include "mozilla/gfx/BasePoint.h"      // for BasePoint
      34             : #include "mozilla/gfx/BaseRect.h"       // for BaseRect
      35             : #include "mozilla/gfx/Matrix.h"         // for Matrix
      36             : #include "mozilla/gfx/PathHelpers.h"
      37             : #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
      38             : #include "mozilla/layers/LayersTypes.h"  // for BufferMode::BUFFER_NONE, etc
      39             : #include "mozilla/mozalloc.h"           // for operator new
      40             : #include "nsCOMPtr.h"                   // for already_AddRefed
      41             : #include "nsDebug.h"                    // for NS_ASSERTION, etc
      42             : #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
      43             : #include "nsPoint.h"                    // for nsIntPoint
      44             : #include "nsRect.h"                     // for mozilla::gfx::IntRect
      45             : #include "nsRegion.h"                   // for nsIntRegion, etc
      46             : #include "nsTArray.h"                   // for AutoTArray
      47             : #include "TreeTraversal.h"              // for ForEachNode
      48             : 
      49             : class nsIWidget;
      50             : 
      51             : namespace mozilla {
      52             : namespace layers {
      53             : 
      54             : using namespace mozilla::gfx;
      55             : 
      56             : /**
      57             :  * Clips to the smallest device-pixel-aligned rectangle containing aRect
      58             :  * in user space.
      59             :  * Returns true if the clip is "perfect", i.e. we actually clipped exactly to
      60             :  * aRect.
      61             :  */
      62             : static bool
      63          19 : ClipToContain(gfxContext* aContext, const IntRect& aRect)
      64             : {
      65          19 :   gfxRect userRect(aRect.x, aRect.y, aRect.width, aRect.height);
      66          19 :   gfxRect deviceRect = aContext->UserToDevice(userRect);
      67          19 :   deviceRect.RoundOut();
      68             : 
      69          19 :   gfxMatrix currentMatrix = aContext->CurrentMatrix();
      70          19 :   aContext->SetMatrix(gfxMatrix());
      71          19 :   aContext->NewPath();
      72          19 :   aContext->Rectangle(deviceRect);
      73          19 :   aContext->Clip();
      74          19 :   aContext->SetMatrix(currentMatrix);
      75             : 
      76          19 :   return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
      77             : }
      78             : 
      79             : bool
      80          19 : BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegion,  PushedGroup& aGroupResult)
      81             : {
      82          19 :   aGroupResult.mVisibleRegion = aRegion;
      83          19 :   aGroupResult.mFinalTarget = aContext;
      84          19 :   aGroupResult.mOperator = GetEffectiveOperator(aLayer);
      85          19 :   aGroupResult.mOpacity = aLayer->GetEffectiveOpacity();
      86             : 
      87             :   // If we need to call PushGroup, we should clip to the smallest possible
      88             :   // area first to minimize the size of the temporary surface.
      89          19 :   bool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
      90             : 
      91          38 :   bool canPushGroup = aGroupResult.mOperator == CompositionOp::OP_OVER ||
      92          19 :     (aGroupResult.mOperator == CompositionOp::OP_SOURCE && (aLayer->CanUseOpaqueSurface() || aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA));
      93             : 
      94          19 :   if (!canPushGroup) {
      95           0 :     aContext->Save();
      96           0 :     gfxUtils::ClipToRegion(aGroupResult.mFinalTarget, aGroupResult.mVisibleRegion);
      97             : 
      98             :     // PushGroup/PopGroup do not support non operator over.
      99           0 :     gfxMatrix oldMat = aContext->CurrentMatrix();
     100           0 :     aContext->SetMatrix(gfxMatrix());
     101           0 :     gfxRect rect = aContext->GetClipExtents();
     102           0 :     aContext->SetMatrix(oldMat);
     103           0 :     rect.RoundOut();
     104           0 :     IntRect surfRect;
     105           0 :     ToRect(rect).ToIntRect(&surfRect);
     106             : 
     107           0 :     if (!surfRect.IsEmpty()) {
     108           0 :       RefPtr<DrawTarget> dt = aContext->GetDrawTarget()->CreateSimilarDrawTarget(surfRect.Size(), SurfaceFormat::B8G8R8A8);
     109             : 
     110             :       RefPtr<gfxContext> ctx =
     111           0 :         gfxContext::CreateOrNull(dt, ToRect(rect).TopLeft());
     112           0 :       if (!ctx) {
     113           0 :         gfxCriticalNote << "BasicLayerManager context problem in PushGroupForLayer " << gfx::hexa(dt);
     114           0 :         return false;
     115             :       }
     116           0 :       ctx->SetMatrix(oldMat);
     117             : 
     118           0 :       aGroupResult.mGroupOffset = surfRect.TopLeft();
     119           0 :       aGroupResult.mGroupTarget = ctx;
     120             : 
     121           0 :       aGroupResult.mMaskSurface = GetMaskForLayer(aLayer, &aGroupResult.mMaskTransform);
     122           0 :       return true;
     123             :     }
     124           0 :     aContext->Restore();
     125             :   }
     126             : 
     127          19 :   Matrix maskTransform;
     128          38 :   RefPtr<SourceSurface> maskSurf = GetMaskForLayer(aLayer, &maskTransform);
     129             : 
     130          19 :   if (maskSurf) {
     131             :     // The returned transform will transform the mask to device space on the
     132             :     // destination. Since the User->Device space transform will be applied
     133             :     // to the mask by PopGroupAndBlend we need to adjust the transform to
     134             :     // transform the mask to user space.
     135           0 :     Matrix currentTransform = ToMatrix(aGroupResult.mFinalTarget->CurrentMatrix());
     136           0 :     currentTransform.Invert();
     137           0 :     maskTransform = maskTransform * currentTransform;
     138             :   }
     139             : 
     140          57 :   if (aLayer->CanUseOpaqueSurface() &&
     141           0 :       ((didCompleteClip && aRegion.GetNumRects() == 1) ||
     142          19 :        !aContext->CurrentMatrix().HasNonIntegerTranslation())) {
     143             :     // If the layer is opaque in its visible region we can push a gfxContentType::COLOR
     144             :     // group. We need to make sure that only pixels inside the layer's visible
     145             :     // region are copied back to the destination. Remember if we've already
     146             :     // clipped precisely to the visible region.
     147           0 :     aGroupResult.mNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
     148           0 :     if (aGroupResult.mNeedsClipToVisibleRegion) {
     149           0 :       aGroupResult.mFinalTarget->Save();
     150           0 :       gfxUtils::ClipToRegion(aGroupResult.mFinalTarget, aGroupResult.mVisibleRegion);
     151             :     }
     152             : 
     153           0 :     aContext->PushGroupForBlendBack(gfxContentType::COLOR, aGroupResult.mOpacity, maskSurf, maskTransform);
     154             :   } else {
     155          19 :     if (aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) {
     156           0 :       aContext->PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA, aGroupResult.mOpacity, maskSurf, maskTransform);
     157             :     } else {
     158          19 :       aContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, aGroupResult.mOpacity, maskSurf, maskTransform);
     159             :     }
     160             :   }
     161             : 
     162          19 :   aGroupResult.mGroupTarget = aGroupResult.mFinalTarget;
     163             : 
     164          19 :   return true;
     165             : }
     166             : 
     167             : void
     168          19 : BasicLayerManager::PopGroupForLayer(PushedGroup &group)
     169             : {
     170          19 :   if (group.mFinalTarget == group.mGroupTarget) {
     171          19 :     group.mFinalTarget->PopGroupAndBlend();
     172          19 :     if (group.mNeedsClipToVisibleRegion) {
     173           0 :       group.mFinalTarget->Restore();
     174             :     }
     175          19 :     return;
     176             :   }
     177             : 
     178           0 :   DrawTarget* dt = group.mFinalTarget->GetDrawTarget();
     179           0 :   RefPtr<DrawTarget> sourceDT = group.mGroupTarget->GetDrawTarget();
     180           0 :   group.mGroupTarget = nullptr;
     181             : 
     182           0 :   RefPtr<SourceSurface> src = sourceDT->Snapshot();
     183             : 
     184           0 :   if (group.mMaskSurface) {
     185           0 :     Point finalOffset = group.mFinalTarget->GetDeviceOffset();
     186           0 :     dt->SetTransform(group.mMaskTransform * Matrix::Translation(-finalOffset));
     187           0 :     Matrix surfTransform = group.mMaskTransform;
     188           0 :     surfTransform.Invert();
     189           0 :     dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP, surfTransform *
     190           0 :                                                            Matrix::Translation(group.mGroupOffset.x, group.mGroupOffset.y)),
     191           0 :                     group.mMaskSurface, Point(0, 0), DrawOptions(group.mOpacity, group.mOperator));
     192             :   } else {
     193             :     // For now this is required since our group offset is in device space of the final target,
     194             :     // context but that may still have its own device offset. Once PushGroup/PopGroup logic is
     195             :     // migrated to DrawTargets this can go as gfxContext::GetDeviceOffset will essentially
     196             :     // always become null.
     197           0 :     dt->SetTransform(Matrix::Translation(-group.mFinalTarget->GetDeviceOffset()));
     198           0 :     dt->DrawSurface(src, Rect(group.mGroupOffset.x, group.mGroupOffset.y, src->GetSize().width, src->GetSize().height),
     199           0 :                     Rect(0, 0, src->GetSize().width, src->GetSize().height), DrawSurfaceOptions(SamplingFilter::POINT), DrawOptions(group.mOpacity, group.mOperator));
     200             :   }
     201             : 
     202           0 :   if (group.mNeedsClipToVisibleRegion) {
     203           0 :     dt->PopClip();
     204             :   }
     205             : 
     206           0 :   group.mFinalTarget->Restore();
     207             : }
     208             : 
     209             : static IntRect
     210           0 : ToInsideIntRect(const gfxRect& aRect)
     211             : {
     212           0 :   return IntRect::RoundIn(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
     213             : }
     214             : 
     215             : // A context helper for BasicLayerManager::PaintLayer() that holds all the
     216             : // painting context together in a data structure so it can be easily passed
     217             : // around. It also uses ensures that the Transform and Opaque rect are restored
     218             : // to their former state on destruction.
     219             : 
     220             : class PaintLayerContext {
     221             : public:
     222         123 :   PaintLayerContext(gfxContext* aTarget, Layer* aLayer,
     223             :                     LayerManager::DrawPaintedLayerCallback aCallback,
     224             :                     void* aCallbackData)
     225         123 :    : mTarget(aTarget)
     226             :    , mTargetMatrixSR(aTarget)
     227             :    , mLayer(aLayer)
     228             :    , mCallback(aCallback)
     229             :    , mCallbackData(aCallbackData)
     230         123 :    , mPushedOpaqueRect(false)
     231         123 :   {}
     232             : 
     233         123 :   ~PaintLayerContext()
     234         123 :   {
     235             :     // Matrix is restored by mTargetMatrixSR
     236         123 :     if (mPushedOpaqueRect)
     237             :     {
     238           2 :       ClearOpaqueRect();
     239             :     }
     240         123 :   }
     241             : 
     242             :   // Gets the effective transform and returns true if it is a 2D
     243             :   // transform.
     244         123 :   bool Setup2DTransform()
     245             :   {
     246             :     // Will return an identity matrix for 3d transforms.
     247         123 :     return mLayer->GetEffectiveTransformForBuffer().CanDraw2D(&mTransform);
     248             :   }
     249             : 
     250             :   // Applies the effective transform if it's 2D. If it's a 3D transform then
     251             :   // it applies an identity.
     252         123 :   void Apply2DTransform()
     253             :   {
     254         123 :     mTarget->SetMatrix(ThebesMatrix(mTransform));
     255         123 :   }
     256             : 
     257             :   // Set the opaque rect to match the bounds of the visible region.
     258         123 :   void AnnotateOpaqueRect()
     259             :   {
     260         246 :     const nsIntRegion visibleRegion = mLayer->GetLocalVisibleRegion().ToUnknownRegion();
     261         123 :     const IntRect& bounds = visibleRegion.GetBounds();
     262             : 
     263         123 :     DrawTarget *dt = mTarget->GetDrawTarget();
     264         123 :     const IntRect& targetOpaqueRect = dt->GetOpaqueRect();
     265             : 
     266             :     // Try to annotate currentSurface with a region of pixels that have been
     267             :     // (or will be) painted opaque, if no such region is currently set.
     268         485 :     if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
     269         243 :         (mLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
     270           2 :         !mTransform.HasNonAxisAlignedTransform()) {
     271             : 
     272           4 :       gfx::Rect opaqueRect = dt->GetTransform().TransformBounds(
     273           6 :         gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height));
     274           2 :       opaqueRect.RoundIn();
     275           2 :       IntRect intOpaqueRect;
     276           2 :       if (opaqueRect.ToIntRect(&intOpaqueRect)) {
     277           2 :         mTarget->GetDrawTarget()->SetOpaqueRect(intOpaqueRect);
     278           2 :         mPushedOpaqueRect = true;
     279             :       }
     280             :     }
     281         123 :   }
     282             : 
     283             :   // Clear the Opaque rect. Although this doesn't really restore it to it's
     284             :   // previous state it will happen on the exit path of the PaintLayer() so when
     285             :   // painting is complete the opaque rect qill be clear.
     286           2 :   void ClearOpaqueRect() {
     287           2 :     mTarget->GetDrawTarget()->SetOpaqueRect(IntRect());
     288           2 :   }
     289             : 
     290             :   gfxContext* mTarget;
     291             :   gfxContextMatrixAutoSaveRestore mTargetMatrixSR;
     292             :   Layer* mLayer;
     293             :   LayerManager::DrawPaintedLayerCallback mCallback;
     294             :   void* mCallbackData;
     295             :   Matrix mTransform;
     296             :   bool mPushedOpaqueRect;
     297             : };
     298             : 
     299           0 : BasicLayerManager::BasicLayerManager(nsIWidget* aWidget)
     300             :   : mPhase(PHASE_NONE)
     301             :   , mWidget(aWidget)
     302             :   , mDoubleBuffering(BufferMode::BUFFER_NONE)
     303             :   , mType(BLM_WIDGET)
     304             :   , mUsingDefaultTarget(false)
     305             :   , mTransactionIncomplete(false)
     306           0 :   , mCompositorMightResample(false)
     307             : {
     308           0 :   MOZ_COUNT_CTOR(BasicLayerManager);
     309           0 :   NS_ASSERTION(aWidget, "Must provide a widget");
     310           0 : }
     311             : 
     312          30 : BasicLayerManager::BasicLayerManager(BasicLayerManagerType aType)
     313             :   : mPhase(PHASE_NONE)
     314             :   , mWidget(nullptr)
     315             :   , mDoubleBuffering(BufferMode::BUFFER_NONE)
     316             :   , mType(aType)
     317             :   , mUsingDefaultTarget(false)
     318          30 :   , mTransactionIncomplete(false)
     319             : {
     320          30 :   MOZ_COUNT_CTOR(BasicLayerManager);
     321          30 :   MOZ_ASSERT(mType != BLM_WIDGET);
     322          30 : }
     323             : 
     324          72 : BasicLayerManager::~BasicLayerManager()
     325             : {
     326          24 :   NS_ASSERTION(!InTransaction(), "Died during transaction?");
     327             : 
     328          24 :   ClearCachedResources();
     329             : 
     330          24 :   mRoot = nullptr;
     331             : 
     332          24 :   MOZ_COUNT_DTOR(BasicLayerManager);
     333          72 : }
     334             : 
     335             : void
     336           0 : BasicLayerManager::SetDefaultTarget(gfxContext* aContext)
     337             : {
     338           0 :   NS_ASSERTION(!InTransaction(),
     339             :                "Must set default target outside transaction");
     340           0 :   mDefaultTarget = aContext;
     341           0 : }
     342             : 
     343             : void
     344           0 : BasicLayerManager::SetDefaultTargetConfiguration(BufferMode aDoubleBuffering, ScreenRotation aRotation)
     345             : {
     346           0 :   mDoubleBuffering = aDoubleBuffering;
     347           0 : }
     348             : 
     349             : bool
     350         173 : BasicLayerManager::BeginTransaction()
     351             : {
     352         173 :   mInTransaction = true;
     353         173 :   mUsingDefaultTarget = true;
     354         173 :   return BeginTransactionWithTarget(mDefaultTarget);
     355             : }
     356             : 
     357             : bool
     358         191 : BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
     359             : {
     360         191 :   mInTransaction = true;
     361             : 
     362             : #ifdef MOZ_LAYERS_HAVE_LOG
     363         191 :   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
     364         191 :   Log();
     365             : #endif
     366             : 
     367         191 :   NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
     368         191 :   mPhase = PHASE_CONSTRUCTION;
     369         191 :   mTarget = aTarget;
     370         191 :   return true;
     371             : }
     372             : 
     373             : static void
     374           0 : TransformIntRect(IntRect& aRect, const Matrix& aMatrix,
     375             :                  IntRect (*aRoundMethod)(const gfxRect&))
     376             : {
     377           0 :   Rect gr = Rect(aRect.x, aRect.y, aRect.width, aRect.height);
     378           0 :   gr = aMatrix.TransformBounds(gr);
     379           0 :   aRect = (*aRoundMethod)(ThebesRect(gr));
     380           0 : }
     381             : 
     382             : /**
     383             :  * This function assumes that GetEffectiveTransform transforms
     384             :  * all layers to the same coordinate system (the "root coordinate system").
     385             :  * It can't be used as is by accelerated layers because of intermediate surfaces.
     386             :  * This must set the hidden flag to true or false on *all* layers in the subtree.
     387             :  * It also sets the operator for all layers to "OVER", and call
     388             :  * SetDrawAtomically(false).
     389             :  * It clears mClipToVisibleRegion on all layers.
     390             :  * @param aClipRect the cliprect, in the root coordinate system. We assume
     391             :  * that any layer drawing is clipped to this rect. It is therefore not
     392             :  * allowed to add to the opaque region outside that rect.
     393             :  * @param aDirtyRect the dirty rect that will be painted, in the root
     394             :  * coordinate system. Layers outside this rect should be hidden.
     395             :  * @param aOpaqueRegion the opaque region covering aLayer, in the
     396             :  * root coordinate system.
     397             :  */
     398             : enum {
     399             :     ALLOW_OPAQUE = 0x01,
     400             : };
     401             : static void
     402           0 : MarkLayersHidden(Layer* aLayer, const IntRect& aClipRect,
     403             :                  const IntRect& aDirtyRect,
     404             :                  nsIntRegion& aOpaqueRegion,
     405             :                  uint32_t aFlags)
     406             : {
     407           0 :   IntRect newClipRect(aClipRect);
     408           0 :   uint32_t newFlags = aFlags;
     409             : 
     410             :   // Allow aLayer or aLayer's descendants to cover underlying layers
     411             :   // only if it's opaque.
     412           0 :   if (aLayer->GetOpacity() != 1.0f) {
     413           0 :     newFlags &= ~ALLOW_OPAQUE;
     414             :   }
     415             : 
     416             :   {
     417           0 :     const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
     418           0 :     if (clipRect) {
     419           0 :       IntRect cr = clipRect->ToUnknownRect();
     420             :       // clipRect is in the container's coordinate system. Get it into the
     421             :       // global coordinate system.
     422           0 :       if (aLayer->GetParent()) {
     423           0 :         Matrix tr;
     424           0 :         if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
     425             :           // Clip rect is applied after aLayer's transform, i.e., in the coordinate
     426             :           // system of aLayer's parent.
     427           0 :           TransformIntRect(cr, tr, ToInsideIntRect);
     428             :         } else {
     429           0 :           cr.SetRect(0, 0, 0, 0);
     430             :         }
     431             :       }
     432           0 :       newClipRect.IntersectRect(newClipRect, cr);
     433             :     }
     434             :   }
     435             : 
     436           0 :   BasicImplData* data = ToData(aLayer);
     437           0 :   data->SetOperator(CompositionOp::OP_OVER);
     438           0 :   data->SetClipToVisibleRegion(false);
     439           0 :   data->SetDrawAtomically(false);
     440             : 
     441           0 :   if (!aLayer->AsContainerLayer()) {
     442           0 :     Matrix transform;
     443           0 :     if (!aLayer->GetEffectiveTransform().CanDraw2D(&transform)) {
     444           0 :       data->SetHidden(false);
     445           0 :       return;
     446             :     }
     447             : 
     448           0 :     nsIntRegion region = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
     449           0 :     IntRect r = region.GetBounds();
     450           0 :     TransformIntRect(r, transform, ToOutsideIntRect);
     451           0 :     r.IntersectRect(r, aDirtyRect);
     452           0 :     data->SetHidden(aOpaqueRegion.Contains(r));
     453             : 
     454             :     // Allow aLayer to cover underlying layers only if aLayer's
     455             :     // content is opaque
     456           0 :     if ((aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
     457           0 :         (newFlags & ALLOW_OPAQUE)) {
     458           0 :       for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
     459           0 :         r = iter.Get();
     460           0 :         TransformIntRect(r, transform, ToInsideIntRect);
     461             : 
     462           0 :         r.IntersectRect(r, newClipRect);
     463           0 :         aOpaqueRegion.Or(aOpaqueRegion, r);
     464             :       }
     465             :     }
     466             :   } else {
     467           0 :     Layer* child = aLayer->GetLastChild();
     468           0 :     bool allHidden = true;
     469           0 :     for (; child; child = child->GetPrevSibling()) {
     470           0 :       MarkLayersHidden(child, newClipRect, aDirtyRect, aOpaqueRegion, newFlags);
     471           0 :       if (!ToData(child)->IsHidden()) {
     472           0 :         allHidden = false;
     473             :       }
     474             :     }
     475           0 :     data->SetHidden(allHidden);
     476             :   }
     477             : }
     478             : 
     479             : /**
     480             :  * This function assumes that GetEffectiveTransform transforms
     481             :  * all layers to the same coordinate system (the "root coordinate system").
     482             :  * MarkLayersHidden must be called before calling this.
     483             :  * @param aVisibleRect the rectangle of aLayer that is visible (i.e. not
     484             :  * clipped and in the dirty rect), in the root coordinate system.
     485             :  */
     486             : static void
     487           0 : ApplyDoubleBuffering(Layer* aLayer, const IntRect& aVisibleRect)
     488             : {
     489           0 :   BasicImplData* data = ToData(aLayer);
     490           0 :   if (data->IsHidden())
     491           0 :     return;
     492             : 
     493           0 :   IntRect newVisibleRect(aVisibleRect);
     494             : 
     495             :   {
     496           0 :     const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
     497           0 :     if (clipRect) {
     498           0 :       IntRect cr = clipRect->ToUnknownRect();
     499             :       // clipRect is in the container's coordinate system. Get it into the
     500             :       // global coordinate system.
     501           0 :       if (aLayer->GetParent()) {
     502           0 :         Matrix tr;
     503           0 :         if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
     504           0 :           NS_ASSERTION(!ThebesMatrix(tr).HasNonIntegerTranslation(),
     505             :                        "Parent can only have an integer translation");
     506           0 :           cr += nsIntPoint(int32_t(tr._31), int32_t(tr._32));
     507             :         } else {
     508           0 :           NS_ERROR("Parent can only have an integer translation");
     509             :         }
     510             :       }
     511           0 :       newVisibleRect.IntersectRect(newVisibleRect, cr);
     512             :     }
     513             :   }
     514             : 
     515             :   BasicContainerLayer* container =
     516           0 :     static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
     517             :   // Layers that act as their own backbuffers should be drawn to the destination
     518             :   // using OP_SOURCE to ensure that alpha values in a transparent window are
     519             :   // cleared. This can also be faster than OP_OVER.
     520           0 :   if (!container) {
     521           0 :     data->SetOperator(CompositionOp::OP_SOURCE);
     522           0 :     data->SetDrawAtomically(true);
     523             :   } else {
     524           0 :     if (container->UseIntermediateSurface() ||
     525           0 :         !container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
     526             :       // We need to double-buffer this container.
     527           0 :       data->SetOperator(CompositionOp::OP_SOURCE);
     528           0 :       container->ForceIntermediateSurface();
     529             :     } else {
     530             :       // Tell the children to clip to their visible regions so our assumption
     531             :       // that they don't paint outside their visible regions is valid!
     532           0 :       for (Layer* child = aLayer->GetFirstChild(); child;
     533             :            child = child->GetNextSibling()) {
     534           0 :         ToData(child)->SetClipToVisibleRegion(true);
     535           0 :         ApplyDoubleBuffering(child, newVisibleRect);
     536             :       }
     537             :     }
     538             :   }
     539             : }
     540             : 
     541             : void
     542          48 : BasicLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
     543             :                                   void* aCallbackData,
     544             :                                   EndTransactionFlags aFlags)
     545             : {
     546          48 :   mInTransaction = false;
     547             : 
     548          48 :   EndTransactionInternal(aCallback, aCallbackData, aFlags);
     549          48 : }
     550             : 
     551             : void
     552         143 : BasicLayerManager::AbortTransaction()
     553             : {
     554         143 :   NS_ASSERTION(InConstruction(), "Should be in construction phase");
     555         143 :   mPhase = PHASE_NONE;
     556         143 :   mUsingDefaultTarget = false;
     557         143 :   mInTransaction = false;
     558         143 : }
     559             : 
     560             : bool
     561          48 : BasicLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
     562             :                                           void* aCallbackData,
     563             :                                           EndTransactionFlags aFlags)
     564             : {
     565          96 :   AUTO_PROFILER_LABEL("BasicLayerManager::EndTransactionInternal", GRAPHICS);
     566             : 
     567             : #ifdef MOZ_LAYERS_HAVE_LOG
     568          48 :   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
     569          48 :   Log();
     570             : #endif
     571             : 
     572          48 :   NS_ASSERTION(InConstruction(), "Should be in construction phase");
     573          48 :   mPhase = PHASE_DRAWING;
     574             : 
     575          48 :   SetCompositionTime(TimeStamp::Now());
     576             : 
     577          48 :   RenderTraceLayers(mRoot, "FF00");
     578             : 
     579          48 :   mTransactionIncomplete = false;
     580             : 
     581          48 :   if (mRoot) {
     582          48 :     if (aFlags & END_NO_COMPOSITE) {
     583             :       // Apply pending tree updates before recomputing effective
     584             :       // properties.
     585           0 :       mRoot->ApplyPendingUpdatesToSubtree();
     586             :     }
     587             : 
     588             :     // Need to do this before we call ApplyDoubleBuffering,
     589             :     // which depends on correct effective transforms
     590          48 :     if (mTarget) {
     591          48 :       mSnapEffectiveTransforms =
     592          48 :         !mTarget->GetDrawTarget()->GetUserData(&sDisablePixelSnapping);
     593             :     } else {
     594           0 :       mSnapEffectiveTransforms = true;
     595             :     }
     596          48 :     mRoot->ComputeEffectiveTransforms(mTarget ? Matrix4x4::From2D(ToMatrix(mTarget->CurrentMatrix())) : Matrix4x4());
     597             : 
     598          48 :     ToData(mRoot)->Validate(aCallback, aCallbackData, nullptr);
     599          48 :     if (mRoot->GetMaskLayer()) {
     600           0 :       ToData(mRoot->GetMaskLayer())->Validate(aCallback, aCallbackData, nullptr);
     601             :     }
     602             :   }
     603             : 
     604         192 :   if (mTarget && mRoot &&
     605         144 :       !(aFlags & END_NO_IMMEDIATE_REDRAW) &&
     606          48 :       !(aFlags & END_NO_COMPOSITE)) {
     607          48 :     IntRect clipRect;
     608             : 
     609             :     {
     610          96 :       gfxContextMatrixAutoSaveRestore save(mTarget);
     611          48 :       mTarget->SetMatrix(gfxMatrix());
     612          48 :       clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
     613             :     }
     614             : 
     615          48 :     if (IsRetained()) {
     616           0 :       nsIntRegion region;
     617           0 :       MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
     618           0 :       if (mUsingDefaultTarget && mDoubleBuffering != BufferMode::BUFFER_NONE) {
     619           0 :         ApplyDoubleBuffering(mRoot, clipRect);
     620             :       }
     621             :     }
     622             : 
     623          48 :     PaintLayer(mTarget, mRoot, aCallback, aCallbackData);
     624          48 :     if (!mRegionToClear.IsEmpty()) {
     625           0 :       for (auto iter = mRegionToClear.RectIter(); !iter.Done(); iter.Next()) {
     626           0 :         const IntRect& r = iter.Get();
     627           0 :         mTarget->GetDrawTarget()->ClearRect(Rect(r.x, r.y, r.width, r.height));
     628             :       }
     629             :     }
     630          48 :     if (mWidget) {
     631           0 :       FlashWidgetUpdateArea(mTarget);
     632             :     }
     633          48 :     RecordFrame();
     634             : 
     635          48 :     if (!mTransactionIncomplete) {
     636             :       // Clear out target if we have a complete transaction.
     637          48 :       mTarget = nullptr;
     638             :     }
     639             :   }
     640             : 
     641          48 :   if (mRoot) {
     642          48 :     mAnimationReadyTime = TimeStamp::Now();
     643          48 :     mRoot->StartPendingAnimations(mAnimationReadyTime);
     644             :   }
     645             : 
     646             : #ifdef MOZ_LAYERS_HAVE_LOG
     647          48 :   Log();
     648          48 :   MOZ_LAYERS_LOG(("]----- EndTransaction"));
     649             : #endif
     650             : 
     651             :   // Go back to the construction phase if the transaction isn't complete.
     652             :   // Layout will update the layer tree and call EndTransaction().
     653          48 :   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
     654             : 
     655          48 :   if (!mTransactionIncomplete) {
     656             :     // This is still valid if the transaction was incomplete.
     657          48 :     mUsingDefaultTarget = false;
     658             :   }
     659             : 
     660          48 :   NS_ASSERTION(!aCallback || !mTransactionIncomplete,
     661             :                "If callback is not null, transaction must be complete");
     662             : 
     663          48 :   ClearDisplayItemLayers();
     664             : 
     665             :   // XXX - We should probably assert here that for an incomplete transaction
     666             :   // out target is the default target.
     667             : 
     668          96 :   return !mTransactionIncomplete;
     669             : }
     670             : 
     671             : void
     672           0 : BasicLayerManager::FlashWidgetUpdateArea(gfxContext *aContext)
     673             : {
     674           0 :   if (gfxPrefs::WidgetUpdateFlashing()) {
     675           0 :     float r = float(rand()) / RAND_MAX;
     676           0 :     float g = float(rand()) / RAND_MAX;
     677           0 :     float b = float(rand()) / RAND_MAX;
     678           0 :     aContext->SetColor(Color(r, g, b, 0.2f));
     679           0 :     aContext->Paint();
     680             :   }
     681           0 : }
     682             : 
     683             : bool
     684           0 : BasicLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
     685             : {
     686           0 :   mInTransaction = false;
     687             : 
     688           0 :   if (!mRoot) {
     689           0 :     return false;
     690             :   }
     691             : 
     692           0 :   return EndTransactionInternal(nullptr, nullptr, aFlags);
     693             : }
     694             : 
     695             : void
     696         161 : BasicLayerManager::SetRoot(Layer* aLayer)
     697             : {
     698         161 :   NS_ASSERTION(aLayer, "Root can't be null");
     699         161 :   NS_ASSERTION(aLayer->Manager() == this, "Wrong manager");
     700         161 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
     701         161 :   mRoot = aLayer;
     702         161 : }
     703             : 
     704             : void
     705         123 : BasicLayerManager::PaintSelfOrChildren(PaintLayerContext& aPaintContext,
     706             :                                        gfxContext* aGroupTarget)
     707             : {
     708         123 :   MOZ_ASSERT(aGroupTarget);
     709         123 :   BasicImplData* data = ToData(aPaintContext.mLayer);
     710             : 
     711             :   /* Only paint ourself, or our children - This optimization relies on this! */
     712         123 :   Layer* child = aPaintContext.mLayer->GetFirstChild();
     713         123 :   if (!child) {
     714          51 :     if (aPaintContext.mLayer->AsPaintedLayer()) {
     715          51 :       data->PaintThebes(aGroupTarget, aPaintContext.mLayer->GetMaskLayer(),
     716         102 :           aPaintContext.mCallback, aPaintContext.mCallbackData);
     717             :     } else {
     718           0 :       data->Paint(aGroupTarget->GetDrawTarget(),
     719           0 :                   aGroupTarget->GetDeviceOffset(),
     720           0 :                   aPaintContext.mLayer->GetMaskLayer());
     721             :     }
     722             :   } else {
     723             :     ContainerLayer* container =
     724          72 :         static_cast<ContainerLayer*>(aPaintContext.mLayer);
     725             : 
     726             :     nsTArray<LayerPolygon> children =
     727         144 :       container->SortChildrenBy3DZOrder(ContainerLayer::SortMode::WITHOUT_GEOMETRY);
     728             : 
     729         168 :     for (uint32_t i = 0; i < children.Length(); i++) {
     730          96 :       Layer* layer = children.ElementAt(i).layer;
     731          96 :       if (layer->IsBackfaceHidden()) {
     732           0 :         continue;
     733             :       }
     734          96 :       if (!layer->AsContainerLayer() && !layer->IsVisible()) {
     735          21 :         continue;
     736             :       }
     737             : 
     738          75 :       PaintLayer(aGroupTarget, layer, aPaintContext.mCallback,
     739          75 :                 aPaintContext.mCallbackData);
     740          75 :       if (mTransactionIncomplete)
     741           0 :         break;
     742             :     }
     743             :   }
     744         123 : }
     745             : 
     746             : void
     747           0 : BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipToVisibleRegion)
     748             : {
     749             :   // If we're doing our own double-buffering, we need to avoid drawing
     750             :   // the results of an incomplete transaction to the destination surface ---
     751             :   // that could cause flicker. Double-buffering is implemented using a
     752             :   // temporary surface for one or more container layers, so we need to stop
     753             :   // those temporary surfaces from being composited to aTarget.
     754             :   // ApplyDoubleBuffering guarantees that this container layer can't
     755             :   // intersect any other leaf layers, so if the transaction is not yet marked
     756             :   // incomplete, the contents of this container layer are the final contents
     757             :   // for the window.
     758           0 :   if (!mTransactionIncomplete) {
     759           0 :     if (aNeedsClipToVisibleRegion) {
     760           0 :       gfxUtils::ClipToRegion(aPaintContext.mTarget,
     761           0 :                              aPaintContext.mLayer->GetLocalVisibleRegion().ToUnknownRegion());
     762             :     }
     763             : 
     764           0 :     CompositionOp op = GetEffectiveOperator(aPaintContext.mLayer);
     765           0 :     AutoSetOperator setOperator(aPaintContext.mTarget, op);
     766             : 
     767           0 :     PaintWithMask(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveOpacity(),
     768           0 :                   aPaintContext.mLayer->GetMaskLayer());
     769             :   }
     770           0 : }
     771             : 
     772             : /**
     773             :  * Install the clip applied to the layer on the given gfxContext.  The
     774             :  * given gfxContext is the buffer that the layer will be painted to.
     775             :  */
     776             : static void
     777          22 : InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer)
     778             : {
     779          22 :   const Maybe<ParentLayerIntRect> &clipRect = aLayer->GetLocalClipRect();
     780             : 
     781          22 :   if (!clipRect) {
     782           0 :     return;
     783             :   }
     784          22 :   MOZ_ASSERT(!aLayer->Extend3DContext() ||
     785             :              !aLayer->Combines3DTransformWithAncestors(),
     786             :              "Layers in a preserve 3D context have no clip"
     787             :              " except leaves and the estabisher!");
     788             : 
     789          22 :   Layer* parent = aLayer->GetParent();
     790             :   Matrix4x4 transform3d =
     791          22 :     parent && parent->Extend3DContext() ?
     792           0 :     parent->GetEffectiveTransform() :
     793           0 :     Matrix4x4();
     794          22 :   Matrix transform;
     795          22 :   if (!transform3d.CanDraw2D(&transform)) {
     796           0 :     gfxDevCrash(LogReason::CannotDraw3D) << "GFX: We should not have a 3D transform that CanDraw2D() is false!";
     797             :   }
     798          22 :   gfxMatrix oldTransform = aTarget->CurrentMatrix();
     799          22 :   transform *= ToMatrix(oldTransform);
     800          22 :   aTarget->SetMatrix(ThebesMatrix(transform));
     801             : 
     802          22 :   aTarget->NewPath();
     803          66 :   aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y,
     804          66 :                                     clipRect->width, clipRect->height));
     805          22 :   aTarget->Clip();
     806             : 
     807          22 :   aTarget->SetMatrix(oldTransform);
     808             : }
     809             : 
     810             : void
     811         123 : BasicLayerManager::PaintLayer(gfxContext* aTarget,
     812             :                               Layer* aLayer,
     813             :                               DrawPaintedLayerCallback aCallback,
     814             :                               void* aCallbackData)
     815             : {
     816         123 :   MOZ_ASSERT(aTarget);
     817             : 
     818         246 :   AUTO_PROFILER_LABEL("BasicLayerManager::PaintLayer", GRAPHICS);
     819             : 
     820             :   PaintLayerContext paintLayerContext(aTarget, aLayer,
     821         246 :                                       aCallback, aCallbackData);
     822             : 
     823             :   // Don't attempt to paint layers with a singular transform, cairo will
     824             :   // just throw an error.
     825         123 :   if (aLayer->GetEffectiveTransform().IsSingular()) {
     826           0 :     return;
     827             :   }
     828             : 
     829         246 :   RenderTraceScope trace("BasicLayerManager::PaintLayer", "707070");
     830             : 
     831         123 :   const Maybe<ParentLayerIntRect>& clipRect = aLayer->GetLocalClipRect();
     832             :   BasicContainerLayer* container =
     833         123 :     static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
     834         123 :   bool needsGroup = container && container->UseIntermediateSurface();
     835         123 :   BasicImplData* data = ToData(aLayer);
     836             :   bool needsClipToVisibleRegion =
     837         123 :     data->GetClipToVisibleRegion() && !aLayer->AsPaintedLayer();
     838         123 :   NS_ASSERTION(needsGroup || !container ||
     839             :                container->GetOperator() == CompositionOp::OP_OVER,
     840             :                "non-OVER operator should have forced UseIntermediateSurface");
     841         123 :   NS_ASSERTION(!container || !aLayer->GetMaskLayer() ||
     842             :                container->UseIntermediateSurface(),
     843             :                "ContainerLayer with mask layer should force UseIntermediateSurface");
     844             : 
     845         246 :   gfxContextAutoSaveRestore contextSR;
     846         123 :   gfxMatrix transform;
     847             :   // Will return an identity matrix for 3d transforms, and is handled separately below.
     848         123 :   bool is2D = paintLayerContext.Setup2DTransform();
     849         123 :   MOZ_ASSERT(is2D || needsGroup || !container ||
     850             :              container->Extend3DContext() ||
     851             :              container->Is3DContextLeaf(),
     852             :              "Must PushGroup for 3d transforms!");
     853             : 
     854         123 :   Layer* parent = aLayer->GetParent();
     855         123 :   bool inPreserves3DChain = parent && parent->Extend3DContext();
     856             :   bool needsSaveRestore =
     857         123 :     needsGroup || clipRect || needsClipToVisibleRegion || !is2D ||
     858         123 :     inPreserves3DChain;
     859         123 :   if (needsSaveRestore) {
     860          22 :     contextSR.SetContext(aTarget);
     861             : 
     862             :     // The clips on ancestors on the preserved3d chain should be
     863             :     // installed on the aTarget before painting the layer.
     864          22 :     InstallLayerClipPreserves3D(aTarget, aLayer);
     865          22 :     for (Layer* l = parent; l && l->Extend3DContext(); l = l->GetParent()) {
     866           0 :       InstallLayerClipPreserves3D(aTarget, l);
     867             :     }
     868             :   }
     869             : 
     870         123 :   paintLayerContext.Apply2DTransform();
     871             : 
     872         246 :   nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
     873             :   // If needsGroup is true, we'll clip to the visible region after we've popped the group
     874         123 :   if (needsClipToVisibleRegion && !needsGroup) {
     875           0 :     gfxUtils::ClipToRegion(aTarget, visibleRegion);
     876             :     // Don't need to clip to visible region again
     877           0 :     needsClipToVisibleRegion = false;
     878             :   }
     879             : 
     880         123 :   if (is2D) {
     881         123 :     paintLayerContext.AnnotateOpaqueRect();
     882             :   }
     883             : 
     884         123 :   bool clipIsEmpty = aTarget->GetClipExtents().IsEmpty();
     885         123 :   if (clipIsEmpty) {
     886           0 :     PaintSelfOrChildren(paintLayerContext, aTarget);
     887           0 :     return;
     888             :   }
     889             : 
     890         123 :   if (is2D) {
     891         123 :     if (needsGroup) {
     892           0 :       PushedGroup pushedGroup;
     893           0 :       if (PushGroupForLayer(aTarget, aLayer, aLayer->GetLocalVisibleRegion().ToUnknownRegion(), pushedGroup)) {
     894           0 :         PaintSelfOrChildren(paintLayerContext, pushedGroup.mGroupTarget);
     895           0 :         PopGroupForLayer(pushedGroup);
     896             :       }
     897             :     } else {
     898         123 :       PaintSelfOrChildren(paintLayerContext, aTarget);
     899             :     }
     900             :   } else {
     901           0 :     if (!needsGroup && container) {
     902           0 :       PaintSelfOrChildren(paintLayerContext, aTarget);
     903           0 :       return;
     904             :     }
     905             : 
     906           0 :     IntRect bounds = visibleRegion.GetBounds();
     907             :     // DrawTarget without the 3D transform applied:
     908             :     RefPtr<DrawTarget> untransformedDT =
     909           0 :       gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height),
     910           0 :                                                                    SurfaceFormat::B8G8R8A8);
     911           0 :     if (!untransformedDT || !untransformedDT->IsValid()) {
     912           0 :       return;
     913             :     }
     914           0 :     untransformedDT->SetTransform(Matrix::Translation(-Point(bounds.x, bounds.y)));
     915             : 
     916             :     RefPtr<gfxContext> groupTarget =
     917           0 :       gfxContext::CreatePreservingTransformOrNull(untransformedDT);
     918           0 :     MOZ_ASSERT(groupTarget); // already checked the target above
     919             : 
     920           0 :     PaintSelfOrChildren(paintLayerContext, groupTarget);
     921             : 
     922             :     // Temporary fast fix for bug 725886
     923             :     // Revert these changes when 725886 is ready
     924             : #ifdef DEBUG
     925           0 :     if (aLayer->GetDebugColorIndex() != 0) {
     926           0 :       Color color((aLayer->GetDebugColorIndex() & 1) ? 1.f : 0.f,
     927           0 :                   (aLayer->GetDebugColorIndex() & 2) ? 1.f : 0.f,
     928           0 :                   (aLayer->GetDebugColorIndex() & 4) ? 1.f : 0.f);
     929           0 :       untransformedDT->FillRect(Rect(bounds), ColorPattern(color));
     930             :     }
     931             : #endif
     932           0 :     Matrix4x4 effectiveTransform = aLayer->GetEffectiveTransform();
     933             :     Rect xformBounds =
     934           0 :       effectiveTransform.TransformAndClipBounds(Rect(bounds),
     935           0 :                                                 ToRect(aTarget->GetClipExtents()));
     936           0 :     xformBounds.RoundOut();
     937           0 :     effectiveTransform.PostTranslate(-xformBounds.x, -xformBounds.y, 0);
     938           0 :     effectiveTransform.PreTranslate(bounds.x, bounds.y, 0);
     939             : 
     940           0 :     RefPtr<SourceSurface> untransformedSurf = untransformedDT->Snapshot();
     941             :     RefPtr<DrawTarget> xformDT =
     942           0 :       untransformedDT->CreateSimilarDrawTarget(IntSize::Truncate(xformBounds.width, xformBounds.height),
     943           0 :                                                SurfaceFormat::B8G8R8A8);
     944           0 :     RefPtr<SourceSurface> xformSurf;
     945           0 :     if(xformDT && untransformedSurf &&
     946           0 :        xformDT->Draw3DTransformedSurface(untransformedSurf, effectiveTransform)) {
     947           0 :       xformSurf = xformDT->Snapshot();
     948             :     }
     949             : 
     950           0 :     if (xformSurf) {
     951           0 :       aTarget->SetPattern(
     952             :         new gfxPattern(xformSurf,
     953           0 :                        Matrix::Translation(xformBounds.TopLeft())));
     954             : 
     955             :       // Azure doesn't support EXTEND_NONE, so to avoid extending the edges
     956             :       // of the source surface out to the current clip region, clip to
     957             :       // the rectangle of the result surface now.
     958           0 :       aTarget->NewPath();
     959           0 :       aTarget->SnappedRectangle(ThebesRect(xformBounds));
     960           0 :       aTarget->Clip();
     961           0 :       FlushGroup(paintLayerContext, needsClipToVisibleRegion);
     962             :     }
     963             :   }
     964             : }
     965             : 
     966             : void
     967          24 : BasicLayerManager::ClearCachedResources(Layer* aSubtree)
     968             : {
     969          24 :   MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
     970          24 :   if (aSubtree) {
     971           0 :     ClearLayer(aSubtree);
     972          24 :   } else if (mRoot) {
     973          24 :     ClearLayer(mRoot);
     974             :   }
     975          24 : }
     976             : void
     977          96 : BasicLayerManager::ClearLayer(Layer* aLayer)
     978             : {
     979          96 :   ToData(aLayer)->ClearCachedResources();
     980         168 :   for (Layer* child = aLayer->GetFirstChild(); child;
     981             :        child = child->GetNextSibling()) {
     982          72 :     ClearLayer(child);
     983             :   }
     984          96 : }
     985             : 
     986             : already_AddRefed<ReadbackLayer>
     987           0 : BasicLayerManager::CreateReadbackLayer()
     988             : {
     989           0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
     990           0 :   RefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
     991           0 :   return layer.forget();
     992             : }
     993             : 
     994             : } // namespace layers
     995             : } // namespace mozilla

Generated by: LCOV version 1.13