Bug 1660236 - Hold mutex while accessing shared SkImage data. r=lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D93442
This commit is contained in:
Matt Woodrow 2020-10-29 17:19:52 +00:00
Родитель 258b39d5e6
Коммит 31bb79f3a4
3 изменённых файлов: 48 добавлений и 18 удалений

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

@ -218,6 +218,7 @@ static bool VerifyRGBXCorners(uint8_t* aData, const IntSize& aSize,
#endif
static sk_sp<SkImage> GetSkImageForSurface(SourceSurface* aSurface,
Maybe<MutexAutoLock>* aLock,
const Rect* aBounds = nullptr,
const Matrix* aMatrix = nullptr) {
if (!aSurface) {
@ -233,11 +234,11 @@ static sk_sp<SkImage> GetSkImageForSurface(SourceSurface* aSurface,
return nullptr;
}
MOZ_ASSERT(resolved->GetType() != SurfaceType::CAPTURE);
return GetSkImageForSurface(resolved, aBounds, aMatrix);
return GetSkImageForSurface(resolved, aLock, aBounds, aMatrix);
}
if (aSurface->GetType() == SurfaceType::SKIA) {
return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage();
return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage(aLock);
}
DataSourceSurface* surf = aSurface->GetDataSurface().take();
@ -406,8 +407,9 @@ static bool ExtractAlphaBitmap(const sk_sp<SkImage>& aImage,
return false;
}
static sk_sp<SkImage> ExtractAlphaForSurface(SourceSurface* aSurface) {
sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
static sk_sp<SkImage> ExtractAlphaForSurface(SourceSurface* aSurface,
Maybe<MutexAutoLock>& aLock) {
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &aLock);
if (!image) {
return nullptr;
}
@ -426,7 +428,7 @@ static sk_sp<SkImage> ExtractAlphaForSurface(SourceSurface* aSurface) {
}
static void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern,
Float aAlpha = 1.0,
Maybe<MutexAutoLock>& aLock, Float aAlpha = 1.0,
const SkMatrix* aMatrix = nullptr,
const Rect* aBounds = nullptr) {
switch (aPattern.GetType()) {
@ -544,7 +546,7 @@ static void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern,
case PatternType::SURFACE: {
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
sk_sp<SkImage> image =
GetSkImageForSurface(pat.mSurface, aBounds, &pat.mMatrix);
GetSkImageForSurface(pat.mSurface, &aLock, aBounds, &pat.mMatrix);
if (!image) {
aPaint.setColor(SK_ColorTRANSPARENT);
break;
@ -598,7 +600,7 @@ struct AutoPaintSetup {
const Rect* aSourceBounds = nullptr)
: mNeedsRestore(false), mAlpha(1.0) {
Init(aCanvas, aOptions, aMaskBounds, false);
SetPaintPattern(mPaint, aPattern, mAlpha, aMatrix, aSourceBounds);
SetPaintPattern(mPaint, aPattern, mLock, mAlpha, aMatrix, aSourceBounds);
}
AutoPaintSetup(SkCanvas* aCanvas, const DrawOptions& aOptions,
@ -654,6 +656,7 @@ struct AutoPaintSetup {
SkPaint mPaint;
bool mNeedsRestore;
SkCanvas* mCanvas;
Maybe<MutexAutoLock> mLock;
Float mAlpha;
};
@ -669,7 +672,8 @@ void DrawTargetSkia::DrawSurface(SourceSurface* aSurface, const Rect& aDest,
MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) {
return;
}
@ -709,7 +713,8 @@ void DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface* aSurface,
MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) {
return;
}
@ -1389,8 +1394,9 @@ void DrawTargetSkia::Mask(const Pattern& aSource, const Pattern& aMask,
MarkChanged();
AutoPaintSetup paint(mCanvas, aOptions, aSource, nullptr, &maskMatrix);
Maybe<MutexAutoLock> lock;
SkPaint maskPaint;
SetPaintPattern(maskPaint, aMask);
SetPaintPattern(maskPaint, aMask, lock);
SkBitmap maskBitmap;
if (!maskBitmap.tryAllocPixelsFlags(
@ -1419,7 +1425,8 @@ void DrawTargetSkia::MaskSurface(const Pattern& aSource, SourceSurface* aMask,
SkFloatToScalar(-aOffset.y));
AutoPaintSetup paint(mCanvas, aOptions, aSource, nullptr, &invOffset);
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask, lock);
if (!alphaMask) {
gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
return;
@ -1447,7 +1454,8 @@ bool DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface,
fullMat.PostTranslate(-xformBounds.X(), -xformBounds.Y(), 0);
// Read in the source data.
sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface, &lock);
if (!srcImage) {
return true;
}
@ -1509,7 +1517,8 @@ bool DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface,
MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) {
return true;
}
@ -1647,7 +1656,8 @@ void DrawTargetSkia::CopySurface(SourceSurface* aSurface,
const IntPoint& aDestination) {
MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface);
Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) {
return;
}
@ -1881,7 +1891,12 @@ void DrawTargetSkia::PushLayerWithBlend(bool aOpaque, Float aOpacity,
}
}
sk_sp<SkImage> clipImage = aMask ? GetSkImageForSurface(aMask) : nullptr;
// We don't pass a lock object to GetSkImageForSurface here, to force a
// copy of the data if this is a copy-on-write snapshot. If we instead held
// the lock until the corresponding PopLayer, we'd risk deadlocking if someone
// tried to touch the originating DrawTarget while the layer was pushed.
sk_sp<SkImage> clipImage =
aMask ? GetSkImageForSurface(aMask, nullptr) : nullptr;
SkMatrix clipMatrix;
GfxMatrixToSkiaMatrix(aMaskTransform, clipMatrix);
if (aMask) {

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

@ -31,8 +31,23 @@ IntSize SourceSurfaceSkia::GetSize() const { return mSize; }
SurfaceFormat SourceSurfaceSkia::GetFormat() const { return mFormat; }
sk_sp<SkImage> SourceSurfaceSkia::GetImage() {
MutexAutoLock lock(mChangeMutex);
sk_sp<SkImage> SourceSurfaceSkia::GetImage(Maybe<MutexAutoLock>* aLock) {
// If we were provided a lock object, we can let the caller access
// a shared SkImage and we know it won't go away while the lock is held.
// Otherwise we need to call DrawTargetWillChange to ensure we have our
// own SkImage.
if (aLock) {
MOZ_ASSERT(aLock->isNothing());
aLock->emplace(mChangeMutex);
// Now that we are locked, we can check mDrawTarget. If it's null, then
// we're not shared and we can unlock eagerly.
if (!mDrawTarget) {
aLock->reset();
}
} else {
DrawTargetWillChange();
}
sk_sp<SkImage> image = mImage;
return image;
}

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

@ -40,7 +40,7 @@ class SourceSurfaceSkia : public DataSourceSurface {
mDrawTarget = nullptr;
}
sk_sp<SkImage> GetImage();
sk_sp<SkImage> GetImage(Maybe<MutexAutoLock>* aLock);
bool InitFromData(unsigned char* aData, const IntSize& aSize, int32_t aStride,
SurfaceFormat aFormat);