aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-08-26 14:16:43 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-26 14:16:43 -0700
commitd5c448fd857a77a375886bc1a8da83a7f1bf32fe (patch)
tree6483120e62732b2a74a685448e343da3e43391fc /src/core
parent9c84b112aa2ffc5bd7a18b6dc66bd64ce9d08843 (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.cpp89
-rw-r--r--src/core/SkImageCacherator.h29
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;