From f0c38f5fe625bc67f647d58ac803bf4ba427e99e Mon Sep 17 00:00:00 2001 From: fmalita Date: Thu, 27 Oct 2016 14:22:41 -0700 Subject: [PATCH] Shared image generator Introduce a new ref counted class (SharedGenerator), to facilitate SkImageGenerator sharing among multiple cacherators. Plumbing only for now, no actual sharing. R=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2451273006 Review-Url: https://codereview.chromium.org/2451273006 --- src/core/SkImageCacherator.cpp | 69 ++++++++++++++++++++++++++++------ src/core/SkImageCacherator.h | 40 ++++++++------------ 2 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index 6858a4c09e..75f8734e83 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 { +public: + static sk_sp Make(SkImageGenerator* gen) { + return gen ? sk_sp(new SharedGenerator(gen)) : nullptr; + } + +private: + explicit SharedGenerator(SkImageGenerator* gen) : fGenerator(gen) { SkASSERT(gen); } + + friend class ScopedGenerator; + + std::unique_ptr fGenerator; + SkMutex fMutex; +}; + + +// Helper for exclusive access to a shared generator. +class SkImageCacherator::ScopedGenerator { +public: + ScopedGenerator(const sk_sp& 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& 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 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 tex = provider.refAsTexture(ctx, desc, true); if (tex) { diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h index 2d9e94cc4d..cd5ac9ba09 100644 --- a/src/core/SkImageCacherator.h +++ b/src/core/SkImageCacherator.h @@ -9,7 +9,6 @@ #define SkImageCacherator_DEFINED #include "SkImageGenerator.h" -#include "SkMutex.h" #include "SkTemplates.h" class GrContext; @@ -26,6 +25,8 @@ public: // Takes ownership of the generator static SkImageCacherator* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr); + ~SkImageCacherator(); + const SkImageInfo& info() const { return fInfo; } uint32_t uniqueID() const { return fUniqueID; } @@ -68,15 +69,19 @@ public: int srcX, int srcY); private: + class SharedGenerator; + class ScopedGenerator; + struct Validator { Validator(SkImageGenerator*, const SkIRect* subset); + ~Validator(); - operator bool() const { return fGenerator.get(); } + operator bool() const { return fSharedGenerator.get(); } - std::unique_ptr fGenerator; - SkImageInfo fInfo; - SkIPoint fOrigin; - uint32_t fUniqueID; + sk_sp fSharedGenerator; + SkImageInfo fInfo; + SkIPoint fOrigin; + uint32_t fUniqueID; }; SkImageCacherator(Validator*); @@ -90,25 +95,10 @@ private: SkImage::CachingHint, bool willBeMipped, SkSourceGammaTreatment); #endif - class ScopedGenerator { - SkImageCacherator* fCacher; - public: - ScopedGenerator(SkImageCacherator* cacher) : fCacher(cacher) { - fCacher->fMutexForGenerator.acquire(); - } - ~ScopedGenerator() { - fCacher->fMutexForGenerator.release(); - } - SkImageGenerator* operator->() const { return fCacher->fNotThreadSafeGenerator; } - operator SkImageGenerator*() const { return fCacher->fNotThreadSafeGenerator; } - }; - - SkMutex fMutexForGenerator; - SkAutoTDelete fNotThreadSafeGenerator; - - const SkImageInfo fInfo; - const SkIPoint fOrigin; - const uint32_t fUniqueID; + sk_sp fSharedGenerator; + const SkImageInfo fInfo; + const SkIPoint fOrigin; + const uint32_t fUniqueID; friend class GrImageTextureMaker; friend class SkImage;