Index: src/core/SkImageCacherator.cpp |
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp |
index 6858a4c09e04f5cc0e2a7a016042eb2aa4e54933..75f8734e838004ac63b3bc393524b2223d69603f 100644 |
--- a/src/core/SkImageCacherator.cpp |
+++ b/src/core/SkImageCacherator.cpp |
@@ -10,6 +10,7 @@ |
#include "SkImage_Base.h" |
#include "SkImageCacherator.h" |
#include "SkMallocPixelRef.h" |
+#include "SkMutex.h" |
#include "SkNextID.h" |
#include "SkPixelRef.h" |
#include "SkResourceCache.h" |
@@ -32,18 +33,58 @@ |
// see skbug.com/ 4971, 5128, ... |
//#define SK_SUPPORT_COMPRESSED_TEXTURES_IN_CACHERATOR |
+// Ref-counted tuple(SkImageGenerator, SkMutex) which allows sharing of one generator |
+// among several cacherators. |
+class SkImageCacherator::SharedGenerator final : public SkNVRefCnt<SharedGenerator> { |
+public: |
+ static sk_sp<SharedGenerator> Make(SkImageGenerator* gen) { |
+ return gen ? sk_sp<SharedGenerator>(new SharedGenerator(gen)) : nullptr; |
+ } |
+ |
+private: |
+ explicit SharedGenerator(SkImageGenerator* gen) : fGenerator(gen) { SkASSERT(gen); } |
+ |
+ friend class ScopedGenerator; |
+ |
+ std::unique_ptr<SkImageGenerator> fGenerator; |
+ SkMutex fMutex; |
+}; |
+ |
+ |
+// Helper for exclusive access to a shared generator. |
+class SkImageCacherator::ScopedGenerator { |
+public: |
+ ScopedGenerator(const sk_sp<SharedGenerator>& gen) |
+ : fSharedGenerator(gen) |
+ , fAutoAquire(gen->fMutex) {} |
+ |
+ SkImageGenerator* operator->() const { |
+ fSharedGenerator->fMutex.assertHeld(); |
+ return fSharedGenerator->fGenerator.get(); |
+ } |
+ |
+ operator SkImageGenerator*() const { |
+ fSharedGenerator->fMutex.assertHeld(); |
+ return fSharedGenerator->fGenerator.get(); |
+ } |
+ |
+private: |
+ const sk_sp<SharedGenerator>& fSharedGenerator; |
+ SkAutoExclusive fAutoAquire; |
+}; |
+ |
SkImageCacherator::Validator::Validator(SkImageGenerator* gen, const SkIRect* subset) |
// We are required to take ownership of gen, regardless of whether we instantiate a cacherator |
// or not. On instantiation, the client is responsible for transferring ownership. |
- : fGenerator(gen) { |
+ : fSharedGenerator(SkImageCacherator::SharedGenerator::Make(gen)) { |
- if (!gen) { |
+ if (!fSharedGenerator) { |
return; |
} |
const SkImageInfo& info = gen->getInfo(); |
if (info.isEmpty()) { |
- fGenerator.reset(); |
+ fSharedGenerator.reset(); |
return; |
} |
@@ -51,7 +92,7 @@ SkImageCacherator::Validator::Validator(SkImageGenerator* gen, const SkIRect* su |
const SkIRect bounds = SkIRect::MakeWH(info.width(), info.height()); |
if (subset) { |
if (!bounds.contains(*subset)) { |
- fGenerator.reset(); |
+ fSharedGenerator.reset(); |
return; |
} |
if (*subset != bounds) { |
@@ -66,6 +107,8 @@ SkImageCacherator::Validator::Validator(SkImageGenerator* gen, const SkIRect* su |
fOrigin = SkIPoint::Make(subset->x(), subset->y()); |
} |
+SkImageCacherator::Validator::~Validator() {} |
+ |
SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen, |
const SkIRect* subset) { |
Validator validator(gen, subset); |
@@ -74,16 +117,18 @@ SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen, |
} |
SkImageCacherator::SkImageCacherator(Validator* validator) |
- : fNotThreadSafeGenerator(validator->fGenerator.release()) // we take ownership |
+ : fSharedGenerator(std::move(validator->fSharedGenerator)) // we take ownership |
, fInfo(validator->fInfo) |
, fOrigin(validator->fOrigin) |
, fUniqueID(validator->fUniqueID) |
{ |
- SkASSERT(fNotThreadSafeGenerator); |
+ SkASSERT(fSharedGenerator); |
} |
+SkImageCacherator::~SkImageCacherator() {} |
+ |
SkData* SkImageCacherator::refEncoded(GrContext* ctx) { |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
return generator->refEncodedData(ctx); |
} |
@@ -100,7 +145,7 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { |
bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { |
SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator(); |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
const SkImageInfo& genInfo = generator->getInfo(); |
if (fInfo.dimensions() == genInfo.dimensions()) { |
SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); |
@@ -124,7 +169,7 @@ bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { |
bool SkImageCacherator::directGeneratePixels(const SkImageInfo& info, void* pixels, size_t rb, |
int srcX, int srcY) { |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
const SkImageInfo& genInfo = generator->getInfo(); |
// Currently generators do not natively handle subsets, so check that first. |
if (srcX || srcY || genInfo.width() != info.width() || genInfo.height() != info.height()) { |
@@ -169,7 +214,7 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client, |
SkAutoTUnref<GrTexture> tex; |
{ |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); |
tex.reset(generator->generateTexture(nullptr, &subset)); |
} |
@@ -281,7 +326,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key |
// 2. Ask the generator to natively create one |
{ |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); |
if (GrTexture* tex = generator->generateTexture(ctx, &subset)) { |
SK_HISTOGRAM_ENUMERATION("LockTexturePath", kNative_LockTexturePath, |
@@ -307,7 +352,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key |
// 4. Ask the generator to return YUV planes, which the GPU can convert |
{ |
- ScopedGenerator generator(this); |
+ ScopedGenerator generator(fSharedGenerator); |
Generator_GrYUVProvider provider(generator); |
sk_sp<GrTexture> tex = provider.refAsTexture(ctx, desc, true); |
if (tex) { |