From 10809f5f7879395d53bfd0c1705ff909cf780481 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Fri, 1 Jul 2016 10:58:13 +0200 Subject: [PATCH] Bug 1167235 - Part 2 - Detach DrawTarget snapshots before unlocking TextureClient. r=Bas --- gfx/2d/2D.h | 11 +++++++++++ gfx/2d/DrawTargetCG.h | 1 + gfx/2d/DrawTargetCairo.h | 2 ++ gfx/2d/DrawTargetCapture.cpp | 4 ++++ gfx/2d/DrawTargetCapture.h | 3 +++ gfx/2d/DrawTargetD2D1.h | 2 ++ gfx/2d/DrawTargetDual.cpp | 7 +++++++ gfx/2d/DrawTargetDual.h | 4 +++- gfx/2d/DrawTargetRecording.cpp | 6 ++++++ gfx/2d/DrawTargetRecording.h | 2 ++ gfx/2d/DrawTargetSkia.h | 1 + gfx/2d/DrawTargetTiled.cpp | 4 ++++ gfx/2d/DrawTargetTiled.h | 1 + gfx/layers/client/TextureClient.cpp | 7 ++++++- gfx/layers/d3d11/TextureD3D11.cpp | 1 + 15 files changed, 54 insertions(+), 2 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index a7f47653ab7d..0245ee4dfdbb 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -1175,6 +1175,17 @@ public: return mPermitSubpixelAA; } + /** + * Ensures that no snapshot is still pointing to this DrawTarget's surface data. + * + * This can be useful if the DrawTarget is wrapped around data that it does not + * own, and for some reason the owner of the data has to make it temporarily + * unavailable without the DrawTarget knowing about it. + * This can cause costly surface copies, so it should not be used without a + * a good reason. + */ + virtual void DetachAllSnapshots() = 0; + #ifdef USE_SKIA_GPU virtual bool InitWithGrContext(GrContext* aGrContext, const IntSize &aSize, diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index 50c13818003f..54da435ba24a 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -128,6 +128,7 @@ public: virtual DrawTargetType GetType() const override; virtual BackendType GetBackendType() const override; virtual already_AddRefed Snapshot() override; + virtual void DetachAllSnapshots() override { MarkChanged(); } virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 70fa7303cef1..9333855b69fb 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -177,6 +177,8 @@ public: virtual void SetTransform(const Matrix& aTransform) override; + virtual void DetachAllSnapshots() override { MarkSnapshotIndependent(); } + // Call to set up aContext for drawing (with the current transform, etc). // Pass the path you're going to be using if you have one. // Implicitly calls WillChange(aPath). diff --git a/gfx/2d/DrawTargetCapture.cpp b/gfx/2d/DrawTargetCapture.cpp index f3dd4d0923e5..f0584c427cc6 100644 --- a/gfx/2d/DrawTargetCapture.cpp +++ b/gfx/2d/DrawTargetCapture.cpp @@ -45,6 +45,10 @@ DrawTargetCaptureImpl::Snapshot() return dt->Snapshot(); } +void +DrawTargetCaptureImpl::DetachAllSnapshots() +{} + #define AppendCommand(arg) new (AppendToCommandList()) arg void diff --git a/gfx/2d/DrawTargetCapture.h b/gfx/2d/DrawTargetCapture.h index 0e33ff5a6bfe..a60e07b56b12 100644 --- a/gfx/2d/DrawTargetCapture.h +++ b/gfx/2d/DrawTargetCapture.h @@ -28,6 +28,9 @@ public: virtual DrawTargetType GetType() const { return mRefDT->GetType(); } virtual already_AddRefed Snapshot(); + + virtual void DetachAllSnapshots(); + virtual IntSize GetSize() { return mSize; } virtual void Flush() {} diff --git a/gfx/2d/DrawTargetD2D1.h b/gfx/2d/DrawTargetD2D1.h index 0d1256eb3d2f..971a1e7db5a9 100644 --- a/gfx/2d/DrawTargetD2D1.h +++ b/gfx/2d/DrawTargetD2D1.h @@ -127,6 +127,8 @@ public: virtual void *GetNativeSurface(NativeSurfaceType aType) override { return nullptr; } + virtual void DetachAllSnapshots() override { MarkChanged(); } + bool Init(const IntSize &aSize, SurfaceFormat aFormat); bool Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat); uint32_t GetByteSize() const; diff --git a/gfx/2d/DrawTargetDual.cpp b/gfx/2d/DrawTargetDual.cpp index 50d1e6ab0bee..87714f123e48 100644 --- a/gfx/2d/DrawTargetDual.cpp +++ b/gfx/2d/DrawTargetDual.cpp @@ -86,6 +86,13 @@ public: bool mPatternsInitialized; }; +void +DrawTargetDual::DetachAllSnapshots() +{ + mA->DetachAllSnapshots(); + mB->DetachAllSnapshots(); +} + void DrawTargetDual::DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource, const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions) diff --git a/gfx/2d/DrawTargetDual.h b/gfx/2d/DrawTargetDual.h index 7cbb8ac576ba..190346e447fe 100644 --- a/gfx/2d/DrawTargetDual.h +++ b/gfx/2d/DrawTargetDual.h @@ -49,7 +49,9 @@ public: return MakeAndAddRef(mA, mB); } virtual IntSize GetSize() override { return mA->GetSize(); } - + + virtual void DetachAllSnapshots() override; + FORWARD_FUNCTION(Flush) FORWARD_FUNCTION1(PushClip, const Path *, aPath) FORWARD_FUNCTION1(PushClipRect, const Rect &, aRect) diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index 8a4e99099b16..877631aa09e0 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -477,6 +477,12 @@ DrawTargetRecording::Snapshot() return retSurf.forget(); } +void +DrawTargetRecording::DetachAllSnapshots() +{ + mFinalDT->DetachAllSnapshots(); +} + void DrawTargetRecording::DrawSurface(SourceSurface *aSurface, const Rect &aDest, diff --git a/gfx/2d/DrawTargetRecording.h b/gfx/2d/DrawTargetRecording.h index df30971a5579..86bed022b575 100644 --- a/gfx/2d/DrawTargetRecording.h +++ b/gfx/2d/DrawTargetRecording.h @@ -37,6 +37,8 @@ public: virtual already_AddRefed Snapshot() override; + virtual void DetachAllSnapshots() override; + virtual IntSize GetSize() override { return mFinalDT->GetSize(); } /* Ensure that the DrawTarget backend has flushed all drawing operations to diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index ec3add9bd2bc..e00f9957f38c 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -125,6 +125,7 @@ public: virtual already_AddRefed CreateFilter(FilterType aType) override; virtual void SetTransform(const Matrix &aTransform) override; virtual void *GetNativeSurface(NativeSurfaceType aType) override; + virtual void DetachAllSnapshots() override { MarkChanged(); } bool Init(const IntSize &aSize, SurfaceFormat aFormat); void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat, bool aUninitialized = false); diff --git a/gfx/2d/DrawTargetTiled.cpp b/gfx/2d/DrawTargetTiled.cpp index bcdfc71f2023..fd7465408852 100644 --- a/gfx/2d/DrawTargetTiled.cpp +++ b/gfx/2d/DrawTargetTiled.cpp @@ -54,6 +54,10 @@ DrawTargetTiled::Snapshot() return MakeAndAddRef(mTiles, mRect); } +void +DrawTargetTiled::DetachAllSnapshots() +{} + // Skip the mClippedOut check since this is only used for Flush() which // should happen even if we're clipped. #define TILED_COMMAND(command) \ diff --git a/gfx/2d/DrawTargetTiled.h b/gfx/2d/DrawTargetTiled.h index 087f85263204..23e8318a391d 100644 --- a/gfx/2d/DrawTargetTiled.h +++ b/gfx/2d/DrawTargetTiled.h @@ -41,6 +41,7 @@ public: virtual DrawTargetType GetType() const override { return mTiles[0].mDrawTarget->GetType(); } virtual BackendType GetBackendType() const override { return mTiles[0].mDrawTarget->GetBackendType(); } virtual already_AddRefed Snapshot() override; + virtual void DetachAllSnapshots() override; virtual IntSize GetSize() override { MOZ_ASSERT(mRect.width > 0 && mRect.height > 0); return IntSize(mRect.XMost(), mRect.YMost()); diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 8c62f6686852..f0934bee4684 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -494,7 +494,6 @@ TextureClient::Unlock() } if (mBorrowedDrawTarget) { - MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs); if (mOpenMode & OpenMode::OPEN_WRITE) { mBorrowedDrawTarget->Flush(); if (mReadbackSink && !mData->ReadBack(mReadbackSink)) { @@ -505,6 +504,12 @@ TextureClient::Unlock() mReadbackSink->ProcessReadback(dataSurf); } } + + mBorrowedDrawTarget->DetachAllSnapshots(); + // If this assertion is hit, it means something is holding a strong reference + // to our DrawTarget externally, which is not allowed. + MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs); + mBorrowedDrawTarget = nullptr; } diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 6ac5687d67dc..281ec70883ff 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -397,6 +397,7 @@ D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocation void D3D11TextureData::Deallocate(ClientIPCAllocator* aAllocator) { + mDrawTarget = nullptr; mTexture = nullptr; }