aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2015-08-18 11:16:09 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-18 11:16:09 -0700
commit935d6cfaa78b6be75c9fcc596805f0f9b8da972e (patch)
tree2e3eb27f6c0a2d538f2e4e4922627a7c9e1fb30d /src
parentf272bb03df9b86e7ea2cf23fb4d5cc56624e0118 (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.cpp110
-rw-r--r--src/core/SkImageCacherator.h13
-rw-r--r--src/core/SkImageGenerator.cpp7
-rw-r--r--src/core/SkPictureImageGenerator.cpp17
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;