Bug 687372 - ImageLayerOGL should not destroy surface given as argument. r=cjones
authorOleg Romashin <romaxa@gmail.com>
Tue, 27 Sep 2011 15:19:26 -0700
changeset 77779 261bb33e9c53c477279633b488812feb20d72d7c
parent 77778 2a443d5f2944f2537c20304f45b0d614759a6e23
child 77780 455bee36af33e57b0635d64bb4a6e69ee63e56f6
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewerscjones
bugs687372
milestone10.0a1
Bug 687372 - ImageLayerOGL should not destroy surface given as argument. r=cjones
gfx/layers/basic/BasicLayers.cpp
gfx/layers/d3d9/ImageLayerD3D9.cpp
gfx/layers/d3d9/ImageLayerD3D9.h
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/ipc/ShadowLayersParent.h
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.h
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -2354,19 +2354,17 @@ class BasicShadowableImageLayer : public
 public:
   BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
     BasicImageLayer(aManager)
   {
     MOZ_COUNT_CTOR(BasicShadowableImageLayer);
   }
   virtual ~BasicShadowableImageLayer()
   {
-    if (IsSurfaceDescriptorValid(mBackBuffer)) {
-      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
-    }
+    DestroyBackBuffer();
     MOZ_COUNT_DTOR(BasicShadowableImageLayer);
   }
 
   virtual void Paint(gfxContext* aContext);
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = ImageLayerAttributes(mFilter);
@@ -2386,20 +2384,33 @@ public:
   {
     mBackBufferY = aYBuffer;
     mBackBufferU = aUBuffer;
     mBackBufferV = aVBuffer;
   }
 
   virtual void Disconnect()
   {
+    mBackBufferY = mBackBufferU = mBackBufferV = nsnull;
     mBackBuffer = SurfaceDescriptor();
     BasicShadowableLayer::Disconnect();
   }
 
+  void DestroyBackBuffer()
+  {
+    if (IsSurfaceDescriptorValid(mBackBuffer)) {
+      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
+    }
+    if (mBackBufferY) {
+      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferY);
+      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferU);
+      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferV);
+    }
+  }
+
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   // For YUV Images these are the 3 planes (Y, Cb and Cr),
   // for RGB images only mBackSurface is used.
@@ -2422,108 +2433,69 @@ BasicShadowableImageLayer::Paint(gfxCont
     return;
   }
 
   if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
     PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image.get());
     const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
     NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
 
-    if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize) {
-
-      if (mBackBufferY) {
-        BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferY);
-        BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferU);
-        BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferV);
-        BasicManager()->DestroyedImageBuffer(BasicManager()->Hold(this));
-      }
+    if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !mBackBufferY) {
+      DestroyBackBuffer();
       mSize = data->mYSize;
       mCbCrSize = data->mCbCrSize;
 
-      nsRefPtr<gfxSharedImageSurface> tmpYSurface;
-      nsRefPtr<gfxSharedImageSurface> tmpUSurface;
-      nsRefPtr<gfxSharedImageSurface> tmpVSurface;
-
-      if (!BasicManager()->AllocDoubleBuffer(
-            mSize,
-            gfxASurface::CONTENT_ALPHA,
-            getter_AddRefs(tmpYSurface), getter_AddRefs(mBackBufferY)))
-        NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
-      
-      if (!BasicManager()->AllocDoubleBuffer(
-            mCbCrSize,
-            gfxASurface::CONTENT_ALPHA,
-            getter_AddRefs(tmpUSurface), getter_AddRefs(mBackBufferU)))
+      if (!BasicManager()->AllocBuffer(mSize, gfxASurface::CONTENT_ALPHA,
+                                       getter_AddRefs(mBackBufferY)) ||
+          !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
+                                       getter_AddRefs(mBackBufferU)) ||
+          !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
+                                       getter_AddRefs(mBackBufferV))) {
         NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
-      
-      if (!BasicManager()->AllocDoubleBuffer(
-            mCbCrSize,
-            gfxASurface::CONTENT_ALPHA,
-            getter_AddRefs(tmpVSurface), getter_AddRefs(mBackBufferV)))
-        NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
-
-      YUVImage yuv(tmpYSurface->GetShmem(),
-                   tmpUSurface->GetShmem(),
-                   tmpVSurface->GetShmem(),
-                   nsIntRect());
-
-      BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this),
-                                         nsIntSize(mSize.width, mSize.height),
-                                         yuv);
-
+      }
     }
-      
+
     for (int i = 0; i < data->mYSize.height; i++) {
       memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(),
              data->mYChannel + i * data->mYStride,
              data->mYSize.width);
     }
     for (int i = 0; i < data->mCbCrSize.height; i++) {
       memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(),
              data->mCbChannel + i * data->mCbCrStride,
              data->mCbCrSize.width);
       memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(),
              data->mCrChannel + i * data->mCbCrStride,
              data->mCbCrSize.width);
     }
-      
+
     YUVImage yuv(mBackBufferY->GetShmem(),
                  mBackBufferU->GetShmem(),
                  mBackBufferV->GetShmem(),
                  data->GetPictureRect());
