Bug 1167235 - Part 4 - Forward the shutdown notification to CanvasRenderingContext2D. r=Bas

This commit is contained in:
Nicolas Silva 2016-07-01 10:58:18 +02:00
Родитель d7bdab458f
Коммит 6837c5c2f2
6 изменённых файлов: 107 добавлений и 12 удалений

Просмотреть файл

@ -745,6 +745,36 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPattern, Release)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasPattern, mContext) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasPattern, mContext)
class CanvasShutdownObserver final : public nsIObserver
{
public:
explicit CanvasShutdownObserver(CanvasRenderingContext2D* aCanvas)
: mCanvas(aCanvas)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
~CanvasShutdownObserver() {}
CanvasRenderingContext2D* mCanvas;
};
NS_IMPL_ISUPPORTS(CanvasShutdownObserver, nsIObserver)
NS_IMETHODIMP
CanvasShutdownObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
if (mCanvas && strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
mCanvas->OnShutdown();
nsContentUtils::UnregisterShutdownObserver(this);
}
return NS_OK;
}
class CanvasDrawObserver class CanvasDrawObserver
{ {
public: public:
@ -1044,6 +1074,9 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
{ {
sNumLivingContexts++; sNumLivingContexts++;
mShutdownObserver = new CanvasShutdownObserver(this);
nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
// The default is to use OpenGL mode // The default is to use OpenGL mode
if (gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) { if (gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
mDrawObserver = new CanvasDrawObserver(this); mDrawObserver = new CanvasDrawObserver(this);
@ -1056,6 +1089,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D()
{ {
RemoveDrawObserver(); RemoveDrawObserver();
RemovePostRefreshObserver(); RemovePostRefreshObserver();
RemoveShutdownObserver();
Reset(); Reset();
// Drop references from all CanvasRenderingContext2DUserData to this context // Drop references from all CanvasRenderingContext2DUserData to this context
for (uint32_t i = 0; i < mUserDatas.Length(); ++i) { for (uint32_t i = 0; i < mUserDatas.Length(); ++i) {
@ -1148,6 +1182,29 @@ CanvasRenderingContext2D::Reset()
return NS_OK; return NS_OK;
} }
void
CanvasRenderingContext2D::OnShutdown()
{
mShutdownObserver = nullptr;
RefPtr<PersistentBufferProvider> provider = mBufferProvider;
Reset();
if (provider) {
provider->OnShutdown();
}
}
void
CanvasRenderingContext2D::RemoveShutdownObserver()
{
if (mShutdownObserver) {
nsContentUtils::UnregisterShutdownObserver(mShutdownObserver);
mShutdownObserver = nullptr;
}
}
void void
CanvasRenderingContext2D::SetStyleFromString(const nsAString& aStr, CanvasRenderingContext2D::SetStyleFromString(const nsAString& aStr,
Style aWhichStyle) Style aWhichStyle)
@ -1456,6 +1513,13 @@ CanvasRenderingContext2D::RenderingMode
CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect, CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect,
RenderingMode aRenderingMode) RenderingMode aRenderingMode)
{ {
if (AlreadyShutDown()) {
gfxCriticalError() << "Attempt to render into a Canvas2d after shutdown.";
EnsureErrorTarget();
mTarget = sErrorTarget;
return aRenderingMode;
}
// This would make no sense, so make sure we don't get ourselves in a mess // This would make no sense, so make sure we don't get ourselves in a mess
MOZ_ASSERT(mRenderingMode != RenderingMode::DefaultBackendMode); MOZ_ASSERT(mRenderingMode != RenderingMode::DefaultBackendMode);
@ -5691,6 +5755,10 @@ void CanvasRenderingContext2D::RemoveDrawObserver()
PersistentBufferProvider* PersistentBufferProvider*
CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager) CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
{ {
if (AlreadyShutDown()) {
return nullptr;
}
if (mBufferProvider) { if (mBufferProvider) {
return mBufferProvider; return mBufferProvider;
} }

Просмотреть файл

@ -54,6 +54,7 @@ template<typename T> class Optional;
struct CanvasBidiProcessor; struct CanvasBidiProcessor;
class CanvasRenderingContext2DUserData; class CanvasRenderingContext2DUserData;
class CanvasDrawObserver; class CanvasDrawObserver;
class CanvasShutdownObserver;
/** /**
** CanvasRenderingContext2D ** CanvasRenderingContext2D
@ -545,6 +546,7 @@ public:
// return true and fills in the bound rect if element has a hit region. // return true and fills in the bound rect if element has a hit region.
bool GetHitRegionRect(Element* aElement, nsRect& aRect) override; bool GetHitRegionRect(Element* aElement, nsRect& aRect) override;
void OnShutdown();
protected: protected:
nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY, nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
uint32_t aWidth, uint32_t aHeight, uint32_t aWidth, uint32_t aHeight,
@ -749,6 +751,10 @@ protected:
CanvasDrawObserver* mDrawObserver; CanvasDrawObserver* mDrawObserver;
void RemoveDrawObserver(); void RemoveDrawObserver();
RefPtr<CanvasShutdownObserver> mShutdownObserver;
void RemoveShutdownObserver();
bool AlreadyShutDown() const { return !mShutdownObserver; }
/** /**
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
* Redraw is called, reset to false when Render is called. * Redraw is called, reset to false when Render is called.

Просмотреть файл

@ -353,8 +353,7 @@ HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& a
: nsGenericHTMLElement(aNodeInfo), : nsGenericHTMLElement(aNodeInfo),
mResetLayer(true) , mResetLayer(true) ,
mWriteOnly(false) mWriteOnly(false)
{ {}
}
HTMLCanvasElement::~HTMLCanvasElement() HTMLCanvasElement::~HTMLCanvasElement()
{ {

Просмотреть файл

@ -126,16 +126,7 @@ PersistentBufferProviderShared::~PersistentBufferProviderShared()
mFwd->GetActiveResourceTracker().RemoveObject(this); mFwd->GetActiveResourceTracker().RemoveObject(this);
} }
mDrawTarget = nullptr; Destroy();
if (mBack && mBack->IsLocked()) {
mBack->Unlock();
}
if (mFront && mFront->IsLocked()) {
mFront->Unlock();
}
if (mBuffer && mBuffer->IsLocked()) {
mBuffer->Unlock();
}
} }
already_AddRefed<gfx::DrawTarget> already_AddRefed<gfx::DrawTarget>
@ -276,5 +267,28 @@ PersistentBufferProviderShared::NotifyInactive()
mBuffer = nullptr; mBuffer = nullptr;
} }
void
PersistentBufferProviderShared::Destroy()
{
mSnapshot = nullptr;
mDrawTarget = nullptr;
if (mFront && mFront->IsLocked()) {
mFront->Unlock();
}
if (mBack && mBack->IsLocked()) {
mBack->Unlock();
}
if (mBuffer && mBuffer->IsLocked()) {
mBuffer->Unlock();
}
mFront = nullptr;
mBack = nullptr;
mBuffer = nullptr;
}
} // namespace layers } // namespace layers
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -60,6 +60,8 @@ public:
virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) = 0; virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) = 0;
virtual TextureClient* GetTextureClient() { return nullptr; } virtual TextureClient* GetTextureClient() { return nullptr; }
virtual void OnShutdown() {}
}; };
@ -121,6 +123,8 @@ public:
virtual void NotifyInactive() override; virtual void NotifyInactive() override;
virtual void OnShutdown() override { Destroy(); }
protected: protected:
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
CompositableForwarder* aFwd, CompositableForwarder* aFwd,
@ -128,6 +132,8 @@ protected:
~PersistentBufferProviderShared(); ~PersistentBufferProviderShared();
void Destroy();
gfx::IntSize mSize; gfx::IntSize mSize;
gfx::SurfaceFormat mFormat; gfx::SurfaceFormat mFormat;
RefPtr<CompositableForwarder> mFwd; RefPtr<CompositableForwarder> mFwd;

Просмотреть файл

@ -364,6 +364,8 @@ void TextureClient::Destroy(bool aForceSync)
mActor->Lock(); mActor->Lock();
} }
mReadLock = nullptr;
CancelWaitFenceHandleOnImageBridge(); CancelWaitFenceHandleOnImageBridge();
RefPtr<TextureChild> actor = mActor; RefPtr<TextureChild> actor = mActor;
mActor = nullptr; mActor = nullptr;