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
This commit is contained in:
fmalita 2016-10-27 14:22:41 -07:00 committed by Commit bot
parent a70558e2bb
commit f0c38f5fe6
2 changed files with 72 additions and 37 deletions

View File

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

View File

@ -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<SkImageGenerator> fGenerator;
SkImageInfo fInfo;
SkIPoint fOrigin;
uint32_t fUniqueID;
sk_sp<SharedGenerator> 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<SkImageGenerator> fNotThreadSafeGenerator;
const SkImageInfo fInfo;
const SkIPoint fOrigin;
const uint32_t fUniqueID;
sk_sp<SharedGenerator> fSharedGenerator;
const SkImageInfo fInfo;
const SkIPoint fOrigin;
const uint32_t fUniqueID;
friend class GrImageTextureMaker;
friend class SkImage;