-  
+
     BasicManager()->PaintedImage(BasicManager()->Hold(this),
                                  yuv);
-
     return;
   }
 
   gfxIntSize oldSize = mSize;
   nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
   if (!pat || !HasShadow())
     return;
 
-  if (oldSize != mSize) {
-    if (IsSurfaceDescriptorValid(mBackBuffer)) {
-      BasicManager()->DestroyedImageBuffer(BasicManager()->Hold(this));
-      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
-    }
-
-    SurfaceDescriptor tmpFrontSurface;
-    // XXX error handling?
-    if (!BasicManager()->AllocDoubleBuffer(
+  if (oldSize != mSize || !IsSurfaceDescriptorValid(mBackBuffer)) {
+    DestroyBackBuffer();
+
+    if (!BasicManager()->AllocBuffer(
           mSize,
           (GetContentFlags() & CONTENT_OPAQUE) ?
             gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
-          &tmpFrontSurface, &mBackBuffer))
+          &mBackBuffer))
       NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
-
-    BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this),
-                                       nsIntSize(mSize.width, mSize.height),
-                                       tmpFrontSurface);
   }
 
   nsRefPtr<gfxASurface> backSurface =
     BasicManager()->OpenDescriptor(mBackBuffer);
   nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
   tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
   PaintContext(pat,
                nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
@@ -2736,17 +2708,17 @@ public:
 
   virtual void DestroyFrontBuffer()
   {
     mFrontBuffer.Clear();
     mValidRegion.SetEmpty();
     mOldValidRegion.SetEmpty();
 
     if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
-      BasicManager()->ShadowLayerManager::DestroySharedSurface(&mFrontBufferDescriptor, mAllocator);
+      mAllocator->DestroySharedSurface(&mFrontBufferDescriptor);
     }
   }
 
   virtual void PaintThebes(gfxContext* aContext,
                            LayerManager::DrawThebesLayerCallback aCallback,
                            void* aCallbackData,
                            ReadbackProcessor* aReadback);
 
@@ -2897,56 +2869,60 @@ public:
   }
   virtual ~BasicShadowImageLayer()
   {
     MOZ_COUNT_DTOR(BasicShadowImageLayer);
   }
 
   virtual void Disconnect()
   {
-    DestroyFrontBuffer();
+    mFrontBuffer = SurfaceDescriptor();
     ShadowImageLayer::Disconnect();
   }
 
-  virtual PRBool Init(const SharedImage& front, const nsIntSize& size);
-
-  virtual void Swap(const SharedImage& aNewFront, SharedImage* aNewBack);
+  virtual void Swap(const SharedImage& aNewFront,
+                    SharedImage* aNewBack);
 
   virtual void DestroyFrontBuffer()
   {
-    if (IsSurfaceDescriptorValid(mFrontBuffer)) {
-      BasicManager()->ShadowLayerManager::DestroySharedSurface(&mFrontBuffer, mAllocator);
+    if (mAllocator && IsSurfaceDescriptorValid(mFrontBuffer)) {
+      mAllocator->DestroySharedSurface(&mFrontBuffer);
     }
   }
 
   virtual void Paint(gfxContext* aContext);
 
 protected:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   SurfaceDescriptor mFrontBuffer;
   gfxIntSize mSize;
 };
 
