aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/image_pict.cpp90
-rw-r--r--gyp/core.gypi1
-rw-r--r--include/core/SkImageGenerator.h33
-rw-r--r--include/core/SkImageInfo.h16
-rw-r--r--include/core/SkPixelRef.h1
-rw-r--r--include/gpu/SkGr.h1
-rw-r--r--src/core/SkImageCacherator.cpp144
-rw-r--r--src/core/SkImageCacherator.h51
-rw-r--r--src/core/SkImageGenerator.cpp13
-rw-r--r--src/core/SkPictureImageGenerator.cpp30
-rw-r--r--src/gpu/SkGr.cpp76
-rw-r--r--src/gpu/SkGrPriv.h32
12 files changed, 477 insertions, 11 deletions
diff --git a/gm/image_pict.cpp b/gm/image_pict.cpp
index ce2d2ecb0c..dd1fab549a 100644
--- a/gm/image_pict.cpp
+++ b/gm/image_pict.cpp
@@ -8,10 +8,14 @@
#include "gm.h"
#include "SkCanvas.h"
#include "SkImage.h"
+#include "SkImageCacherator.h"
#include "SkPictureRecorder.h"
+#include "SkSurface.h"
#if SK_SUPPORT_GPU
#include "GrContext.h"
+#include "GrTexture.h"
+#include "../src/image/SkImage_Gpu.h"
#endif
static void draw_something(SkCanvas* canvas, const SkRect& bounds) {
@@ -94,3 +98,89 @@ private:
};
DEF_GM( return new ImagePictGM; )
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+class ImageCacheratorGM : public skiagm::GM {
+ SkAutoTUnref<SkPicture> fPicture;
+ SkAutoTDelete<SkImageCacherator> fCache;
+
+public:
+ ImageCacheratorGM() {}
+
+protected:
+ SkString onShortName() override {
+ return SkString("image-cacherator");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(850, 450);
+ }
+
+ void onOnceBeforeDraw() override {
+ const SkRect bounds = SkRect::MakeXYWH(100, 100, 100, 100);
+ SkPictureRecorder recorder;
+ draw_something(recorder.beginRecording(bounds), bounds);
+ fPicture.reset(recorder.endRecording());
+
+ // extract enough just for the oval.
+ const SkISize size = SkISize::Make(100, 100);
+
+ SkMatrix matrix;
+ matrix.setTranslate(-100, -100);
+ fCache.reset(new SkImageCacherator(SkImageGenerator::NewFromPicture(size,
+ fPicture,
+ &matrix,
+ nullptr)));
+ }
+
+ void drawSet(SkCanvas* canvas) const {
+ SkMatrix matrix = SkMatrix::MakeTrans(-100, -100);
+ canvas->drawPicture(fPicture, &matrix, nullptr);
+
+ {
+ SkBitmap bitmap;
+ fCache->lockAsBitmap(&bitmap);
+ canvas->drawBitmap(bitmap, 150, 0);
+ }
+#if SK_SUPPORT_GPU
+ {
+ SkAutoTUnref<GrTexture> texture(fCache->lockAsTexture(canvas->getGrContext(),
+ kUntiled_SkImageUsageType));
+ if (!texture) {
+ return;
+ }
+ // No API to draw a GrTexture directly, so we cheat and create a private image subclass
+ SkAutoTUnref<SkImage> image(new SkImage_Gpu(100, 100, fCache->generator()->uniqueID(),
+ kPremul_SkAlphaType, texture, 0,
+ SkSurface::kNo_Budgeted));
+ canvas->drawImage(image, 300, 0);
+ }
+#endif
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ canvas->translate(20, 20);
+
+ this->drawSet(canvas);
+
+ canvas->save();
+ canvas->translate(0, 130);
+ canvas->scale(0.25f, 0.25f);
+ this->drawSet(canvas);
+ canvas->restore();
+
+ canvas->save();
+ canvas->translate(0, 200);
+ canvas->scale(2, 2);
+ this->drawSet(canvas);
+ canvas->restore();
+ }
+
+private:
+ typedef skiagm::GM INHERITED;
+};
+DEF_GM( return new ImageCacheratorGM; )
+
+
+
diff --git a/gyp/core.gypi b/gyp/core.gypi
index d1ac89547f..26e8f70b6f 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -114,6 +114,7 @@
'<(skia_src_path)/core/SkHalf.h',
'<(skia_src_path)/core/SkImageFilter.cpp',
'<(skia_src_path)/core/SkImageInfo.cpp',
+ '<(skia_src_path)/core/SkImageCacherator.cpp',
'<(skia_src_path)/core/SkImageGenerator.cpp',
'<(skia_src_path)/core/SkLayerInfo.h',
'<(skia_src_path)/core/SkLocalMatrixShader.cpp',
diff --git a/include/core/SkImageGenerator.h b/include/core/SkImageGenerator.h
index 83f36e09a7..d5885babd7 100644
--- a/include/core/SkImageGenerator.h
+++ b/include/core/SkImageGenerator.h
@@ -11,8 +11,10 @@
#include "SkColor.h"
#include "SkImageInfo.h"
+class GrContext;
class SkBitmap;
class SkData;
+class GrTexture;
class SkImageGenerator;
class SkMatrix;
class SkPaint;
@@ -56,6 +58,8 @@ public:
*/
virtual ~SkImageGenerator() { }
+ uint32_t uniqueID() const { return fUniqueID; }
+
/**
* Return a ref to the encoded (i.e. compressed) representation,
* of this data.
@@ -123,6 +127,30 @@ public:
SkYUVColorSpace* colorSpace);
/**
+ * If the generator can natively/efficiently return its pixels as a GPU image (backed by a
+ * texture) this will return that image. If not, this will return NULL.
+ *
+ * Regarding the GrContext parameter:
+ *
+ * The caller may pass NULL for the context. In that case the generator may assume that its
+ * internal context is current. If it has no internal context, then it should just return
+ * null.
+ *
+ * If the caller passes a non-null context, then the generator should only succeed if:
+ * - it has no intrinsic context, and will use the caller's
+ * - its internal context is the same
+ * - it can somehow convert its texture into one that is valid for the provided context.
+ *
+ * Regarding the SkImageUsageType parameter:
+ *
+ * If the context (the provided one or the generator's intrinsic one) determines that to
+ * support the specified usage, it must return a different sized texture (from the generator's
+ * native size) it may, so the caller must inspect the texture's width/height
+ * (unless kUntiled_SkImageUsedType was specified).
+ */
+ GrTexture* generateTexture(GrContext*, SkImageUsageType);
+
+ /**
* If the default image decoder system can interpret the specified (encoded) data, then
* this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
* the caller is still responsible for managing their ownership of the data.
@@ -138,7 +166,7 @@ public:
const SkPaint*);
protected:
- SkImageGenerator(const SkImageInfo& info) : fInfo(info) {}
+ SkImageGenerator(const SkImageInfo& info);
virtual SkData* onRefEncodedData();
@@ -148,8 +176,11 @@ protected:
virtual bool onGetYUV8Planes(SkISize sizes[3], void* planes[3], size_t rowBytes[3],
SkYUVColorSpace* colorSpace);
+ virtual GrTexture* onGenerateTexture(GrContext*, SkImageUsageType) { return nullptr; }
+
private:
const SkImageInfo fInfo;
+ const uint32_t fUniqueID;
// This is our default impl, which may be different on different platforms.
// It is called from NewFromEncoded() after it has checked for any runtime factory.
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index 459a0ee43e..7b48c3a430 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -16,6 +16,22 @@ class SkReadBuffer;
class SkWriteBuffer;
/**
+ * This enum provides information about "how" an image will be used. For older GPUs that do not
+ * support non-power-of-2 tiling, some routines need to know this information before they create
+ * a texture.
+ */
+enum SkImageUsageType {
+ /* Image will not be tiled (regardless of filtering) */
+ kUntiled_SkImageUsageType,
+
+ /* Image will be tiled, but not filtered */
+ kTiled_Unfiltered_SkImageUsageType,
+
+ /* Image will be tiled and filtered */
+ kTiled_Filtered_SkImageUsageType,
+};
+
+/**
* Describes how to interpret the alpha compoent of a pixel.
*/
enum SkAlphaType {
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index 0ed3099126..98153b7e08 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -381,6 +381,7 @@ private:
void setImmutableWithID(uint32_t genID);
friend class SkImage_Gpu;
+ friend class SkImageCacherator;
typedef SkRefCnt INHERITED;
};
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index e46479eb0f..db318b0b4c 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -72,6 +72,7 @@ static inline GrColor SkColor2GrColorJustAlpha(SkColor c) {
bool GrIsBitmapInCache(const GrContext*, const SkBitmap&, const GrTextureParams*);
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams*);
+GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, SkImageUsageType);
////////////////////////////////////////////////////////////////////////////////
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
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 53f640b601..6c1ec4bed0 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -143,7 +143,7 @@ static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretc
uint32_t width = SkToU16(stretch.fWidth);
uint32_t height = SkToU16(stretch.fHeight);
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 3);
+ GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2);
builder[0] = stretch.fType;
builder[1] = width | (height << 16);
builder.finish();
@@ -153,22 +153,55 @@ static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretc
return false;
}
-static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) {
- // Our id includes the offset, width, and height so that bitmaps created by extractSubset()
- // are unique.
- uint32_t genID = bitmap.getGenerationID();
- SkIPoint origin = bitmap.pixelRefOrigin();
- uint32_t width = SkToU16(bitmap.width());
- uint32_t height = SkToU16(bitmap.height());
+static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID,
+ U16CPU width, U16CPU height, SkIPoint origin) {
+ SkASSERT((uint16_t)width == width);
+ SkASSERT((uint16_t)height == height);
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey::Builder builder(key, kDomain, 4);
- builder[0] = genID;
+ builder[0] = imageID;
builder[1] = origin.fX;
builder[2] = origin.fY;
builder[3] = width | (height << 16);
}
+void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
+ U16CPU width, U16CPU height, SkIPoint origin,
+ const GrCaps& caps, SkImageUsageType usage) {
+ const Stretch::Type stretches[] = {
+ Stretch::kNone_Type, // kUntiled_SkImageUsageType
+ Stretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType
+ Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType
+ };
+
+ const bool isPow2 = SkIsPow2(width) && SkIsPow2(height);
+ const bool needToStretch = !isPow2 &&
+ usage != kUntiled_SkImageUsageType &&
+ !caps.npotTextureTileSupport();
+
+ if (needToStretch) {
+ GrUniqueKey tmpKey;
+ make_unstretched_key(&tmpKey, imageID, width, height, origin);
+
+ Stretch stretch;
+ stretch.fType = stretches[usage];
+ stretch.fWidth = SkNextPow2(width);
+ stretch.fHeight = SkNextPow2(height);
+ if (!make_stretched_key(tmpKey, stretch, key)) {
+ goto UNSTRETCHED;
+ }
+ } else {
+ UNSTRETCHED:
+ make_unstretched_key(key, imageID, width, height, origin);
+ }
+}
+
+static void make_unstretched_key(const SkBitmap& bitmap, GrUniqueKey* key) {
+ make_unstretched_key(key, bitmap.getGenerationID(), bitmap.width(), bitmap.height(),
+ bitmap.pixelRefOrigin());
+}
+
static void make_bitmap_keys(const SkBitmap& bitmap,
const Stretch& stretch,
GrUniqueKey* key,
@@ -649,6 +682,31 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
return NULL;
}
+
+// TODO: make this be the canonical signature, and turn the version that takes GrTextureParams*
+// into a wrapper that contains the inverse of these tables.
+GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
+ const SkBitmap& bitmap,
+ SkImageUsageType usage) {
+ // Just need a params that will trigger the correct cache key / etc, since the usage doesn't
+ // tell us the specifics about filter level or specific tiling.
+
+ const SkShader::TileMode tiles[] = {
+ SkShader::kClamp_TileMode, // kUntiled_SkImageUsageType
+ SkShader::kRepeat_TileMode, // kTiled_Unfiltered_SkImageUsageType
+ SkShader::kRepeat_TileMode, // kTiled_Filtered_SkImageUsageType
+ };
+
+ const GrTextureParams::FilterMode filters[] = {
+ GrTextureParams::kNone_FilterMode, // kUntiled_SkImageUsageType
+ GrTextureParams::kNone_FilterMode, // kTiled_Unfiltered_SkImageUsageType
+ GrTextureParams::kBilerp_FilterMode, // kTiled_Filtered_SkImageUsageType
+ };
+
+ GrTextureParams params(tiles[usage], filters[usage]);
+ return GrRefCachedBitmapTexture(ctx, bitmap, &params);
+}
+
///////////////////////////////////////////////////////////////////////////////
// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h
new file mode 100644
index 0000000000..4688adb045
--- /dev/null
+++ b/src/gpu/SkGrPriv.h
@@ -0,0 +1,32 @@
+/*
+ * 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 SkGrPriv_DEFINED
+#define SkGrPriv_DEFINED
+
+#include "GrTypes.h"
+#include "SkPoint.h"
+
+class GrCaps;
+class GrUniqueKey;
+
+/**
+ * Our key includes the offset, width, and height so that bitmaps created by extractSubset()
+ * are unique.
+ *
+ * The imageID is in the shared namespace (see SkNextID::ImageID()
+ * - SkBitmap/SkPixelRef
+ * - SkImage
+ * - SkImageGenerator
+ *
+ * Note: width/height must fit in 16bits for this impl.
+ */
+void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID,
+ U16CPU width, U16CPU height, SkIPoint origin,
+ const GrCaps&, SkImageUsageType);
+
+#endif