| 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) {
|
|
|