diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkImageCacherator.cpp | 144 | ||||
-rw-r--r-- | src/core/SkImageCacherator.h | 51 | ||||
-rw-r--r-- | src/core/SkImageGenerator.cpp | 13 | ||||
-rw-r--r-- | src/core/SkPictureImageGenerator.cpp | 30 |
4 files changed, 237 insertions, 1 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 +} + diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h new file mode 100644 index 0000000000..86dbd8874f --- /dev/null +++ b/src/core/SkImageCacherator.h @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkImageCacherator_DEFINED +#define SkImageCacherator_DEFINED + +#include "SkImageGenerator.h" + +class GrContext; +class SkBitmap; + +/* + * Internal class to manage caching the output of an ImageGenerator. + */ +class SkImageCacherator { +public: + // Takes ownership of the generator + SkImageCacherator(SkImageGenerator* gen); + ~SkImageCacherator(); + + const SkImageInfo& info() const { return fGenerator->getInfo(); } + SkImageGenerator* generator() const { return fGenerator; } + + /** + * On success (true), bitmap will point to the pixels for this generator. If this returns + * false, the bitmap will be reset to empty. + * + * The cached bitmap is valid until it goes out of scope. + */ + bool lockAsBitmap(SkBitmap*); + + /** + * Returns a ref() on the texture produced by this generator. The caller must call unref() + * when it is done. Will return NULL on failure. + * + * The cached texture is valid until it is unref'd. + */ + GrTexture* lockAsTexture(GrContext*, SkImageUsageType); + +private: + bool tryLockAsBitmap(SkBitmap*); + GrTexture* tryLockAsTexture(GrContext*, SkImageUsageType); + + SkImageGenerator* fGenerator; +}; + +#endif diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp index 82b42d7a97..d42ece828a 100644 --- a/src/core/SkImageGenerator.cpp +++ b/src/core/SkImageGenerator.cpp @@ -6,6 +6,12 @@ */ #include "SkImageGenerator.h" +#include "SkNextID.h" + +SkImageGenerator::SkImageGenerator(const SkImageInfo& info) + : fInfo(info) + , fUniqueID(SkNextID::ImageID()) +{} bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount) { @@ -98,6 +104,13 @@ bool SkImageGenerator::onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t return this->onGetYUV8Planes(sizes, planes, rowBytes); } +GrTexture* SkImageGenerator::generateTexture(GrContext* ctx, SkImageUsageType usage) { + if (!ctx) { + return nullptr; + } + return this->onGenerateTexture(ctx, usage); +} + ///////////////////////////////////////////////////////////////////////////////////////////// SkData* SkImageGenerator::onRefEncodedData() { diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp index 6c3faef250..f92de3b986 100644 --- a/src/core/SkPictureImageGenerator.cpp +++ b/src/core/SkPictureImageGenerator.cpp @@ -6,11 +6,11 @@ */ #include "SkImageGenerator.h" - #include "SkCanvas.h" #include "SkMatrix.h" #include "SkPaint.h" #include "SkPicture.h" +#include "SkSurface.h" #include "SkTLazy.h" class SkPictureImageGenerator : SkImageGenerator { @@ -21,6 +21,9 @@ public: protected: bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount) override; +#if SK_SUPPORT_GPU + GrTexture* onGenerateTexture(GrContext*, SkImageUsageType) override; +#endif private: SkPictureImageGenerator(const SkISize&, const SkPicture*, const SkMatrix*, const SkPaint*); @@ -79,3 +82,28 @@ SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const Sk const SkMatrix* matrix, const SkPaint* paint) { return SkPictureImageGenerator::Create(size, picture, matrix, paint); } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#if SK_SUPPORT_GPU +#include "GrTexture.h" + +GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, SkImageUsageType usage) { + // + // TODO: respect the usage, by possibly creating a different (pow2) surface + // + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, + SkSurface::kYes_Budgeted, + this->getInfo())); + if (!surface.get()) { + return nullptr; + } + surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us? + surface->getCanvas()->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull()); + SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); + if (!image.get()) { + return nullptr; + } + return SkSafeRef(image->getTexture()); +} +#endif |