diff options
author | reed <reed@google.com> | 2015-08-13 13:32:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-13 13:32:39 -0700 |
commit | 8f34372f7e97482e5e61ab298b7edaa008ba2f4c (patch) | |
tree | 48581497c1bcfb3420c6aba6c6fe27d344f96855 /src/core | |
parent | 5a16cf654548190841b5af27af04e7995582ad7b (diff) |
Extend SkImageGenerator to support natively generated GrTextures. As part of this, added uniqueID() to the generator, and made it be in the same namespace is bitmaps, pixelrefs, images.
To do this, create SkImageCacherator, which wraps a generator and provides an
interface to get a cached answer for either the raster or texture output of
the generator.
BUG=skia:
Review URL: https://codereview.chromium.org/1291803002
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 |