diff --git a/gfx/layers/Makefile.in b/gfx/layers/Makefile.in index 9ea382af17e..849b77a1144 100644 --- a/gfx/layers/Makefile.in +++ b/gfx/layers/Makefile.in @@ -105,10 +105,14 @@ ifdef MOZ_IPC #{ EXPORTS_NAMESPACES = mozilla/layers EXPORTS_mozilla/layers =\ ShadowLayers.h \ + ShadowLayersChild.h \ + ShadowLayersParent.h \ $(NULL) CPPSRCS += \ ShadowLayers.cpp \ + ShadowLayerChild.cpp \ + ShadowLayersChild.cpp \ ShadowLayerParent.cpp \ ShadowLayersParent.cpp \ $(NULL) @@ -135,4 +139,3 @@ LayerManagerOGLShaders.h: LayerManagerOGLShaders.txt genshaders.py $(GLOBAL_DEPS LayerManagerOGL.$(OBJ_SUFFIX): LayerManagerOGLShaders.h GARBAGE += LayerManagerOGLShaders.h - diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index d28b6ed9a99..6cb898361d7 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -1177,6 +1177,16 @@ public: { NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks"); } + + virtual void Disconnect() + { + // This is an "emergency Disconnect()", called when the compositing + // process has died. |mShadow| and our Shmem buffers are + // automatically managed by IPDL, so we don't need to explicitly + // free them here (it's hard to get that right on emergency + // shutdown anyway). + mShadow = nsnull; + } }; static ShadowableLayer* @@ -1212,6 +1222,11 @@ public: virtual Layer* AsLayer() { return this; } virtual ShadowableLayer* AsShadowableLayer() { return this; } + virtual void Disconnect() + { + BasicShadowableLayer::Disconnect(); + } + private: BasicShadowLayerManager* ShadowManager() { @@ -1271,6 +1286,12 @@ public: mBackBuffer = aBuffer; } + virtual void Disconnect() + { + mBackBuffer = nsnull; + BasicShadowableLayer::Disconnect(); + } + private: BasicShadowLayerManager* BasicManager() { @@ -1375,6 +1396,12 @@ public: mBackSurface = aBuffer; } + virtual void Disconnect() + { + mBackSurface = nsnull; + BasicShadowableLayer::Disconnect(); + } + private: BasicShadowLayerManager* BasicManager() { @@ -1439,6 +1466,11 @@ public: virtual Layer* AsLayer() { return this; } virtual ShadowableLayer* AsShadowableLayer() { return this; } + + virtual void Disconnect() + { + BasicShadowableLayer::Disconnect(); + } }; class BasicShadowableCanvasLayer : public BasicCanvasLayer, @@ -1476,6 +1508,12 @@ public: { mBackBuffer = aBuffer; } + + virtual void Disconnect() + { + mBackBuffer = nsnull; + BasicShadowableLayer::Disconnect(); + } private: BasicShadowLayerManager* BasicManager() @@ -1567,7 +1605,15 @@ public: { MOZ_COUNT_CTOR(BasicShadowThebesLayer); } - virtual ~BasicShadowThebesLayer(); + virtual ~BasicShadowThebesLayer() + { + // If Disconnect() wasn't called on us, then we assume that the + // remote side shut down and IPC is disconnected, so we let IPDL + // clean up our front surface Shmem. + MOZ_COUNT_DTOR(BasicShadowThebesLayer); + } + + virtual void Disconnect(); virtual already_AddRefed Swap(gfxSharedImageSurface* aNewFront, @@ -1591,7 +1637,8 @@ private: ShadowThebesLayerBuffer mFrontBuffer; }; -BasicShadowThebesLayer::~BasicShadowThebesLayer() +void +BasicShadowThebesLayer::Disconnect() { nsRefPtr frontBuffer = mFrontBuffer.Swap(0, nsIntRect()); @@ -1599,7 +1646,7 @@ BasicShadowThebesLayer::~BasicShadowThebesLayer() BasicManager()->ShadowLayerManager::DestroySharedSurface(frontBuffer); } - MOZ_COUNT_DTOR(BasicShadowThebesLayer); + ShadowThebesLayer::Disconnect(); } void @@ -1613,6 +1660,10 @@ BasicShadowThebesLayer::Paint(gfxContext* aContext, NS_ASSERTION(BasicManager()->IsRetained(), "ShadowThebesLayer makes no sense without retained mode"); + if (!mFrontBuffer.GetBuffer()) { + return; + } + gfxContext* target = BasicManager()->GetTarget(); NS_ASSERTION(target, "We shouldn't be called if there's no target"); @@ -1635,12 +1686,11 @@ public: } virtual ~BasicShadowImageLayer() { - if (mFrontSurface) { - BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface); - } MOZ_COUNT_DTOR(BasicShadowImageLayer); } + virtual void Disconnect(); + virtual PRBool Init(gfxSharedImageSurface* front, const nsIntSize& size); virtual already_AddRefed @@ -1662,6 +1712,17 @@ protected: gfxIntSize mSize; }; +void +BasicShadowImageLayer::Disconnect() +{ + if (mFrontSurface) { + BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface); + } + mFrontSurface = nsnull; + + ShadowImageLayer::Disconnect(); +} + PRBool BasicShadowImageLayer::Init(gfxSharedImageSurface* front, const nsIntSize& size) @@ -1685,6 +1746,10 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, void* aCallbackData, float aOpacity) { + if (!mFrontSurface) { + return; + } + nsRefPtr pat = new gfxPattern(mFrontSurface); pat->SetFilter(mFilter); BasicImageLayer::PaintContext(pat, mSize, aOpacity, aContext); @@ -1701,12 +1766,11 @@ public: } virtual ~BasicShadowCanvasLayer() { - if (mFrontSurface) { - BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface); - } MOZ_COUNT_DTOR(BasicShadowCanvasLayer); } + virtual void Disconnect(); + virtual void Initialize(const Data& aData); virtual void Updated(const nsIntRect& aRect) @@ -1730,6 +1794,17 @@ private: nsIntRect mBounds; }; +void +BasicShadowCanvasLayer::Disconnect() +{ + if (mFrontSurface) { + BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface); + } + mFrontSurface = nsnull; + + ShadowCanvasLayer::Disconnect(); +} + void BasicShadowCanvasLayer::Initialize(const Data& aData) { @@ -1755,11 +1830,13 @@ BasicShadowCanvasLayer::Paint(gfxContext* aContext, void* aCallbackData, float aOpacity) { - MOZ_LAYERS_LOG(("[ShadowLayersChild] %s()", __FUNCTION__)); - NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); + if (!mFrontSurface) { + return; + } + nsRefPtr pat = new gfxPattern(mFrontSurface); pat->SetFilter(mFilter); diff --git a/gfx/layers/ipc/ShadowLayerChild.cpp b/gfx/layers/ipc/ShadowLayerChild.cpp new file mode 100644 index 00000000000..5a923a62c89 --- /dev/null +++ b/gfx/layers/ipc/ShadowLayerChild.cpp @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ShadowLayerChild.h" +#include "Layers.h" +#include "ShadowLayers.h" + +namespace mozilla { +namespace layers { + +ShadowLayerChild::ShadowLayerChild(ShadowableLayer* aLayer) + : mLayer(aLayer) +{ } + +ShadowLayerChild::~ShadowLayerChild() +{ } + +void +ShadowLayerChild::ActorDestroy(ActorDestroyReason why) +{ + NS_ABORT_IF_FALSE(AncestorDeletion != why, + "shadowable layer should have been cleaned up by now"); + + if (AbnormalShutdown == why) { + // This is last-ditch emergency shutdown. Just have the layer + // forget its IPDL resources; IPDL-generated code will clean up + // automatically in this case. + mLayer->AsLayer()->Disconnect(); + mLayer = nsnull; + } +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/ipc/ShadowLayerChild.h b/gfx/layers/ipc/ShadowLayerChild.h index 4f534ec978b..c0ecfc30d0a 100644 --- a/gfx/layers/ipc/ShadowLayerChild.h +++ b/gfx/layers/ipc/ShadowLayerChild.h @@ -51,14 +51,15 @@ class ShadowableLayer; class ShadowLayerChild : public PLayerChild { public: - ShadowLayerChild(ShadowableLayer* aLayer) : mLayer(aLayer) - { } - - virtual ~ShadowLayerChild() - { } + ShadowLayerChild(ShadowableLayer* aLayer); + virtual ~ShadowLayerChild(); ShadowableLayer* layer() const { return mLayer; } +protected: + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); + private: ShadowableLayer* mLayer; }; diff --git a/gfx/layers/ipc/ShadowLayerParent.cpp b/gfx/layers/ipc/ShadowLayerParent.cpp index a5ec36ff8af..719e91b268d 100644 --- a/gfx/layers/ipc/ShadowLayerParent.cpp +++ b/gfx/layers/ipc/ShadowLayerParent.cpp @@ -67,11 +67,26 @@ ShadowLayerParent::AsContainer() const return static_cast(AsLayer()); } -bool -ShadowLayerParent::Recv__delete__() +void +ShadowLayerParent::ActorDestroy(ActorDestroyReason why) { + switch (why) { + case AncestorDeletion: + NS_RUNTIMEABORT("shadow layer deleted out of order!"); + return; // unreached + + case Deletion: + mLayer->Disconnect(); + break; + + case AbnormalShutdown: + case NormalShutdown: + // let IPDL-generated code automatically clean up Shmems and so + // forth; our channel is disconnected anyway + break; + } + mLayer = NULL; - return true; } } // namespace layers diff --git a/gfx/layers/ipc/ShadowLayerParent.h b/gfx/layers/ipc/ShadowLayerParent.h index e089fb8b338..fa843f8602e 100644 --- a/gfx/layers/ipc/ShadowLayerParent.h +++ b/gfx/layers/ipc/ShadowLayerParent.h @@ -64,7 +64,8 @@ public: ContainerLayer* AsContainer() const; private: - NS_OVERRIDE virtual bool Recv__delete__(); + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); nsRefPtr mLayer; }; diff --git a/gfx/layers/ipc/ShadowLayersChild.cpp b/gfx/layers/ipc/ShadowLayersChild.cpp new file mode 100644 index 00000000000..18685a4304d --- /dev/null +++ b/gfx/layers/ipc/ShadowLayersChild.cpp @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "ShadowLayerChild.h" +#include "ShadowLayersChild.h" + +namespace mozilla { +namespace layers { + +void +ShadowLayersChild::Destroy() +{ + NS_ABORT_IF_FALSE(0 == ManagedPLayerChild().Length(), + "layers should have been cleaned up by now"); + // + // FIXME: uncomment this when we have a manager + // + //PLayersChild::Send__delete__(this); + // WARNING: |this| has gone to the great heap in the sky +} + +PLayerChild* +ShadowLayersChild::AllocPLayer() +{ + // we always use the "power-user" ctor + NS_RUNTIMEABORT("not reached"); + return NULL; +} + +bool +ShadowLayersChild::DeallocPLayer(PLayerChild* actor) +{ + delete actor; + return true; +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/ipc/ShadowLayersChild.h b/gfx/layers/ipc/ShadowLayersChild.h index f9937006bdc..26d360d3e9d 100644 --- a/gfx/layers/ipc/ShadowLayersChild.h +++ b/gfx/layers/ipc/ShadowLayersChild.h @@ -42,7 +42,6 @@ #define mozilla_layers_ShadowLayersChild_h #include "mozilla/layers/PLayersChild.h" -#include "mozilla/layers/ShadowLayerChild.h" namespace mozilla { namespace layers { @@ -53,17 +52,18 @@ public: ShadowLayersChild() { } ~ShadowLayersChild() { } -protected: - NS_OVERRIDE virtual PLayerChild* AllocPLayer() { - // we always use the "power-user" ctor - NS_RUNTIMEABORT("not reached"); - return NULL; - } + /** + * Clean this up, finishing with Send__delete__(). + * + * It is expected (checked with an assert) that all shadow layers + * created by this have already been destroyed and + * Send__delete__()d by the time this method is called. + */ + void Destroy(); - NS_OVERRIDE virtual bool DeallocPLayer(PLayerChild* actor) { - delete actor; - return true; - } +protected: + NS_OVERRIDE virtual PLayerChild* AllocPLayer(); + NS_OVERRIDE virtual bool DeallocPLayer(PLayerChild* actor); }; } // namespace layers