LCOV - code coverage report
Current view: directory - gfx/layers/basic - BasicLayers.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1567 0 0.0 %
Date: 2012-06-02 Functions: 246 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  * ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Corporation code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Robert O'Callahan <robert@ocallahan.org>
      23                 :  *   Chris Jones <jones.chris.g@gmail.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "mozilla/Attributes.h"
      40                 : 
      41                 : #include "gfxSharedImageSurface.h"
      42                 : 
      43                 : #include "mozilla/layers/PLayerChild.h"
      44                 : #include "mozilla/layers/PLayersChild.h"
      45                 : #include "mozilla/layers/PLayersParent.h"
      46                 : #include "mozilla/gfx/2D.h"
      47                 : 
      48                 : #include "ipc/ShadowLayerChild.h"
      49                 : 
      50                 : #include "BasicLayers.h"
      51                 : #include "ImageLayers.h"
      52                 : #include "RenderTrace.h"
      53                 : 
      54                 : #include "prprf.h"
      55                 : #include "nsTArray.h"
      56                 : #include "nsGUIEvent.h"
      57                 : #include "gfxContext.h"
      58                 : #include "gfxImageSurface.h"
      59                 : #include "gfxPattern.h"
      60                 : #include "gfxPlatform.h"
      61                 : #include "gfxUtils.h"
      62                 : #include "ThebesLayerBuffer.h"
      63                 : #include "nsIWidget.h"
      64                 : #include "ReadbackProcessor.h"
      65                 : #ifdef MOZ_X11
      66                 : #include "gfxXlibSurface.h"
      67                 : #endif
      68                 : 
      69                 : #include "GLContext.h"
      70                 : 
      71                 : #define PIXMAN_DONT_DEFINE_STDINT
      72                 : #include "pixman.h"
      73                 : 
      74                 : namespace mozilla {
      75                 : namespace layers {
      76                 : 
      77                 : class BasicContainerLayer;
      78                 : class ShadowableLayer;
      79                 : 
      80                 : /**
      81                 :  * This is the ImplData for all Basic layers. It also exposes methods
      82                 :  * private to the Basic implementation that are common to all Basic layer types.
      83                 :  * In particular, there is an internal Paint() method that we can use
      84                 :  * to paint the contents of non-Thebes layers.
      85                 :  *
      86                 :  * The class hierarchy for Basic layers is like this:
      87                 :  *                                 BasicImplData
      88                 :  * Layer                            |   |   |
      89                 :  *  |                               |   |   |
      90                 :  *  +-> ContainerLayer              |   |   |
      91                 :  *  |    |                          |   |   |
      92                 :  *  |    +-> BasicContainerLayer <--+   |   |
      93                 :  *  |                                   |   |
      94                 :  *  +-> ThebesLayer                     |   |
      95                 :  *  |    |                              |   |
      96                 :  *  |    +-> BasicThebesLayer <---------+   |
      97                 :  *  |                                       |
      98                 :  *  +-> ImageLayer                          |
      99                 :  *       |                                  |
     100                 :  *       +-> BasicImageLayer <--------------+
     101                 :  */
     102                 : class BasicImplData {
     103                 : public:
     104               0 :   BasicImplData() : mHidden(false),
     105               0 :     mClipToVisibleRegion(false), mOperator(gfxContext::OPERATOR_OVER)
     106                 :   {
     107               0 :     MOZ_COUNT_CTOR(BasicImplData);
     108               0 :   }
     109               0 :   virtual ~BasicImplData()
     110               0 :   {
     111               0 :     MOZ_COUNT_DTOR(BasicImplData);
     112               0 :   }
     113                 : 
     114                 :   /**
     115                 :    * Layers that paint themselves, such as ImageLayers, should paint
     116                 :    * in response to this method call. aContext will already have been
     117                 :    * set up to account for all the properties of the layer (transform,
     118                 :    * opacity, etc).
     119                 :    */
     120               0 :   virtual void Paint(gfxContext* aContext) {}
     121                 : 
     122                 :   /**
     123                 :    * Like Paint() but called for ThebesLayers with the additional parameters
     124                 :    * they need.
     125                 :    * If mClipToVisibleRegion is set, then the layer must clip to its
     126                 :    * effective visible region (snapped or unsnapped, it doesn't matter).
     127                 :    */
     128               0 :   virtual void PaintThebes(gfxContext* aContext,
     129                 :                            LayerManager::DrawThebesLayerCallback aCallback,
     130                 :                            void* aCallbackData,
     131               0 :                            ReadbackProcessor* aReadback) {}
     132                 : 
     133               0 :   virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
     134                 : 
     135                 :   /**
     136                 :    * Implementations return true here if they *must* retain their
     137                 :    * layer contents.  This is true of shadowable layers with shadows,
     138                 :    * because there's no target on which to composite directly in the
     139                 :    * layer-publishing child process.
     140                 :    */
     141               0 :   virtual bool MustRetainContent() { return false; }
     142                 : 
     143                 :   /**
     144                 :    * Layers will get this call when their layer manager is destroyed, this
     145                 :    * indicates they should clear resources they don't really need after their
     146                 :    * LayerManager ceases to exist.
     147                 :    */
     148               0 :   virtual void ClearCachedResources() {}
     149                 : 
     150                 :   /**
     151                 :    * This variable is set by MarkLayersHidden() before painting. It indicates
     152                 :    * that the layer should not be composited during this transaction.
     153                 :    */
     154               0 :   void SetHidden(bool aCovered) { mHidden = aCovered; }
     155               0 :   bool IsHidden() const { return false; }
     156                 :   /**
     157                 :    * This variable is set by MarkLayersHidden() before painting. This is
     158                 :    * the operator to be used when compositing the layer in this transaction. It must
     159                 :    * be OVER or SOURCE.
     160                 :    */
     161               0 :   void SetOperator(gfxContext::GraphicsOperator aOperator)
     162                 :   {
     163               0 :     NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
     164                 :                  aOperator == gfxContext::OPERATOR_SOURCE,
     165                 :                  "Bad composition operator");
     166               0 :     mOperator = aOperator;
     167               0 :   }
     168               0 :   gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
     169                 : 
     170               0 :   bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
     171               0 :   void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
     172                 : 
     173                 : protected:
     174                 :   bool mHidden;
     175                 :   bool mClipToVisibleRegion;
     176                 :   gfxContext::GraphicsOperator mOperator;
     177                 : };
     178                 : 
     179                 : class AutoSetOperator {
     180                 : public:
     181               0 :   AutoSetOperator(gfxContext* aContext, gfxContext::GraphicsOperator aOperator) {
     182               0 :     if (aOperator != gfxContext::OPERATOR_OVER) {
     183               0 :       aContext->SetOperator(aOperator);
     184               0 :       mContext = aContext;
     185                 :     }
     186               0 :   }
     187               0 :   ~AutoSetOperator() {
     188               0 :     if (mContext) {
     189               0 :       mContext->SetOperator(gfxContext::OPERATOR_OVER);
     190                 :     }
     191               0 :   }
     192                 : private:
     193                 :   nsRefPtr<gfxContext> mContext;
     194                 : };
     195                 : 
     196                 : static BasicImplData*
     197               0 : ToData(Layer* aLayer)
     198                 : {
     199               0 :   return static_cast<BasicImplData*>(aLayer->ImplData());
     200                 : }
     201                 : 
     202                 : template<class Container>
     203               0 : static void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
     204                 : template<class Container>
     205               0 : static void ContainerRemoveChild(Layer* aChild, Container* aContainer);
     206                 : 
     207                 : class BasicContainerLayer : public ContainerLayer, public BasicImplData {
     208                 :   template<class Container>
     209                 :   friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
     210                 :   template<class Container>
     211                 :   friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
     212                 : 
     213                 : public:
     214               0 :   BasicContainerLayer(BasicLayerManager* aManager) :
     215               0 :     ContainerLayer(aManager, static_cast<BasicImplData*>(this))
     216                 :   {
     217               0 :     MOZ_COUNT_CTOR(BasicContainerLayer);
     218               0 :     mSupportsComponentAlphaChildren = true;
     219               0 :   }
     220                 :   virtual ~BasicContainerLayer();
     221                 : 
     222               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
     223                 :   {
     224               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     225                 :                  "Can only set properties in construction phase");
     226               0 :     ContainerLayer::SetVisibleRegion(aRegion);
     227               0 :   }
     228               0 :   virtual void InsertAfter(Layer* aChild, Layer* aAfter)
     229                 :   {
     230               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     231                 :                  "Can only set properties in construction phase");
     232               0 :     ContainerInsertAfter(aChild, aAfter, this);
     233               0 :   }
     234                 : 
     235               0 :   virtual void RemoveChild(Layer* aChild)
     236                 :   { 
     237               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     238                 :                  "Can only set properties in construction phase");
     239               0 :     ContainerRemoveChild(aChild, this);
     240               0 :   }
     241                 : 
     242               0 :   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
     243                 :   {
     244                 :     // We push groups for container layers if we need to, which always
     245                 :     // are aligned in device space, so it doesn't really matter how we snap
     246                 :     // containers.
     247               0 :     gfxMatrix residual;
     248               0 :     gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
     249               0 :     idealTransform.ProjectTo2D();
     250                 : 
     251               0 :     if (!idealTransform.CanDraw2D()) {
     252               0 :       mEffectiveTransform = idealTransform;
     253               0 :       ComputeEffectiveTransformsForChildren(gfx3DMatrix());
     254               0 :       mUseIntermediateSurface = true;
     255               0 :       return;
     256                 :     }
     257                 : 
     258               0 :     mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
     259                 :     // We always pass the ideal matrix down to our children, so there is no
     260                 :     // need to apply any compensation using the residual from SnapTransform.
     261               0 :     ComputeEffectiveTransformsForChildren(idealTransform);
     262                 : 
     263                 :     /* If we have a single child, it can just inherit our opacity,
     264                 :      * otherwise we need a PushGroup and we need to mark ourselves as using
     265                 :      * an intermediate surface so our children don't inherit our opacity
     266                 :      * via GetEffectiveOpacity.
     267                 :      */
     268               0 :     mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren();
     269                 :   }
     270                 : 
     271                 :   /**
     272                 :    * Returns true when:
     273                 :    * a) no (non-hidden) childrens' visible areas overlap in
     274                 :    * (aInRect intersected with this layer's visible region).
     275                 :    * b) the (non-hidden) childrens' visible areas cover
     276                 :    * (aInRect intersected with this layer's visible region).
     277                 :    * c) this layer and all (non-hidden) children have transforms that are translations
     278                 :    * by integers.
     279                 :    * aInRect is in the root coordinate system.
     280                 :    * Child layers with opacity do not contribute to the covered area in check b).
     281                 :    * This method can be conservative; it's OK to return false under any
     282                 :    * circumstances.
     283                 :    */
     284                 :   bool ChildrenPartitionVisibleRegion(const nsIntRect& aInRect);
     285                 : 
     286               0 :   void ForceIntermediateSurface() { mUseIntermediateSurface = true; }
     287                 : 
     288                 : protected:
     289               0 :   BasicLayerManager* BasicManager()
     290                 :   {
     291               0 :     return static_cast<BasicLayerManager*>(mManager);
     292                 :   }
     293                 : };
     294                 : 
     295               0 : BasicContainerLayer::~BasicContainerLayer()
     296                 : {
     297               0 :   while (mFirstChild) {
     298               0 :     ContainerRemoveChild(mFirstChild, this);
     299                 :   }
     300                 : 
     301               0 :   MOZ_COUNT_DTOR(BasicContainerLayer);
     302               0 : }
     303                 : 
     304                 : bool
     305               0 : BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
     306                 : {
     307               0 :   gfxMatrix transform;
     308               0 :   if (!GetEffectiveTransform().CanDraw2D(&transform) ||
     309               0 :       transform.HasNonIntegerTranslation())
     310               0 :     return false;
     311                 : 
     312               0 :   nsIntPoint offset(PRInt32(transform.x0), PRInt32(transform.y0));
     313               0 :   nsIntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset);
     314               0 :   nsIntRegion covered;
     315                 : 
     316               0 :   for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
     317               0 :     if (ToData(l)->IsHidden())
     318               0 :       continue;
     319                 : 
     320               0 :     gfxMatrix childTransform;
     321               0 :     if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) ||
     322               0 :         childTransform.HasNonIntegerTranslation() ||
     323               0 :         l->GetEffectiveOpacity() != 1.0)
     324               0 :       return false;
     325               0 :     nsIntRegion childRegion = l->GetEffectiveVisibleRegion();
     326               0 :     childRegion.MoveBy(PRInt32(childTransform.x0), PRInt32(childTransform.y0));
     327               0 :     childRegion.And(childRegion, rect);
     328               0 :     if (l->GetClipRect()) {
     329               0 :       childRegion.And(childRegion, *l->GetClipRect() + offset);
     330                 :     }
     331               0 :     nsIntRegion intersection;
     332               0 :     intersection.And(covered, childRegion);
     333               0 :     if (!intersection.IsEmpty())
     334               0 :       return false;
     335               0 :     covered.Or(covered, childRegion);
     336                 :   }
     337                 : 
     338               0 :   return covered.Contains(rect);
     339                 : }
     340                 : 
     341                 : template<class Container>
     342                 : static void
     343               0 : ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
     344                 : {
     345               0 :   NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
     346                 :                "Child has wrong manager");
     347               0 :   NS_ASSERTION(!aChild->GetParent(),
     348                 :                "aChild already in the tree");
     349               0 :   NS_ASSERTION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
     350                 :                "aChild already has siblings?");
     351               0 :   NS_ASSERTION(!aAfter ||
     352                 :                (aAfter->Manager() == aContainer->Manager() &&
     353                 :                 aAfter->GetParent() == aContainer),
     354                 :                "aAfter is not our child");
     355                 : 
     356               0 :   aChild->SetParent(aContainer);
     357               0 :   if (aAfter == aContainer->mLastChild) {
     358               0 :     aContainer->mLastChild = aChild;
     359                 :   }
     360               0 :   if (!aAfter) {
     361               0 :     aChild->SetNextSibling(aContainer->mFirstChild);
     362               0 :     if (aContainer->mFirstChild) {
     363               0 :       aContainer->mFirstChild->SetPrevSibling(aChild);
     364                 :     }
     365               0 :     aContainer->mFirstChild = aChild;
     366               0 :     NS_ADDREF(aChild);
     367               0 :     aContainer->DidInsertChild(aChild);
     368               0 :     return;
     369                 :   }
     370                 : 
     371               0 :   Layer* next = aAfter->GetNextSibling();
     372               0 :   aChild->SetNextSibling(next);
     373               0 :   aChild->SetPrevSibling(aAfter);
     374               0 :   if (next) {
     375               0 :     next->SetPrevSibling(aChild);
     376                 :   }
     377               0 :   aAfter->SetNextSibling(aChild);
     378               0 :   NS_ADDREF(aChild);
     379               0 :   aContainer->DidInsertChild(aChild);
     380                 : }
     381                 : 
     382                 : template<class Container>
     383                 : static void
     384               0 : ContainerRemoveChild(Layer* aChild, Container* aContainer)
     385                 : {
     386               0 :   NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
     387                 :                "Child has wrong manager");
     388               0 :   NS_ASSERTION(aChild->GetParent() == aContainer,
     389                 :                "aChild not our child");
     390                 : 
     391               0 :   Layer* prev = aChild->GetPrevSibling();
     392               0 :   Layer* next = aChild->GetNextSibling();
     393               0 :   if (prev) {
     394               0 :     prev->SetNextSibling(next);
     395                 :   } else {
     396               0 :     aContainer->mFirstChild = next;
     397                 :   }
     398               0 :   if (next) {
     399               0 :     next->SetPrevSibling(prev);
     400                 :   } else {
     401               0 :     aContainer->mLastChild = prev;
     402                 :   }
     403                 : 
     404               0 :   aChild->SetNextSibling(nsnull);
     405               0 :   aChild->SetPrevSibling(nsnull);
     406               0 :   aChild->SetParent(nsnull);
     407                 : 
     408               0 :   aContainer->DidRemoveChild(aChild);
     409               0 :   NS_RELEASE(aChild);
     410               0 : }
     411                 : 
     412                 : class BasicThebesLayer;
     413                 : class BasicThebesLayerBuffer : public ThebesLayerBuffer {
     414                 :   typedef ThebesLayerBuffer Base;
     415                 : 
     416                 : public:
     417               0 :   BasicThebesLayerBuffer(BasicThebesLayer* aLayer)
     418                 :     : Base(ContainsVisibleBounds)
     419               0 :     , mLayer(aLayer)
     420                 :   {
     421               0 :   }
     422                 : 
     423               0 :   virtual ~BasicThebesLayerBuffer()
     424               0 :   {}
     425                 : 
     426                 :   using Base::BufferRect;
     427                 :   using Base::BufferRotation;
     428                 : 
     429                 :   /**
     430                 :    * Complete the drawing operation. The region to draw must have been
     431                 :    * drawn before this is called. The contents of the buffer are drawn
     432                 :    * to aTarget.
     433                 :    */
     434                 :   void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity);
     435                 : 
     436                 :   virtual already_AddRefed<gfxASurface>
     437                 :   CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags);
     438                 : 
     439                 :   /**
     440                 :    * Swap out the old backing buffer for |aBuffer| and attributes.
     441                 :    */
     442               0 :   void SetBackingBuffer(gfxASurface* aBuffer,
     443                 :                         const nsIntRect& aRect, const nsIntPoint& aRotation)
     444                 :   {
     445               0 :     gfxIntSize prevSize = gfxIntSize(BufferRect().width, BufferRect().height);
     446               0 :     gfxIntSize newSize = aBuffer->GetSize();
     447               0 :     NS_ABORT_IF_FALSE(newSize == prevSize,
     448                 :                       "Swapped-in buffer size doesn't match old buffer's!");
     449               0 :     nsRefPtr<gfxASurface> oldBuffer;
     450               0 :     oldBuffer = SetBuffer(aBuffer, aRect, aRotation);
     451               0 :   }
     452                 : 
     453                 :   void SetBackingBufferAndUpdateFrom(
     454                 :     gfxASurface* aBuffer,
     455                 :     gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
     456                 :     const nsIntRegion& aUpdateRegion);
     457                 : 
     458                 : private:
     459               0 :   BasicThebesLayerBuffer(gfxASurface* aBuffer,
     460                 :                          const nsIntRect& aRect, const nsIntPoint& aRotation)
     461                 :     // The size policy doesn't really matter here; this constructor is
     462                 :     // intended to be used for creating temporaries
     463               0 :     : ThebesLayerBuffer(ContainsVisibleBounds)
     464                 :   {
     465               0 :     SetBuffer(aBuffer, aRect, aRotation);
     466               0 :   }
     467                 : 
     468                 :   BasicThebesLayer* mLayer;
     469                 : };
     470                 : 
     471                 : class BasicThebesLayer : public ThebesLayer, public BasicImplData {
     472                 : public:
     473                 :   typedef BasicThebesLayerBuffer Buffer;
     474                 : 
     475               0 :   BasicThebesLayer(BasicLayerManager* aLayerManager) :
     476                 :     ThebesLayer(aLayerManager, static_cast<BasicImplData*>(this)),
     477               0 :     mBuffer(this)
     478                 :   {
     479               0 :     MOZ_COUNT_CTOR(BasicThebesLayer);
     480               0 :   }
     481               0 :   virtual ~BasicThebesLayer()
     482               0 :   {
     483               0 :     MOZ_COUNT_DTOR(BasicThebesLayer);
     484               0 :   }
     485                 : 
     486               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
     487                 :   {
     488               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     489                 :                  "Can only set properties in construction phase");
     490               0 :     ThebesLayer::SetVisibleRegion(aRegion);
     491               0 :   }
     492               0 :   virtual void InvalidateRegion(const nsIntRegion& aRegion)
     493                 :   {
     494               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     495                 :                  "Can only set properties in construction phase");
     496               0 :     mValidRegion.Sub(mValidRegion, aRegion);
     497               0 :   }
     498                 : 
     499                 :   virtual void PaintThebes(gfxContext* aContext,
     500                 :                            LayerManager::DrawThebesLayerCallback aCallback,
     501                 :                            void* aCallbackData,
     502                 :                            ReadbackProcessor* aReadback);
     503                 : 
     504               0 :   virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); }
     505                 :   
     506                 :   virtual already_AddRefed<gfxASurface>
     507               0 :   CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize)
     508                 :   {
     509               0 :     nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer();
     510               0 :     if (!referenceSurface) {
     511               0 :       gfxContext* defaultTarget = BasicManager()->GetDefaultTarget();
     512               0 :       if (defaultTarget) {
     513               0 :         referenceSurface = defaultTarget->CurrentSurface();
     514                 :       } else {
     515               0 :         nsIWidget* widget = BasicManager()->GetRetainerWidget();
     516               0 :         if (widget) {
     517               0 :           referenceSurface = widget->GetThebesSurface();
     518                 :         } else {
     519               0 :           referenceSurface = BasicManager()->GetTarget()->CurrentSurface();
     520                 :         }
     521                 :       }
     522                 :     }
     523               0 :     return referenceSurface->CreateSimilarSurface(
     524               0 :       aType, gfxIntSize(aSize.width, aSize.height));
     525                 :   }
     526                 : 
     527               0 :   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
     528                 :   {
     529               0 :     if (!BasicManager()->IsRetained()) {
     530                 :       // Don't do any snapping of our transform, since we're just going to
     531                 :       // draw straight through without intermediate buffers.
     532               0 :       mEffectiveTransform = GetLocalTransform()*aTransformToSurface;
     533               0 :       if (gfxPoint(0,0) != mResidualTranslation) {
     534               0 :         mResidualTranslation = gfxPoint(0,0);
     535               0 :         mValidRegion.SetEmpty();
     536                 :       }
     537               0 :       return;
     538                 :     }
     539               0 :     ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface);
     540                 :   }
     541                 : 
     542                 :   // Sync front/back buffers content
     543               0 :   virtual void SyncFrontBufferToBackBuffer() {}
     544                 : 
     545                 : protected:
     546               0 :   BasicLayerManager* BasicManager()
     547                 :   {
     548               0 :     return static_cast<BasicLayerManager*>(mManager);
     549                 :   }
     550                 : 
     551                 :   virtual void
     552               0 :   PaintBuffer(gfxContext* aContext,
     553                 :               const nsIntRegion& aRegionToDraw,
     554                 :               const nsIntRegion& aExtendedRegionToDraw,
     555                 :               const nsIntRegion& aRegionToInvalidate,
     556                 :               bool aDidSelfCopy,
     557                 :               LayerManager::DrawThebesLayerCallback aCallback,
     558                 :               void* aCallbackData)
     559                 :   {
     560               0 :     if (!aCallback) {
     561               0 :       BasicManager()->SetTransactionIncomplete();
     562               0 :       return;
     563                 :     }
     564                 :     aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate,
     565               0 :               aCallbackData);
     566                 :     // Everything that's visible has been validated. Do this instead of just
     567                 :     // OR-ing with aRegionToDraw, since that can lead to a very complex region
     568                 :     // here (OR doesn't automatically simplify to the simplest possible
     569                 :     // representation of a region.)
     570               0 :     nsIntRegion tmp;
     571               0 :     tmp.Or(mVisibleRegion, aExtendedRegionToDraw);
     572               0 :     mValidRegion.Or(mValidRegion, tmp);
     573                 :   }
     574                 : 
     575                 :   Buffer mBuffer;
     576                 : };
     577                 : 
     578                 : /**
     579                 :  * Clips to the smallest device-pixel-aligned rectangle containing aRect
     580                 :  * in user space.
     581                 :  * Returns true if the clip is "perfect", i.e. we actually clipped exactly to
     582                 :  * aRect.
     583                 :  */
     584                 : static bool
     585               0 : ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
     586                 : {
     587               0 :   gfxRect userRect(aRect.x, aRect.y, aRect.width, aRect.height);
     588               0 :   gfxRect deviceRect = aContext->UserToDevice(userRect);
     589               0 :   deviceRect.RoundOut();
     590                 : 
     591               0 :   gfxMatrix currentMatrix = aContext->CurrentMatrix();
     592               0 :   aContext->IdentityMatrix();
     593               0 :   aContext->NewPath();
     594               0 :   aContext->Rectangle(deviceRect);
     595               0 :   aContext->Clip();
     596               0 :   aContext->SetMatrix(currentMatrix);
     597                 : 
     598               0 :   return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
     599                 : }
     600                 : 
     601                 : static nsIntRegion
     602               0 : IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
     603                 : {
     604               0 :   gfxRect clip = aContext->GetClipExtents();
     605               0 :   clip.RoundOut();
     606               0 :   nsIntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
     607               0 :   nsIntRegion result;
     608               0 :   result.And(aRegion, r);
     609                 :   return result;
     610                 : }
     611                 : 
     612                 : static void
     613               0 : SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
     614                 : {
     615               0 :   if (!aTarget->IsCairo()) {
     616                 :     // Azure targets don't contain antialiasing flags at this point.
     617               0 :     return;
     618                 :   }
     619                 : 
     620               0 :   nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
     621               0 :   if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
     622                 :     // Destination doesn't have alpha channel; no need to set any special flags
     623                 :     return;
     624                 :   }
     625                 : 
     626               0 :   const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
     627                 :   surface->SetSubpixelAntialiasingEnabled(
     628               0 :       !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
     629               0 :       surface->GetOpaqueRect().Contains(
     630               0 :         aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
     631                 : }
     632                 : 
     633                 : already_AddRefed<gfxContext>
     634               0 : BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
     635                 :                                      const nsIntRegion& aRegion,
     636                 :                                      bool* aNeedsClipToVisibleRegion)
     637                 : {
     638                 :   // If we need to call PushGroup, we should clip to the smallest possible
     639                 :   // area first to minimize the size of the temporary surface.
     640               0 :   bool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
     641                 : 
     642               0 :   nsRefPtr<gfxContext> result;
     643               0 :   if (aLayer->CanUseOpaqueSurface() &&
     644               0 :       ((didCompleteClip && aRegion.GetNumRects() == 1) ||
     645               0 :        !aContext->CurrentMatrix().HasNonIntegerTranslation())) {
     646                 :     // If the layer is opaque in its visible region we can push a CONTENT_COLOR
     647                 :     // group. We need to make sure that only pixels inside the layer's visible
     648                 :     // region are copied back to the destination. Remember if we've already
     649                 :     // clipped precisely to the visible region.
     650               0 :     *aNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
     651               0 :     result = PushGroupWithCachedSurface(aContext, gfxASurface::CONTENT_COLOR);
     652                 :   } else {
     653               0 :     *aNeedsClipToVisibleRegion = false;
     654               0 :     result = aContext;
     655               0 :     aContext->PushGroupAndCopyBackground(gfxASurface::CONTENT_COLOR_ALPHA);
     656                 :   }
     657               0 :   return result.forget();
     658                 : }
     659                 : 
     660                 : void
     661               0 : BasicThebesLayer::PaintThebes(gfxContext* aContext,
     662                 :                               LayerManager::DrawThebesLayerCallback aCallback,
     663                 :                               void* aCallbackData,
     664                 :                               ReadbackProcessor* aReadback)
     665                 : {
     666               0 :   NS_ASSERTION(BasicManager()->InDrawing(),
     667                 :                "Can only draw in drawing phase");
     668               0 :   nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
     669                 : 
     670               0 :   nsTArray<ReadbackProcessor::Update> readbackUpdates;
     671               0 :   if (aReadback && UsedForReadback()) {
     672               0 :     aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
     673                 :   }
     674               0 :   SyncFrontBufferToBackBuffer();
     675                 : 
     676               0 :   bool canUseOpaqueSurface = CanUseOpaqueSurface();
     677                 :   Buffer::ContentType contentType =
     678                 :     canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
     679               0 :                           gfxASurface::CONTENT_COLOR_ALPHA;
     680               0 :   float opacity = GetEffectiveOpacity();
     681                 : 
     682               0 :   if (!BasicManager()->IsRetained() ||
     683               0 :       (!canUseOpaqueSurface &&
     684                 :        (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
     685               0 :        !MustRetainContent())) {
     686               0 :     NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
     687                 : 
     688               0 :     mValidRegion.SetEmpty();
     689               0 :     mBuffer.Clear();
     690                 : 
     691               0 :     nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
     692                 : 
     693                 : #ifdef MOZ_RENDERTRACE
     694                 :     RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
     695                 : #endif
     696                 : 
     697               0 :     if (!toDraw.IsEmpty() && !IsHidden()) {
     698               0 :       if (!aCallback) {
     699               0 :         BasicManager()->SetTransactionIncomplete();
     700                 :         return;
     701                 :       }
     702                 : 
     703               0 :       aContext->Save();
     704                 : 
     705               0 :       bool needsClipToVisibleRegion = GetClipToVisibleRegion();
     706                 :       bool needsGroup =
     707               0 :           opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER;
     708               0 :       nsRefPtr<gfxContext> groupContext;
     709               0 :       if (needsGroup) {
     710                 :         groupContext =
     711                 :           BasicManager()->PushGroupForLayer(aContext, this, toDraw,
     712               0 :                                             &needsClipToVisibleRegion);
     713               0 :         if (GetOperator() != gfxContext::OPERATOR_OVER) {
     714               0 :           needsClipToVisibleRegion = true;
     715                 :         }
     716                 :       } else {
     717               0 :         groupContext = aContext;
     718                 :       }
     719               0 :       SetAntialiasingFlags(this, groupContext);
     720               0 :       aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
     721               0 :       if (needsGroup) {
     722               0 :         BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
     723               0 :         if (needsClipToVisibleRegion) {
     724               0 :           gfxUtils::ClipToRegion(aContext, toDraw);
     725                 :         }
     726               0 :         AutoSetOperator setOperator(aContext, GetOperator());
     727               0 :         aContext->Paint(opacity);
     728                 :       }
     729                 : 
     730               0 :       aContext->Restore();
     731                 :     }
     732                 : 
     733                 : #ifdef MOZ_RENDERTRACE
     734                 :     RenderTraceInvalidateEnd(this, "FFFF00");
     735                 : #endif
     736                 :     return;
     737                 :   }
     738                 : 
     739                 :   {
     740               0 :     PRUint32 flags = 0;
     741                 : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
     742               0 :     gfxMatrix transform;
     743               0 :     if (!GetEffectiveTransform().CanDraw2D(&transform) ||
     744               0 :         transform.HasNonIntegerTranslation()) {
     745               0 :       flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
     746                 :     }
     747                 : #endif
     748                 :     Buffer::PaintState state =
     749               0 :       mBuffer.BeginPaint(this, contentType, flags);
     750               0 :     mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
     751                 : 
     752               0 :     if (state.mContext) {
     753                 :       // The area that became invalid and is visible needs to be repainted
     754                 :       // (this could be the whole visible area if our buffer switched
     755                 :       // from RGB to RGBA, because we might need to repaint with
     756                 :       // subpixel AA)
     757                 :       state.mRegionToInvalidate.And(state.mRegionToInvalidate,
     758               0 :                                     GetEffectiveVisibleRegion());
     759               0 :       nsIntRegion extendedDrawRegion = state.mRegionToDraw;
     760               0 :       SetAntialiasingFlags(this, state.mContext);
     761                 : 
     762                 : #ifdef MOZ_RENDERTRACE
     763                 :       RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
     764                 : #endif
     765                 : 
     766                 :       PaintBuffer(state.mContext,
     767                 :                   state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
     768                 :                   state.mDidSelfCopy,
     769               0 :                   aCallback, aCallbackData);
     770               0 :       Mutated();
     771                 : 
     772                 : #ifdef MOZ_RENDERTRACE
     773                 :       RenderTraceInvalidateEnd(this, "FFFF00");
     774                 : #endif
     775                 :     } else {
     776                 :       // It's possible that state.mRegionToInvalidate is nonempty here,
     777                 :       // if we are shrinking the valid region to nothing.
     778               0 :       NS_ASSERTION(state.mRegionToDraw.IsEmpty(),
     779                 :                    "If we need to draw, we should have a context");
     780                 :     }
     781                 :   }
     782                 : 
     783               0 :   if (BasicManager()->IsTransactionIncomplete())
     784                 :     return;
     785                 : 
     786               0 :   gfxRect clipExtents;
     787               0 :   clipExtents = aContext->GetClipExtents();
     788               0 :   if (!IsHidden() && !clipExtents.IsEmpty()) {
     789               0 :     AutoSetOperator setOperator(aContext, GetOperator());
     790               0 :     mBuffer.DrawTo(this, aContext, opacity);
     791                 :   }
     792                 : 
     793               0 :   for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
     794               0 :     ReadbackProcessor::Update& update = readbackUpdates[i];
     795               0 :     nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
     796                 :     nsRefPtr<gfxContext> ctx =
     797               0 :       update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
     798               0 :                                             update.mSequenceCounter);
     799               0 :     if (ctx) {
     800               0 :       NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
     801               0 :       ctx->Translate(gfxPoint(offset.x, offset.y));
     802               0 :       mBuffer.DrawTo(this, ctx, 1.0);
     803               0 :       update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
     804                 :     }
     805                 :   }
     806                 : }
     807                 : 
     808                 : static bool
     809               0 : IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
     810                 : {
     811                 :   // Assume clipping is cheap if the context just has an integer
     812                 :   // translation, and the visible region is simple.
     813               0 :   return !aTarget->CurrentMatrix().HasNonIntegerTranslation() &&
     814               0 :          aRegion.GetNumRects() <= 1; 
     815                 : }
     816                 : 
     817                 : void
     818               0 : BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
     819                 :                                gfxContext* aTarget,
     820                 :                                float aOpacity)
     821                 : {
     822               0 :   aTarget->Save();
     823                 :   // If the entire buffer is valid, we can just draw the whole thing,
     824                 :   // no need to clip. But we'll still clip if clipping is cheap ---
     825                 :   // that might let us copy a smaller region of the buffer.
     826                 :   // Also clip to the visible region if we're told to.
     827               0 :   if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
     828               0 :       (ToData(aLayer)->GetClipToVisibleRegion() &&
     829               0 :        !aLayer->GetVisibleRegion().Contains(BufferRect())) ||
     830               0 :       IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
     831                 :     // We don't want to draw invalid stuff, so we need to clip. Might as
     832                 :     // well clip to the smallest area possible --- the visible region.
     833                 :     // Bug 599189 if there is a non-integer-translation transform in aTarget,
     834                 :     // we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
     835                 :     // and may cause gray lines.
     836               0 :     gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
     837                 :   }
     838               0 :   DrawBufferWithRotation(aTarget, aOpacity);
     839               0 :   aTarget->Restore();
     840               0 : }
     841                 : 
     842                 : already_AddRefed<gfxASurface>
     843               0 : BasicThebesLayerBuffer::CreateBuffer(ContentType aType, 
     844                 :                                      const nsIntSize& aSize, PRUint32 aFlags)
     845                 : {
     846               0 :   return mLayer->CreateBuffer(aType, aSize);
     847                 : }
     848                 : 
     849                 : void
     850               0 : BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
     851                 :   gfxASurface* aBuffer,
     852                 :   gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
     853                 :   const nsIntRegion& aUpdateRegion)
     854                 : {
     855               0 :   SetBackingBuffer(aBuffer, aRect, aRotation);
     856                 :   nsRefPtr<gfxContext> destCtx =
     857               0 :     GetContextForQuadrantUpdate(aUpdateRegion.GetBounds());
     858               0 :   destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
     859               0 :   if (IsClippingCheap(destCtx, aUpdateRegion)) {
     860               0 :     gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
     861                 :   }
     862                 : 
     863               0 :   BasicThebesLayerBuffer srcBuffer(aSource, aRect, aRotation);
     864               0 :   srcBuffer.DrawBufferWithRotation(destCtx, 1.0);
     865               0 : }
     866                 : 
     867                 : class BasicImageLayer : public ImageLayer, public BasicImplData {
     868                 : public:
     869               0 :   BasicImageLayer(BasicLayerManager* aLayerManager) :
     870                 :     ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
     871               0 :     mSize(-1, -1)
     872                 :   {
     873               0 :     MOZ_COUNT_CTOR(BasicImageLayer);
     874               0 :   }
     875               0 :   virtual ~BasicImageLayer()
     876               0 :   {
     877               0 :     MOZ_COUNT_DTOR(BasicImageLayer);
     878               0 :   }
     879                 : 
     880               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
     881                 :   {
     882               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
     883                 :                  "Can only set properties in construction phase");
     884               0 :     ImageLayer::SetVisibleRegion(aRegion);
     885               0 :   }
     886                 : 
     887                 :   virtual void Paint(gfxContext* aContext);
     888                 : 
     889                 :   static void PaintContext(gfxPattern* aPattern,
     890                 :                            const nsIntRegion& aVisible,
     891                 :                            const nsIntRect* aTileSourceRect,
     892                 :                            float aOpacity,
     893                 :                            gfxContext* aContext);
     894                 : 
     895                 : protected:
     896               0 :   BasicLayerManager* BasicManager()
     897                 :   {
     898               0 :     return static_cast<BasicLayerManager*>(mManager);
     899                 :   }
     900                 : 
     901                 :   already_AddRefed<gfxPattern>
     902                 :   GetAndPaintCurrentImage(gfxContext* aContext,
     903                 :                           float aOpacity);
     904                 : 
     905                 :   gfxIntSize mSize;
     906                 : };
     907                 : 
     908                 : void
     909               0 : BasicImageLayer::Paint(gfxContext* aContext)
     910                 : {
     911               0 :   if (IsHidden())
     912               0 :     return;
     913                 :   nsRefPtr<gfxPattern> dontcare =
     914               0 :       GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
     915                 : }
     916                 : 
     917                 : already_AddRefed<gfxPattern>
     918               0 : BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
     919                 :                                          float aOpacity)
     920                 : {
     921               0 :   if (!mContainer)
     922               0 :     return nsnull;
     923                 : 
     924               0 :   mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nsnull : BasicManager()->GetImageFactory());
     925                 : 
     926               0 :   nsRefPtr<gfxASurface> surface;
     927               0 :   AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
     928               0 :   Image *image = autoLock.GetImage();
     929               0 :   gfxIntSize size = mSize = autoLock.GetSize();
     930                 : 
     931               0 :   if (!surface || surface->CairoStatus()) {
     932               0 :     return nsnull;
     933                 :   }
     934                 : 
     935               0 :   nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
     936               0 :   if (!pat) {
     937               0 :     return nsnull;
     938                 :   }
     939                 : 
     940               0 :   pat->SetFilter(mFilter);
     941               0 :   gfxIntSize sourceSize = surface->GetSize();
     942               0 :   if (mScaleMode != SCALE_NONE) {
     943               0 :     NS_ASSERTION(mScaleMode == SCALE_STRETCH,
     944                 :       "No other scalemodes than stretch and none supported yet.");
     945               0 :     gfxMatrix mat = pat->GetMatrix();
     946               0 :     mat.Scale(float(sourceSize.width) / mScaleToSize.width, float(sourceSize.height) / mScaleToSize.height);
     947               0 :     pat->SetMatrix(mat);
     948               0 :     size = mScaleToSize;
     949                 :   }
     950                 : 
     951                 :   // The visible region can extend outside the image.  If we're not
     952                 :   // tiling, we don't want to draw into that area, so just draw within
     953                 :   // the image bounds.
     954               0 :   const nsIntRect* tileSrcRect = GetTileSourceRect();
     955               0 :   AutoSetOperator setOperator(aContext, GetOperator());
     956                 :   PaintContext(pat,
     957               0 :                tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
     958                 :                tileSrcRect,
     959               0 :                aOpacity, aContext);
     960                 : 
     961               0 :   GetContainer()->NotifyPaintedImage(image);
     962                 : 
     963               0 :   return pat.forget();
     964                 : }
     965                 : 
     966                 : /*static*/ void
     967               0 : BasicImageLayer::PaintContext(gfxPattern* aPattern,
     968                 :                               const nsIntRegion& aVisible,
     969                 :                               const nsIntRect* aTileSourceRect,
     970                 :                               float aOpacity,
     971                 :                               gfxContext* aContext)
     972                 : {
     973                 :   // Set PAD mode so that when the video is being scaled, we do not sample
     974                 :   // outside the bounds of the video image.
     975               0 :   gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD;
     976                 : 
     977               0 :   if (aContext->IsCairo()) {
     978                 :     // PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness
     979                 :     // and use NONE.
     980               0 :     nsRefPtr<gfxASurface> target = aContext->CurrentSurface();
     981               0 :     gfxASurface::gfxSurfaceType type = target->GetType();
     982               0 :     if (type == gfxASurface::SurfaceTypeXlib ||
     983                 :         type == gfxASurface::SurfaceTypeXcb ||
     984                 :         type == gfxASurface::SurfaceTypeQuartz) {
     985               0 :       extend = gfxPattern::EXTEND_NONE;
     986                 :     }
     987                 :   }
     988                 : 
     989               0 :   if (!aTileSourceRect) {
     990               0 :     aContext->NewPath();
     991                 :     // No need to snap here; our transform has already taken care of it.
     992                 :     // XXX true for arbitrary regions?  Don't care yet though
     993               0 :     gfxUtils::PathFromRegion(aContext, aVisible);
     994               0 :     aPattern->SetExtend(extend);
     995               0 :     aContext->SetPattern(aPattern);
     996               0 :     aContext->FillWithOpacity(aOpacity);
     997                 :   } else {
     998               0 :     nsRefPtr<gfxASurface> source = aPattern->GetSurface();
     999               0 :     NS_ABORT_IF_FALSE(source, "Expecting a surface pattern");
    1000               0 :     gfxIntSize sourceSize = source->GetSize();
    1001               0 :     nsIntRect sourceRect(0, 0, sourceSize.width, sourceSize.height);
    1002               0 :     NS_ABORT_IF_FALSE(sourceRect == *aTileSourceRect,
    1003                 :                       "Cowardly refusing to create a temporary surface for tiling");
    1004                 : 
    1005               0 :     gfxContextAutoSaveRestore saveRestore(aContext);
    1006                 : 
    1007               0 :     aContext->NewPath();
    1008               0 :     gfxUtils::PathFromRegion(aContext, aVisible);
    1009                 : 
    1010               0 :     aPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
    1011               0 :     aContext->SetPattern(aPattern);
    1012               0 :     aContext->FillWithOpacity(aOpacity);
    1013                 :   }
    1014                 : 
    1015                 :   // Reset extend mode for callers that need to reuse the pattern
    1016               0 :   aPattern->SetExtend(extend);
    1017               0 : }
    1018                 : 
    1019                 : class BasicColorLayer : public ColorLayer, public BasicImplData {
    1020                 : public:
    1021               0 :   BasicColorLayer(BasicLayerManager* aLayerManager) :
    1022               0 :     ColorLayer(aLayerManager, static_cast<BasicImplData*>(this))
    1023                 :   {
    1024               0 :     MOZ_COUNT_CTOR(BasicColorLayer);
    1025               0 :   }
    1026               0 :   virtual ~BasicColorLayer()
    1027               0 :   {
    1028               0 :     MOZ_COUNT_DTOR(BasicColorLayer);
    1029               0 :   }
    1030                 : 
    1031               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
    1032                 :   {
    1033               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
    1034                 :                  "Can only set properties in construction phase");
    1035               0 :     ColorLayer::SetVisibleRegion(aRegion);
    1036               0 :   }
    1037                 : 
    1038               0 :   virtual void Paint(gfxContext* aContext)
    1039                 :   {
    1040               0 :     if (IsHidden())
    1041               0 :       return;
    1042               0 :     AutoSetOperator setOperator(aContext, GetOperator());
    1043               0 :     PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
    1044                 :   }
    1045                 : 
    1046                 :   static void PaintColorTo(gfxRGBA aColor, float aOpacity,
    1047                 :                            gfxContext* aContext);
    1048                 : 
    1049                 : protected:
    1050               0 :   BasicLayerManager* BasicManager()
    1051                 :   {
    1052               0 :     return static_cast<BasicLayerManager*>(mManager);
    1053                 :   }
    1054                 : };
    1055                 : 
    1056                 : /*static*/ void
    1057               0 : BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
    1058                 :                               gfxContext* aContext)
    1059                 : {
    1060               0 :   aContext->SetColor(aColor);
    1061               0 :   aContext->Paint(aOpacity);
    1062               0 : }
    1063                 : 
    1064                 : class BasicCanvasLayer : public CanvasLayer,
    1065                 :                          public BasicImplData
    1066                 : {
    1067                 : public:
    1068               0 :   BasicCanvasLayer(BasicLayerManager* aLayerManager) :
    1069               0 :     CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
    1070                 :   {
    1071               0 :     MOZ_COUNT_CTOR(BasicCanvasLayer);
    1072               0 :   }
    1073               0 :   virtual ~BasicCanvasLayer()
    1074               0 :   {
    1075               0 :     MOZ_COUNT_DTOR(BasicCanvasLayer);
    1076               0 :   }
    1077                 : 
    1078               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
    1079                 :   {
    1080               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
    1081                 :                  "Can only set properties in construction phase");
    1082               0 :     CanvasLayer::SetVisibleRegion(aRegion);
    1083               0 :   }
    1084                 : 
    1085                 :   virtual void Initialize(const Data& aData);
    1086                 :   virtual void Paint(gfxContext* aContext);
    1087                 : 
    1088                 :   virtual void PaintWithOpacity(gfxContext* aContext,
    1089                 :                                 float aOpacity);
    1090                 : 
    1091                 : protected:
    1092               0 :   BasicLayerManager* BasicManager()
    1093                 :   {
    1094               0 :     return static_cast<BasicLayerManager*>(mManager);
    1095                 :   }
    1096                 :   void UpdateSurface(gfxASurface* aDestSurface = nsnull);
    1097                 : 
    1098                 :   nsRefPtr<gfxASurface> mSurface;
    1099                 :   nsRefPtr<mozilla::gl::GLContext> mGLContext;
    1100                 :   mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
    1101                 :   
    1102                 :   PRUint32 mCanvasFramebuffer;
    1103                 : 
    1104                 :   bool mGLBufferIsPremultiplied;
    1105                 :   bool mNeedsYFlip;
    1106                 : };
    1107                 : 
    1108                 : void
    1109               0 : BasicCanvasLayer::Initialize(const Data& aData)
    1110                 : {
    1111               0 :   NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
    1112                 : 
    1113               0 :   if (aData.mSurface) {
    1114               0 :     mSurface = aData.mSurface;
    1115               0 :     NS_ASSERTION(aData.mGLContext == nsnull,
    1116                 :                  "CanvasLayer can't have both surface and GLContext");
    1117               0 :     mNeedsYFlip = false;
    1118               0 :   } else if (aData.mGLContext) {
    1119               0 :     NS_ASSERTION(aData.mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
    1120               0 :     mGLContext = aData.mGLContext;
    1121               0 :     mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
    1122               0 :     mCanvasFramebuffer = mGLContext->GetOffscreenFBO();
    1123               0 :     mNeedsYFlip = true;
    1124               0 :   } else if (aData.mDrawTarget) {
    1125               0 :     mDrawTarget = aData.mDrawTarget;
    1126               0 :     mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
    1127               0 :     mNeedsYFlip = false;
    1128                 :   } else {
    1129               0 :     NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
    1130                 :   }
    1131                 : 
    1132               0 :   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
    1133               0 : }
    1134                 : 
    1135                 : void
    1136               0 : BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
    1137                 : {
    1138               0 :   if (mDrawTarget) {
    1139               0 :     mDrawTarget->Flush();
    1140                 :   }
    1141                 : 
    1142               0 :   if (!mGLContext && aDestSurface) {
    1143               0 :     nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
    1144               0 :     tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
    1145               0 :     BasicCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f);
    1146                 :     return;
    1147                 :   }
    1148                 : 
    1149               0 :   if (!mDirty)
    1150               0 :     return;
    1151               0 :   mDirty = false;
    1152                 : 
    1153               0 :   if (mGLContext) {
    1154               0 :     if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
    1155               0 :       NS_ASSERTION(aDestSurface->GetType() == gfxASurface::SurfaceTypeImage,
    1156                 :                    "Destination surface must be ImageSurface type");
    1157               0 :       return;
    1158                 :     }
    1159                 : 
    1160                 :     // We need to read from the GLContext
    1161               0 :     mGLContext->MakeCurrent();
    1162                 : 
    1163                 : #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
    1164                 :     mGLContext->fFinish();
    1165                 :     gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
    1166                 : 
    1167                 :     // XRender can only blend premuliplied alpha, so only allow xrender
    1168                 :     // path if we have premultiplied alpha or opaque content.
    1169                 :     if (offscreenSurface && (mGLBufferIsPremultiplied || (GetContentFlags() & CONTENT_OPAQUE))) {  
    1170                 :         mSurface = offscreenSurface;
    1171                 :         mNeedsYFlip = false;
    1172                 :     }
    1173                 :     else
    1174                 : #endif
    1175                 :     {
    1176                 :     nsRefPtr<gfxImageSurface> isurf = aDestSurface ?
    1177                 :         static_cast<gfxImageSurface*>(aDestSurface) :
    1178                 :         new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
    1179               0 :                             (GetContentFlags() & CONTENT_OPAQUE)
    1180                 :                               ? gfxASurface::ImageFormatRGB24
    1181               0 :                               : gfxASurface::ImageFormatARGB32);
    1182                 : 
    1183               0 :     if (!isurf || isurf->CairoStatus() != 0) {
    1184                 :       return;
    1185                 :     }
    1186                 : 
    1187               0 :     NS_ASSERTION(isurf->Stride() == mBounds.width * 4, "gfxImageSurface stride isn't what we expect!");
    1188                 : 
    1189               0 :     PRUint32 currentFramebuffer = 0;
    1190                 : 
    1191               0 :     mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&currentFramebuffer);
    1192                 : 
    1193                 :     // Make sure that we read pixels from the correct framebuffer, regardless
    1194                 :     // of what's currently bound.
    1195               0 :     if (currentFramebuffer != mCanvasFramebuffer)
    1196               0 :       mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer);
    1197                 : 
    1198                 :     mGLContext->ReadPixelsIntoImageSurface(0, 0,
    1199                 :                                            mBounds.width, mBounds.height,
    1200               0 :                                            isurf);
    1201                 : 
    1202                 :     // Put back the previous framebuffer binding.
    1203               0 :     if (currentFramebuffer != mCanvasFramebuffer)
    1204               0 :       mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer);
    1205                 : 
    1206                 :     // If the underlying GLContext doesn't have a framebuffer into which
    1207                 :     // premultiplied values were written, we have to do this ourselves here.
    1208                 :     // Note that this is a WebGL attribute; GL itself has no knowledge of
    1209                 :     // premultiplied or unpremultiplied alpha.
    1210               0 :     if (!mGLBufferIsPremultiplied)
    1211               0 :       gfxUtils::PremultiplyImageSurface(isurf);
    1212                 : 
    1213                 :     // stick our surface into mSurface, so that the Paint() path is the same
    1214               0 :     if (!aDestSurface) {
    1215               0 :       mSurface = isurf;
    1216                 :     }
    1217                 :   }
    1218                 : }
    1219                 : }
    1220                 : 
    1221                 : void
    1222               0 : BasicCanvasLayer::Paint(gfxContext* aContext)
    1223                 : {
    1224               0 :   if (IsHidden())
    1225               0 :     return;
    1226               0 :   UpdateSurface();
    1227               0 :   FireDidTransactionCallback();
    1228               0 :   PaintWithOpacity(aContext, GetEffectiveOpacity());
    1229                 : }
    1230                 : 
    1231                 : void
    1232               0 : BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
    1233                 :                                    float aOpacity)
    1234                 : {
    1235               0 :   NS_ASSERTION(BasicManager()->InDrawing(),
    1236                 :                "Can only draw in drawing phase");
    1237                 : 
    1238               0 :   if (!mSurface) {
    1239               0 :     NS_WARNING("No valid surface to draw!");
    1240               0 :     return;
    1241                 :   }
    1242                 : 
    1243               0 :   nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
    1244                 : 
    1245               0 :   pat->SetFilter(mFilter);
    1246               0 :   pat->SetExtend(gfxPattern::EXTEND_PAD);
    1247                 : 
    1248               0 :   gfxMatrix m;
    1249               0 :   if (mNeedsYFlip) {
    1250               0 :     m = aContext->CurrentMatrix();
    1251               0 :     aContext->Translate(gfxPoint(0.0, mBounds.height));
    1252               0 :     aContext->Scale(1.0, -1.0);
    1253                 :   }
    1254                 : 
    1255                 :   // If content opaque, then save off current operator and set to source.
    1256                 :   // This ensures that alpha is not applied even if the source surface
    1257                 :   // has an alpha channel
    1258                 :   gfxContext::GraphicsOperator savedOp;
    1259               0 :   if (GetContentFlags() & CONTENT_OPAQUE) {
    1260               0 :     savedOp = aContext->CurrentOperator();
    1261               0 :     aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
    1262                 :   }
    1263                 : 
    1264               0 :   AutoSetOperator setOperator(aContext, GetOperator());
    1265               0 :   aContext->NewPath();
    1266                 :   // No need to snap here; our transform is already set up to snap our rect
    1267               0 :   aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
    1268               0 :   aContext->SetPattern(pat);
    1269               0 :   aContext->FillWithOpacity(aOpacity);
    1270                 : 
    1271                 : #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
    1272                 :   if (mGLContext) {
    1273                 :     // Wait for X to complete all operations before continuing
    1274                 :     // Otherwise gl context could get cleared before X is done.
    1275                 :     mGLContext->WaitNative();
    1276                 :   }
    1277                 : #endif
    1278                 : 
    1279                 :   // Restore surface operator
    1280               0 :   if (GetContentFlags() & CONTENT_OPAQUE) {
    1281               0 :     aContext->SetOperator(savedOp);
    1282                 :   }  
    1283                 : 
    1284               0 :   if (mNeedsYFlip) {
    1285               0 :     aContext->SetMatrix(m);
    1286                 :   }
    1287                 : }
    1288                 : 
    1289                 : class BasicReadbackLayer : public ReadbackLayer,
    1290                 :                            public BasicImplData
    1291                 : {
    1292                 : public:
    1293               0 :   BasicReadbackLayer(BasicLayerManager* aLayerManager) :
    1294               0 :     ReadbackLayer(aLayerManager, static_cast<BasicImplData*>(this))
    1295                 :   {
    1296               0 :     MOZ_COUNT_CTOR(BasicReadbackLayer);
    1297               0 :   }
    1298               0 :   virtual ~BasicReadbackLayer()
    1299               0 :   {
    1300               0 :     MOZ_COUNT_DTOR(BasicReadbackLayer);
    1301               0 :   }
    1302                 : 
    1303               0 :   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
    1304                 :   {
    1305               0 :     NS_ASSERTION(BasicManager()->InConstruction(),
    1306                 :                  "Can only set properties in construction phase");
    1307               0 :     ReadbackLayer::SetVisibleRegion(aRegion);
    1308               0 :   }
    1309                 : 
    1310                 : protected:
    1311               0 :   BasicLayerManager* BasicManager()
    1312                 :   {
    1313               0 :     return static_cast<BasicLayerManager*>(mManager);
    1314                 :   }
    1315                 : };
    1316                 : 
    1317                 : static nsIntRect
    1318               0 : ToOutsideIntRect(const gfxRect &aRect)
    1319                 : {
    1320               0 :   gfxRect r = aRect;
    1321               0 :   r.RoundOut();
    1322               0 :   return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
    1323                 : }
    1324                 : 
    1325                 : static nsIntRect
    1326               0 : ToInsideIntRect(const gfxRect& aRect)
    1327                 : {
    1328               0 :   gfxRect r = aRect;
    1329               0 :   r.RoundIn();
    1330               0 :   return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
    1331                 : }
    1332                 : 
    1333               0 : BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
    1334                 : #ifdef DEBUG
    1335                 :   mPhase(PHASE_NONE),
    1336                 : #endif
    1337                 :   mWidget(aWidget)
    1338                 :   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
    1339                 :   , mCachedSurfaceInUse(false)
    1340               0 :   , mTransactionIncomplete(false)
    1341                 : {
    1342               0 :   MOZ_COUNT_CTOR(BasicLayerManager);
    1343               0 :   NS_ASSERTION(aWidget, "Must provide a widget");
    1344               0 : }
    1345                 : 
    1346               0 : BasicLayerManager::BasicLayerManager() :
    1347                 : #ifdef DEBUG
    1348                 :   mPhase(PHASE_NONE),
    1349                 : #endif
    1350                 :   mWidget(nsnull)
    1351                 :   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
    1352                 :   , mCachedSurfaceInUse(false)
    1353               0 :   , mTransactionIncomplete(false)
    1354                 : {
    1355               0 :   MOZ_COUNT_CTOR(BasicLayerManager);
    1356               0 : }
    1357                 : 
    1358               0 : BasicLayerManager::~BasicLayerManager()
    1359                 : {
    1360               0 :   NS_ASSERTION(!InTransaction(), "Died during transaction?");
    1361                 : 
    1362               0 :   ClearCachedResources();
    1363                 : 
    1364               0 :   mRoot = nsnull;
    1365                 : 
    1366               0 :   MOZ_COUNT_DTOR(BasicLayerManager);
    1367               0 : }
    1368                 : 
    1369                 : void
    1370               0 : BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
    1371                 :                                     BufferMode aDoubleBuffering)
    1372                 : {
    1373               0 :   NS_ASSERTION(!InTransaction(),
    1374                 :                "Must set default target outside transaction");
    1375               0 :   mDefaultTarget = aContext;
    1376               0 :   mDoubleBuffering = aDoubleBuffering;
    1377               0 : }
    1378                 : 
    1379                 : void
    1380               0 : BasicLayerManager::BeginTransaction()
    1381                 : {
    1382               0 :   mUsingDefaultTarget = true;
    1383               0 :   BeginTransactionWithTarget(mDefaultTarget);
    1384               0 : }
    1385                 : 
    1386                 : already_AddRefed<gfxContext>
    1387               0 : BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
    1388                 :                                               gfxASurface::gfxContentType aContent)
    1389                 : {
    1390               0 :   if (mCachedSurfaceInUse || !aTarget->IsCairo()) {
    1391                 :     // We can't cache Azure DrawTargets at this point.
    1392               0 :     aTarget->PushGroup(aContent);
    1393               0 :     nsRefPtr<gfxContext> result = aTarget;
    1394               0 :     return result.forget();
    1395                 :   }
    1396               0 :   mCachedSurfaceInUse = true;
    1397                 : 
    1398               0 :   gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
    1399               0 :   aTarget->IdentityMatrix();
    1400                 : 
    1401               0 :   nsRefPtr<gfxASurface> currentSurf = aTarget->CurrentSurface();
    1402               0 :   gfxRect clip = aTarget->GetClipExtents();
    1403               0 :   clip.RoundOut();
    1404                 : 
    1405               0 :   nsRefPtr<gfxContext> ctx = mCachedSurface.Get(aContent, clip, currentSurf);
    1406                 :   /* Align our buffer for the original surface */
    1407               0 :   ctx->SetMatrix(saveMatrix.Matrix());
    1408               0 :   return ctx.forget();
    1409                 : }
    1410                 : 
    1411                 : void
    1412               0 : BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed)
    1413                 : {
    1414               0 :   if (!aTarget)
    1415               0 :     return;
    1416               0 :   nsRefPtr<gfxASurface> current = aPushed->CurrentSurface();
    1417               0 :   if (aTarget->IsCairo() && mCachedSurface.IsSurface(current)) {
    1418               0 :     gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
    1419               0 :     aTarget->IdentityMatrix();
    1420               0 :     aTarget->SetSource(current);
    1421               0 :     mCachedSurfaceInUse = false;
    1422                 :   } else {
    1423               0 :     aTarget->PopGroupToSource();
    1424                 :   }
    1425                 : }
    1426                 : 
    1427                 : void
    1428               0 : BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
    1429                 : {
    1430                 : #ifdef MOZ_LAYERS_HAVE_LOG
    1431               0 :   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
    1432               0 :   Log();
    1433                 : #endif
    1434                 : 
    1435               0 :   NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
    1436                 : #ifdef DEBUG
    1437               0 :   mPhase = PHASE_CONSTRUCTION;
    1438                 : #endif
    1439               0 :   mTarget = aTarget;
    1440               0 : }
    1441                 : 
    1442                 : static void
    1443               0 : TransformIntRect(nsIntRect& aRect, const gfxMatrix& aMatrix,
    1444                 :                  nsIntRect (*aRoundMethod)(const gfxRect&))
    1445                 : {
    1446               0 :   gfxRect gr = gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
    1447               0 :   gr = aMatrix.TransformBounds(gr);
    1448               0 :   aRect = (*aRoundMethod)(gr);
    1449               0 : }
    1450                 : 
    1451                 : /**
    1452                 :  * This function assumes that GetEffectiveTransform transforms
    1453                 :  * all layers to the same coordinate system (the "root coordinate system").
    1454                 :  * It can't be used as is by accelerated layers because of intermediate surfaces.
    1455                 :  * This must set the hidden flag to true or false on *all* layers in the subtree.
    1456                 :  * It also sets the operator for all layers to "OVER".
    1457                 :  * It clears mClipToVisibleRegion on all layers.
    1458                 :  * @param aClipRect the cliprect, in the root coordinate system. We assume
    1459                 :  * that any layer drawing is clipped to this rect. It is therefore not
    1460                 :  * allowed to add to the opaque region outside that rect.
    1461                 :  * @param aDirtyRect the dirty rect that will be painted, in the root
    1462                 :  * coordinate system. Layers outside this rect should be hidden.
    1463                 :  * @param aOpaqueRegion the opaque region covering aLayer, in the
    1464                 :  * root coordinate system.
    1465                 :  */
    1466                 : enum {
    1467                 :     ALLOW_OPAQUE = 0x01,
    1468                 : };
    1469                 : static void
    1470               0 : MarkLayersHidden(Layer* aLayer, const nsIntRect& aClipRect,
    1471                 :                  const nsIntRect& aDirtyRect,
    1472                 :                  nsIntRegion& aOpaqueRegion,
    1473                 :                  PRUint32 aFlags)
    1474                 : {
    1475               0 :   nsIntRect newClipRect(aClipRect);
    1476               0 :   PRUint32 newFlags = aFlags;
    1477                 : 
    1478                 :   // Allow aLayer or aLayer's descendants to cover underlying layers
    1479                 :   // only if it's opaque.
    1480               0 :   if (aLayer->GetOpacity() != 1.0f) {
    1481               0 :     newFlags &= ~ALLOW_OPAQUE;
    1482                 :   }
    1483                 : 
    1484                 :   {
    1485               0 :     const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
    1486               0 :     if (clipRect) {
    1487               0 :       nsIntRect cr = *clipRect;
    1488                 :       // clipRect is in the container's coordinate system. Get it into the
    1489                 :       // global coordinate system.
    1490               0 :       if (aLayer->GetParent()) {
    1491               0 :         gfxMatrix tr;
    1492               0 :         if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
    1493                 :           // Clip rect is applied after aLayer's transform, i.e., in the coordinate
    1494                 :           // system of aLayer's parent.
    1495               0 :           TransformIntRect(cr, tr, ToInsideIntRect);
    1496                 :         } else {
    1497               0 :           cr.SetRect(0, 0, 0, 0);
    1498                 :         }
    1499                 :       }
    1500               0 :       newClipRect.IntersectRect(newClipRect, cr);
    1501                 :     }
    1502                 :   }
    1503                 : 
    1504               0 :   BasicImplData* data = ToData(aLayer);
    1505               0 :   data->SetOperator(gfxContext::OPERATOR_OVER);
    1506               0 :   data->SetClipToVisibleRegion(false);
    1507                 : 
    1508               0 :   if (!aLayer->AsContainerLayer()) {
    1509               0 :     gfxMatrix transform;
    1510               0 :     if (!aLayer->GetEffectiveTransform().CanDraw2D(&transform)) {
    1511               0 :       data->SetHidden(false);
    1512               0 :       return;
    1513                 :     }
    1514                 : 
    1515               0 :     nsIntRegion region = aLayer->GetEffectiveVisibleRegion();
    1516               0 :     nsIntRect r = region.GetBounds();
    1517               0 :     TransformIntRect(r, transform, ToOutsideIntRect);
    1518               0 :     r.IntersectRect(r, aDirtyRect);
    1519               0 :     data->SetHidden(aOpaqueRegion.Contains(r));
    1520                 : 
    1521                 :     // Allow aLayer to cover underlying layers only if aLayer's
    1522                 :     // content is opaque
    1523               0 :     if ((aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
    1524                 :         (newFlags & ALLOW_OPAQUE)) {
    1525               0 :       nsIntRegionRectIterator it(region);
    1526               0 :       while (const nsIntRect* sr = it.Next()) {
    1527               0 :         r = *sr;
    1528               0 :         TransformIntRect(r, transform, ToInsideIntRect);
    1529                 : 
    1530               0 :         r.IntersectRect(r, newClipRect);
    1531               0 :         aOpaqueRegion.Or(aOpaqueRegion, r);
    1532                 :       }
    1533                 :     }
    1534                 :   } else {
    1535               0 :     Layer* child = aLayer->GetLastChild();
    1536               0 :     bool allHidden = true;
    1537               0 :     for (; child; child = child->GetPrevSibling()) {
    1538               0 :       MarkLayersHidden(child, newClipRect, aDirtyRect, aOpaqueRegion, newFlags);
    1539               0 :       if (!ToData(child)->IsHidden()) {
    1540               0 :         allHidden = false;
    1541                 :       }
    1542                 :     }
    1543               0 :     data->SetHidden(allHidden);
    1544                 :   }
    1545                 : }
    1546                 : 
    1547                 : /**
    1548                 :  * This function assumes that GetEffectiveTransform transforms
    1549                 :  * all layers to the same coordinate system (the "root coordinate system").
    1550                 :  * MarkLayersHidden must be called before calling this.
    1551                 :  * @param aVisibleRect the rectangle of aLayer that is visible (i.e. not
    1552                 :  * clipped and in the dirty rect), in the root coordinate system.
    1553                 :  */
    1554                 : static void
    1555               0 : ApplyDoubleBuffering(Layer* aLayer, const nsIntRect& aVisibleRect)
    1556                 : {
    1557               0 :   BasicImplData* data = ToData(aLayer);
    1558               0 :   if (data->IsHidden())
    1559               0 :     return;
    1560                 : 
    1561               0 :   nsIntRect newVisibleRect(aVisibleRect);
    1562                 : 
    1563                 :   {
    1564               0 :     const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
    1565               0 :     if (clipRect) {
    1566               0 :       nsIntRect cr = *clipRect;
    1567                 :       // clipRect is in the container's coordinate system. Get it into the
    1568                 :       // global coordinate system.
    1569               0 :       if (aLayer->GetParent()) {
    1570               0 :         gfxMatrix tr;
    1571               0 :         if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
    1572               0 :           NS_ASSERTION(!tr.HasNonIntegerTranslation(),
    1573                 :                        "Parent can only have an integer translation");
    1574               0 :           cr += nsIntPoint(PRInt32(tr.x0), PRInt32(tr.y0));
    1575                 :         } else {
    1576               0 :           NS_ERROR("Parent can only have an integer translation");
    1577                 :         }
    1578                 :       }
    1579               0 :       newVisibleRect.IntersectRect(newVisibleRect, cr);
    1580                 :     }
    1581                 :   }
    1582                 : 
    1583                 :   BasicContainerLayer* container =
    1584               0 :     static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
    1585                 :   // Layers that act as their own backbuffers should be drawn to the destination
    1586                 :   // using OPERATOR_SOURCE to ensure that alpha values in a transparent window
    1587                 :   // are cleared. This can also be faster than OPERATOR_OVER.
    1588               0 :   if (!container) {
    1589               0 :     data->SetOperator(gfxContext::OPERATOR_SOURCE);
    1590                 :   } else {
    1591               0 :     if (container->UseIntermediateSurface() ||
    1592               0 :         !container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
    1593                 :       // We need to double-buffer this container.
    1594               0 :       data->SetOperator(gfxContext::OPERATOR_SOURCE);
    1595               0 :       container->ForceIntermediateSurface();
    1596                 :     } else {
    1597                 :       // Tell the children to clip to their visible regions so our assumption
    1598                 :       // that they don't paint outside their visible regions is valid!
    1599               0 :       for (Layer* child = aLayer->GetFirstChild(); child;
    1600                 :            child = child->GetNextSibling()) {
    1601               0 :         ToData(child)->SetClipToVisibleRegion(true);
    1602               0 :         ApplyDoubleBuffering(child, newVisibleRect);
    1603                 :       }
    1604                 :     }
    1605                 :   }
    1606                 : }
    1607                 : 
    1608                 : void
    1609               0 : BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
    1610                 :                                   void* aCallbackData,
    1611                 :                                   EndTransactionFlags aFlags)
    1612                 : {
    1613               0 :   EndTransactionInternal(aCallback, aCallbackData, aFlags);
    1614               0 : }
    1615                 : 
    1616                 : bool
    1617               0 : BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
    1618                 :                                           void* aCallbackData,
    1619                 :                                           EndTransactionFlags aFlags)
    1620                 : {
    1621                 : #ifdef MOZ_LAYERS_HAVE_LOG
    1622               0 :   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
    1623               0 :   Log();
    1624                 : #endif
    1625                 : 
    1626               0 :   NS_ASSERTION(InConstruction(), "Should be in construction phase");
    1627                 : #ifdef DEBUG
    1628               0 :   mPhase = PHASE_DRAWING;
    1629                 : #endif
    1630                 : 
    1631                 : #ifdef MOZ_RENDERTRACE
    1632                 :   Layer* aLayer = GetRoot();
    1633                 :   RenderTraceLayers(aLayer, "FF00");
    1634                 : #endif
    1635                 : 
    1636               0 :   mTransactionIncomplete = false;
    1637                 : 
    1638               0 :   if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
    1639               0 :     nsIntRect clipRect;
    1640               0 :     if (HasShadowManager()) {
    1641                 :       // If this has a shadow manager, the clip extents of mTarget are meaningless.
    1642                 :       // So instead just use the root layer's visible region bounds.
    1643               0 :       const nsIntRect& bounds = mRoot->GetVisibleRegion().GetBounds();
    1644                 :       gfxRect deviceRect =
    1645               0 :           mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
    1646               0 :       clipRect = ToOutsideIntRect(deviceRect);
    1647                 :     } else {
    1648               0 :       gfxContextMatrixAutoSaveRestore save(mTarget);
    1649               0 :       mTarget->SetMatrix(gfxMatrix());
    1650               0 :       clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
    1651                 :     }
    1652                 : 
    1653                 :     // Need to do this before we call ApplyDoubleBuffering,
    1654                 :     // which depends on correct effective transforms
    1655                 :     mSnapEffectiveTransforms =
    1656               0 :       !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING);
    1657               0 :     mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix()));
    1658                 : 
    1659               0 :     if (IsRetained()) {
    1660               0 :       nsIntRegion region;
    1661               0 :       MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
    1662               0 :       if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
    1663               0 :         ApplyDoubleBuffering(mRoot, clipRect);
    1664                 :       }
    1665                 :     }
    1666                 : 
    1667               0 :     PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
    1668                 : 
    1669               0 :     if (!mTransactionIncomplete) {
    1670                 :       // Clear out target if we have a complete transaction.
    1671               0 :       mTarget = nsnull;
    1672                 :     }
    1673                 :   }
    1674                 : 
    1675                 : #ifdef MOZ_LAYERS_HAVE_LOG
    1676               0 :   Log();
    1677               0 :   MOZ_LAYERS_LOG(("]----- EndTransaction"));
    1678                 : #endif
    1679                 : 
    1680                 : #ifdef DEBUG
    1681                 :   // Go back to the construction phase if the transaction isn't complete.
    1682                 :   // Layout will update the layer tree and call EndTransaction().
    1683               0 :   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
    1684                 : #endif
    1685                 : 
    1686               0 :   if (!mTransactionIncomplete) {
    1687                 :     // This is still valid if the transaction was incomplete.
    1688               0 :     mUsingDefaultTarget = false;
    1689                 :   }
    1690                 : 
    1691               0 :   NS_ASSERTION(!aCallback || !mTransactionIncomplete,
    1692                 :                "If callback is not null, transaction must be complete");
    1693                 : 
    1694                 :   // XXX - We should probably assert here that for an incomplete transaction
    1695                 :   // out target is the default target.
    1696                 : 
    1697               0 :   return !mTransactionIncomplete;
    1698                 : }
    1699                 : 
    1700                 : bool
    1701               0 : BasicLayerManager::EndEmptyTransaction()
    1702                 : {
    1703               0 :   if (!mRoot) {
    1704               0 :     return false;
    1705                 :   }
    1706                 : 
    1707               0 :   return EndTransactionInternal(nsnull, nsnull);
    1708                 : }
    1709                 : 
    1710                 : void
    1711               0 : BasicLayerManager::SetRoot(Layer* aLayer)
    1712                 : {
    1713               0 :   NS_ASSERTION(aLayer, "Root can't be null");
    1714               0 :   NS_ASSERTION(aLayer->Manager() == this, "Wrong manager");
    1715               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    1716               0 :   mRoot = aLayer;
    1717               0 : }
    1718                 : 
    1719                 : static pixman_transform
    1720               0 : Matrix3DToPixman(const gfx3DMatrix& aMatrix)
    1721                 : {
    1722                 :   pixman_f_transform transform;
    1723                 : 
    1724               0 :   transform.m[0][0] = aMatrix._11;
    1725               0 :   transform.m[0][1] = aMatrix._21;
    1726               0 :   transform.m[0][2] = aMatrix._41;
    1727               0 :   transform.m[1][0] = aMatrix._12;
    1728               0 :   transform.m[1][1] = aMatrix._22;
    1729               0 :   transform.m[1][2] = aMatrix._42;
    1730               0 :   transform.m[2][0] = aMatrix._14;
    1731               0 :   transform.m[2][1] = aMatrix._24;
    1732               0 :   transform.m[2][2] = aMatrix._44;
    1733                 : 
    1734                 :   pixman_transform result;
    1735               0 :   pixman_transform_from_pixman_f_transform(&result, &transform);
    1736                 : 
    1737                 :   return result;
    1738                 : }
    1739                 : 
    1740                 : static void
    1741               0 : PixmanTransform(const gfxImageSurface *aDest, 
    1742                 :                 const gfxImageSurface *aSrc, 
    1743                 :                 const gfx3DMatrix& aTransform, 
    1744                 :                 gfxPoint aDestOffset)
    1745                 : {
    1746               0 :   gfxIntSize destSize = aDest->GetSize();
    1747               0 :   pixman_image_t* dest = pixman_image_create_bits(aDest->Format() == gfxASurface::ImageFormatARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
    1748                 :                                                   destSize.width,
    1749                 :                                                   destSize.height,
    1750               0 :                                                   (uint32_t*)aDest->Data(),
    1751               0 :                                                   aDest->Stride());
    1752                 : 
    1753               0 :   gfxIntSize srcSize = aSrc->GetSize();
    1754               0 :   pixman_image_t* src = pixman_image_create_bits(aSrc->Format() == gfxASurface::ImageFormatARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
    1755                 :                                                  srcSize.width,
    1756                 :                                                  srcSize.height,
    1757               0 :                                                  (uint32_t*)aSrc->Data(),
    1758               0 :                                                  aSrc->Stride());
    1759                 : 
    1760               0 :   NS_ABORT_IF_FALSE(src && dest, "Failed to create pixman images?");
    1761                 : 
    1762               0 :   pixman_transform pixTransform = Matrix3DToPixman(aTransform);
    1763                 :   pixman_transform pixTransformInverted;
    1764                 : 
    1765                 :   // If the transform is singular then nothing would be drawn anyway, return here
    1766               0 :   if (!pixman_transform_invert(&pixTransformInverted, &pixTransform)) {
    1767               0 :     return;
    1768                 :   }
    1769               0 :   pixman_image_set_transform(src, &pixTransformInverted);
    1770                 : 
    1771                 :   pixman_image_composite32(PIXMAN_OP_SRC,
    1772                 :                            src,
    1773                 :                            nsnull,
    1774                 :                            dest,
    1775                 :                            aDestOffset.x,
    1776                 :                            aDestOffset.y,
    1777                 :                            0,
    1778                 :                            0,
    1779                 :                            0,
    1780                 :                            0,
    1781                 :                            destSize.width,
    1782               0 :                            destSize.height);
    1783                 : 
    1784               0 :   pixman_image_unref(dest);
    1785               0 :   pixman_image_unref(src);
    1786                 : }
    1787                 : 
    1788                 : /**
    1789                 :  * Transform a surface using a gfx3DMatrix and blit to the destination if
    1790                 :  * it is efficient to do so.
    1791                 :  *
    1792                 :  * @param aSource       Source surface.
    1793                 :  * @param aDest         Desintation context.
    1794                 :  * @param aBounds       Area represented by aSource.
    1795                 :  * @param aTransform    Transformation matrix.
    1796                 :  * @param aDrawOffset   Location to draw returned surface on aDest.
    1797                 :  * @param aDontBlit     Never draw to aDest if this is true.
    1798                 :  * @return              Transformed surface, or nsnull if it has been drawn to aDest.
    1799                 :  */
    1800                 : static already_AddRefed<gfxASurface> 
    1801               0 : Transform3D(gfxASurface* aSource, gfxContext* aDest, 
    1802                 :             const gfxRect& aBounds, const gfx3DMatrix& aTransform, 
    1803                 :             gfxPoint& aDrawOffset, bool aDontBlit)
    1804                 : {
    1805               0 :   nsRefPtr<gfxImageSurface> sourceImage = aSource->GetAsImageSurface();
    1806               0 :   if (!sourceImage) {
    1807               0 :     sourceImage = new gfxImageSurface(gfxIntSize(aBounds.width, aBounds.height), gfxASurface::FormatFromContent(aSource->GetContentType()));
    1808               0 :     nsRefPtr<gfxContext> ctx = new gfxContext(sourceImage);
    1809                 : 
    1810               0 :     aSource->SetDeviceOffset(gfxPoint(0, 0));
    1811               0 :     ctx->SetSource(aSource);
    1812               0 :     ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
    1813               0 :     ctx->Paint();
    1814                 :   }
    1815                 : 
    1816                 :   // Find the transformed rectangle of our layer.
    1817               0 :   gfxRect offsetRect = aTransform.TransformBounds(aBounds);
    1818                 : 
    1819                 :   // Intersect the transformed layer with the destination rectangle.
    1820                 :   // This is in device space since we have an identity transform set on aTarget.
    1821               0 :   gfxRect destRect = aDest->GetClipExtents();
    1822               0 :   destRect.IntersectRect(destRect, offsetRect);
    1823                 : 
    1824                 :   // Create a surface the size of the transformed object.
    1825               0 :   nsRefPtr<gfxASurface> dest = aDest->CurrentSurface();
    1826               0 :   nsRefPtr<gfxImageSurface> destImage = dest->GetAsImageSurface();
    1827               0 :   destImage = nsnull;
    1828               0 :   gfxPoint offset;
    1829                 :   bool blitComplete;
    1830               0 :   if (!destImage || aDontBlit || !aDest->ClipContainsRect(destRect)) {
    1831                 :     destImage = new gfxImageSurface(gfxIntSize(destRect.width, destRect.height),
    1832               0 :                                     gfxASurface::ImageFormatARGB32);
    1833               0 :     offset = destRect.TopLeft();
    1834               0 :     blitComplete = false;
    1835                 :   } else {
    1836               0 :     offset = -dest->GetDeviceOffset();
    1837               0 :     blitComplete = true;
    1838                 :   }
    1839                 : 
    1840                 :   // Include a translation to the correct origin.
    1841               0 :   gfx3DMatrix translation = gfx3DMatrix::Translation(aBounds.x, aBounds.y, 0);
    1842                 : 
    1843                 :   // Transform the content and offset it such that the content begins at the origin.
    1844               0 :   PixmanTransform(destImage, sourceImage, translation * aTransform, offset);
    1845                 : 
    1846               0 :   if (blitComplete) {
    1847               0 :     return nsnull;
    1848                 :   }
    1849                 : 
    1850                 :   // If we haven't actually drawn to aDest then return our temporary image so that
    1851                 :   // the caller can do this.
    1852               0 :   aDrawOffset = destRect.TopLeft();
    1853               0 :   return destImage.forget(); 
    1854                 : }
    1855                 : 
    1856                 : 
    1857                 : 
    1858                 : void
    1859               0 : BasicLayerManager::PaintLayer(gfxContext* aTarget,
    1860                 :                               Layer* aLayer,
    1861                 :                               DrawThebesLayerCallback aCallback,
    1862                 :                               void* aCallbackData,
    1863                 :                               ReadbackProcessor* aReadback)
    1864                 : {
    1865               0 :   const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
    1866               0 :   const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
    1867               0 :   BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
    1868               0 :   bool needsGroup = aLayer->GetFirstChild() &&
    1869               0 :     container->UseIntermediateSurface();
    1870               0 :   BasicImplData* data = ToData(aLayer);
    1871                 :   bool needsClipToVisibleRegion =
    1872               0 :     data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
    1873               0 :   NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
    1874                 :                container->GetOperator() == gfxContext::OPERATOR_OVER,
    1875                 :                "non-OVER operator should have forced UseIntermediateSurface");
    1876                 : 
    1877                 :   // If needsSaveRestore is false, we should still save and restore
    1878                 :   // the CTM
    1879               0 :   bool needsSaveRestore = needsGroup || clipRect || needsClipToVisibleRegion;
    1880               0 :   gfxMatrix savedMatrix;
    1881               0 :   if (needsSaveRestore) {
    1882               0 :     aTarget->Save();
    1883                 : 
    1884               0 :     if (clipRect) {
    1885               0 :       aTarget->NewPath();
    1886               0 :       aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true);
    1887               0 :       aTarget->Clip();
    1888                 :     }
    1889                 :   } else {
    1890               0 :     savedMatrix = aTarget->CurrentMatrix();
    1891                 :   }
    1892                 : 
    1893               0 :   gfxMatrix transform;
    1894                 :   // Will return an identity matrix for 3d transforms, and is handled separately below.
    1895               0 :   bool is2D = effectiveTransform.CanDraw2D(&transform);
    1896               0 :   NS_ABORT_IF_FALSE(is2D || needsGroup || !aLayer->GetFirstChild(), "Must PushGroup for 3d transforms!");
    1897               0 :   if (is2D) {
    1898               0 :     aTarget->SetMatrix(transform);
    1899                 :   } else {
    1900               0 :     aTarget->SetMatrix(gfxMatrix());
    1901                 :   }
    1902                 : 
    1903               0 :   const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
    1904                 :   // If needsGroup is true, we'll clip to the visible region after we've popped the group
    1905               0 :   if (needsClipToVisibleRegion && !needsGroup) {
    1906               0 :     gfxUtils::ClipToRegion(aTarget, visibleRegion);
    1907                 :     // Don't need to clip to visible region again
    1908               0 :     needsClipToVisibleRegion = false;
    1909                 :   }
    1910                 : 
    1911               0 :   bool pushedTargetOpaqueRect = false;
    1912               0 :   nsRefPtr<gfxASurface> currentSurface = aTarget->CurrentSurface();
    1913               0 :   const nsIntRect& bounds = visibleRegion.GetBounds();
    1914                 :   
    1915               0 :   if (aTarget->IsCairo()) {
    1916               0 :     const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect();
    1917                 : 
    1918                 :     // Try to annotate currentSurface with a region of pixels that have been
    1919                 :     // (or will be) painted opaque, if no such region is currently set.
    1920               0 :     if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
    1921               0 :         (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
    1922               0 :         !transform.HasNonAxisAlignedTransform()) {
    1923                 :       currentSurface->SetOpaqueRect(
    1924               0 :           aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
    1925               0 :       pushedTargetOpaqueRect = true;
    1926                 :     }
    1927                 :   }
    1928                 : 
    1929               0 :   nsRefPtr<gfxContext> groupTarget;
    1930               0 :   nsRefPtr<gfxASurface> untransformedSurface;
    1931               0 :   if (!is2D) {
    1932                 :     untransformedSurface = 
    1933               0 :       gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height), 
    1934               0 :                                                          gfxASurface::CONTENT_COLOR_ALPHA);
    1935               0 :     if (!untransformedSurface) {
    1936               0 :       if (pushedTargetOpaqueRect) {
    1937               0 :         currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
    1938                 :       }
    1939               0 :       NS_ASSERTION(needsSaveRestore, "Should always need to restore with 3d transforms!");
    1940               0 :       aTarget->Restore();
    1941                 :       return;
    1942                 :     }
    1943               0 :     untransformedSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
    1944               0 :     groupTarget = new gfxContext(untransformedSurface);
    1945               0 :   } else if (needsGroup) {
    1946               0 :     groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
    1947               0 :                                     &needsClipToVisibleRegion);
    1948                 :   } else {
    1949               0 :     groupTarget = aTarget;
    1950                 :   }
    1951                 : 
    1952                 :   /* Only paint ourself, or our children - This optimization relies on this! */
    1953               0 :   Layer* child = aLayer->GetFirstChild();
    1954               0 :   if (!child) {
    1955                 : #ifdef MOZ_LAYERS_HAVE_LOG
    1956               0 :     MOZ_LAYERS_LOG(("%s (0x%p) is covered: %i\n", __FUNCTION__,
    1957                 :                    (void*)aLayer, data->IsHidden()));
    1958                 : #endif
    1959               0 :     if (aLayer->AsThebesLayer()) {
    1960               0 :       data->PaintThebes(groupTarget, aCallback, aCallbackData, aReadback);
    1961                 :     } else {
    1962               0 :       data->Paint(groupTarget);
    1963                 :     }
    1964                 :   } else {
    1965               0 :     ReadbackProcessor readback;
    1966               0 :     ContainerLayer* container = static_cast<ContainerLayer*>(aLayer);
    1967               0 :     if (IsRetained()) {
    1968               0 :       readback.BuildUpdates(container);
    1969                 :     }
    1970                 :   
    1971               0 :     nsAutoTArray<Layer*, 12> children;
    1972               0 :     container->SortChildrenBy3DZOrder(children);
    1973                 : 
    1974               0 :     for (PRUint32 i = 0; i < children.Length(); i++) {
    1975               0 :       PaintLayer(groupTarget, children.ElementAt(i), aCallback, aCallbackData, &readback);
    1976               0 :       if (mTransactionIncomplete)
    1977               0 :         break;
    1978                 :     }
    1979                 :   }
    1980                 : 
    1981               0 :   if (needsGroup) {
    1982               0 :     bool blitComplete = false;
    1983               0 :     if (is2D) {
    1984               0 :       PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
    1985                 :     } else {
    1986               0 :       NS_ABORT_IF_FALSE(untransformedSurface, 
    1987                 :                         "We should always allocate an untransformed surface with 3d transforms!");
    1988                 : 
    1989                 :       // Temporary fast fix for bug 725886
    1990                 :       // Revert these changes when 725886 is ready
    1991               0 :       gfxRect clipExtents;
    1992               0 :       clipExtents = aTarget->GetClipExtents();
    1993               0 :       if (!clipExtents.IsEmpty()) {
    1994               0 :         gfxPoint offset;
    1995                 :         bool dontBlit = needsClipToVisibleRegion || mTransactionIncomplete ||
    1996               0 :                           aLayer->GetEffectiveOpacity() != 1.0f;
    1997                 :         nsRefPtr<gfxASurface> result =
    1998                 :           Transform3D(untransformedSurface, aTarget, bounds,
    1999               0 :                       effectiveTransform, offset, dontBlit);
    2000                 : 
    2001               0 :         blitComplete = !result;
    2002               0 :         if (result) {
    2003               0 :           aTarget->SetSource(result, offset);
    2004                 :         }
    2005                 :       }
    2006                 :     }
    2007                 :     // If we're doing our own double-buffering, we need to avoid drawing
    2008                 :     // the results of an incomplete transaction to the destination surface ---
    2009                 :     // that could cause flicker. Double-buffering is implemented using a
    2010                 :     // temporary surface for one or more container layers, so we need to stop
    2011                 :     // those temporary surfaces from being composited to aTarget.
    2012                 :     // ApplyDoubleBuffering guarantees that this container layer can't
    2013                 :     // intersect any other leaf layers, so if the transaction is not yet marked
    2014                 :     // incomplete, the contents of this container layer are the final contents
    2015                 :     // for the window.
    2016               0 :     if (!mTransactionIncomplete && !blitComplete) {
    2017               0 :       if (needsClipToVisibleRegion) {
    2018               0 :         gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
    2019                 :       }
    2020               0 :       AutoSetOperator setOperator(aTarget, container->GetOperator());
    2021               0 :       aTarget->Paint(aLayer->GetEffectiveOpacity());
    2022                 :     }
    2023                 :   }
    2024                 : 
    2025               0 :   if (pushedTargetOpaqueRect) {
    2026               0 :     currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
    2027                 :   }
    2028                 : 
    2029               0 :   if (needsSaveRestore) {
    2030               0 :     aTarget->Restore();
    2031                 :   } else {
    2032               0 :     aTarget->SetMatrix(savedMatrix);
    2033                 :   }
    2034                 : }
    2035                 : 
    2036                 : void
    2037               0 : BasicLayerManager::ClearCachedResources()
    2038                 : {
    2039               0 :   if (mRoot) {
    2040               0 :     ClearLayer(mRoot);
    2041                 :   }
    2042                 : 
    2043               0 :   mCachedSurface.Expire();
    2044               0 : }
    2045                 : void
    2046               0 : BasicLayerManager::ClearLayer(Layer* aLayer)
    2047                 : {
    2048               0 :   ToData(aLayer)->ClearCachedResources();
    2049               0 :   for (Layer* child = aLayer->GetFirstChild(); child;
    2050                 :        child = child->GetNextSibling()) {
    2051               0 :     ClearLayer(child);
    2052                 :   }
    2053               0 : }
    2054                 : 
    2055                 : already_AddRefed<ThebesLayer>
    2056               0 : BasicLayerManager::CreateThebesLayer()
    2057                 : {
    2058               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2059               0 :   nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this);
    2060               0 :   return layer.forget();
    2061                 : }
    2062                 : 
    2063                 : already_AddRefed<ContainerLayer>
    2064               0 : BasicLayerManager::CreateContainerLayer()
    2065                 : {
    2066               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2067               0 :   nsRefPtr<ContainerLayer> layer = new BasicContainerLayer(this);
    2068               0 :   return layer.forget();
    2069                 : }
    2070                 : 
    2071                 : already_AddRefed<ImageLayer>
    2072               0 : BasicLayerManager::CreateImageLayer()
    2073                 : {
    2074               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2075               0 :   nsRefPtr<ImageLayer> layer = new BasicImageLayer(this);
    2076               0 :   return layer.forget();
    2077                 : }
    2078                 : 
    2079                 : already_AddRefed<ColorLayer>
    2080               0 : BasicLayerManager::CreateColorLayer()
    2081                 : {
    2082               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2083               0 :   nsRefPtr<ColorLayer> layer = new BasicColorLayer(this);
    2084               0 :   return layer.forget();
    2085                 : }
    2086                 : 
    2087                 : already_AddRefed<CanvasLayer>
    2088               0 : BasicLayerManager::CreateCanvasLayer()
    2089                 : {
    2090               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2091               0 :   nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
    2092               0 :   return layer.forget();
    2093                 : }
    2094                 : 
    2095                 : already_AddRefed<ReadbackLayer>
    2096               0 : BasicLayerManager::CreateReadbackLayer()
    2097                 : {
    2098               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    2099               0 :   nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
    2100               0 :   return layer.forget();
    2101                 : }
    2102                 : 
    2103                 : class BasicShadowableThebesLayer;
    2104                 : class BasicShadowableLayer : public ShadowableLayer
    2105                 : {
    2106                 : public:
    2107               0 :   BasicShadowableLayer()
    2108               0 :   {
    2109               0 :     MOZ_COUNT_CTOR(BasicShadowableLayer);
    2110               0 :   }
    2111                 : 
    2112               0 :   ~BasicShadowableLayer()
    2113               0 :   {
    2114               0 :     if (HasShadow()) {
    2115               0 :       PLayerChild::Send__delete__(GetShadow());
    2116                 :     }
    2117               0 :     MOZ_COUNT_DTOR(BasicShadowableLayer);
    2118               0 :   }
    2119                 : 
    2120               0 :   void SetShadow(PLayerChild* aShadow)
    2121                 :   {
    2122               0 :     NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
    2123               0 :     mShadow = aShadow;
    2124               0 :   }
    2125                 : 
    2126               0 :   virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
    2127                 :   {
    2128               0 :     NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
    2129               0 :   }
    2130                 :   
    2131               0 :   virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
    2132                 :                                      gfxSharedImageSurface* aUBuffer,
    2133                 :                                      gfxSharedImageSurface* aVBuffer)
    2134                 :   {
    2135               0 :     NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
    2136               0 :   }
    2137                 : 
    2138               0 :   virtual void Disconnect()
    2139                 :   {
    2140                 :     // This is an "emergency Disconnect()", called when the compositing
    2141                 :     // process has died.  |mShadow| and our Shmem buffers are
    2142                 :     // automatically managed by IPDL, so we don't need to explicitly
    2143                 :     // free them here (it's hard to get that right on emergency
    2144                 :     // shutdown anyway).
    2145               0 :     mShadow = nsnull;
    2146               0 :   }
    2147                 : 
    2148               0 :   virtual BasicShadowableThebesLayer* AsThebes() { return nsnull; }
    2149                 : };
    2150                 : 
    2151                 : static ShadowableLayer*
    2152               0 : ToShadowable(Layer* aLayer)
    2153                 : {
    2154               0 :   return ToData(aLayer)->AsShadowableLayer();
    2155                 : }
    2156                 : 
    2157                 : // Some layers, like ReadbackLayers, can't be shadowed and shadowing
    2158                 : // them doesn't make sense anyway
    2159                 : static bool
    2160               0 : ShouldShadow(Layer* aLayer)
    2161                 : {
    2162               0 :   if (!ToShadowable(aLayer)) {
    2163               0 :     NS_ABORT_IF_FALSE(aLayer->GetType() == Layer::TYPE_READBACK,
    2164                 :                       "Only expect not to shadow ReadbackLayers");
    2165               0 :     return false;
    2166                 :   }
    2167               0 :   return true;
    2168                 : }
    2169                 : 
    2170                 : template<class OpT>
    2171                 : static BasicShadowableLayer*
    2172               0 : GetBasicShadowable(const OpT& op)
    2173                 : {
    2174                 :   return static_cast<BasicShadowableLayer*>(
    2175               0 :     static_cast<const ShadowLayerChild*>(op.layerChild())->layer());
    2176                 : }
    2177                 : 
    2178                 : class BasicShadowableContainerLayer : public BasicContainerLayer,
    2179                 :                                       public BasicShadowableLayer {
    2180                 : public:
    2181               0 :   BasicShadowableContainerLayer(BasicShadowLayerManager* aManager) :
    2182               0 :     BasicContainerLayer(aManager)
    2183                 :   {
    2184               0 :     MOZ_COUNT_CTOR(BasicShadowableContainerLayer);
    2185               0 :   }
    2186               0 :   virtual ~BasicShadowableContainerLayer()
    2187               0 :   {
    2188               0 :     MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
    2189               0 :   }
    2190                 : 
    2191                 :   virtual void InsertAfter(Layer* aChild, Layer* aAfter);
    2192                 :   virtual void RemoveChild(Layer* aChild);
    2193                 : 
    2194               0 :   virtual Layer* AsLayer() { return this; }
    2195               0 :   virtual ShadowableLayer* AsShadowableLayer() { return this; }
    2196                 : 
    2197               0 :   virtual void Disconnect()
    2198                 :   {
    2199               0 :     BasicShadowableLayer::Disconnect();
    2200               0 :   }
    2201                 : 
    2202                 : private:
    2203               0 :   BasicShadowLayerManager* ShadowManager()
    2204                 :   {
    2205               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    2206                 :   }
    2207                 : };
    2208                 : 
    2209                 : void
    2210               0 : BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
    2211                 : {
    2212               0 :   if (HasShadow() && ShouldShadow(aChild)) {
    2213               0 :     while (aAfter && !ShouldShadow(aAfter)) {
    2214               0 :       aAfter = aAfter->GetPrevSibling();
    2215                 :     }
    2216               0 :     ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
    2217                 :                                  ShadowManager()->Hold(aChild),
    2218               0 :                                  aAfter ? ShadowManager()->Hold(aAfter) : nsnull);
    2219                 :   }
    2220               0 :   BasicContainerLayer::InsertAfter(aChild, aAfter);
    2221               0 : }
    2222                 : 
    2223                 : void
    2224               0 : BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
    2225                 : {
    2226               0 :   if (HasShadow() && ShouldShadow(aChild)) {
    2227               0 :     ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
    2228               0 :                                  ShadowManager()->Hold(aChild));
    2229                 :   }
    2230               0 :   BasicContainerLayer::RemoveChild(aChild);
    2231               0 : }
    2232                 : 
    2233                 : class BasicShadowableThebesLayer : public BasicThebesLayer,
    2234                 :                                    public BasicShadowableLayer
    2235                 : {
    2236                 :   typedef BasicThebesLayer Base;
    2237                 : 
    2238                 : public:
    2239               0 :   BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
    2240                 :     : BasicThebesLayer(aManager)
    2241                 :     , mIsNewBuffer(false)
    2242               0 :     , mFrontAndBackBufferDiffer(false)
    2243                 :   {
    2244               0 :     MOZ_COUNT_CTOR(BasicShadowableThebesLayer);
    2245               0 :   }
    2246               0 :   virtual ~BasicShadowableThebesLayer()
    2247               0 :   {
    2248               0 :     DestroyBackBuffer();
    2249               0 :     MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
    2250               0 :   }
    2251                 : 
    2252               0 :   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    2253                 :   {
    2254               0 :     aAttrs = ThebesLayerAttributes(GetValidRegion());
    2255               0 :   }
    2256                 : 
    2257               0 :   virtual Layer* AsLayer() { return this; }
    2258               0 :   virtual ShadowableLayer* AsShadowableLayer() { return this; }
    2259               0 :   virtual bool MustRetainContent() { return HasShadow(); }
    2260                 : 
    2261                 :   void SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
    2262                 :                              const nsIntRegion& aValidRegion,
    2263                 :                              const OptionalThebesBuffer& aReadOnlyFrontBuffer,
    2264                 :                              const nsIntRegion& aFrontUpdatedRegion);
    2265                 : 
    2266               0 :   virtual void Disconnect()
    2267                 :   {
    2268               0 :     mBackBuffer = SurfaceDescriptor();
    2269               0 :     BasicShadowableLayer::Disconnect();
    2270               0 :   }
    2271                 : 
    2272               0 :   virtual BasicShadowableThebesLayer* AsThebes() { return this; }
    2273                 : 
    2274                 :   virtual void SyncFrontBufferToBackBuffer();
    2275                 : 
    2276                 : private:
    2277               0 :   BasicShadowLayerManager* BasicManager()
    2278                 :   {
    2279               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    2280                 :   }
    2281                 : 
    2282                 :   virtual void
    2283                 :   PaintBuffer(gfxContext* aContext,
    2284                 :               const nsIntRegion& aRegionToDraw,
    2285                 :               const nsIntRegion& aExtendedRegionToDraw,
    2286                 :               const nsIntRegion& aRegionToInvalidate,
    2287                 :               bool aDidSelfCopy,
    2288                 :               LayerManager::DrawThebesLayerCallback aCallback,
    2289                 :               void* aCallbackData) MOZ_OVERRIDE;
    2290                 : 
    2291                 :   virtual already_AddRefed<gfxASurface>
    2292                 :   CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
    2293                 : 
    2294               0 :   void DestroyBackBuffer()
    2295                 :   {
    2296               0 :     if (IsSurfaceDescriptorValid(mBackBuffer)) {
    2297               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
    2298                 :     }
    2299               0 :   }
    2300                 : 
    2301                 :   // This describes the gfxASurface we hand to mBuffer.  We keep a
    2302                 :   // copy of the descriptor here so that we can call
    2303                 :   // DestroySharedSurface() on the descriptor.
    2304                 :   SurfaceDescriptor mBackBuffer;
    2305                 :   nsIntRect mBackBufferRect;
    2306                 :   nsIntPoint mBackBufferRectRotation;
    2307                 : 
    2308                 :   bool mIsNewBuffer;
    2309                 :   OptionalThebesBuffer mROFrontBuffer;
    2310                 :   nsIntRegion mFrontUpdatedRegion;
    2311                 :   nsIntRegion mFrontValidRegion;
    2312                 :   PRPackedBool mFrontAndBackBufferDiffer;
    2313                 : };
    2314                 : 
    2315                 : void
    2316               0 : BasicShadowableThebesLayer::SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
    2317                 :                                                   const nsIntRegion& aValidRegion,
    2318                 :                                                   const OptionalThebesBuffer& aReadOnlyFrontBuffer,
    2319                 :                                                   const nsIntRegion& aFrontUpdatedRegion)
    2320                 : {
    2321               0 :   if (OptionalThebesBuffer::Tnull_t == aBuffer.type()) {
    2322               0 :     mBackBuffer = SurfaceDescriptor();
    2323               0 :   } else if (!IsSurfaceDescriptorValid(mBackBuffer)) {
    2324               0 :     mBackBuffer = aBuffer.get_ThebesBuffer().buffer();
    2325               0 :     mBackBufferRect = aBuffer.get_ThebesBuffer().rect();
    2326               0 :     mBackBufferRectRotation = aBuffer.get_ThebesBuffer().rotation();
    2327                 :   } else {
    2328               0 :     SurfaceDescriptor obsoleteBuffer = aBuffer.get_ThebesBuffer().buffer();
    2329               0 :     BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&obsoleteBuffer);
    2330                 :   }
    2331               0 :   mFrontAndBackBufferDiffer = true;
    2332               0 :   mROFrontBuffer = aReadOnlyFrontBuffer;
    2333               0 :   mFrontUpdatedRegion = aFrontUpdatedRegion;
    2334               0 :   mFrontValidRegion = aValidRegion;
    2335               0 :   if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
    2336                 :     // For null readonly front, we have single buffer mode
    2337                 :     // so we can do sync right now, because it does not create new buffer and
    2338                 :     // don't do any graphic operations
    2339               0 :     SyncFrontBufferToBackBuffer();
    2340                 :   }
    2341               0 : }
    2342                 : 
    2343                 : void
    2344               0 : BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
    2345                 : {
    2346               0 :   if (!mFrontAndBackBufferDiffer) {
    2347               0 :     return;
    2348                 :   }
    2349                 : 
    2350               0 :   nsRefPtr<gfxASurface> backBuffer;
    2351               0 :   if (!IsSurfaceDescriptorValid(mBackBuffer)) {
    2352               0 :     NS_ABORT_IF_FALSE(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer,
    2353                 :                       "should have a front RO buffer by now");
    2354               0 :     const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
    2355               0 :     nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
    2356               0 :     backBuffer = CreateBuffer(roFrontBuffer->GetContentType(), roFrontBuffer->GetSize());
    2357                 :   } else {
    2358               0 :     backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
    2359                 :   }
    2360               0 :   mFrontAndBackBufferDiffer = false;
    2361                 : 
    2362               0 :   if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
    2363                 :     // We didn't get back a read-only ref to our old back buffer (the
    2364                 :     // parent's new front buffer).  If the parent is pushing updates
    2365                 :     // to a texture it owns, then we probably got back the same buffer
    2366                 :     // we pushed in the update and all is well.  If not, ...
    2367               0 :     mValidRegion = mFrontValidRegion;
    2368               0 :     mBuffer.SetBackingBuffer(backBuffer, mBackBufferRect, mBackBufferRectRotation);
    2369                 :     return;
    2370                 :   }
    2371                 : 
    2372               0 :   MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
    2373                 :                   this,
    2374                 :                   mFrontUpdatedRegion.GetBounds().x,
    2375                 :                   mFrontUpdatedRegion.GetBounds().y,
    2376                 :                   mFrontUpdatedRegion.GetBounds().width,
    2377                 :                   mFrontUpdatedRegion.GetBounds().height));
    2378                 : 
    2379               0 :   const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
    2380               0 :   nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
    2381                 :   mBuffer.SetBackingBufferAndUpdateFrom(
    2382                 :     backBuffer,
    2383               0 :     roFrontBuffer, roFront.rect(), roFront.rotation(),
    2384               0 :     mFrontUpdatedRegion);
    2385               0 :   mIsNewBuffer = false;
    2386                 :   // Now the new back buffer has the same (interesting) pixels as the
    2387                 :   // new front buffer, and mValidRegion et al. are correct wrt the new
    2388                 :   // back buffer (i.e. as they were for the old back buffer)
    2389                 : }
    2390                 : 
    2391                 : void
    2392               0 : BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
    2393                 :                                         const nsIntRegion& aRegionToDraw,
    2394                 :                                         const nsIntRegion& aExtendedRegionToDraw,
    2395                 :                                         const nsIntRegion& aRegionToInvalidate,
    2396                 :                                         bool aDidSelfCopy,
    2397                 :                                         LayerManager::DrawThebesLayerCallback aCallback,
    2398                 :                                         void* aCallbackData)
    2399                 : {
    2400                 :   Base::PaintBuffer(aContext,
    2401                 :                     aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate,
    2402                 :                     aDidSelfCopy,
    2403               0 :                     aCallback, aCallbackData);
    2404               0 :   if (!HasShadow()) {
    2405               0 :     return;
    2406                 :   }
    2407                 : 
    2408               0 :   nsIntRegion updatedRegion;
    2409               0 :   if (mIsNewBuffer || aDidSelfCopy) {
    2410                 :     // A buffer reallocation clears both buffers. The front buffer has all the
    2411                 :     // content by now, but the back buffer is still clear. Here, in effect, we
    2412                 :     // are saying to copy all of the pixels of the front buffer to the back.
    2413                 :     // Also when we self-copied in the buffer, the buffer space
    2414                 :     // changes and some changed buffer content isn't reflected in the
    2415                 :     // draw or invalidate region (on purpose!).  When this happens, we
    2416                 :     // need to read back the entire buffer too.
    2417               0 :     updatedRegion = mVisibleRegion;
    2418               0 :     mIsNewBuffer = false;
    2419                 :   } else {
    2420               0 :     updatedRegion = aRegionToDraw;
    2421                 :   }
    2422                 : 
    2423               0 :   NS_ASSERTION(mBuffer.BufferRect().Contains(aRegionToDraw.GetBounds()),
    2424                 :                "Update outside of buffer rect!");
    2425               0 :   NS_ABORT_IF_FALSE(IsSurfaceDescriptorValid(mBackBuffer),
    2426                 :                     "should have a back buffer by now");
    2427               0 :   BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
    2428                 :                                       updatedRegion,
    2429               0 :                                       mBuffer.BufferRect(),
    2430               0 :                                       mBuffer.BufferRotation(),
    2431               0 :                                       mBackBuffer);
    2432               0 :   mROFrontBuffer = ThebesBuffer(mBackBuffer, mBuffer.BufferRect(), mBuffer.BufferRotation());
    2433               0 :   mBackBuffer = SurfaceDescriptor();
    2434                 : }
    2435                 : 
    2436                 : already_AddRefed<gfxASurface>
    2437               0 : BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
    2438                 :                                          const nsIntSize& aSize)
    2439                 : {
    2440               0 :   if (!HasShadow()) {
    2441               0 :     return BasicThebesLayer::CreateBuffer(aType, aSize);
    2442                 :   }
    2443                 : 
    2444               0 :   MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): creating %d x %d buffer(x2)",
    2445                 :                   this,
    2446                 :                   aSize.width, aSize.height));
    2447                 : 
    2448               0 :   if (IsSurfaceDescriptorValid(mBackBuffer)) {
    2449               0 :     BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
    2450               0 :                                           mBackBuffer);
    2451               0 :     mBackBuffer = SurfaceDescriptor();
    2452                 :   }
    2453                 : 
    2454                 :   // XXX error handling
    2455               0 :   if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
    2456                 :                                    aType,
    2457               0 :                                    &mBackBuffer)) {
    2458                 :       enum { buflen = 256 };
    2459                 :       char buf[buflen];
    2460                 :       PR_snprintf(buf, buflen,
    2461                 :                   "creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
    2462               0 :                   aSize.width, aSize.height, int(aType));
    2463               0 :       NS_RUNTIMEABORT(buf);
    2464                 :   }
    2465                 : 
    2466               0 :   NS_ABORT_IF_FALSE(!mIsNewBuffer,
    2467                 :                     "Bad! Did we create a buffer twice without painting?");
    2468                 : 
    2469               0 :   mIsNewBuffer = true;
    2470                 : 
    2471               0 :   return BasicManager()->OpenDescriptor(mBackBuffer);
    2472                 : }
    2473                 : 
    2474                 : 
    2475                 : class BasicShadowableImageLayer : public BasicImageLayer,
    2476                 :                                   public BasicShadowableLayer
    2477                 : {
    2478                 : public:
    2479               0 :   BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
    2480                 :     BasicImageLayer(aManager),
    2481               0 :     mBufferIsOpaque(false)
    2482                 :   {
    2483               0 :     MOZ_COUNT_CTOR(BasicShadowableImageLayer);
    2484               0 :   }
    2485               0 :   virtual ~BasicShadowableImageLayer()
    2486               0 :   {
    2487               0 :     DestroyBackBuffer();
    2488               0 :     MOZ_COUNT_DTOR(BasicShadowableImageLayer);
    2489               0 :   }
    2490                 : 
    2491                 :   virtual void Paint(gfxContext* aContext);
    2492                 : 
    2493               0 :   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    2494                 :   {
    2495               0 :     aAttrs = ImageLayerAttributes(mFilter);
    2496               0 :   }
    2497                 : 
    2498               0 :   virtual Layer* AsLayer() { return this; }
    2499               0 :   virtual ShadowableLayer* AsShadowableLayer() { return this; }
    2500                 : 
    2501               0 :   virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
    2502                 :   {
    2503               0 :     mBackBuffer = aBuffer;
    2504               0 :   }
    2505                 : 
    2506               0 :   virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
    2507                 :                                      gfxSharedImageSurface* aUBuffer,
    2508                 :                                      gfxSharedImageSurface* aVBuffer)
    2509                 :   {
    2510               0 :     mBackBufferY = aYBuffer;
    2511               0 :     mBackBufferU = aUBuffer;
    2512               0 :     mBackBufferV = aVBuffer;
    2513               0 :   }
    2514                 : 
    2515               0 :   virtual void Disconnect()
    2516                 :   {
    2517               0 :     mBackBufferY = mBackBufferU = mBackBufferV = nsnull;
    2518               0 :     mBackBuffer = SurfaceDescriptor();
    2519               0 :     BasicShadowableLayer::Disconnect();
    2520               0 :   }
    2521                 : 
    2522               0 :   void DestroyBackBuffer()
    2523                 :   {
    2524               0 :     if (IsSurfaceDescriptorValid(mBackBuffer)) {
    2525               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
    2526                 :     }
    2527               0 :     if (mBackBufferY) {
    2528               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferY);
    2529               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferU);
    2530               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferV);
    2531                 :     }
    2532               0 :   }
    2533                 : 
    2534                 : private:
    2535               0 :   BasicShadowLayerManager* BasicManager()
    2536                 :   {
    2537               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    2538                 :   }
    2539                 : 
    2540                 :   // For YUV Images these are the 3 planes (Y, Cb and Cr),
    2541                 :   // for RGB images only mBackSurface is used.
    2542                 :   SurfaceDescriptor mBackBuffer;
    2543                 :   bool mBufferIsOpaque;
    2544                 :   nsRefPtr<gfxSharedImageSurface> mBackBufferY;
    2545                 :   nsRefPtr<gfxSharedImageSurface> mBackBufferU;
    2546                 :   nsRefPtr<gfxSharedImageSurface> mBackBufferV;
    2547                 :   gfxIntSize mCbCrSize;
    2548                 : };
    2549                 :  
    2550                 : void
    2551               0 : BasicShadowableImageLayer::Paint(gfxContext* aContext)
    2552                 : {
    2553               0 :   if (!HasShadow()) {
    2554               0 :     BasicImageLayer::Paint(aContext);
    2555               0 :     return;
    2556                 :   }
    2557                 : 
    2558               0 :   if (!mContainer) {
    2559               0 :     return;
    2560                 :   }
    2561                 : 
    2562               0 :   AutoLockImage autoLock(mContainer);
    2563                 : 
    2564               0 :   Image *image = autoLock.GetImage();
    2565                 : 
    2566               0 :   if (!image) {
    2567                 :     return;
    2568                 :   }
    2569                 : 
    2570               0 :   if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
    2571               0 :     PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
    2572               0 :     const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
    2573               0 :     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
    2574                 : 
    2575               0 :     if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !mBackBufferY) {
    2576               0 :       DestroyBackBuffer();
    2577               0 :       mSize = data->mYSize;
    2578               0 :       mCbCrSize = data->mCbCrSize;
    2579                 : 
    2580               0 :       if (!BasicManager()->AllocBuffer(mSize, gfxASurface::CONTENT_ALPHA,
    2581               0 :                                        getter_AddRefs(mBackBufferY)) ||
    2582               0 :           !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
    2583               0 :                                        getter_AddRefs(mBackBufferU)) ||
    2584               0 :           !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
    2585               0 :                                        getter_AddRefs(mBackBufferV))) {
    2586               0 :         NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
    2587                 :       }
    2588                 :     }
    2589                 : 
    2590               0 :     for (int i = 0; i < data->mYSize.height; i++) {
    2591               0 :       memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(),
    2592                 :              data->mYChannel + i * data->mYStride,
    2593               0 :              data->mYSize.width);
    2594                 :     }
    2595               0 :     for (int i = 0; i < data->mCbCrSize.height; i++) {
    2596               0 :       memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(),
    2597                 :              data->mCbChannel + i * data->mCbCrStride,
    2598               0 :              data->mCbCrSize.width);
    2599               0 :       memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(),
    2600                 :              data->mCrChannel + i * data->mCbCrStride,
    2601               0 :              data->mCbCrSize.width);
    2602                 :     }
    2603                 : 
    2604               0 :     YUVImage yuv(mBackBufferY->GetShmem(),
    2605               0 :                  mBackBufferU->GetShmem(),
    2606               0 :                  mBackBufferV->GetShmem(),
    2607               0 :                  data->GetPictureRect());
    2608                 : 
    2609               0 :     BasicManager()->PaintedImage(BasicManager()->Hold(this),
    2610               0 :                                  yuv);
    2611                 :     return;
    2612                 :   }
    2613                 : 
    2614               0 :   gfxIntSize oldSize = mSize;
    2615               0 :   nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
    2616               0 :   if (!pat || !HasShadow())
    2617                 :     return;
    2618                 : 
    2619               0 :   bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
    2620               0 :   if (oldSize != mSize || 
    2621               0 :       !IsSurfaceDescriptorValid(mBackBuffer) ||
    2622                 :       isOpaque != mBufferIsOpaque) {
    2623               0 :     DestroyBackBuffer();
    2624               0 :     mBufferIsOpaque = isOpaque;
    2625                 : 
    2626               0 :     if (!BasicManager()->AllocBuffer(
    2627                 :           mSize,
    2628                 :           isOpaque ?
    2629                 :             gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
    2630               0 :           &mBackBuffer))
    2631               0 :       NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
    2632                 :   }
    2633                 : 
    2634                 :   nsRefPtr<gfxASurface> backSurface =
    2635               0 :     BasicManager()->OpenDescriptor(mBackBuffer);
    2636               0 :   nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
    2637               0 :   tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
    2638                 :   PaintContext(pat,
    2639               0 :                nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
    2640               0 :                nsnull, 1.0, tmpCtx);
    2641                 : 
    2642               0 :   BasicManager()->PaintedImage(BasicManager()->Hold(this),
    2643               0 :                                mBackBuffer);
    2644                 : }
    2645                 : 
    2646                 : 
    2647                 : class BasicShadowableColorLayer : public BasicColorLayer,
    2648                 :                                   public BasicShadowableLayer
    2649                 : {
    2650                 : public:
    2651               0 :   BasicShadowableColorLayer(BasicShadowLayerManager* aManager) :
    2652               0 :     BasicColorLayer(aManager)
    2653                 :   {
    2654               0 :     MOZ_COUNT_CTOR(BasicShadowableColorLayer);
    2655               0 :   }
    2656               0 :   virtual ~BasicShadowableColorLayer()
    2657               0 :   {
    2658               0 :     MOZ_COUNT_DTOR(BasicShadowableColorLayer);
    2659               0 :   }
    2660                 : 
    2661               0 :   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    2662                 :   {
    2663               0 :     aAttrs = ColorLayerAttributes(GetColor());
    2664               0 :   }
    2665                 : 
    2666               0 :   virtual Layer* AsLayer() { return this; }
    2667               0 :   virtual ShadowableLayer* AsShadowableLayer() { return this; }
    2668                 : 
    2669               0 :   virtual void Disconnect()
    2670                 :   {
    2671               0 :     BasicShadowableLayer::Disconnect();
    2672               0 :   }
    2673                 : };
    2674                 : 
    2675                 : class BasicShadowableCanvasLayer : public BasicCanvasLayer,
    2676                 :                                    public BasicShadowableLayer
    2677                 : {
    2678                 : public:
    2679               0 :   BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
    2680                 :     BasicCanvasLayer(aManager),
    2681               0 :     mBufferIsOpaque(false)
    2682                 :   {
    2683               0 :     MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
    2684               0 :   }
    2685               0 :   virtual ~BasicShadowableCanvasLayer()
    2686               0 :   {
    2687               0 :     DestroyBackBuffer();
    2688               0 :     MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
    2689               0 :   }
    2690                 : 
    2691                 :   virtual void Initialize(const Data& aData);
    2692                 :   virtual void Paint(gfxContext* aContext);
    2693                 : 
    2694               0 :   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
    2695                 :   {
    2696               0 :     aAttrs = CanvasLayerAttributes(mFilter);
    2697               0 :   }
    2698                 : 
    2699               0 :   virtual Layer* AsLayer() { return this; }
    2700               0 :   virtual ShadowableLayer* AsShadowableLayer() { return this; }
    2701                 : 
    2702               0 :   virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
    2703                 :   {
    2704               0 :     mBackBuffer = aBuffer;
    2705               0 :   }
    2706                 : 
    2707               0 :   virtual void Disconnect()
    2708                 :   {
    2709               0 :     mBackBuffer = SurfaceDescriptor();
    2710               0 :     BasicShadowableLayer::Disconnect();
    2711               0 :   }
    2712                 : 
    2713               0 :   void DestroyBackBuffer()
    2714                 :   {
    2715               0 :     if (IsSurfaceDescriptorValid(mBackBuffer)) {
    2716               0 :       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
    2717               0 :       mBackBuffer = SurfaceDescriptor();
    2718                 :     }
    2719               0 :   }
    2720                 : 
    2721                 : private:
    2722               0 :   BasicShadowLayerManager* BasicManager()
    2723                 :   {
    2724               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    2725                 :   }
    2726                 : 
    2727                 :   SurfaceDescriptor mBackBuffer;
    2728                 :   bool mBufferIsOpaque;
    2729                 : };
    2730                 : 
    2731                 : void
    2732               0 : BasicShadowableCanvasLayer::Initialize(const Data& aData)
    2733                 : {
    2734               0 :   BasicCanvasLayer::Initialize(aData);
    2735               0 :   if (!HasShadow())
    2736               0 :       return;
    2737                 : 
    2738                 :   // XXX won't get here currently; need to figure out what to do on
    2739                 :   // canvas resizes
    2740                 : 
    2741               0 :   if (IsSurfaceDescriptorValid(mBackBuffer)) {
    2742                 :     nsRefPtr<gfxASurface> backSurface =
    2743               0 :       BasicManager()->OpenDescriptor(mBackBuffer);
    2744               0 :     if (gfxIntSize(mBounds.width, mBounds.height) != backSurface->GetSize()) {
    2745               0 :       DestroyBackBuffer();
    2746                 :     }
    2747                 :   }
    2748                 : }
    2749                 : 
    2750                 : void
    2751               0 : BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
    2752                 : {
    2753               0 :   if (!HasShadow()) {
    2754               0 :     BasicCanvasLayer::Paint(aContext);
    2755               0 :     return;
    2756                 :   }
    2757                 : 
    2758               0 :   bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
    2759               0 :   if (!IsSurfaceDescriptorValid(mBackBuffer) ||
    2760                 :       isOpaque != mBufferIsOpaque) {
    2761               0 :     DestroyBackBuffer();
    2762               0 :     mBufferIsOpaque = isOpaque;
    2763               0 :     if (!BasicManager()->AllocBuffer(
    2764                 :         gfxIntSize(mBounds.width, mBounds.height),
    2765                 :         isOpaque ?
    2766                 :           gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
    2767               0 :         &mBackBuffer))
    2768               0 :     NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!");
    2769                 :   }
    2770                 : 
    2771                 :   nsRefPtr<gfxASurface> backSurface =
    2772               0 :     BasicManager()->OpenDescriptor(mBackBuffer);
    2773                 : 
    2774               0 :   UpdateSurface(backSurface);
    2775               0 :   FireDidTransactionCallback();
    2776                 : 
    2777               0 :   BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
    2778                 :                                 mNeedsYFlip ? true : false,
    2779               0 :                                 mBackBuffer);
    2780                 : }
    2781                 : 
    2782                 : class ShadowThebesLayerBuffer : public BasicThebesLayerBuffer
    2783                 : {
    2784                 :   typedef BasicThebesLayerBuffer Base;
    2785                 : 
    2786                 : public:
    2787               0 :   ShadowThebesLayerBuffer()
    2788               0 :     : Base(NULL)
    2789                 :   {
    2790               0 :     MOZ_COUNT_CTOR(ShadowThebesLayerBuffer);
    2791               0 :   }
    2792                 : 
    2793               0 :   ~ShadowThebesLayerBuffer()
    2794               0 :   {
    2795               0 :     MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
    2796               0 :   }
    2797                 : 
    2798               0 :   void Swap(gfxASurface* aNewBuffer,
    2799                 :             const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
    2800                 :             gfxASurface** aOldBuffer,
    2801                 :             nsIntRect* aOldRect, nsIntPoint* aOldRotation)
    2802                 :   {
    2803               0 :     *aOldRect = BufferRect();
    2804               0 :     *aOldRotation = BufferRotation();
    2805                 : 
    2806               0 :     nsRefPtr<gfxASurface> oldBuffer;
    2807                 :     oldBuffer = SetBuffer(aNewBuffer,
    2808               0 :                           aNewRect, aNewRotation);
    2809               0 :     oldBuffer.forget(aOldBuffer);
    2810               0 :   }
    2811                 : 
    2812                 : protected:
    2813                 :   virtual already_AddRefed<gfxASurface>
    2814               0 :   CreateBuffer(ContentType, const nsIntSize&, PRUint32)
    2815                 :   {
    2816               0 :     NS_RUNTIMEABORT("ShadowThebesLayer can't paint content");
    2817               0 :     return nsnull;
    2818                 :   }
    2819                 : };
    2820                 : 
    2821                 : 
    2822                 : class BasicShadowThebesLayer : public ShadowThebesLayer, public BasicImplData {
    2823                 : public:
    2824               0 :   BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager)
    2825               0 :     : ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
    2826                 :   {
    2827               0 :     MOZ_COUNT_CTOR(BasicShadowThebesLayer);
    2828               0 :   }
    2829               0 :   virtual ~BasicShadowThebesLayer()
    2830               0 :   {
    2831                 :     // If Disconnect() wasn't called on us, then we assume that the
    2832                 :     // remote side shut down and IPC is disconnected, so we let IPDL
    2833                 :     // clean up our front surface Shmem.
    2834               0 :     MOZ_COUNT_DTOR(BasicShadowThebesLayer);
    2835               0 :   }
    2836                 : 
    2837               0 :   virtual void SetValidRegion(const nsIntRegion& aRegion)
    2838                 :   {
    2839               0 :     mOldValidRegion = mValidRegion;
    2840               0 :     ShadowThebesLayer::SetValidRegion(aRegion);
    2841               0 :   }
    2842                 : 
    2843               0 :   virtual void Disconnect()
    2844                 :   {
    2845               0 :     DestroyFrontBuffer();
    2846               0 :     ShadowThebesLayer::Disconnect();
    2847               0 :   }
    2848                 : 
    2849                 :   virtual void
    2850                 :   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
    2851                 :        OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
    2852                 :        OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
    2853                 : 
    2854               0 :   virtual void DestroyFrontBuffer()
    2855                 :   {
    2856               0 :     mFrontBuffer.Clear();
    2857               0 :     mValidRegion.SetEmpty();
    2858               0 :     mOldValidRegion.SetEmpty();
    2859                 : 
    2860               0 :     if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
    2861               0 :       mAllocator->DestroySharedSurface(&mFrontBufferDescriptor);
    2862                 :     }
    2863               0 :   }
    2864                 : 
    2865                 :   virtual void PaintThebes(gfxContext* aContext,
    2866                 :                            LayerManager::DrawThebesLayerCallback aCallback,
    2867                 :                            void* aCallbackData,
    2868                 :                            ReadbackProcessor* aReadback);
    2869                 : 
    2870                 : private:
    2871               0 :   BasicShadowLayerManager* BasicManager()
    2872                 :   {
    2873               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    2874                 :   }
    2875                 : 
    2876                 :   ShadowThebesLayerBuffer mFrontBuffer;
    2877                 :   // Describes the gfxASurface we hand out to |mFrontBuffer|.
    2878                 :   SurfaceDescriptor mFrontBufferDescriptor;
    2879                 :   // When we receive an update from our remote partner, we stow away
    2880                 :   // our previous parameters that described our previous front buffer.
    2881                 :   // Then when we Swap() back/front buffers, we can return these
    2882                 :   // parameters to our partner (adjusted as needed).
    2883                 :   nsIntRegion mOldValidRegion;
    2884                 : };
    2885                 : 
    2886                 : void
    2887               0 : BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
    2888                 :                              const nsIntRegion& aUpdatedRegion,
    2889                 :                              OptionalThebesBuffer* aNewBack,
    2890                 :                              nsIntRegion* aNewBackValidRegion,
    2891                 :                              OptionalThebesBuffer* aReadOnlyFront,
    2892                 :                              nsIntRegion* aFrontUpdatedRegion)
    2893                 : {
    2894                 :   nsRefPtr<gfxASurface> newFrontBuffer =
    2895               0 :     BasicManager()->OpenDescriptor(aNewFront.buffer());
    2896                 : 
    2897               0 :   if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
    2898               0 :     nsRefPtr<gfxASurface> currentFront = BasicManager()->OpenDescriptor(mFrontBufferDescriptor);
    2899               0 :     if (currentFront->GetSize() != newFrontBuffer->GetSize()) {
    2900                 :       // Current front buffer is obsolete
    2901               0 :       DestroyFrontBuffer();
    2902                 :     }
    2903                 :   }
    2904                 :   // This code relies on Swap() arriving *after* attribute mutations.
    2905               0 :   if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
    2906               0 :     *aNewBack = ThebesBuffer();
    2907               0 :     aNewBack->get_ThebesBuffer().buffer() = mFrontBufferDescriptor;
    2908                 :   } else {
    2909               0 :     *aNewBack = null_t();
    2910                 :   }
    2911                 :   // We have to invalidate the pixels painted into the new buffer.
    2912                 :   // They might overlap with our old pixels.
    2913               0 :   aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
    2914                 : 
    2915               0 :   nsRefPtr<gfxASurface> unused;
    2916               0 :   nsIntRect backRect;
    2917               0 :   nsIntPoint backRotation;
    2918                 :   mFrontBuffer.Swap(
    2919               0 :     newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
    2920               0 :     getter_AddRefs(unused), &backRect, &backRotation);
    2921                 : 
    2922               0 :   if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
    2923               0 :     aNewBack->get_ThebesBuffer().rect() = backRect;
    2924               0 :     aNewBack->get_ThebesBuffer().rotation() = backRotation;
    2925                 :   }
    2926                 : 
    2927               0 :   mFrontBufferDescriptor = aNewFront.buffer();
    2928                 : 
    2929               0 :   *aReadOnlyFront = aNewFront;
    2930               0 :   *aFrontUpdatedRegion = aUpdatedRegion;
    2931               0 : }
    2932                 : 
    2933                 : void
    2934               0 : BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
    2935                 :                                     LayerManager::DrawThebesLayerCallback aCallback,
    2936                 :                                     void* aCallbackData,
    2937                 :                                     ReadbackProcessor* aReadback)
    2938                 : {
    2939               0 :   NS_ASSERTION(BasicManager()->InDrawing(),
    2940                 :                "Can only draw in drawing phase");
    2941               0 :   NS_ASSERTION(BasicManager()->IsRetained(),
    2942                 :                "ShadowThebesLayer makes no sense without retained mode");
    2943                 : 
    2944               0 :   if (!mFrontBuffer.GetBuffer()) {
    2945               0 :     return;
    2946                 :   }
    2947                 : 
    2948               0 :   mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity());
    2949                 : }
    2950                 : 
    2951                 : class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
    2952                 :   template<class Container>
    2953                 :   friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
    2954                 :   template<class Container>
    2955                 :   friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
    2956                 : 
    2957                 : public:
    2958               0 :   BasicShadowContainerLayer(BasicShadowLayerManager* aLayerManager) :
    2959               0 :     ShadowContainerLayer(aLayerManager, static_cast<BasicImplData*>(this))
    2960                 :   {
    2961               0 :     MOZ_COUNT_CTOR(BasicShadowContainerLayer);
    2962               0 :   }
    2963               0 :   virtual ~BasicShadowContainerLayer()
    2964               0 :   {
    2965               0 :     while (mFirstChild) {
    2966               0 :       ContainerRemoveChild(mFirstChild, this);
    2967                 :     }
    2968                 : 
    2969               0 :     MOZ_COUNT_DTOR(BasicShadowContainerLayer);
    2970               0 :   }
    2971                 : 
    2972               0 :   virtual void InsertAfter(Layer* aChild, Layer* aAfter)
    2973               0 :   { ContainerInsertAfter(aChild, aAfter, this); }
    2974               0 :   virtual void RemoveChild(Layer* aChild)
    2975               0 :   { ContainerRemoveChild(aChild, this); }
    2976                 : 
    2977               0 :   virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
    2978                 :   {
    2979                 :     // We push groups for container layers if we need to, which always
    2980                 :     // are aligned in device space, so it doesn't really matter how we snap
    2981                 :     // containers.
    2982               0 :     gfxMatrix residual;
    2983               0 :     gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
    2984               0 :     idealTransform.ProjectTo2D();
    2985                 : 
    2986               0 :     if (!idealTransform.CanDraw2D()) {
    2987               0 :       mEffectiveTransform = idealTransform;
    2988               0 :       ComputeEffectiveTransformsForChildren(gfx3DMatrix());
    2989               0 :       mUseIntermediateSurface = true;
    2990               0 :       return;
    2991                 :     }
    2992                 : 
    2993               0 :     mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
    2994                 :     // We always pass the ideal matrix down to our children, so there is no
    2995                 :     // need to apply any compensation using the residual from SnapTransform.
    2996               0 :     ComputeEffectiveTransformsForChildren(idealTransform);
    2997                 : 
    2998                 :     /* If we have a single child, it can just inherit our opacity,
    2999                 :      * otherwise we need a PushGroup and we need to mark ourselves as using
    3000                 :      * an intermediate surface so our children don't inherit our opacity
    3001                 :      * via GetEffectiveOpacity.
    3002                 :      */
    3003               0 :     mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren();
    3004                 :   }
    3005                 : };
    3006                 : 
    3007                 : class BasicShadowImageLayer : public ShadowImageLayer, public BasicImplData {
    3008                 : public:
    3009               0 :   BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
    3010               0 :     ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
    3011                 :   {
    3012               0 :     MOZ_COUNT_CTOR(BasicShadowImageLayer);
    3013               0 :   }
    3014               0 :   virtual ~BasicShadowImageLayer()
    3015               0 :   {
    3016               0 :     MOZ_COUNT_DTOR(BasicShadowImageLayer);
    3017               0 :   }
    3018                 : 
    3019               0 :   virtual void Disconnect()
    3020                 :   {
    3021               0 :     DestroyFrontBuffer();
    3022               0 :     ShadowImageLayer::Disconnect();
    3023               0 :   }
    3024                 : 
    3025                 :   virtual void Swap(const SharedImage& aNewFront,
    3026                 :                     SharedImage* aNewBack);
    3027                 : 
    3028               0 :   virtual void DestroyFrontBuffer()
    3029                 :   {
    3030               0 :     if (mAllocator && IsSurfaceDescriptorValid(mFrontBuffer)) {
    3031               0 :       mAllocator->DestroySharedSurface(&mFrontBuffer);
    3032                 :     }
    3033               0 :   }
    3034                 : 
    3035                 :   virtual void Paint(gfxContext* aContext);
    3036                 : 
    3037                 : protected:
    3038               0 :   BasicShadowLayerManager* BasicManager()
    3039                 :   {
    3040               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    3041                 :   }
    3042                 : 
    3043                 :   SurfaceDescriptor mFrontBuffer;
    3044                 :   gfxIntSize mSize;
    3045                 : };
    3046                 : 
    3047                 : void
    3048               0 : BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
    3049                 :                             SharedImage* aNewBack)
    3050                 : {
    3051                 :   nsRefPtr<gfxASurface> surface =
    3052               0 :     BasicManager()->OpenDescriptor(aNewFront);
    3053                 :   // Destroy mFrontBuffer if size different or image type is different
    3054               0 :   bool surfaceConfigChanged = surface->GetSize() != mSize;
    3055               0 :   if (IsSurfaceDescriptorValid(mFrontBuffer)) {
    3056               0 :     nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer);
    3057                 :     surfaceConfigChanged = surfaceConfigChanged ||
    3058               0 :                            surface->GetContentType() != front->GetContentType();
    3059                 :   }
    3060               0 :   if (surfaceConfigChanged) {
    3061               0 :     DestroyFrontBuffer();
    3062               0 :     mSize = surface->GetSize();
    3063                 :   }
    3064                 : 
    3065                 :   // If mFrontBuffer
    3066               0 :   if (IsSurfaceDescriptorValid(mFrontBuffer)) {
    3067               0 :     *aNewBack = mFrontBuffer;
    3068                 :   } else {
    3069               0 :     *aNewBack = null_t();
    3070                 :   }
    3071               0 :   mFrontBuffer = aNewFront.get_SurfaceDescriptor();
    3072               0 : }
    3073                 : 
    3074                 : void
    3075               0 : BasicShadowImageLayer::Paint(gfxContext* aContext)
    3076                 : {
    3077               0 :   if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
    3078               0 :     return;
    3079                 :   }
    3080                 : 
    3081                 :   nsRefPtr<gfxASurface> surface =
    3082               0 :     BasicManager()->OpenDescriptor(mFrontBuffer);
    3083               0 :   nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
    3084               0 :   pat->SetFilter(mFilter);
    3085                 : 
    3086                 :   // The visible region can extend outside the image.  If we're not
    3087                 :   // tiling, we don't want to draw into that area, so just draw within
    3088                 :   // the image bounds.
    3089               0 :   const nsIntRect* tileSrcRect = GetTileSourceRect();
    3090               0 :   AutoSetOperator setOperator(aContext, GetOperator());
    3091                 :   BasicImageLayer::PaintContext(pat,
    3092               0 :                                 tileSrcRect ? GetEffectiveVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
    3093                 :                                 tileSrcRect,
    3094               0 :                                 GetEffectiveOpacity(), aContext);
    3095                 : }
    3096                 : 
    3097                 : class BasicShadowColorLayer : public ShadowColorLayer,
    3098                 :                               public BasicImplData
    3099                 : {
    3100                 : public:
    3101               0 :   BasicShadowColorLayer(BasicShadowLayerManager* aLayerManager) :
    3102               0 :     ShadowColorLayer(aLayerManager, static_cast<BasicImplData*>(this))
    3103                 :   {
    3104               0 :     MOZ_COUNT_CTOR(BasicShadowColorLayer);
    3105               0 :   }
    3106               0 :   virtual ~BasicShadowColorLayer()
    3107               0 :   {
    3108               0 :     MOZ_COUNT_DTOR(BasicShadowColorLayer);
    3109               0 :   }
    3110                 : 
    3111               0 :   virtual void Paint(gfxContext* aContext)
    3112                 :   {
    3113               0 :     AutoSetOperator setOperator(aContext, GetOperator());
    3114               0 :     BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
    3115               0 :   }
    3116                 : };
    3117                 : 
    3118                 : class BasicShadowCanvasLayer : public ShadowCanvasLayer,
    3119                 :                                public BasicImplData
    3120                 : {
    3121                 : public:
    3122               0 :   BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
    3123               0 :     ShadowCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
    3124                 :   {
    3125               0 :     MOZ_COUNT_CTOR(BasicShadowCanvasLayer);
    3126               0 :   }
    3127               0 :   virtual ~BasicShadowCanvasLayer()
    3128               0 :   {
    3129               0 :     MOZ_COUNT_DTOR(BasicShadowCanvasLayer);
    3130               0 :   }
    3131                 : 
    3132               0 :   virtual void Disconnect()
    3133                 :   {
    3134               0 :     DestroyFrontBuffer();
    3135               0 :     ShadowCanvasLayer::Disconnect();
    3136               0 :   }
    3137                 : 
    3138                 :   virtual void Initialize(const Data& aData);
    3139                 :   void Swap(const CanvasSurface& aNewFront, bool needYFlip, CanvasSurface* aNewBack);
    3140                 : 
    3141               0 :   virtual void DestroyFrontBuffer()
    3142                 :   {
    3143               0 :     if (IsSurfaceDescriptorValid(mFrontSurface)) {
    3144               0 :       mAllocator->DestroySharedSurface(&mFrontSurface);
    3145                 :     }
    3146               0 :   }
    3147                 : 
    3148                 :   virtual void Paint(gfxContext* aContext);
    3149                 : 
    3150                 : private:
    3151               0 :   BasicShadowLayerManager* BasicManager()
    3152                 :   {
    3153               0 :     return static_cast<BasicShadowLayerManager*>(mManager);
    3154                 :   }
    3155                 : 
    3156                 :   SurfaceDescriptor mFrontSurface;
    3157                 :   bool mNeedsYFlip;
    3158                 : };
    3159                 : 
    3160                 : 
    3161                 : void
    3162               0 : BasicShadowCanvasLayer::Initialize(const Data& aData)
    3163                 : {
    3164               0 :   NS_RUNTIMEABORT("Incompatibe surface type");
    3165               0 : }
    3166                 : 
    3167                 : void
    3168               0 : BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
    3169                 :                              CanvasSurface* aNewBack)
    3170                 : {
    3171                 :   nsRefPtr<gfxASurface> surface =
    3172               0 :     BasicManager()->OpenDescriptor(aNewFront);
    3173                 :   // Destroy mFrontBuffer if size different
    3174               0 :   gfxIntSize sz = surface->GetSize();
    3175               0 :   bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height);
    3176               0 :   if (IsSurfaceDescriptorValid(mFrontSurface)) {
    3177               0 :     nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface);
    3178                 :     surfaceConfigChanged = surfaceConfigChanged ||
    3179               0 :                            surface->GetContentType() != front->GetContentType();
    3180                 :   }
    3181               0 :   if (surfaceConfigChanged) {
    3182               0 :     DestroyFrontBuffer();
    3183               0 :     mBounds.SetRect(0, 0, sz.width, sz.height);
    3184                 :   }
    3185                 : 
    3186               0 :   mNeedsYFlip = needYFlip;
    3187                 :   // If mFrontBuffer
    3188               0 :   if (IsSurfaceDescriptorValid(mFrontSurface)) {
    3189               0 :     *aNewBack = mFrontSurface;
    3190                 :   } else {
    3191               0 :     *aNewBack = null_t();
    3192                 :   }
    3193               0 :   mFrontSurface = aNewFront.get_SurfaceDescriptor();
    3194               0 : }
    3195                 : 
    3196                 : void
    3197               0 : BasicShadowCanvasLayer::Paint(gfxContext* aContext)
    3198                 : {
    3199               0 :   NS_ASSERTION(BasicManager()->InDrawing(),
    3200                 :                "Can only draw in drawing phase");
    3201                 : 
    3202               0 :   if (!IsSurfaceDescriptorValid(mFrontSurface)) {
    3203               0 :     return;
    3204                 :   }
    3205                 : 
    3206                 :   nsRefPtr<gfxASurface> surface =
    3207               0 :     BasicManager()->OpenDescriptor(mFrontSurface);
    3208               0 :   nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
    3209                 : 
    3210               0 :   pat->SetFilter(mFilter);
    3211               0 :   pat->SetExtend(gfxPattern::EXTEND_PAD);
    3212                 : 
    3213               0 :   gfxRect r(0, 0, mBounds.width, mBounds.height);
    3214                 : 
    3215               0 :   gfxMatrix m;
    3216               0 :   if (mNeedsYFlip) {
    3217               0 :     m = aContext->CurrentMatrix();
    3218               0 :     aContext->Translate(gfxPoint(0.0, mBounds.height));
    3219               0 :     aContext->Scale(1.0, -1.0);
    3220                 :   }
    3221                 : 
    3222               0 :   AutoSetOperator setOperator(aContext, GetOperator());
    3223               0 :   aContext->NewPath();
    3224                 :   // No need to snap here; our transform has already taken care of it
    3225               0 :   aContext->Rectangle(r);
    3226               0 :   aContext->SetPattern(pat);
    3227               0 :   aContext->FillWithOpacity(GetEffectiveOpacity());
    3228                 : 
    3229               0 :   if (mNeedsYFlip) {
    3230               0 :     aContext->SetMatrix(m);
    3231                 :   }
    3232                 : }
    3233                 : 
    3234                 : // Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
    3235                 : // our layer tree to a parent process.  Record the new layer creation
    3236                 : // in the current open transaction as a side effect.
    3237                 : template<typename CreatedMethod>
    3238                 : static void
    3239               0 : MaybeCreateShadowFor(BasicShadowableLayer* aLayer,
    3240                 :                      BasicShadowLayerManager* aMgr,
    3241                 :                      CreatedMethod aMethod)
    3242                 : {
    3243               0 :   if (!aMgr->HasShadowManager()) {
    3244               0 :     return;
    3245                 :   }
    3246                 : 
    3247               0 :   PLayerChild* shadow = aMgr->ConstructShadowFor(aLayer);
    3248                 :   // XXX error handling
    3249               0 :   NS_ABORT_IF_FALSE(shadow, "failed to create shadow");
    3250                 : 
    3251               0 :   aLayer->SetShadow(shadow);
    3252               0 :   (aMgr->*aMethod)(aLayer);
    3253               0 :   aMgr->Hold(aLayer->AsLayer());
    3254                 : }
    3255                 : #define MAYBE_CREATE_SHADOW(_type)                                      \
    3256                 :   MaybeCreateShadowFor(layer, this,                                     \
    3257                 :                        &ShadowLayerForwarder::Created ## _type ## Layer)
    3258                 : 
    3259                 : already_AddRefed<ThebesLayer>
    3260               0 : BasicShadowLayerManager::CreateThebesLayer()
    3261                 : {
    3262               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3263                 :   nsRefPtr<BasicShadowableThebesLayer> layer =
    3264               0 :     new BasicShadowableThebesLayer(this);
    3265               0 :   MAYBE_CREATE_SHADOW(Thebes);
    3266               0 :   return layer.forget();
    3267                 : }
    3268                 : 
    3269                 : already_AddRefed<ContainerLayer>
    3270               0 : BasicShadowLayerManager::CreateContainerLayer()
    3271                 : {
    3272               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3273                 :   nsRefPtr<BasicShadowableContainerLayer> layer =
    3274               0 :     new BasicShadowableContainerLayer(this);
    3275               0 :   MAYBE_CREATE_SHADOW(Container);
    3276               0 :   return layer.forget();
    3277                 : }
    3278                 : 
    3279                 : already_AddRefed<ImageLayer>
    3280               0 : BasicShadowLayerManager::CreateImageLayer()
    3281                 : {
    3282               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3283                 :   nsRefPtr<BasicShadowableImageLayer> layer =
    3284               0 :     new BasicShadowableImageLayer(this);
    3285               0 :   MAYBE_CREATE_SHADOW(Image);
    3286               0 :   return layer.forget();
    3287                 : }
    3288                 : 
    3289                 : already_AddRefed<ColorLayer>
    3290               0 : BasicShadowLayerManager::CreateColorLayer()
    3291                 : {
    3292               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3293                 :   nsRefPtr<BasicShadowableColorLayer> layer =
    3294               0 :     new BasicShadowableColorLayer(this);
    3295               0 :   MAYBE_CREATE_SHADOW(Color);
    3296               0 :   return layer.forget();
    3297                 : }
    3298                 : 
    3299                 : already_AddRefed<CanvasLayer>
    3300               0 : BasicShadowLayerManager::CreateCanvasLayer()
    3301                 : {
    3302               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3303                 :   nsRefPtr<BasicShadowableCanvasLayer> layer =
    3304               0 :     new BasicShadowableCanvasLayer(this);
    3305               0 :   MAYBE_CREATE_SHADOW(Canvas);
    3306               0 :   return layer.forget();
    3307                 : }
    3308                 : already_AddRefed<ShadowThebesLayer>
    3309               0 : BasicShadowLayerManager::CreateShadowThebesLayer()
    3310                 : {
    3311               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3312               0 :   nsRefPtr<ShadowThebesLayer> layer = new BasicShadowThebesLayer(this);
    3313               0 :   return layer.forget();
    3314                 : }
    3315                 : 
    3316                 : already_AddRefed<ShadowContainerLayer>
    3317               0 : BasicShadowLayerManager::CreateShadowContainerLayer()
    3318                 : {
    3319               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3320               0 :   nsRefPtr<ShadowContainerLayer> layer = new BasicShadowContainerLayer(this);
    3321               0 :   return layer.forget();
    3322                 : }
    3323                 : 
    3324                 : already_AddRefed<ShadowImageLayer>
    3325               0 : BasicShadowLayerManager::CreateShadowImageLayer()
    3326                 : {
    3327               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3328               0 :   nsRefPtr<ShadowImageLayer> layer = new BasicShadowImageLayer(this);
    3329               0 :   return layer.forget();
    3330                 : }
    3331                 : 
    3332                 : already_AddRefed<ShadowColorLayer>
    3333               0 : BasicShadowLayerManager::CreateShadowColorLayer()
    3334                 : {
    3335               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3336               0 :   nsRefPtr<ShadowColorLayer> layer = new BasicShadowColorLayer(this);
    3337               0 :   return layer.forget();
    3338                 : }
    3339                 : 
    3340                 : already_AddRefed<ShadowCanvasLayer>
    3341               0 : BasicShadowLayerManager::CreateShadowCanvasLayer()
    3342                 : {
    3343               0 :   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
    3344               0 :   nsRefPtr<ShadowCanvasLayer> layer = new BasicShadowCanvasLayer(this);
    3345               0 :   return layer.forget();
    3346                 : }
    3347                 : 
    3348               0 : BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
    3349               0 :   BasicLayerManager(aWidget)
    3350                 : {
    3351               0 :   MOZ_COUNT_CTOR(BasicShadowLayerManager);
    3352               0 : }
    3353                 : 
    3354               0 : BasicShadowLayerManager::~BasicShadowLayerManager()
    3355                 : {
    3356               0 :   MOZ_COUNT_DTOR(BasicShadowLayerManager);
    3357               0 : }
    3358                 : 
    3359                 : void
    3360               0 : BasicShadowLayerManager::SetRoot(Layer* aLayer)
    3361                 : {
    3362               0 :   if (mRoot != aLayer) {
    3363               0 :     if (HasShadowManager()) {
    3364                 :       // Have to hold the old root and its children in order to
    3365                 :       // maintain the same view of the layer tree in this process as
    3366                 :       // the parent sees.  Otherwise layers can be destroyed
    3367                 :       // mid-transaction and bad things can happen (v. bug 612573)
    3368               0 :       if (mRoot) {
    3369               0 :         Hold(mRoot);
    3370                 :       }
    3371               0 :       ShadowLayerForwarder::SetRoot(Hold(aLayer));
    3372                 :     }
    3373               0 :     BasicLayerManager::SetRoot(aLayer);
    3374                 :   }
    3375               0 : }
    3376                 : 
    3377                 : void
    3378               0 : BasicShadowLayerManager::Mutated(Layer* aLayer)
    3379                 : {
    3380               0 :   BasicLayerManager::Mutated(aLayer);
    3381                 : 
    3382               0 :   NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
    3383               0 :   if (HasShadowManager() && ShouldShadow(aLayer)) {
    3384               0 :     ShadowLayerForwarder::Mutated(Hold(aLayer));
    3385                 :   }
    3386               0 : }
    3387                 : 
    3388                 : void
    3389               0 : BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
    3390                 : {
    3391               0 :   NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
    3392                 :   // If the last transaction was incomplete (a failed DoEmptyTransaction),
    3393                 :   // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
    3394                 :   // to the previous transaction.
    3395               0 :   if (HasShadowManager()) {
    3396               0 :     ShadowLayerForwarder::BeginTransaction();
    3397                 :   }
    3398               0 :   BasicLayerManager::BeginTransactionWithTarget(aTarget);
    3399               0 : }
    3400                 : 
    3401                 : void
    3402               0 : BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
    3403                 :                                         void* aCallbackData,
    3404                 :                                         EndTransactionFlags aFlags)
    3405                 : {
    3406               0 :   BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
    3407               0 :   ForwardTransaction();
    3408               0 : }
    3409                 : 
    3410                 : bool
    3411               0 : BasicShadowLayerManager::EndEmptyTransaction()
    3412                 : {
    3413               0 :   if (!BasicLayerManager::EndEmptyTransaction()) {
    3414                 :     // Return without calling ForwardTransaction. This leaves the
    3415                 :     // ShadowLayerForwarder transaction open; the following
    3416                 :     // EndTransaction will complete it.
    3417               0 :     return false;
    3418                 :   }
    3419               0 :   ForwardTransaction();
    3420               0 :   return true;
    3421                 : }
    3422                 : 
    3423                 : void
    3424               0 : BasicShadowLayerManager::ForwardTransaction()
    3425                 : {
    3426                 : #ifdef DEBUG
    3427               0 :   mPhase = PHASE_FORWARD;
    3428                 : #endif
    3429                 : 
    3430                 :   // forward this transaction's changeset to our ShadowLayerManager
    3431               0 :   AutoInfallibleTArray<EditReply, 10> replies;
    3432               0 :   if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
    3433               0 :     for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
    3434               0 :       const EditReply& reply = replies[i];
    3435                 : 
    3436               0 :       switch (reply.type()) {
    3437                 :       case EditReply::TOpThebesBufferSwap: {
    3438               0 :         MOZ_LAYERS_LOG(("[LayersForwarder] ThebesBufferSwap"));
    3439                 : 
    3440               0 :         const OpThebesBufferSwap& obs = reply.get_OpThebesBufferSwap();
    3441               0 :         BasicShadowableThebesLayer* thebes = GetBasicShadowable(obs)->AsThebes();
    3442                 :         thebes->SetBackBufferAndAttrs(
    3443               0 :           obs.newBackBuffer(), obs.newValidRegion(),
    3444               0 :           obs.readOnlyFrontBuffer(), obs.frontUpdatedRegion());
    3445               0 :         break;
    3446                 :       }
    3447                 :       case EditReply::TOpBufferSwap: {
    3448               0 :         MOZ_LAYERS_LOG(("[LayersForwarder] BufferSwap"));
    3449                 : 
    3450               0 :         const OpBufferSwap& obs = reply.get_OpBufferSwap();
    3451               0 :         const CanvasSurface& newBack = obs.newBackBuffer();
    3452               0 :         if (newBack.type() == CanvasSurface::TSurfaceDescriptor) {
    3453               0 :           GetBasicShadowable(obs)->SetBackBuffer(newBack.get_SurfaceDescriptor());
    3454               0 :         } else if (newBack.type() == CanvasSurface::Tnull_t) {
    3455               0 :           GetBasicShadowable(obs)->SetBackBuffer(SurfaceDescriptor());
    3456                 :         } else {
    3457               0 :           NS_RUNTIMEABORT("Unknown back image type");
    3458                 :         }
    3459               0 :         break;
    3460                 :       }
    3461                 : 
    3462                 :       case EditReply::TOpImageSwap: {
    3463               0 :         MOZ_LAYERS_LOG(("[LayersForwarder] YUVBufferSwap"));
    3464                 : 
    3465               0 :         const OpImageSwap& ois = reply.get_OpImageSwap();
    3466               0 :         BasicShadowableLayer* layer = GetBasicShadowable(ois);
    3467               0 :         const SharedImage& newBack = ois.newBackImage();
    3468                 : 
    3469               0 :         if (newBack.type() == SharedImage::TSurfaceDescriptor) {
    3470               0 :           layer->SetBackBuffer(newBack.get_SurfaceDescriptor());
    3471               0 :         } else if (newBack.type() == SharedImage::TYUVImage) {
    3472               0 :           const YUVImage& yuv = newBack.get_YUVImage();
    3473               0 :           nsRefPtr<gfxSharedImageSurface> YSurf = gfxSharedImageSurface::Open(yuv.Ydata());
    3474               0 :           nsRefPtr<gfxSharedImageSurface> USurf = gfxSharedImageSurface::Open(yuv.Udata());
    3475               0 :           nsRefPtr<gfxSharedImageSurface> VSurf = gfxSharedImageSurface::Open(yuv.Vdata());
    3476               0 :           layer->SetBackBufferYUVImage(YSurf, USurf, VSurf);
    3477                 :         } else {
    3478               0 :           layer->SetBackBuffer(SurfaceDescriptor());
    3479               0 :           layer->SetBackBufferYUVImage(nsnull, nsnull, nsnull);
    3480                 :         }
    3481                 : 
    3482               0 :         break;
    3483                 :       }
    3484                 : 
    3485                 :       default:
    3486               0 :         NS_RUNTIMEABORT("not reached");
    3487                 :       }
    3488                 :     }
    3489               0 :   } else if (HasShadowManager()) {
    3490               0 :     NS_WARNING("failed to forward Layers transaction");
    3491                 :   }
    3492                 : 
    3493                 : #ifdef DEBUG
    3494               0 :   mPhase = PHASE_NONE;
    3495                 : #endif
    3496                 : 
    3497                 :   // this may result in Layers being deleted, which results in
    3498                 :   // PLayer::Send__delete__() and DeallocShmem()
    3499               0 :   mKeepAlive.Clear();
    3500               0 : }
    3501                 : 
    3502                 : ShadowableLayer*
    3503               0 : BasicShadowLayerManager::Hold(Layer* aLayer)
    3504                 : {
    3505               0 :   NS_ABORT_IF_FALSE(HasShadowManager(),
    3506                 :                     "top-level tree, no shadow tree to remote to");
    3507                 : 
    3508               0 :   ShadowableLayer* shadowable = ToShadowable(aLayer);
    3509               0 :   NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
    3510                 : 
    3511               0 :   mKeepAlive.AppendElement(aLayer);
    3512               0 :   return shadowable;
    3513                 : }
    3514                 : 
    3515                 : bool
    3516               0 : BasicShadowLayerManager::IsCompositingCheap()
    3517                 : {
    3518                 :   // Whether compositing is cheap depends on the parent backend.
    3519                 :   return mShadowManager &&
    3520               0 :          LayerManager::IsCompositingCheap(GetParentBackendType());
    3521                 : }
    3522                 : 
    3523                 : }
    3524                 : }

Generated by: LCOV version 1.7