| Index: src/gpu/SkGr.cpp
|
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
|
| index e0892d8ab974e88db4034b429cba09727ab8cb93..6ef3d953d97715d3cb6fd60d12eafa0f82af0db1 100644
|
| --- a/src/gpu/SkGr.cpp
|
| +++ b/src/gpu/SkGr.cpp
|
| @@ -5,6 +5,8 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| +#include "GrTextureMaker.h"
|
| +
|
| #include "SkGr.h"
|
|
|
| #include "GrCaps.h"
|
| @@ -94,19 +96,9 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| -struct Stretch {
|
| - enum Type {
|
| - kNone_Type,
|
| - kBilerp_Type,
|
| - kNearest_Type
|
| - } fType;
|
| - int fWidth;
|
| - int fHeight;
|
| -};
|
| -
|
| static void get_stretch(const GrContext* ctx, int width, int height,
|
| - const GrTextureParams* params, Stretch* stretch) {
|
| - stretch->fType = Stretch::kNone_Type;
|
| + const GrTextureParams* params, SkGrStretch* stretch) {
|
| + stretch->fType = SkGrStretch::kNone_Type;
|
| bool doStretch = false;
|
| if (params && params->isTiled() && !ctx->caps()->npotTextureTileSupport() &&
|
| (!SkIsPow2(width) || !SkIsPow2(height))) {
|
| @@ -124,26 +116,26 @@ static void get_stretch(const GrContext* ctx, int width, int height,
|
| if (params) {
|
| switch(params->filterMode()) {
|
| case GrTextureParams::kNone_FilterMode:
|
| - stretch->fType = Stretch::kNearest_Type;
|
| + stretch->fType = SkGrStretch::kNearest_Type;
|
| break;
|
| case GrTextureParams::kBilerp_FilterMode:
|
| case GrTextureParams::kMipMap_FilterMode:
|
| - stretch->fType = Stretch::kBilerp_Type;
|
| + stretch->fType = SkGrStretch::kBilerp_Type;
|
| break;
|
| }
|
| } else {
|
| - stretch->fType = Stretch::kBilerp_Type;
|
| + stretch->fType = SkGrStretch::kBilerp_Type;
|
| }
|
| } else {
|
| stretch->fWidth = -1;
|
| stretch->fHeight = -1;
|
| - stretch->fType = Stretch::kNone_Type;
|
| + stretch->fType = SkGrStretch::kNone_Type;
|
| }
|
| }
|
|
|
| -static bool make_stretched_key(const GrUniqueKey& origKey, const Stretch& stretch,
|
| +static bool make_stretched_key(const GrUniqueKey& origKey, const SkGrStretch& stretch,
|
| GrUniqueKey* stretchedKey) {
|
| - if (origKey.isValid() && Stretch::kNone_Type != stretch.fType) {
|
| + if (origKey.isValid() && SkGrStretch::kNone_Type != stretch.fType) {
|
| uint32_t width = SkToU16(stretch.fWidth);
|
| uint32_t height = SkToU16(stretch.fHeight);
|
| static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
|
| @@ -171,10 +163,10 @@ static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRe
|
|
|
| void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset,
|
| 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 SkGrStretch::Type stretches[] = {
|
| + SkGrStretch::kNone_Type, // kUntiled_SkImageUsageType
|
| + SkGrStretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType
|
| + SkGrStretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType
|
| };
|
|
|
| const bool isPow2 = SkIsPow2(subset.width()) && SkIsPow2(subset.height());
|
| @@ -186,7 +178,7 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
|
| GrUniqueKey tmpKey;
|
| make_unstretched_key(&tmpKey, imageID, subset);
|
|
|
| - Stretch stretch;
|
| + SkGrStretch stretch;
|
| stretch.fType = stretches[usage];
|
| stretch.fWidth = SkNextPow2(subset.width());
|
| stretch.fHeight = SkNextPow2(subset.height());
|
| @@ -199,10 +191,10 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& sub
|
| }
|
| }
|
|
|
| -static void make_image_keys(uint32_t imageID, const SkIRect& subset, const Stretch& stretch,
|
| +static void make_image_keys(uint32_t imageID, const SkIRect& subset, const SkGrStretch& stretch,
|
| GrUniqueKey* key, GrUniqueKey* stretchedKey) {
|
| make_unstretched_key(key, imageID, subset);
|
| - if (Stretch::kNone_Type != stretch.fType) {
|
| + if (SkGrStretch::kNone_Type != stretch.fType) {
|
| make_stretched_key(*key, stretch, stretchedKey);
|
| }
|
| }
|
| @@ -254,10 +246,10 @@ GrTexture* GrCreateTextureForPixels(GrContext* ctx,
|
| // creates a new texture that is the input texture scaled up. If optionalKey is valid it will be
|
| // set on the new texture. stretch controls whether the scaling is done using nearest or bilerp
|
| // filtering and the size to stretch the texture to.
|
| -GrTexture* stretch_texture(GrTexture* inputTexture, const Stretch& stretch,
|
| +GrTexture* stretch_texture(GrTexture* inputTexture, const SkGrStretch& stretch,
|
| SkPixelRef* pixelRef,
|
| const GrUniqueKey& optionalKey) {
|
| - SkASSERT(Stretch::kNone_Type != stretch.fType);
|
| + SkASSERT(SkGrStretch::kNone_Type != stretch.fType);
|
|
|
| GrContext* context = inputTexture->getContext();
|
| SkASSERT(context);
|
| @@ -303,7 +295,7 @@ GrTexture* stretch_texture(GrTexture* inputTexture, const Stretch& stretch,
|
| // If filtering is not desired then we want to ensure all texels in the resampled image are
|
| // copies of texels from the original.
|
| GrTextureParams params(SkShader::kClamp_TileMode,
|
| - Stretch::kBilerp_Type == stretch.fType ?
|
| + SkGrStretch::kBilerp_Type == stretch.fType ?
|
| GrTextureParams::kBilerp_FilterMode :
|
| GrTextureParams::kNone_FilterMode);
|
| paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
|
| @@ -482,19 +474,19 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
|
| bitmap->getPixels(), bitmap->rowBytes());
|
| }
|
|
|
| -static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const Stretch& stretch) {
|
| +static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const SkGrStretch& stretch) {
|
| SkBitmap stretched;
|
| stretched.allocN32Pixels(stretch.fWidth, stretch.fHeight);
|
| SkCanvas canvas(stretched);
|
| SkPaint paint;
|
| switch (stretch.fType) {
|
| - case Stretch::kNearest_Type:
|
| + case SkGrStretch::kNearest_Type:
|
| paint.setFilterQuality(kNone_SkFilterQuality);
|
| break;
|
| - case Stretch::kBilerp_Type:
|
| + case SkGrStretch::kBilerp_Type:
|
| paint.setFilterQuality(kLow_SkFilterQuality);
|
| break;
|
| - case Stretch::kNone_Type:
|
| + case SkGrStretch::kNone_Type:
|
| SkDEBUGFAIL("Shouldn't get here.");
|
| break;
|
| }
|
| @@ -503,39 +495,14 @@ static SkBitmap stretch_on_cpu(const SkBitmap& bmp, const Stretch& stretch) {
|
| return stretched;
|
| }
|
|
|
| -static GrTexture* create_bitmap_texture(GrContext* ctx,
|
| - const SkBitmap& bmp,
|
| - const Stretch& stretch,
|
| - const GrUniqueKey& unstretchedKey,
|
| - const GrUniqueKey& stretchedKey) {
|
| - if (Stretch::kNone_Type != stretch.fType) {
|
| - SkAutoTUnref<GrTexture> unstretched;
|
| - // Check if we have the unstretched version in the cache, if not create it.
|
| - if (unstretchedKey.isValid()) {
|
| - unstretched.reset(ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey));
|
| - }
|
| - if (!unstretched) {
|
| - unstretched.reset(create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey));
|
| - if (!unstretched) {
|
| - // We might not have been able to create a unstrecthed texture because it is smaller
|
| - // than the min texture size. In that case do cpu stretching.
|
| - SkBitmap stretchedBmp = stretch_on_cpu(bmp, stretch);
|
| - return create_unstretched_bitmap_texture(ctx, stretchedBmp, stretchedKey);
|
| - }
|
| - }
|
| - return stretch_texture(unstretched, stretch, bmp.pixelRef(), stretchedKey);
|
| - }
|
| - return create_unstretched_bitmap_texture(ctx, bmp, unstretchedKey);
|
| -}
|
| -
|
| bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& subset,
|
| GrTexture* nativeTexture, const GrTextureParams* params) {
|
| - Stretch stretch;
|
| + SkGrStretch stretch;
|
| get_stretch(ctx, subset.width(), subset.height(), params, &stretch);
|
|
|
| // Handle the case where the bitmap/image is explicitly texture backed.
|
| if (nativeTexture) {
|
| - if (Stretch::kNone_Type == stretch.fType) {
|
| + if (SkGrStretch::kNone_Type == stretch.fType) {
|
| return true;
|
| }
|
| const GrUniqueKey& key = nativeTexture->getUniqueKey();
|
| @@ -550,7 +517,7 @@ bool GrIsImageInCache(const GrContext* ctx, uint32_t imageID, const SkIRect& sub
|
| GrUniqueKey key, stretchedKey;
|
| make_image_keys(imageID, subset, stretch, &key, &stretchedKey);
|
| return ctx->textureProvider()->existsTextureWithUniqueKey(
|
| - (Stretch::kNone_Type == stretch.fType) ? key : stretchedKey);
|
| + (SkGrStretch::kNone_Type == stretch.fType) ? key : stretchedKey);
|
| }
|
|
|
| bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap,
|
| @@ -562,57 +529,58 @@ bool GrIsBitmapInCache(const GrContext* ctx, const SkBitmap& bitmap,
|
| params);
|
| }
|
|
|
| -GrTexture* GrRefCachedBitmapTexture(GrContext* ctx,
|
| - const SkBitmap& bitmap,
|
| - const GrTextureParams* params) {
|
| +class Bitmap_GrTextureMaker : public GrTextureMaker {
|
| +public:
|
| + Bitmap_GrTextureMaker(const SkBitmap& bitmap)
|
| + : INHERITED(bitmap.width(), bitmap.height())
|
| + , fBitmap(bitmap)
|
| + {}
|
| +
|
| +protected:
|
| + GrTexture* onRefUnstretchedTexture(GrContext* ctx) override {
|
| + GrTexture* tex = fBitmap.getTexture();
|
| + if (tex) {
|
| + return SkRef(tex);
|
| + }
|
|
|
| - Stretch stretch;
|
| - get_stretch(ctx, bitmap.width(), bitmap.height(), params, &stretch);
|
| + GrUniqueKey unstretchedKey;
|
| + make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
|
|
|
| - GrTexture* result = bitmap.getTexture();
|
| - if (result) {
|
| - if (Stretch::kNone_Type == stretch.fType) {
|
| - return SkRef(result);
|
| - }
|
| - GrUniqueKey stretchedKey;
|
| - // Don't create a key for the resized version if the bmp is volatile.
|
| - if (!bitmap.isVolatile()) {
|
| - const GrUniqueKey& key = result->getUniqueKey();
|
| - if (key.isValid()) {
|
| - make_stretched_key(key, stretch, &stretchedKey);
|
| - GrTexture* stretched =
|
| - ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
|
| - if (stretched) {
|
| - return stretched;
|
| - }
|
| - }
|
| + GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey);
|
| + if (result) {
|
| + return result;
|
| }
|
| - return stretch_texture(result, stretch, bitmap.pixelRef(), stretchedKey);
|
| + return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey);
|
| }
|
|
|
| - GrUniqueKey key, resizedKey;
|
| + bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override {
|
| + if (fBitmap.isVolatile()) {
|
| + return false;
|
| + }
|
|
|
| - if (!bitmap.isVolatile()) {
|
| - // If the bitmap isn't changing try to find a cached copy first.
|
| - make_image_keys(bitmap.getGenerationID(), bitmap.getSubset(), stretch, &key, &resizedKey);
|
| + GrUniqueKey unstretchedKey;
|
| + make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
|
| + return make_stretched_key(unstretchedKey, stretch, stretchedKey);
|
| + }
|
|
|
| - result = ctx->textureProvider()->findAndRefTextureByUniqueKey(
|
| - resizedKey.isValid() ? resizedKey : key);
|
| - if (result) {
|
| - return result;
|
| - }
|
| + void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override {
|
| + fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretchedKey));
|
| }
|
|
|
| - result = create_bitmap_texture(ctx, bitmap, stretch, key, resizedKey);
|
| - if (result) {
|
| - return result;
|
| + bool onGetROBitmap(SkBitmap* bitmap) override {
|
| + *bitmap = fBitmap;
|
| + return true;
|
| }
|
|
|
| - SkErrorInternals::SetError( kInternalError_SkError,
|
| - "---- failed to create texture for cache [%d %d]\n",
|
| - bitmap.width(), bitmap.height());
|
| +private:
|
| + const SkBitmap fBitmap;
|
| +
|
| + typedef GrTextureMaker INHERITED;
|
| +};
|
|
|
| - return nullptr;
|
| +GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
|
| + const GrTextureParams* params) {
|
| + return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params);
|
| }
|
|
|
| // TODO: make this be the canonical signature, and turn the version that takes GrTextureParams*
|
| @@ -948,3 +916,54 @@ GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality pain
|
| }
|
| return textureFilterMode;
|
| }
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams* params) {
|
| + SkGrStretch stretch;
|
| + get_stretch(ctx, this->width(), this->height(), params, &stretch);
|
| +
|
| + if (SkGrStretch::kNone_Type == stretch.fType) {
|
| + return this->onRefUnstretchedTexture(ctx);
|
| + }
|
| +
|
| + GrUniqueKey stretchedKey;
|
| + if (this->onMakeStretchedKey(stretch, &stretchedKey)) {
|
| + GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(stretchedKey);
|
| + if (result) {
|
| + return result;
|
| + }
|
| + }
|
| +
|
| + GrTexture* result = this->onGenerateStretchedTexture(ctx, stretch);
|
| + if (!result) {
|
| + return nullptr;
|
| + }
|
| +
|
| + if (stretchedKey.isValid()) {
|
| + ctx->textureProvider()->assignUniqueKeyToTexture(stretchedKey, result);
|
| + this->onNotifyStretchCached(stretchedKey);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +GrTexture* GrTextureMaker::onGenerateStretchedTexture(GrContext* ctx, const SkGrStretch& stretch) {
|
| + if (this->width() < ctx->caps()->minTextureSize() ||
|
| + this->height() < ctx->caps()->minTextureSize())
|
| + {
|
| + // we can't trust our ability to use HW to perform the stretch, so we request
|
| + // a raster instead, and perform the stretch on the CPU.
|
| + SkBitmap bitmap;
|
| + if (!this->onGetROBitmap(&bitmap)) {
|
| + return nullptr;
|
| + }
|
| + SkBitmap stretchedBmp = stretch_on_cpu(bitmap, stretch);
|
| + return create_unstretched_bitmap_texture(ctx, stretchedBmp, GrUniqueKey());
|
| + } else {
|
| + SkAutoTUnref<GrTexture> unstretched(this->onRefUnstretchedTexture(ctx));
|
| + if (!unstretched) {
|
| + return nullptr;
|
| + }
|
| + return stretch_texture(unstretched, stretch, nullptr, GrUniqueKey());
|
| + }
|
| +}
|
|
|