diff options
author | 2015-08-18 11:16:09 -0700 | |
---|---|---|
committer | 2015-08-18 11:16:09 -0700 | |
commit | 935d6cfaa78b6be75c9fcc596805f0f9b8da972e (patch) | |
tree | 2e3eb27f6c0a2d538f2e4e4922627a7c9e1fb30d /src | |
parent | f272bb03df9b86e7ea2cf23fb4d5cc56624e0118 (diff) |
Add subsets to SkImageGenerator and SkImageCacherator
... to support subsets in SkImage!
BUG=skia:
Review URL: https://codereview.chromium.org/1301633002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkImageCacherator.cpp | 110 | ||||
-rw-r--r-- | src/core/SkImageCacherator.h | 13 | ||||
-rw-r--r-- | src/core/SkImageGenerator.cpp | 7 | ||||
-rw-r--r-- | src/core/SkPictureImageGenerator.cpp | 17 |
4 files changed, 104 insertions, 43 deletions
diff --git a/src/core/SkImageCacherator.cpp b/src/core/SkImageCacherator.cpp index 1f481d0000..863cc11b1d 100644 --- a/src/core/SkImageCacherator.cpp +++ b/src/core/SkImageCacherator.cpp @@ -8,6 +8,8 @@ #include "SkBitmap.h" #include "SkBitmapCache.h" #include "SkImageCacherator.h" +#include "SkMallocPixelRef.h" +#include "SkNextID.h" #include "SkPixelRef.h" #if SK_SUPPORT_GPU @@ -19,14 +21,43 @@ #include "SkGrPriv.h" #endif -SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen) { +SkImageCacherator* SkImageCacherator::NewFromGenerator(SkImageGenerator* gen, + const SkIRect* subset) { if (!gen) { return nullptr; } - return SkNEW_ARGS(SkImageCacherator, (gen)); + const SkImageInfo& info = gen->getInfo(); + if (info.isEmpty()) { + return nullptr; + } + + uint32_t uniqueID = gen->uniqueID(); + const SkIRect bounds = SkIRect::MakeWH(info.width(), info.height()); + if (subset) { + if (!bounds.contains(*subset)) { + return nullptr; + } + if (*subset != bounds) { + // we need a different uniqueID since we really are a subset of the raw generator + uniqueID = SkNextID::ImageID(); + } + } else { + subset = &bounds; + } + + return SkNEW_ARGS(SkImageCacherator, (gen, + gen->getInfo().makeWH(subset->width(), subset->height()), + SkIPoint::Make(subset->x(), subset->y()), + uniqueID)); } -SkImageCacherator::SkImageCacherator(SkImageGenerator* gen) : fGenerator(gen) {} +SkImageCacherator::SkImageCacherator(SkImageGenerator* gen, const SkImageInfo& info, + const SkIPoint& origin, uint32_t uniqueID) + : fGenerator(gen) + , fInfo(info) + , fOrigin(origin) + , fUniqueID(uniqueID) +{} SkImageCacherator::~SkImageCacherator() { SkDELETE(fGenerator); @@ -39,65 +70,84 @@ static bool check_output_bitmap(const SkBitmap& bitmap, uint32_t expectedID) { 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(); +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)) { return false; } + SkASSERT(bitmap->rowBytes() == rowBytes); + + const SkImageInfo& genInfo = generator->getInfo(); + if (info.dimensions() == genInfo.dimensions()) { + SkASSERT(origin.x() == 0 && origin.y() == 0); + // fast-case, no copy needed + if (!generator->getPixels(bitmap->info(), bitmap->getPixels(), rowBytes)) { + bitmap->reset(); + return false; + } + } else { + // need to handle subsetting + SkBitmap full; + if (!full.tryAllocPixels(genInfo)) { + return false; + } + if (!generator->getPixels(full.info(), full.getPixels(), full.rowBytes())) { + bitmap->reset(); + return false; + } + full.readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), + origin.x(), origin.y()); + } 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 (SkBitmapCache::Find(fUniqueID, bitmap)) { + return check_output_bitmap(*bitmap, fUniqueID); } - if (!generate_bitmap(fGenerator, bitmap)) { + if (!generate_bitmap(bitmap, fInfo, fOrigin, fGenerator)) { return false; } - bitmap->pixelRef()->setImmutableWithID(uniqueID); - SkBitmapCache::Add(uniqueID, *bitmap); + bitmap->pixelRef()->setImmutableWithID(fUniqueID); + SkBitmapCache::Add(fUniqueID, *bitmap); return true; } bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) { - const uint32_t uniqueID = fGenerator->uniqueID(); - if (this->tryLockAsBitmap(bitmap)) { - return check_output_bitmap(*bitmap, uniqueID); + return check_output_bitmap(*bitmap, fUniqueID); } #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)); + SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); + SkAutoTUnref<GrTexture> tex(fGenerator->generateTexture(nullptr, kUntiled_SkImageUsageType, + &subset)); if (!tex) { bitmap->reset(); return false; } - const SkImageInfo& info = this->info(); - if (!bitmap->tryAllocPixels(info)) { + if (!bitmap->tryAllocPixels(fInfo)) { bitmap->reset(); return false; } const uint32_t pixelOpsFlags = 0; - if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), SkImageInfo2GrPixelConfig(info), + if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), SkImageInfo2GrPixelConfig(fInfo), bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) { bitmap->reset(); return false; } - bitmap->pixelRef()->setImmutableWithID(uniqueID); - SkBitmapCache::Add(uniqueID, *bitmap); - return check_output_bitmap(*bitmap, uniqueID); + bitmap->pixelRef()->setImmutableWithID(fUniqueID); + SkBitmapCache::Add(fUniqueID, *bitmap); + return check_output_bitmap(*bitmap, fUniqueID); #else return false; #endif @@ -107,18 +157,16 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap) { 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), + 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! } - tex = fGenerator->generateTexture(ctx, usage); + SkIRect subset = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), fInfo.width(), fInfo.height()); + tex = fGenerator->generateTexture(ctx, usage, &subset); if (tex) { tex->resourcePriv().setUniqueKey(key); } @@ -140,7 +188,7 @@ GrTexture* SkImageCacherator::lockAsTexture(GrContext* ctx, SkImageUsageType usa // Try to get a bitmap and then upload/cache it as a texture SkBitmap bitmap; - if (!generate_bitmap(fGenerator, &bitmap)) { + if (!generate_bitmap(&bitmap, fInfo, fOrigin, fGenerator)) { return nullptr; } return GrRefCachedBitmapTexture(ctx, bitmap, usage); diff --git a/src/core/SkImageCacherator.h b/src/core/SkImageCacherator.h index 2403a50a04..f05147e571 100644 --- a/src/core/SkImageCacherator.h +++ b/src/core/SkImageCacherator.h @@ -19,12 +19,12 @@ class SkBitmap; class SkImageCacherator { public: // Takes ownership of the generator - static SkImageCacherator* NewFromGenerator(SkImageGenerator*); + static SkImageCacherator* NewFromGenerator(SkImageGenerator*, const SkIRect* subset = nullptr); ~SkImageCacherator(); - const SkImageInfo& info() const { return fGenerator->getInfo(); } - SkImageGenerator* generator() const { return fGenerator; } + const SkImageInfo& info() const { return fInfo; } + uint32_t uniqueID() const { return fUniqueID; } /** * On success (true), bitmap will point to the pixels for this generator. If this returns @@ -41,12 +41,15 @@ public: GrTexture* lockAsTexture(GrContext*, SkImageUsageType); private: - SkImageCacherator(SkImageGenerator* gen); + SkImageCacherator(SkImageGenerator*, const SkImageInfo&, const SkIPoint&, uint32_t uniqueID); bool tryLockAsBitmap(SkBitmap*); GrTexture* tryLockAsTexture(GrContext*, SkImageUsageType); - SkImageGenerator* fGenerator; + SkImageGenerator* fGenerator; + const SkImageInfo fInfo; + const SkIPoint fOrigin; + const uint32_t fUniqueID; }; #endif diff --git a/src/core/SkImageGenerator.cpp b/src/core/SkImageGenerator.cpp index d42ece828a..ffccb611d8 100644 --- a/src/core/SkImageGenerator.cpp +++ b/src/core/SkImageGenerator.cpp @@ -104,11 +104,12 @@ 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) { +GrTexture* SkImageGenerator::generateTexture(GrContext* ctx, SkImageUsageType usage, + const SkIRect* subset) { + if (subset && !SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(*subset)) { return nullptr; } - return this->onGenerateTexture(ctx, usage); + return this->onGenerateTexture(ctx, usage, subset); } ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPictureImageGenerator.cpp b/src/core/SkPictureImageGenerator.cpp index f92de3b986..acff84c1b4 100644 --- a/src/core/SkPictureImageGenerator.cpp +++ b/src/core/SkPictureImageGenerator.cpp @@ -22,7 +22,7 @@ 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; + GrTexture* onGenerateTexture(GrContext*, SkImageUsageType, const SkIRect*) override; #endif private: @@ -88,18 +88,27 @@ SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const Sk #if SK_SUPPORT_GPU #include "GrTexture.h" -GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, SkImageUsageType usage) { +GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, SkImageUsageType usage, + const SkIRect* subset) { + const SkImageInfo& info = this->getInfo(); + SkImageInfo surfaceInfo = subset ? info.makeWH(subset->width(), subset->height()) : info; + // // TODO: respect the usage, by possibly creating a different (pow2) surface // SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kYes_Budgeted, - this->getInfo())); + surfaceInfo)); if (!surface.get()) { return nullptr; } + + SkMatrix matrix = fMatrix; + if (subset) { + matrix.postTranslate(-subset->x(), -subset->y()); + } surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us? - surface->getCanvas()->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull()); + surface->getCanvas()->drawPicture(fPicture, &matrix, fPaint.getMaybeNull()); SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); if (!image.get()) { return nullptr; |