[gfx][Skia] Hold mutex while accessing shared SkImage data.

This commit is contained in:
Fedor 2020-11-26 05:42:03 +02:00
parent 5136ec6010
commit 983728fddc
3 changed files with 54 additions and 17 deletions

View File

@ -212,7 +212,7 @@ VerifyRGBXCorners(uint8_t* aData, const IntSize &aSize, const int32_t aStride, S
#endif #endif
static sk_sp<SkImage> static sk_sp<SkImage>
GetSkImageForSurface(SourceSurface* aSurface) GetSkImageForSurface(SourceSurface* aSurface, Maybe<MutexAutoLock>* aLock)
{ {
if (!aSurface) { if (!aSurface) {
gfxDebug() << "Creating null Skia image from null SourceSurface"; gfxDebug() << "Creating null Skia image from null SourceSurface";
@ -220,7 +220,7 @@ GetSkImageForSurface(SourceSurface* aSurface)
} }
if (aSurface->GetType() == SurfaceType::SKIA) { if (aSurface->GetType() == SurfaceType::SKIA) {
return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage(); return static_cast<SourceSurfaceSkia*>(aSurface)->GetImage(aLock);
} }
DataSourceSurface* surf = aSurface->GetDataSurface().take(); DataSourceSurface* surf = aSurface->GetDataSurface().take();
@ -390,9 +390,9 @@ ExtractAlphaBitmap(sk_sp<SkImage> aImage, SkBitmap* aResultBitmap)
} }
static sk_sp<SkImage> static sk_sp<SkImage>
ExtractAlphaForSurface(SourceSurface* aSurface) ExtractAlphaForSurface(SourceSurface* aSurface, Maybe<MutexAutoLock>& aLock)
{ {
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &aLock);
if (!image) { if (!image) {
return nullptr; return nullptr;
} }
@ -411,7 +411,11 @@ ExtractAlphaForSurface(SourceSurface* aSurface)
} }
static void static void
SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Point aOffset = Point(0, 0)) SetPaintPattern(SkPaint& aPaint,
const Pattern& aPattern,
Maybe<MutexAutoLock>& aLock,
Float aAlpha = 1.0,
Point aOffset = Point(0, 0))
{ {
switch (aPattern.GetType()) { switch (aPattern.GetType()) {
case PatternType::COLOR: { case PatternType::COLOR: {
@ -473,7 +477,7 @@ SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0, Po
} }
case PatternType::SURFACE: { case PatternType::SURFACE: {
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern); const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface); sk_sp<SkImage> image = GetSkImageForSurface(pat.mSurface, &aLock);
if (!image) { if (!image) {
aPaint.setColor(SK_ColorTRANSPARENT); aPaint.setColor(SK_ColorTRANSPARENT);
break; break;
@ -525,7 +529,7 @@ struct AutoPaintSetup {
: mNeedsRestore(false), mAlpha(1.0) : mNeedsRestore(false), mAlpha(1.0)
{ {
Init(aCanvas, aOptions, aMaskBounds, false); Init(aCanvas, aOptions, aMaskBounds, false);
SetPaintPattern(mPaint, aPattern, mAlpha, aOffset); SetPaintPattern(mPaint, aPattern, mLock, mAlpha, aOffset);
} }
AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr, bool aForceGroup = false) AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Rect* aMaskBounds = nullptr, bool aForceGroup = false)
@ -579,6 +583,7 @@ struct AutoPaintSetup {
SkPaint mPaint; SkPaint mPaint;
bool mNeedsRestore; bool mNeedsRestore;
SkCanvas* mCanvas; SkCanvas* mCanvas;
Maybe<MutexAutoLock> mLock;
Float mAlpha; Float mAlpha;
}; };
@ -601,7 +606,8 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
MarkChanged(); MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) { if (!image) {
return; return;
} }
@ -654,7 +660,8 @@ DrawTargetSkia::DrawSurfaceWithShadow(SourceSurface *aSurface,
MarkChanged(); MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) { if (!image) {
return; return;
} }
@ -1407,8 +1414,9 @@ DrawTargetSkia::Mask(const Pattern &aSource,
MarkChanged(); MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
Maybe<MutexAutoLock> lock;
SkPaint maskPaint; SkPaint maskPaint;
SetPaintPattern(maskPaint, aMask); SetPaintPattern(maskPaint, aMask, lock);
SkLayerRasterizer::Builder builder; SkLayerRasterizer::Builder builder;
builder.addLayer(maskPaint); builder.addLayer(maskPaint);
@ -1427,7 +1435,8 @@ DrawTargetSkia::MaskSurface(const Pattern &aSource,
MarkChanged(); MarkChanged();
AutoPaintSetup paint(mCanvas.get(), aOptions, aSource, nullptr, -aOffset); AutoPaintSetup paint(mCanvas.get(), aOptions, aSource, nullptr, -aOffset);
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(aMask, lock);
if (!alphaMask) { if (!alphaMask) {
gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask"; gfxDebug() << *this << ": MaskSurface() failed to extract alpha for mask";
return; return;
@ -1456,7 +1465,8 @@ DrawTarget::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x4& a
fullMat.PostTranslate(-xformBounds.x, -xformBounds.y, 0); fullMat.PostTranslate(-xformBounds.x, -xformBounds.y, 0);
// Read in the source data. // Read in the source data.
sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> srcImage = GetSkImageForSurface(aSurface, &lock);
if (!srcImage) { if (!srcImage) {
return true; return true;
} }
@ -1515,7 +1525,8 @@ DrawTargetSkia::Draw3DTransformedSurface(SourceSurface* aSurface, const Matrix4x
MarkChanged(); MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) { if (!image) {
return true; return true;
} }
@ -1599,7 +1610,8 @@ already_AddRefed<SourceSurface>
DrawTargetSkia::OptimizeGPUSourceSurface(SourceSurface *aSurface) const DrawTargetSkia::OptimizeGPUSourceSurface(SourceSurface *aSurface) const
{ {
// Check if the underlying SkImage already has an associated GrTexture. // Check if the underlying SkImage already has an associated GrTexture.
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image || image->isTextureBacked()) { if (!image || image->isTextureBacked()) {
RefPtr<SourceSurface> surface(aSurface); RefPtr<SourceSurface> surface(aSurface);
return surface.forget(); return surface.forget();
@ -1716,7 +1728,8 @@ DrawTargetSkia::CopySurface(SourceSurface *aSurface,
{ {
MarkChanged(); MarkChanged();
sk_sp<SkImage> image = GetSkImageForSurface(aSurface); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> image = GetSkImageForSurface(aSurface, &lock);
if (!image) { if (!image) {
return; return;
} }
@ -2061,7 +2074,8 @@ DrawTargetSkia::PopLayer()
paint.setColor(SK_ColorTRANSPARENT); paint.setColor(SK_ColorTRANSPARENT);
} }
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(layer.mMask); Maybe<MutexAutoLock> lock;
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(layer.mMask, lock);
if (!alphaMask) { if (!alphaMask) {
gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask"; gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask";
} else { } else {

View File

@ -40,6 +40,25 @@ SourceSurfaceSkia::GetFormat() const
return mFormat; return mFormat;
} }
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.
if (aLock) {
// We are locked, so now we can check mDrawTarget.
// If it's null, then we're not shared and we can unlock eagerly.
if (!mDrawTarget) {
aLock->reset();
}
} else {
// Otherwise we need to call DrawTargetWillChange to ensure we have our
// own copy of the SkImage.
DrawTargetWillChange();
}
sk_sp<SkImage> image = mImage;
return image;
}
static sk_sp<SkData> static sk_sp<SkData>
MakeSkData(unsigned char* aData, const IntSize& aSize, int32_t aStride) MakeSkData(unsigned char* aData, const IntSize& aSize, int32_t aStride)
{ {

View File

@ -10,6 +10,10 @@
#include <vector> #include <vector>
#include "skia/include/core/SkCanvas.h" #include "skia/include/core/SkCanvas.h"
#include "skia/include/core/SkImage.h" #include "skia/include/core/SkImage.h"
#include "mozilla/Maybe.h"
#include "mozilla/Mutex.h"
typedef mozilla::MutexAutoLock MutexAutoLock;
namespace mozilla { namespace mozilla {
@ -28,7 +32,7 @@ public:
virtual IntSize GetSize() const; virtual IntSize GetSize() const;
virtual SurfaceFormat GetFormat() const; virtual SurfaceFormat GetFormat() const;
sk_sp<SkImage>& GetImage() { return mImage; } sk_sp<SkImage> GetImage(Maybe<MutexAutoLock>* aLock);
bool InitFromData(unsigned char* aData, bool InitFromData(unsigned char* aData,
const IntSize &aSize, const IntSize &aSize,