-PRBool
-BasicShadowImageLayer::Init(const SharedImage& front,
-                            const nsIntSize& size)
+void
+BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
+                            SharedImage* aNewBack)
 {
-  mFrontBuffer = front.get_SurfaceDescriptor();
-  mSize = gfxIntSize(size.width, size.height);
-  return PR_TRUE;
-}
-
-void
-BasicShadowImageLayer::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
-{
-  *aNewBack = mFrontBuffer;
+  nsRefPtr<gfxASurface> surface =
+    BasicManager()->OpenDescriptor(aNewFront);
+  // Destroy mFrontBuffer if size different
+  if (surface->GetSize() != mSize) {
+    DestroyFrontBuffer();
+    mSize = surface->GetSize();
+  }
+
+  // If mFrontBuffer
+  if (IsSurfaceDescriptorValid(mFrontBuffer)) {
+    *aNewBack = mFrontBuffer;
+  } else {
+    *aNewBack = null_t();
+  }
   mFrontBuffer = aNewFront.get_SurfaceDescriptor();
 }
 
 void
 BasicShadowImageLayer::Paint(gfxContext* aContext)
 {
   if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
     return;
@@ -3012,17 +2988,17 @@ public:
   virtual void Initialize(const Data& aData);
   virtual void Init(const SurfaceDescriptor& aNewFront, const nsIntSize& aSize, bool needYFlip);
 
   void Swap(const SurfaceDescriptor& aNewFront, SurfaceDescriptor* aNewBack);
 
   virtual void DestroyFrontBuffer()
   {
     if (IsSurfaceDescriptorValid(mFrontSurface)) {
-      BasicManager()->ShadowLayerManager::DestroySharedSurface(&mFrontSurface, mAllocator);
+      mAllocator->DestroySharedSurface(&mFrontSurface);
     }
   }
 
   virtual void Paint(gfxContext* aContext);
 
 private:
   BasicShadowLayerManager* BasicManager()
   {
@@ -3319,24 +3295,27 @@ BasicShadowLayerManager::ForwardTransact
         MOZ_LAYERS_LOG(("[LayersForwarder] YUVBufferSwap"));
 
         const OpImageSwap& ois = reply.get_OpImageSwap();
         BasicShadowableLayer* layer = GetBasicShadowable(ois);
         const SharedImage& newBack = ois.newBackImage();
 
         if (newBack.type() == SharedImage::TSurfaceDescriptor) {
           layer->SetBackBuffer(newBack.get_SurfaceDescriptor());
-        } else {
+        } else if (newBack.type() == SharedImage::TYUVImage) {
           const YUVImage& yuv = newBack.get_YUVImage();
           nsRefPtr<gfxSharedImageSurface> YSurf = gfxSharedImageSurface::Open(yuv.Ydata());
           nsRefPtr<gfxSharedImageSurface> USurf = gfxSharedImageSurface::Open(yuv.Udata());
           nsRefPtr<gfxSharedImageSurface> VSurf = gfxSharedImageSurface::Open(yuv.Vdata());
           layer->SetBackBufferYUVImage(YSurf, USurf, VSurf);
+        } else {
+          layer->SetBackBuffer(SurfaceDescriptor());
+          layer->SetBackBufferYUVImage(nsnull, nsnull, nsnull);
         }
-        
+
         break;
       }
 
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
   } else if (HasShadowManager()) {
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -605,50 +605,29 @@ ShadowImageLayerD3D9::ShadowImageLayerD3
   , LayerD3D9(aManager)
 {
   mImplData = static_cast<LayerD3D9*>(this);
 }  
 
 ShadowImageLayerD3D9::~ShadowImageLayerD3D9()
 {}
 
-PRBool
-ShadowImageLayerD3D9::Init(const SharedImage& aFront,
-                          const nsIntSize& aSize)
+void
+ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront,
+                           SharedImage* aNewBack)
 {
-   if (aFront.type() == SharedImage::TSurfaceDescriptor) {
-    SurfaceDescriptor desc = aFront.get_SurfaceDescriptor();
-    nsRefPtr<gfxASurface> surf = 
-      ShadowLayerForwarder::OpenDescriptor(desc);
-    
+  if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
     if (!mBuffer) {
       mBuffer = new ShadowBufferD3D9(this);
     }
-    return !!mBuffer;
-  } else {
-    if (!mYCbCrImage) {
-      mYCbCrImage = new PlanarYCbCrImageD3D9();
-    }
-    return !!mYCbCrImage;
-  }
-}
+    nsRefPtr<gfxASurface> surf =
+      ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
 
-void
-ShadowImageLayerD3D9::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
-{
-  
-  if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
-    nsRefPtr<gfxASurface> surf = 
-      ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
-   
-    if (mBuffer) {
-      mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
-    }
+    mBuffer->Upload(surf, GetVisibleRegion().GetBounds());
   } else {
-
     const YUVImage& yuv = aNewFront.get_YUVImage();
 
     nsRefPtr<gfxSharedImageSurface> surfY =
       gfxSharedImageSurface::Open(yuv.Ydata());
     nsRefPtr<gfxSharedImageSurface> surfU =
       gfxSharedImageSurface::Open(yuv.Udata());
     nsRefPtr<gfxSharedImageSurface> surfV =
       gfxSharedImageSurface::Open(yuv.Vdata());
@@ -660,30 +639,28 @@ ShadowImageLayerD3D9::Swap(const SharedI
     data.mCbChannel = surfU->Data();
     data.mCrChannel = surfV->Data();
     data.mCbCrStride = surfU->Stride();
     data.mCbCrSize = surfU->GetSize();
     data.mPicSize = surfY->GetSize();
     data.mPicX = 0;
     data.mPicY = 0;
 
+    if (!mYCbCrImage) {
+      mYCbCrImage = new PlanarYCbCrImageD3D9();
+    }
+
     mYCbCrImage->SetData(data);
 
   }
   
   *aNewBack = aNewFront;
 }
 
 void
