diff options
author | reed <reed@google.com> | 2015-08-26 14:16:43 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-26 14:16:43 -0700 |
commit | d5c448fd857a77a375886bc1a8da83a7f1bf32fe (patch) | |
tree | 6483120e62732b2a74a685448e343da3e43391fc /src/core | |
parent | 9c84b112aa2ffc5bd7a18b6dc66bd64ce9d08843 (diff) |
make cacherator thread-safe
hoisted from https://codereview.chromium.org/1282363002 as that CL is going to take a while to finish
BUG=skia:
TBR=
Review URL: https://codereview.chromium.org/1313423002
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkImageCacherator.cpp | 89 | ||||
-rw-r--r-- | src/core/SkImageCacherator.h | 29 |
2 files changed, 78 insertions, 40 deletions
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index a65e8fccbd..24d2813909 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -51,13 +51,16 @@ SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen, SkImageCacherator::SkImageCacherator(SkImageGenerator* gen, const SkImageInfo& info, const SkIPoint& origin, uint32_t uniqueID) - : fGenerator(gen) + : fNotThreadSafeGenerator(gen) , fInfo(info) , fOrigin(origin) , fUniqueID(uniqueID) {} -SkImageCacherator::~SkImageCacherator() { delete fGenerator; } +SkData* SkImageCacherator::refEncoded() { + ScopedGenerator generator(this); + return generator->refEncodedData(); +} static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { SkASSERT(bitmap.getGenerationID() == expectedID); @@ -66,17 +69,17 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { return true; } -static bool generate_bitmap(SkBitmap* bitmap, const SkImageInfo& info, const SkIPoint& origin, - SkImageGenerator* generator) { - const size_t rowBytes = info.minRowBytes(); - if (!bitmap->tryAllocPixels(info, rowBytes)) { +bool SkImageCacherator::generateBitmap(SkBitmap* bitmap) { + const size_t rowBytes = fInfo.minRowBytes(); + if (!bitmap->tryAllocPixels(fInfo, rowBytes)) { return false; } SkASSERT(bitmap->rowBytes() == rowBytes); + ScopedGenerator generator(this); const SkImageInfo& genInfo = generator->getInfo(); - if (info.dimensions() == genInfo.dimensions()) { - SkASSERT(origin.x() == 0 && origin.y() == 0); + if (fInfo.dimensions() == genInfo.dimensions()) { + SkASSERT(fOrigin.x() == 0 && fOrigin.y() == 0); // fast-case, no copy needed if (!generator->getPixels(bitmap->info(), bitmap->getPixels(), rowBytes)) { bitmap->reset(); @@ -93,7 +96,7 @@ static bool generate_bitmap(SkBitmap* bitmap, const SkImageInfo& info, const SkI return false; } full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), - origin.x(), origin.y()); + fOrigin.x(), fOrigin.y()); } return true; } @@ -104,7 +107,8 @@ bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap) { if (SkBitmapCache::Find(fUniqueID, bitmap)) { return check_output_bitmap(*bitmap, fUniqueID); } - if (!generate_bitmap(bitmap, fInfo, fOrigin, fGenerator)) { + + if (!this->generateBitmap(bitmap)) { return false; } @@ -120,10 +124,13 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) { #if SK_SUPPORT_GPU // Try to get a texture and read it back to raster (and then cache that with our ID) + SkAutoTUnref<GrTexture> tex; - SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); - SkAutoTUnref<GrTexture> tex(fGenerator->generateTexture(nullptr, kUntiled_SkImageUsageType, - &subset)); + { + ScopedGenerator generator(this); + SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); + tex.reset(generator->generateTexture(nullptr, kUntiled_SkImageUsageType, &subset)); + } if (!tex) { bitmap->reset(); return false; @@ -151,40 +158,50 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) { ////////////////////////////////////////////////////////////////////////////////////////////////// -GrTexture* SkImageCacherator::tryLockAsTexture(GrContext* ctx, SkImageUsageType usage) { +/* + * We have a 5 ways to try to return a texture (in sorted order) + * + * 1. Check the cache for a pre-existing one + * 2. Ask the genreator to natively create one + * 3. Ask the generator to return a compressed form that the GPU might support + * 4. Ask the generator to return YUV planes, which the GPU can convert + * 5. Ask the generator to return RGB(A) data, which the GPU can convert + */ +GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage) { #if SK_SUPPORT_GPU + if (!ctx) { + return nullptr; + } + GrUniqueKey key; GrMakeKeyFromImageID(&key, fUniqueID, fInfo.width(), fInfo.height(), SkIPoint::Make(0, 0), *ctx->caps(), usage); - GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key); - if (tex) { - return tex; // we got a cache hit! - } - SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); - tex = fGenerator->generateTexture(ctx, usage, &subset); - if (tex) { - tex->resourcePriv().setUniqueKey(key); + // 1. Check the cache for a pre-existing one + if (GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key)) { + return tex; } - return tex; -#else - return nullptr; -#endif -} -GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usage) { -#if SK_SUPPORT_GPU - if (!ctx) { - return nullptr; - } - if (GrTexture* tex = this->tryLockAsTexture(ctx, usage)) { - return tex; + // 2. Ask the genreator to natively create one + { + ScopedGenerator generator(this); + SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); + if (GrTexture* tex = generator->generateTexture(ctx, usage, &subset)) { + tex->resourcePriv().setUniqueKey(key); + return tex; + } } - // Try to get a bitmap and then upload/cache it as a texture + // 3. Ask the generator to return a compressed form that the GPU might support + // TODO + + // 4. Ask the generator to return YUV planes, which the GPU can convert + // TODO + + // 5. Ask the generator to return RGB(A) data, which the GPU can convert SkBitmap bitmap; - if (!generate_bitmap(&bitmap, fInfo, fOrigin, fGenerator)) { + if (!this->generateBitmap(&bitmap)) { return nullptr; } return GrRefCachedBitmapTexture(ctx, bitmap, usage); diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h index f05147e571..c9aa121d26 100644 --- a/src/core/SkImageCacherator.h +++ b/src/core/SkImageCacherator.h @@ -9,6 +9,8 @@ #define SkImageCacherator_DEFINED #include "SkImageGenerator.h" +#include "SkMutex.h" +#include "SkTemplates.h" class GrContext; class SkBitmap; @@ -21,8 +23,6 @@ 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; } @@ -40,13 +40,34 @@ public: */ GrTexture* lockAsTexture(GrContext*, SkImageUsageType); + /** + * If the underlying src naturally is represented by an encoded blob (in SkData), this returns + * a ref to that data. If not, it returns null. + */ + SkData* refEncoded(); + private: SkImageCacherator(SkImageGenerator*, const SkImageInfo&, const SkIPoint&, uint32_t uniqueID); + bool generateBitmap(SkBitmap*); bool tryLockAsBitmap(SkBitmap*); - GrTexture* tryLockAsTexture(GrContext*, SkImageUsageType); - SkImageGenerator* fGenerator; + 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; |