diff options
Diffstat (limited to 'src/core/SkImageCacherator.cpp')
-rw-r--r-- | src/core/SkImageCacherator.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp new file mode 100644 index 0000000000..b225612a17 --- /dev/null +++ b/src/core/SkImageCacherator.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmap.h" +#include "SkBitmapCache.h" +#include "SkImageCacherator.h" +#include "SkPixelRef.h" + +#if SK_SUPPORT_GPU +#include "GrContext.h" +#include "GrGpuResourcePriv.h" +#include "GrResourceKey.h" +#include "GrTextureAccess.h" +#include "SkGr.h" +#include "SkGrPriv.h" +#endif + +SkImageCacherator::SkImageCacherator(SkImageGenerator* gen) : fGenerator(gen) {} + +SkImageCacherator::~SkImageCacherator() { + delete fGenerator; +} + +static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { + SkASSERT(bitmap.getGenerationID() == expectedID); + SkASSERT(bitmap.isImmutable()); + SkASSERT(bitmap.getPixels()); + return true; +} + +static bool generate_bitmap(SkImageGenerator* generator, SkBitmap* bitmap) { + if (!bitmap->tryAllocPixels(generator->getInfo()) || + !generator->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes())) + { + bitmap->reset(); + return false; + } + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +bool SkImageCacherator::tryLockAsBitmap(SkBitmap* bitmap) { + const uint32_t uniqueID = fGenerator->uniqueID(); + + if (SkBitmapCache::Find(uniqueID, bitmap)) { + return check_output_bitmap(*bitmap, uniqueID); + } + if (!generate_bitmap(fGenerator, bitmap)) { + return false; + } + + bitmap->pixelRef()->setImmutableWithID(uniqueID); + SkBitmapCache::Add(uniqueID, *bitmap); + return true; +} + +bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) { + const uint32_t uniqueID = fGenerator->uniqueID(); + + if (this->tryLockAsBitmap(bitmap)) { + return check_output_bitmap(*bitmap, uniqueID); + } + +#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(fGenerator->generateTexture(nullptr, kUntiled_SkImageUsageType)); + if (!tex) { + bitmap->reset(); + return false; + } + + const SkImageInfo& info = this->info(); + if (!bitmap->tryAllocPixels(info)) { + bitmap->reset(); + return false; + } + + const uint32_t pixelOpsFlags = 0; + if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), SkImageInfo2GrPixelConfig(info), + bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) { + bitmap->reset(); + return false; + } + + bitmap->pixelRef()->setImmutableWithID(uniqueID); + SkBitmapCache::Add(uniqueID, *bitmap); + return check_output_bitmap(*bitmap, uniqueID); +#else + return false; +#endif +} + +////////////////////////////////////////////////////////////////////////////////////////////////// + +GrTexture* SkImageCacherator::tryLockAsTexture(GrContext* ctx, SkImageUsageType usage) { +#if SK_SUPPORT_GPU + const uint32_t uniqueID = fGenerator->uniqueID(); + const SkImageInfo& info = this->info(); + + GrUniqueKey key; + GrMakeKeyFromImageID(&key, uniqueID, info.width(), info.height(), SkIPoint::Make(0, 0), + *ctx->caps(), usage); + GrTexture* tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(key); + if (tex) { + return tex; // we got a cache hit! + } + + tex = fGenerator->generateTexture(ctx, usage); + if (tex) { + tex->resourcePriv().setUniqueKey(key); + } + 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; + } + + // Try to get a bitmap and then upload/cache it as a texture + + SkBitmap bitmap; + if (!generate_bitmap(fGenerator, &bitmap)) { + return nullptr; + } + return GrRefCachedBitmapTexture(ctx, bitmap, usage); +#else + return nullptr; +#endif +} + |