-ShadowImageLayerD3D9::DestroyFrontBuffer()
-{
-  Destroy();
-}
-
-void
 ShadowImageLayerD3D9::Disconnect()
 {
   Destroy();
 }
 
 void
 ShadowImageLayerD3D9::Destroy()
 {
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -180,21 +180,18 @@ private:
 class ShadowImageLayerD3D9 : public ShadowImageLayer,
                             public LayerD3D9
 {
 public:
   ShadowImageLayerD3D9(LayerManagerD3D9* aManager);
   virtual ~ShadowImageLayerD3D9();
 
   // ShadowImageLayer impl
-  virtual PRBool Init(const SharedImage& aFront, const nsIntSize& aSize);
-
-  virtual void Swap(const SharedImage& aFront, SharedImage* aNewBack);
-
-  virtual void DestroyFrontBuffer();
+  virtual void Swap(const SharedImage& aFront,
+                    SharedImage* aNewBack);
 
   virtual void Disconnect();
 
   // LayerD3D9 impl
   virtual void Destroy();
 
   virtual Layer* GetLayer();
 
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -89,16 +89,17 @@ struct YUVImage {
   Shmem Udata;
   Shmem Vdata;
   nsIntRect picture;
 };
 
 union SharedImage {
   SurfaceDescriptor;
   YUVImage;
+  null_t;
 };
 
 struct ThebesBuffer {
   SurfaceDescriptor buffer;
   nsIntRect rect;
   nsIntPoint rotation; 
 };
 union OptionalThebesBuffer { ThebesBuffer; null_t; };
@@ -117,23 +118,16 @@ struct OpDestroyThebesFrontBuffer { PLay
 struct OpCreateCanvasBuffer {
   PLayer layer;
   nsIntSize size;
   SurfaceDescriptor initialFront;
   bool needYFlip;
 };
 struct OpDestroyCanvasFrontBuffer { PLayer layer; };
 
-struct OpCreateImageBuffer {
-  PLayer layer;
-  nsIntSize size;
-  SharedImage initialFront;
-};
-struct OpDestroyImageFrontBuffer { PLayer layer; };
-
 
 // Change a layer's attributes
 struct CommonLayerAttributes {
   nsIntRegion visibleRegion;
   gfx3DMatrix transform;
   PRUint32 contentFlags;
   float opacity;
   bool useClipRect;
@@ -200,20 +194,18 @@ struct OpPaintImage  {
 union Edit {
   OpCreateThebesLayer;
   OpCreateContainerLayer;
   OpCreateImageLayer;
   OpCreateColorLayer;
   OpCreateCanvasLayer;
   OpCreateCanvasBuffer;
   OpCreateThebesBuffer;
-  OpCreateImageBuffer;
   OpDestroyThebesFrontBuffer;
   OpDestroyCanvasFrontBuffer;
-  OpDestroyImageFrontBuffer;
 
   OpSetLayerAttributes;
 
   OpSetRoot;
   OpInsertAfter;
   OpAppendChild;
   OpRemoveChild;
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -197,26 +197,16 @@ ShadowLayerForwarder::CreatedThebesBuffe
                           nsIntPoint(0, 0));
   }
   mTxn->AddEdit(OpCreateThebesBuffer(NULL, Shadow(aThebes),
                                      buffer,
                                      aFrontValidRegion));
 }
 
 void
-ShadowLayerForwarder::CreatedImageBuffer(ShadowableLayer* aImage,
-                                         nsIntSize aSize,
-                                         const SharedImage& aTempFrontImage)
-{
-  mTxn->AddEdit(OpCreateImageBuffer(NULL, Shadow(aImage),
-                                    aSize,
-                                    aTempFrontImage));
-}
-
-void
 ShadowLayerForwarder::CreatedCanvasBuffer(ShadowableLayer* aCanvas,
                                           nsIntSize aSize,
                                           const SurfaceDescriptor& aTempFrontSurface,
                                           bool aNeedYFlip)
 {
   mTxn->AddEdit(OpCreateCanvasBuffer(NULL, Shadow(aCanvas),
                                      aSize,
                                      aTempFrontSurface,
@@ -227,22 +217,16 @@ void
 ShadowLayerForwarder::DestroyedThebesBuffer(ShadowableLayer* aThebes,
                                             const SurfaceDescriptor& aBackBufferToDestroy)
 {
   mTxn->AddEdit(OpDestroyThebesFrontBuffer(NULL, Shadow(aThebes)));
   mTxn->AddBufferToDestroy(aBackBufferToDestroy);
 }
 
 void
-ShadowLayerForwarder::DestroyedImageBuffer(ShadowableLayer* aImage)
-{
-  mTxn->AddEdit(OpDestroyImageFrontBuffer(NULL, Shadow(aImage)));
-}
-
-void
 ShadowLayerForwarder::DestroyedCanvasBuffer(ShadowableLayer* aCanvas)
 {
   mTxn->AddEdit(OpDestroyCanvasFrontBuffer(NULL, Shadow(aCanvas)));
 }
 
 void
 ShadowLayerForwarder::Mutated(ShadowableLayer* aMutant)
 {
@@ -539,17 +523,19 @@ DestroySharedShmemSurface(SurfaceDescrip
 }
 
 void
 ShadowLayerForwarder::DestroySharedSurface(SurfaceDescriptor* aSurface)
 {
   if (PlatformDestroySharedSurface(aSurface)) {
     return;
   }
-  DestroySharedShmemSurface(aSurface, mShadowManager);
+  if (aSurface->type() == SurfaceDescriptor::TShmem) {
+    DestroySharedShmemSurface(aSurface, mShadowManager);
+  }
 }
 
 
 PLayerChild*
 ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer)
 {
   NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
   return mShadowManager->SendPLayerConstructor(new ShadowLayerChild(aLayer));
@@ -565,17 +551,19 @@ ShadowLayerManager::DestroySharedSurface
 
 void
 ShadowLayerManager::DestroySharedSurface(SurfaceDescriptor* aSurface,
                                          PLayersParent* aDeallocator)
 {
   if (PlatformDestroySharedSurface(aSurface)) {
     return;
   }
-  DestroySharedShmemSurface(aSurface, aDeallocator);
+  if (aSurface->type() == SurfaceDescriptor::TShmem) {
+    DestroySharedShmemSurface(aSurface, aDeallocator);
+  }
 }
 
 
 #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
 
 PRBool
 ShadowLayerForwarder::PlatformAllocDoubleBuffer(const gfxIntSize&,
                                                 gfxASurface::gfxContentType,
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -155,38 +155,34 @@ public:
   /**
    * |aBufferRect| is the screen rect covered by |aInitialFrontBuffer|.
    */
   void CreatedThebesBuffer(ShadowableLayer* aThebes,
                            const nsIntRegion& aFrontValidRegion,
                            const nsIntRect& aBufferRect,
                            const SurfaceDescriptor& aInitialFrontBuffer);
   /**
-   * For the next two methods, |aSize| is the size of
+   * For the next method, |aSize| is the size of
    * |aInitialFrontSurface|.
    */
-  void CreatedImageBuffer(ShadowableLayer* aImage,
-                          nsIntSize aSize,
-                          const SharedImage& aInitialFrontImage);
   void CreatedCanvasBuffer(ShadowableLayer* aCanvas,
                            nsIntSize aSize,
                            const SurfaceDescriptor& aInitialFrontSurface,
                            bool aNeedYFlip);
 
   /**
    * The specified layer is destroying its buffers.
    * |aBackBufferToDestroy| is deallocated when this transaction is
    * posted to the parent.  During the parent-side transaction, the
    * shadow is told to destroy its front buffer.  This can happen when
    * a new front/back buffer pair have been created because of a layer
    * resize, e.g.
    */
   void DestroyedThebesBuffer(ShadowableLayer* aThebes,
                              const SurfaceDescriptor& aBackBufferToDestroy);
-  void DestroyedImageBuffer(ShadowableLayer* aImage);
   void DestroyedCanvasBuffer(ShadowableLayer* aCanvas);
 
 
   /**
    * At least one attribute of |aMutant| has changed, and |aMutant|
    * needs to sync to its shadow layer.  This initial implementation
    * forwards all attributes when any is mutated.
    */
@@ -427,39 +423,54 @@ public:
   PLayerChild* GetShadow() { return mShadow; }
 
 protected:
   ShadowableLayer() : mShadow(NULL) {}
 
   PLayerChild* mShadow;
 };
 
+/**
+ * SurfaceDeallocator interface
+ */
+class ISurfaceDeAllocator
+{
+public:
+  virtual void DestroySharedSurface(gfxSharedImageSurface* aSurface) = 0;
+  virtual void DestroySharedSurface(SurfaceDescriptor* aSurface) = 0;
+protected:
+  ~ISurfaceDeAllocator() {};
+};
 
 /**
  * A ShadowLayer is the representation of a child-context's Layer in a
  * parent context.  They can be transformed, clipped,
  * etc. independently of their origin Layers.
  *
  * Note that ShadowLayers can themselves have a shadow in a parent
  * context.
  */
 class ShadowLayer
 {
 public:
   virtual ~ShadowLayer() {}
 
   /**
-   * CONSTRUCTION PHASE ONLY
+   * Set deallocator for data recieved from IPC protocol
+   * We should be able to set allocator right before swap call
+   * that is why allowed multiple call with the same Allocator
    */
-  void SetAllocator(PLayersParent* aAllocator)
+  virtual void SetAllocator(ISurfaceDeAllocator* aAllocator)
   {
-    NS_ABORT_IF_FALSE(!mAllocator, "Stomping allocator?");
+    NS_ASSERTION(!mAllocator || mAllocator == aAllocator, "Stomping allocator?");
     mAllocator = aAllocator;
   }
 
+  virtual void DestroyFrontBuffer() { };
+
   /**
    * The following methods are
    *
    * CONSTRUCTION PHASE ONLY
    *
    * They are analogous to the Layer interface.
    */
   void SetShadowVisibleRegion(const nsIntRegion& aRegion)
@@ -486,17 +497,17 @@ public:
   const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; }
 
 protected:
   ShadowLayer()
     : mAllocator(nsnull)
     , mUseShadowClipRect(PR_FALSE)
   {}
 
-  PLayersParent* mAllocator;
+  ISurfaceDeAllocator* mAllocator;
   nsIntRegion mShadowVisibleRegion;
   gfx3DMatrix mShadowTransform;
   nsIntRect mShadowClipRect;
   PRPackedBool mUseShadowClipRect;
 };
 
 
 class ShadowThebesLayer : public ShadowLayer,
@@ -614,36 +625,20 @@ protected:
 
 
 class ShadowImageLayer : public ShadowLayer,
                          public ImageLayer
 {
 public:
   /**
    * CONSTRUCTION PHASE ONLY
-   *
-   * Initialize this with a (temporary) front surface with the given
-   * size.  This is expected to be followed with a Swap() in the same
-   * transaction to bring in real pixels.  Init() may only be called
-   * once.
-   */
-  virtual PRBool Init(const SharedImage& front, const nsIntSize& aSize) = 0;
-
-  /**
-   * CONSTRUCTION PHASE ONLY
    * @see ShadowCanvasLayer::Swap
    */
-  virtual void Swap(const SharedImage& aFront, SharedImage* aNewBack) = 0;
-
-  /**
-   * CONSTRUCTION PHASE ONLY
-   *
-   * Destroy the current front buffer.
-   */
-  virtual void DestroyFrontBuffer() = 0;
+  virtual void Swap(const SharedImage& aFront,
+                    SharedImage* aNewBack) = 0;
 
   virtual ShadowLayer* AsShadowLayer() { return this; }
 
   MOZ_LAYER_DECL_NAME("ShadowImageLayer", TYPE_SHADOW)
 
 protected:
   ShadowImageLayer(LayerManager* aManager, void* aImplData)
     : ImageLayer(aManager, aImplData)
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -179,17 +179,16 @@ ShadowLayersParent::RecvUpdate(const Inf
       AsShadowLayer(edit.get_OpCreateContainerLayer())->Bind(layer);
       break;
     }
     case Edit::TOpCreateImageLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateImageLayer"));
 
       nsRefPtr<ShadowImageLayer> layer =
         layer_manager()->CreateShadowImageLayer();
-      layer->SetAllocator(this);
       AsShadowLayer(edit.get_OpCreateImageLayer())->Bind(layer);
       break;
     }
     case Edit::TOpCreateColorLayer: {
       MOZ_LAYERS_LOG(("[ParentSide] CreateColorLayer"));
 
       nsRefPtr<ShadowColorLayer> layer = layer_manager()->CreateShadowColorLayer();
       AsShadowLayer(edit.get_OpCreateColorLayer())->Bind(layer);
@@ -221,27 +220,16 @@ ShadowLayersParent::RecvUpdate(const Inf
       const OpCreateCanvasBuffer& ocb = edit.get_OpCreateCanvasBuffer();
       ShadowCanvasLayer* canvas = static_cast<ShadowCanvasLayer*>(
         AsShadowLayer(ocb)->AsLayer());
 
       canvas->Init(ocb.initialFront(), ocb.size(), ocb.needYFlip());
 
       break;
     }
-    case Edit::TOpCreateImageBuffer: {
-      MOZ_LAYERS_LOG(("[ParentSide] CreateImageBuffer"));
-
-      const OpCreateImageBuffer ocb = edit.get_OpCreateImageBuffer();
-      ShadowImageLayer* image = static_cast<ShadowImageLayer*>(
-        AsShadowLayer(ocb)->AsLayer());
-
-      image->Init(ocb.initialFront(), ocb.size());
-
-      break;
-    }
     case Edit::TOpDestroyThebesFrontBuffer: {
       MOZ_LAYERS_LOG(("[ParentSide] DestroyThebesFrontBuffer"));
 
       const OpDestroyThebesFrontBuffer& odfb =
         edit.get_OpDestroyThebesFrontBuffer();
       ShadowThebesLayer* thebes = static_cast<ShadowThebesLayer*>(
         AsShadowLayer(odfb)->AsLayer());
 
@@ -256,29 +244,16 @@ ShadowLayersParent::RecvUpdate(const Inf
         edit.get_OpDestroyCanvasFrontBuffer();
       ShadowCanvasLayer* canvas = static_cast<ShadowCanvasLayer*>(
         AsShadowLayer(odfb)->AsLayer());
 
       canvas->DestroyFrontBuffer();
 
       break;
     }
-    case Edit::TOpDestroyImageFrontBuffer: {
-      MOZ_LAYERS_LOG(("[ParentSide] DestroyImageFrontBuffer"));
-
-      const OpDestroyImageFrontBuffer& odfb =
-        edit.get_OpDestroyImageFrontBuffer();
-      ShadowImageLayer* image = static_cast<ShadowImageLayer*>(
-        AsShadowLayer(odfb)->AsLayer());
-
-      image->DestroyFrontBuffer();
-
-      break;
-    }
-
       // Attributes
     case Edit::TOpSetLayerAttributes: {
       MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));
 
       const OpSetLayerAttributes& osla = edit.get_OpSetLayerAttributes();
       Layer* layer = AsShadowLayer(osla)->AsLayer();
       const LayerAttributes& attrs = osla.attrs();
 
@@ -426,23 +401,19 @@ ShadowLayersParent::RecvUpdate(const Inf
     case Edit::TOpPaintImage: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint ImageLayer"));
 
       const OpPaintImage& op = edit.get_OpPaintImage();
       ShadowLayerParent* shadow = AsShadowLayer(op);
       ShadowImageLayer* image =
         static_cast<ShadowImageLayer*>(shadow->AsLayer());
 
-      SharedImage newFront = op.newFrontBuffer();
+      image->SetAllocator(this);
       SharedImage newBack;
       image->Swap(op.newFrontBuffer(), &newBack);
-      if (newFront == newBack) {
-        newFront = SharedImage();
-      }
-
       replyv.push_back(OpImageSwap(shadow, NULL,
                                    newBack));
 
       break;
     }
 
     default:
       NS_RUNTIMEABORT("not reached");
@@ -480,10 +451,22 @@ ShadowLayersParent::DeallocPLayer(PLayer
 }
 
 RenderFrameParent*
 ShadowLayersParent::Frame()
 {
   return static_cast<RenderFrameParent*>(Manager());
 }
 
+void
+ShadowLayersParent::DestroySharedSurface(gfxSharedImageSurface* aSurface)
+{
+  layer_manager()->DestroySharedSurface(aSurface, this);
+}
+
+void
+ShadowLayersParent::DestroySharedSurface(SurfaceDescriptor* aSurface)
+{
+  layer_manager()->DestroySharedSurface(aSurface, this);
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -37,44 +37,49 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_layers_ShadowLayersParent_h
 #define mozilla_layers_ShadowLayersParent_h
 
 #include "mozilla/layers/PLayersParent.h"
+#include "ShadowLayers.h"
 
 namespace mozilla {
 
 namespace layout {
 class RenderFrameParent;
 }
 
 namespace layers {
 
 class Layer;
 class ShadowLayerManager;
 
-class ShadowLayersParent : public PLayersParent
+class ShadowLayersParent : public PLayersParent,
+                           public ISurfaceDeAllocator
 {
   typedef mozilla::layout::RenderFrameParent RenderFrameParent;
   typedef InfallibleTArray<Edit> EditArray;
   typedef InfallibleTArray<EditReply> EditReplyArray;
 
 public:
   ShadowLayersParent(ShadowLayerManager* aManager);
   ~ShadowLayersParent();
 
   void Destroy();
 
   ShadowLayerManager* layer_manager() const { return mLayerManager; }
 
   ContainerLayer* GetRoot() const { return mRoot; }
 
+  virtual void DestroySharedSurface(gfxSharedImageSurface* aSurface);
+  virtual void DestroySharedSurface(SurfaceDescriptor* aSurface);
+
 protected:
   NS_OVERRIDE virtual bool RecvUpdate(const EditArray& cset,
                                       EditReplyArray* reply);
 
   NS_OVERRIDE virtual PLayerParent* AllocPLayer();
   NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor);
 
 private:
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -327,17 +327,17 @@ ShadowCanvasLayerOGL::Swap(const Surface
   *aNewBack = aNewFront;
 }
 
 void
 ShadowCanvasLayerOGL::DestroyFrontBuffer()
 {
   mTexImage = nsnull;
   if (IsSurfaceDescriptorValid(mDeadweight)) {
-    mOGLManager->DestroySharedSurface(&mDeadweight, mAllocator);
+    mAllocator->DestroySharedSurface(&mDeadweight);
   }
 }
 
 void
 ShadowCanvasLayerOGL::Disconnect()
 {
   Destroy();
 }
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -817,95 +817,98 @@ void CairoImageOGL::SetTiling(bool aTili
   }
 }
 
 ShadowImageLayerOGL::ShadowImageLayerOGL(LayerManagerOGL* aManager)
   : ShadowImageLayer(aManager, nsnull)
   , LayerOGL(aManager)
 {
   mImplData = static_cast<LayerOGL*>(this);
-}  
+}
 
 ShadowImageLayerOGL::~ShadowImageLayerOGL()
 {}
 
 PRBool
-ShadowImageLayerOGL::Init(const SharedImage& aFront,
-                          const nsIntSize& aSize)
+ShadowImageLayerOGL::Init(const SharedImage& aFront)
 {
   if (aFront.type() == SharedImage::TSurfaceDescriptor) {
     SurfaceDescriptor desc = aFront.get_SurfaceDescriptor();
-    nsRefPtr<gfxASurface> surf = 
+    nsRefPtr<gfxASurface> surf =
       ShadowLayerForwarder::OpenDescriptor(desc);
-    gfxSize sz = surf->GetSize();
-    mTexImage = gl()->CreateTextureImage(nsIntSize(sz.width, sz.height),
+    mSize = surf->GetSize();
+    mTexImage = gl()->CreateTextureImage(nsIntSize(mSize.width, mSize.height),
                                          surf->GetContentType(),
                                          LOCAL_GL_CLAMP_TO_EDGE);
-    mOGLManager->DestroySharedSurface(&desc, mAllocator);
     return PR_TRUE;
   } else {
     YUVImage yuv = aFront.get_YUVImage();
-    
+
     nsRefPtr<gfxSharedImageSurface> surfY =
       gfxSharedImageSurface::Open(yuv.Ydata());
     nsRefPtr<gfxSharedImageSurface> surfU =
       gfxSharedImageSurface::Open(yuv.Udata());
     nsRefPtr<gfxSharedImageSurface> surfV =
       gfxSharedImageSurface::Open(yuv.Vdata());
-    
-    mSize = gfxIntSize(surfY->GetSize().width, surfY->GetSize().height);
-    gfxIntSize CbCrSize = gfxIntSize(surfU->GetSize().width, surfU->GetSize().height);
+
+    mSize = surfY->GetSize();
+    mCbCrSize = surfU->GetSize();
 
     if (!mYUVTexture[0].IsAllocated()) {
       mYUVTexture[0].Allocate(mOGLManager->glForResources());
       mYUVTexture[1].Allocate(mOGLManager->glForResources());
       mYUVTexture[2].Allocate(mOGLManager->glForResources());
     }
 
     NS_ASSERTION(mYUVTexture[0].IsAllocated() &&
                  mYUVTexture[1].IsAllocated() &&
                  mYUVTexture[2].IsAllocated(),
                  "Texture allocation failed!");
 
     gl()->MakeCurrent();
     InitTexture(gl(), mYUVTexture[0].GetTextureID(), LOCAL_GL_LUMINANCE, mSize);
-    InitTexture(gl(), mYUVTexture[1].GetTextureID(), LOCAL_GL_LUMINANCE, CbCrSize);
-    InitTexture(gl(), mYUVTexture[2].GetTextureID(), LOCAL_GL_LUMINANCE, CbCrSize);
-    
-    mOGLManager->DestroySharedSurface(surfY, mAllocator);
-    mOGLManager->DestroySharedSurface(surfU, mAllocator);
-    mOGLManager->DestroySharedSurface(surfV, mAllocator);
+    InitTexture(gl(), mYUVTexture[1].GetTextureID(), LOCAL_GL_LUMINANCE, mCbCrSize);
+    InitTexture(gl(), mYUVTexture[2].GetTextureID(), LOCAL_GL_LUMINANCE, mCbCrSize);
     return PR_TRUE;
   }
+  return PR_FALSE;
 }
 
 void
-ShadowImageLayerOGL::Swap(const SharedImage& aNewFront, SharedImage* aNewBack)
+ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
+                          SharedImage* aNewBack)
 {
   if (!mDestroyed) {
     if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
-      nsRefPtr<gfxASurface> surf = 
+      nsRefPtr<gfxASurface> surf =
         ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
+      gfxIntSize size = surf->GetSize();
+      if (mSize != size || !mTexImage) {
+        Init(aNewFront);
+      }
       // XXX this is always just ridiculously slow
-      gfxSize sz = surf->GetSize();
-      nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
+      nsIntRegion updateRegion(nsIntRect(0, 0, size.width, size.height));
       mTexImage->DirectUpdate(surf, updateRegion);
     } else {
       const YUVImage& yuv = aNewFront.get_YUVImage();
-    
+
       nsRefPtr<gfxSharedImageSurface> surfY =
         gfxSharedImageSurface::Open(yuv.Ydata());
       nsRefPtr<gfxSharedImageSurface> surfU =
         gfxSharedImageSurface::Open(yuv.Udata());
       nsRefPtr<gfxSharedImageSurface> surfV =
         gfxSharedImageSurface::Open(yuv.Vdata());
+      mPictureRect = yuv.picture();
 
-      mPictureRect = yuv.picture();
-      mSize = surfY->GetSize();
- 
+      gfxIntSize size = surfY->GetSize();
+      gfxIntSize CbCrSize = surfU->GetSize();
+      if (size != mSize || mCbCrSize != CbCrSize || !mYUVTexture[0].IsAllocated()) {
+        Init(aNewFront);
+      }
+
       PlanarYCbCrImage::Data data;
       data.mYChannel = surfY->Data();
       data.mYStride = surfY->Stride();
       data.mYSize = surfY->GetSize();
       data.mCbChannel = surfU->Data();
       data.mCrChannel = surfV->Data();
       data.mCbCrStride = surfU->Stride();
       data.mCbCrSize = surfU->GetSize();
@@ -913,22 +916,16 @@ ShadowImageLayerOGL::Swap(const SharedIm
       UploadYUVToTexture(gl(), data, &mYUVTexture[0], &mYUVTexture[1], &mYUVTexture[2]);
     }
   }
 
   *aNewBack = aNewFront;
 }
 
 void
-ShadowImageLayerOGL::DestroyFrontBuffer()
-{
-  mTexImage = nsnull;
-}
-
-void
 ShadowImageLayerOGL::Disconnect()
 {
   Destroy();
 }
 
 void
 ShadowImageLayerOGL::Destroy()
 {
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -248,34 +248,34 @@ class ShadowImageLayerOGL : public Shado
 {
   typedef gl::TextureImage TextureImage;
 
 public:
   ShadowImageLayerOGL(LayerManagerOGL* aManager);
   virtual ~ShadowImageLayerOGL();
 
   // ShadowImageLayer impl
-  virtual PRBool Init(const SharedImage& aFront, const nsIntSize& aSize);
-
-  virtual void Swap(const SharedImage& aFront, SharedImage* aNewBack);
-
-  virtual void DestroyFrontBuffer();
+  virtual void Swap(const SharedImage& aFront,
+                    SharedImage* aNewBack);
 
   virtual void Disconnect();
 
   // LayerOGL impl
   virtual void Destroy();
 
   virtual Layer* GetLayer();
 
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);
 
 private:
+  PRBool Init(const SharedImage& aFront);
+
   nsRefPtr<TextureImage> mTexImage;
   GLTexture mYUVTexture[3];
   gfxIntSize mSize;
+  gfxIntSize mCbCrSize;
   nsIntRect mPictureRect;
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_IMAGELAYEROGL_H */