зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1660236 - Hold mutex while accessing shared SkImage data. r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D93442
This commit is contained in:
Родитель
258b39d5e6
Коммит
31bb79f3a4
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче