Bug 570620, part i: Implement ShadowLayer::Disconnect() for common-case shutdown, and ShadowableLayer::Disconnect() for emergency-case shutdown. r=vlad

This commit is contained in:
Chris Jones 2010-08-20 18:24:41 -05:00
parent d839c7e1a5
commit f30d5c8a27
8 changed files with 275 additions and 32 deletions

View File

@ -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

View File

@ -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<gfxSharedImageSurface>
Swap(gfxSharedImageSurface* aNewFront,
@ -1591,7 +1637,8 @@ private:
ShadowThebesLayerBuffer mFrontBuffer;
};
BasicShadowThebesLayer::~BasicShadowThebesLayer()
void
BasicShadowThebesLayer::Disconnect()
{
nsRefPtr<gfxSharedImageSurface> 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<gfxSharedImageSurface>
@ -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<gfxPattern> 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<gfxPattern> pat = new gfxPattern(mFrontSurface);
pat->SetFilter(mFilter);

View File

@ -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 <jones.chris.g@gmail.com>
*
* 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

View File

@ -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;
};

View File

@ -67,11 +67,26 @@ ShadowLayerParent::AsContainer() const
return static_cast<ContainerLayer*>(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

View File

@ -64,7 +64,8 @@ public:
ContainerLayer* AsContainer() const;
private:
NS_OVERRIDE virtual bool Recv__delete__();
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why);
nsRefPtr<Layer> mLayer;
};

View File

@ -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 <jones.chris.g@gmail.com>
*
* 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

View File

@ -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