| Index: src/gpu/SkGr.cpp
 | 
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
 | 
| index d8444968da6ea2e788b16900fc80af3e314a1243..3c3f3e8fab99e9836564c571d912003901991c2e 100644
 | 
| --- a/src/gpu/SkGr.cpp
 | 
| +++ b/src/gpu/SkGr.cpp
 | 
| @@ -5,13 +5,13 @@
 | 
|   * found in the LICENSE file.
 | 
|   */
 | 
|  
 | 
| -#include "GrTextureMaker.h"
 | 
|  
 | 
|  #include "SkGr.h"
 | 
|  
 | 
|  #include "GrCaps.h"
 | 
|  #include "GrContext.h"
 | 
| -#include "GrDrawContext.h"
 | 
| +#include "GrTextureParamsAdjuster.h"
 | 
| +#include "GrGpuResourcePriv.h"
 | 
|  #include "GrXferProcessor.h"
 | 
|  #include "GrYUVProvider.h"
 | 
|  
 | 
| @@ -48,64 +48,17 @@ GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) {
 | 
|      return desc;
 | 
|  }
 | 
|  
 | 
| -static void get_stretch(const GrCaps& caps, int width, int height,
 | 
| -                        const GrTextureParams& params, SkGrStretch* stretch) {
 | 
| -    stretch->fType = SkGrStretch::kNone_Type;
 | 
| -    bool doStretch = false;
 | 
| -    if (params.isTiled() && !caps.npotTextureTileSupport() &&
 | 
| -        (!SkIsPow2(width) || !SkIsPow2(height))) {
 | 
| -        doStretch = true;
 | 
| -        stretch->fWidth = GrNextPow2(SkTMax(width, caps.minTextureSize()));
 | 
| -        stretch->fHeight = GrNextPow2(SkTMax(height, caps.minTextureSize()));
 | 
| -    } else if (width < caps.minTextureSize() || height < caps.minTextureSize()) {
 | 
| -        // The small texture issues appear to be with tiling. Hence it seems ok to scale them
 | 
| -        // up using the GPU. If issues persist we may need to CPU-stretch.
 | 
| -        doStretch = true;
 | 
| -        stretch->fWidth = SkTMax(width, caps.minTextureSize());
 | 
| -        stretch->fHeight = SkTMax(height, caps.minTextureSize());
 | 
| -    }
 | 
| -    if (doStretch) {
 | 
| -        switch (params.filterMode()) {
 | 
| -            case GrTextureParams::kNone_FilterMode:
 | 
| -                stretch->fType = SkGrStretch::kNearest_Type;
 | 
| -                break;
 | 
| -            case GrTextureParams::kBilerp_FilterMode:
 | 
| -            case GrTextureParams::kMipMap_FilterMode:
 | 
| -                stretch->fType = SkGrStretch::kBilerp_Type;
 | 
| -                break;
 | 
| -        }
 | 
| -    } else {
 | 
| -        stretch->fWidth = -1;
 | 
| -        stretch->fHeight = -1;
 | 
| -        stretch->fType = SkGrStretch::kNone_Type;
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -static void make_unstretched_key(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset) {
 | 
| -    SkASSERT(SkIsU16(subset.width()));
 | 
| -    SkASSERT(SkIsU16(subset.height()));
 | 
| -
 | 
| -    static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
 | 
| -    GrUniqueKey::Builder builder(key, kDomain, 4);
 | 
| +void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& imageBounds) {
 | 
| +    SkASSERT(key);
 | 
| +    SkASSERT(imageID);
 | 
| +    SkASSERT(!imageBounds.isEmpty());
 | 
| +    static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
 | 
| +    GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
 | 
|      builder[0] = imageID;
 | 
| -    builder[1] = subset.x();
 | 
| -    builder[2] = subset.y();
 | 
| -    builder[3] = subset.width() | (subset.height() << 16);
 | 
| -}
 | 
| -
 | 
| -void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset,
 | 
| -                          const GrCaps& caps, const GrTextureParams& params) {
 | 
| -    SkGrStretch stretch;
 | 
| -    get_stretch(caps, subset.width(), subset.height(), params, &stretch);
 | 
| -    if (SkGrStretch::kNone_Type != stretch.fType) {
 | 
| -        GrUniqueKey tmpKey;
 | 
| -        make_unstretched_key(&tmpKey, imageID, subset);
 | 
| -        if (!GrMakeStretchedKey(tmpKey, stretch, key)) {
 | 
| -            *key = tmpKey;
 | 
| -        }
 | 
| -    } else {
 | 
| -        make_unstretched_key(key, imageID, subset);
 | 
| -    }
 | 
| +    builder[1] = imageBounds.fLeft;
 | 
| +    builder[2] = imageBounds.fTop;
 | 
| +    builder[3] = imageBounds.fRight;
 | 
| +    builder[4] = imageBounds.fBottom;
 | 
|  }
 | 
|  
 | 
|  GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
 | 
| @@ -150,16 +103,19 @@ GrPixelConfig GrIsCompressedTextureDataSupported(GrContext* ctx, SkData* data,
 | 
|      return kUnknown_GrPixelConfig;
 | 
|  }
 | 
|  
 | 
| -/*  Fill out buffer with the compressed format Ganesh expects from a colortable
 | 
| - based bitmap. [palette (colortable) + indices].
 | 
| -
 | 
| - At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
 | 
| - we could detect that the colortable.count is <= 16, and then repack the
 | 
| - indices as nibbles to save RAM, but it would take more time (i.e. a lot
 | 
| - slower than memcpy), so skipping that for now.
 | 
| +//////////////////////////////////////////////////////////////////////////////
 | 
|  
 | 
| - Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
 | 
| - as the colortable.count says it is.
 | 
| +/**
 | 
| + * Fill out buffer with the compressed format Ganesh expects from a colortable
 | 
| + * based bitmap. [palette (colortable) + indices].
 | 
| + *
 | 
| + * At the moment Ganesh only supports 8bit version. If Ganesh allowed we others
 | 
| + * we could detect that the colortable.count is <= 16, and then repack the
 | 
| + * indices as nibbles to save RAM, but it would take more time (i.e. a lot
 | 
| + * slower than memcpy), so skipping that for now.
 | 
| + *
 | 
| + * Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big
 | 
| + * as the colortable.count says it is.
 | 
|   */
 | 
|  static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
 | 
|      SkASSERT(kIndex_8_SkColorType == bitmap.colorType());
 | 
| @@ -207,130 +163,7 @@ static void build_index8_data(void* buffer, const SkBitmap& bitmap) {
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -////////////////////////////////////////////////////////////////////////////////
 | 
| -
 | 
| -
 | 
| -bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch& stretch,
 | 
| -                        GrUniqueKey* stretchedKey) {
 | 
| -    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();
 | 
| -        GrUniqueKey::Builder builder(stretchedKey, origKey, kDomain, 2);
 | 
| -        builder[0] = stretch.fType;
 | 
| -        builder[1] = width | (height << 16);
 | 
| -        builder.finish();
 | 
| -        return true;
 | 
| -    }
 | 
| -    SkASSERT(!stretchedKey->isValid());
 | 
| -    return false;
 | 
| -}
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -// When the SkPixelRef genID changes, invalidate a corresponding GrResource described by key.
 | 
| -class BitmapInvalidator : public SkPixelRef::GenIDChangeListener {
 | 
| -public:
 | 
| -    explicit BitmapInvalidator(const GrUniqueKey& key) : fMsg(key) {}
 | 
| -private:
 | 
| -    GrUniqueKeyInvalidatedMessage fMsg;
 | 
| -
 | 
| -    void onChange() override {
 | 
| -        SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
 | 
| -    }
 | 
| -};
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -
 | 
| -GrTexture* GrCreateTextureForPixels(GrContext* ctx,
 | 
| -                                    const GrUniqueKey& optionalKey,
 | 
| -                                    GrSurfaceDesc desc,
 | 
| -                                    SkPixelRef* pixelRefForInvalidationNotification,
 | 
| -                                    const void* pixels,
 | 
| -                                    size_t rowBytes) {
 | 
| -    GrTexture* result = ctx->textureProvider()->createTexture(desc, true, pixels, rowBytes);
 | 
| -    if (result && optionalKey.isValid()) {
 | 
| -        if (pixelRefForInvalidationNotification) {
 | 
| -            BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
 | 
| -            pixelRefForInvalidationNotification->addGenIDChangeListener(listener);
 | 
| -        }
 | 
| -        ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, result);
 | 
| -    }
 | 
| -    return result;
 | 
| -}
 | 
| -
 | 
| -// 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 SkGrStretch& stretch,
 | 
| -                           SkPixelRef* pixelRef,
 | 
| -                           const GrUniqueKey& optionalKey) {
 | 
| -    SkASSERT(SkGrStretch::kNone_Type != stretch.fType);
 | 
| -
 | 
| -    GrContext* context = inputTexture->getContext();
 | 
| -    SkASSERT(context);
 | 
| -    const GrCaps* caps = context->caps();
 | 
| -
 | 
| -    // Either it's a cache miss or the original wasn't cached to begin with.
 | 
| -    GrSurfaceDesc rtDesc = inputTexture->desc();
 | 
| -    rtDesc.fFlags =  rtDesc.fFlags | kRenderTarget_GrSurfaceFlag;
 | 
| -    rtDesc.fWidth  = stretch.fWidth;
 | 
| -    rtDesc.fHeight = stretch.fHeight;
 | 
| -    rtDesc.fConfig = GrMakePixelConfigUncompressed(rtDesc.fConfig);
 | 
| -
 | 
| -    // If the config isn't renderable try converting to either A8 or an 32 bit config. Otherwise,
 | 
| -    // fail.
 | 
| -    if (!caps->isConfigRenderable(rtDesc.fConfig, false)) {
 | 
| -        if (GrPixelConfigIsAlphaOnly(rtDesc.fConfig)) {
 | 
| -            if (caps->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
 | 
| -                rtDesc.fConfig = kAlpha_8_GrPixelConfig;
 | 
| -            } else if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
 | 
| -                rtDesc.fConfig = kSkia8888_GrPixelConfig;
 | 
| -            } else {
 | 
| -                return nullptr;
 | 
| -            }
 | 
| -        } else if (kRGB_GrColorComponentFlags ==
 | 
| -                   (kRGB_GrColorComponentFlags & GrPixelConfigComponentMask(rtDesc.fConfig))) {
 | 
| -            if (caps->isConfigRenderable(kSkia8888_GrPixelConfig, false)) {
 | 
| -                rtDesc.fConfig = kSkia8888_GrPixelConfig;
 | 
| -            } else {
 | 
| -                return nullptr;
 | 
| -            }
 | 
| -        } else {
 | 
| -            return nullptr;
 | 
| -        }
 | 
| -    }
 | 
| -
 | 
| -    SkAutoTUnref<GrTexture> stretched(GrCreateTextureForPixels(context, optionalKey, rtDesc,
 | 
| -                                                               pixelRef, nullptr,0));
 | 
| -    if (!stretched) {
 | 
| -        return nullptr;
 | 
| -    }
 | 
| -    GrPaint paint;
 | 
| -
 | 
| -    // 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,
 | 
| -                           SkGrStretch::kBilerp_Type == stretch.fType ?
 | 
| -                              GrTextureParams::kBilerp_FilterMode :
 | 
| -                              GrTextureParams::kNone_FilterMode);
 | 
| -    paint.addColorTextureProcessor(inputTexture, SkMatrix::I(), params);
 | 
| -
 | 
| -    SkRect rect = SkRect::MakeWH(SkIntToScalar(rtDesc.fWidth), SkIntToScalar(rtDesc.fHeight));
 | 
| -    SkRect localRect = SkRect::MakeWH(1.f, 1.f);
 | 
| -
 | 
| -    SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(stretched->asRenderTarget()));
 | 
| -    if (!drawContext) {
 | 
| -        return nullptr;
 | 
| -    }
 | 
| -
 | 
| -    drawContext->drawNonAARectToRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, localRect);
 | 
| -
 | 
| -    return stretched.detach();
 | 
| -}
 | 
| -
 | 
| -/*
 | 
| +/**
 | 
|   *  Once we have made SkImages handle all lazy/deferred/generated content, the YUV apis will
 | 
|   *  be gone from SkPixelRef, and we can remove this subclass entirely.
 | 
|   */
 | 
| @@ -350,33 +183,22 @@ public:
 | 
|      }
 | 
|  };
 | 
|  
 | 
| -static GrTexture* load_yuv_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
 | 
| -                                   const SkBitmap& bm, const GrSurfaceDesc& desc) {
 | 
| +static GrTexture* create_texture_from_yuv(GrContext* ctx, const SkBitmap& bm,
 | 
| +                                          const GrSurfaceDesc& desc) {
 | 
|      // Subsets are not supported, the whole pixelRef is loaded when using YUV decoding
 | 
|      SkPixelRef* pixelRef = bm.pixelRef();
 | 
|      if ((nullptr == pixelRef) ||
 | 
| -        (pixelRef->info().width()  != bm.info().width()) ||
 | 
| +        (pixelRef->info().width() != bm.info().width()) ||
 | 
|          (pixelRef->info().height() != bm.info().height())) {
 | 
|          return nullptr;
 | 
|      }
 | 
|  
 | 
| -    const bool useCache = optionalKey.isValid();
 | 
|      PixelRef_GrYUVProvider provider(pixelRef);
 | 
| -    GrTexture* texture = provider.refAsTexture(ctx, desc, useCache);
 | 
| -    if (!texture) {
 | 
| -        return nullptr;
 | 
| -    }
 | 
|  
 | 
| -    if (useCache) {
 | 
| -        BitmapInvalidator* listener = new BitmapInvalidator(optionalKey);
 | 
| -        pixelRef->addGenIDChangeListener(listener);
 | 
| -        ctx->textureProvider()->assignUniqueKeyToTexture(optionalKey, texture);
 | 
| -    }
 | 
| -    return texture;
 | 
| +    return provider.refAsTexture(ctx, desc, !bm.isVolatile());
 | 
|  }
 | 
|  
 | 
| -static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalKey,
 | 
| -                                    const SkBitmap &bm, GrSurfaceDesc desc) {
 | 
| +static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfaceDesc desc) {
 | 
|      SkAutoTUnref<SkData> data(bm.pixelRef()->refEncodedData());
 | 
|      if (!data) {
 | 
|          return nullptr;
 | 
| @@ -389,19 +211,19 @@ static GrTexture* load_etc1_texture(GrContext* ctx, const GrUniqueKey& optionalK
 | 
|          return nullptr;
 | 
|      }
 | 
|  
 | 
| -    return GrCreateTextureForPixels(ctx, optionalKey, desc, bm.pixelRef(), startOfTexData, 0);
 | 
| +    return ctx->textureProvider()->createTexture(desc, true, startOfTexData, 0);
 | 
|  }
 | 
|  
 | 
| -static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
 | 
| -                                                    const SkBitmap& origBitmap,
 | 
| -                                                    const GrUniqueKey& optionalKey) {
 | 
| -    if (origBitmap.width() < ctx->caps()->minTextureSize() ||
 | 
| -        origBitmap.height() < ctx->caps()->minTextureSize()) {
 | 
| +GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bmp) {
 | 
| +    SkASSERT(!bmp.getTexture());
 | 
| +
 | 
| +    if (bmp.width() < ctx->caps()->minTextureSize() ||
 | 
| +        bmp.height() < ctx->caps()->minTextureSize()) {
 | 
|          return nullptr;
 | 
|      }
 | 
| -    SkBitmap tmpBitmap;
 | 
|  
 | 
| -    const SkBitmap* bitmap = &origBitmap;
 | 
| +    SkBitmap tmpBitmap;
 | 
| +    const SkBitmap* bitmap = &bmp;
 | 
|  
 | 
|      GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap->info());
 | 
|      const GrCaps* caps = ctx->caps();
 | 
| @@ -411,14 +233,14 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
 | 
|              size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
 | 
|                                                            bitmap->width(), bitmap->height());
 | 
|              SkAutoMalloc storage(imageSize);
 | 
| -            build_index8_data(storage.get(), origBitmap);
 | 
| +            build_index8_data(storage.get(), bmp);
 | 
|  
 | 
|              // our compressed data will be trimmed, so pass width() for its
 | 
|              // "rowBytes", since they are the same now.
 | 
| -            return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
 | 
| -                                            storage.get(), bitmap->width());
 | 
| +            return ctx->textureProvider()->createTexture(desc, true, storage.get(),
 | 
| +                                                         bitmap->width());
 | 
|          } else {
 | 
| -            origBitmap.copyTo(&tmpBitmap, kN32_SkColorType);
 | 
| +            bmp.copyTo(&tmpBitmap, kN32_SkColorType);
 | 
|              // now bitmap points to our temp, which has been promoted to 32bits
 | 
|              bitmap = &tmpBitmap;
 | 
|              desc.fConfig = SkImageInfo2GrPixelConfig(bitmap->info());
 | 
| @@ -428,13 +250,16 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
 | 
|          // compressed data on 'refEncodedData' and upload it. Probably not good, since if
 | 
|          // the bitmap has available pixels, then they might not be what the decompressed
 | 
|          // data is.
 | 
| -        GrTexture *texture = load_etc1_texture(ctx, optionalKey, *bitmap, desc);
 | 
| +
 | 
| +        // Really?? We aren't doing this with YUV.
 | 
| +
 | 
| +        GrTexture *texture = load_etc1_texture(ctx, *bitmap, desc);
 | 
|          if (texture) {
 | 
|              return texture;
 | 
|          }
 | 
|      }
 | 
|  
 | 
| -    GrTexture *texture = load_yuv_texture(ctx, optionalKey, *bitmap, desc);
 | 
| +    GrTexture *texture = create_texture_from_yuv(ctx, *bitmap, desc);
 | 
|      if (texture) {
 | 
|          return texture;
 | 
|      }
 | 
| @@ -444,83 +269,92 @@ static GrTexture* create_unstretched_bitmap_texture(GrContext* ctx,
 | 
|          return nullptr;
 | 
|      }
 | 
|  
 | 
| -    return GrCreateTextureForPixels(ctx, optionalKey, desc, origBitmap.pixelRef(),
 | 
| -                                    bitmap->getPixels(), bitmap->rowBytes());
 | 
| +    return ctx->textureProvider()->createTexture(desc, true, bitmap->getPixels(),
 | 
| +                                                 bitmap->rowBytes());
 | 
|  }
 | 
|  
 | 
| -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 SkGrStretch::kNearest_Type:
 | 
| -            paint.setFilterQuality(kNone_SkFilterQuality);
 | 
| -            break;
 | 
| -        case SkGrStretch::kBilerp_Type:
 | 
| -            paint.setFilterQuality(kLow_SkFilterQuality);
 | 
| -            break;
 | 
| -        case SkGrStretch::kNone_Type:
 | 
| -            SkDEBUGFAIL("Shouldn't get here.");
 | 
| -            break;
 | 
| -    }
 | 
| -    SkRect dstRect = SkRect::MakeWH(SkIntToScalar(stretch.fWidth), SkIntToScalar(stretch.fHeight));
 | 
| -    canvas.drawBitmapRect(bmp, dstRect, &paint);
 | 
| -    return stretched;
 | 
| -}
 | 
|  
 | 
| -class Bitmap_GrTextureMaker : public GrTextureMaker {
 | 
| +////////////////////////////////////////////////////////////////////////////////
 | 
| +
 | 
| +class Bitmap_GrTextureParamsAdjuster : public GrTextureParamsAdjuster {
 | 
|  public:
 | 
| -    Bitmap_GrTextureMaker(const SkBitmap& bitmap)
 | 
| +    Bitmap_GrTextureParamsAdjuster(const SkBitmap& bitmap)
 | 
|          : INHERITED(bitmap.width(), bitmap.height())
 | 
|          , fBitmap(bitmap)
 | 
| -    {}
 | 
| +    {
 | 
| +        if (!bitmap.isVolatile()) {
 | 
| +            SkIPoint origin = bitmap.pixelRefOrigin();
 | 
| +            SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, bitmap.width(),
 | 
| +                                               bitmap.height());
 | 
| +            GrMakeKeyFromImageID(&fOriginalKey, bitmap.pixelRef()->getGenerationID(), subset);
 | 
| +        }
 | 
| +    }
 | 
|  
 | 
|  protected:
 | 
| -    GrTexture* onRefUnstretchedTexture(GrContext* ctx) override {
 | 
| +    GrTexture* peekOriginalTexture() override { return fBitmap.getTexture();  }
 | 
| +
 | 
| +    GrTexture* refOriginalTexture(GrContext* ctx) override {
 | 
|          GrTexture* tex = fBitmap.getTexture();
 | 
|          if (tex) {
 | 
|              return SkRef(tex);
 | 
|          }
 | 
|  
 | 
| -        GrUniqueKey unstretchedKey;
 | 
| -        make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
 | 
| +        if (fOriginalKey.isValid()) {
 | 
| +            tex = ctx->textureProvider()->findAndRefTextureByUniqueKey(fOriginalKey);
 | 
| +            if (tex) {
 | 
| +                return tex;
 | 
| +            }
 | 
| +        }
 | 
|  
 | 
| -        GrTexture* result = ctx->textureProvider()->findAndRefTextureByUniqueKey(unstretchedKey);
 | 
| -        if (result) {
 | 
| -            return result;
 | 
| +        tex = GrUploadBitmapToTexture(ctx, fBitmap);
 | 
| +        if (tex && fOriginalKey.isValid()) {
 | 
| +            tex->resourcePriv().setUniqueKey(fOriginalKey);
 | 
| +            InstallInvalidator(fOriginalKey, fBitmap.pixelRef());
 | 
|          }
 | 
| -        return create_unstretched_bitmap_texture(ctx, fBitmap, unstretchedKey);
 | 
| +        return tex;
 | 
|      }
 | 
|  
 | 
| -    bool onMakeStretchedKey(const SkGrStretch& stretch, GrUniqueKey* stretchedKey) override {
 | 
| -        if (fBitmap.isVolatile()) {
 | 
| -            return false;
 | 
| +    void makeCopyKey(const CopyParams& copyParams, GrUniqueKey* copyKey) override {
 | 
| +        if (fOriginalKey.isValid()) {
 | 
| +            MakeCopyKeyFromOrigKey(fOriginalKey, copyParams, copyKey);
 | 
|          }
 | 
| -
 | 
| -        GrUniqueKey unstretchedKey;
 | 
| -        make_unstretched_key(&unstretchedKey, fBitmap.getGenerationID(), fBitmap.getSubset());
 | 
| -        return GrMakeStretchedKey(unstretchedKey, stretch, stretchedKey);
 | 
|      }
 | 
|  
 | 
| -    void onNotifyStretchCached(const GrUniqueKey& stretchedKey) override {
 | 
| -        fBitmap.pixelRef()->addGenIDChangeListener(new BitmapInvalidator(stretchedKey));
 | 
| +    void didCacheCopy(const GrUniqueKey& copyKey) override {
 | 
| +        InstallInvalidator(copyKey, fBitmap.pixelRef());
 | 
|      }
 | 
|  
 | 
| -    bool onGetROBitmap(SkBitmap* bitmap) override {
 | 
| +    bool getROBitmap(SkBitmap* bitmap) override {
 | 
| +        SkASSERT(!fBitmap.getTexture());
 | 
|          *bitmap = fBitmap;
 | 
|          return true;
 | 
|      }
 | 
|  
 | 
|  private:
 | 
| -    const SkBitmap fBitmap;
 | 
| +    static void InstallInvalidator(const GrUniqueKey& key, SkPixelRef* pixelRef) {
 | 
| +        class Invalidator : public SkPixelRef::GenIDChangeListener {
 | 
| +        public:
 | 
| +            explicit Invalidator(const GrUniqueKey& key) : fMsg(key) {}
 | 
| +        private:
 | 
| +            GrUniqueKeyInvalidatedMessage fMsg;
 | 
| +
 | 
| +            void onChange() override {
 | 
| +                SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
 | 
| +            }
 | 
| +        };
 | 
| +        Invalidator* listener = new Invalidator(key);
 | 
| +        pixelRef->addGenIDChangeListener(listener);
 | 
| +    }
 | 
| +
 | 
| +    const SkBitmap  fBitmap;
 | 
| +    GrUniqueKey     fOriginalKey;
 | 
|  
 | 
| -    typedef GrTextureMaker INHERITED;
 | 
| +    typedef GrTextureParamsAdjuster INHERITED;
 | 
|  };
 | 
|  
 | 
|  GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
 | 
|                                      const GrTextureParams& params) {
 | 
| -    return Bitmap_GrTextureMaker(bitmap).refCachedTexture(ctx, params);
 | 
| +    return Bitmap_GrTextureParamsAdjuster(bitmap).refTextureForParams(ctx, params);
 | 
|  }
 | 
|  
 | 
|  ///////////////////////////////////////////////////////////////////////////////
 | 
| @@ -592,7 +426,6 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
 | 
|      return true;
 | 
|  }
 | 
|  
 | 
| -
 | 
|  ////////////////////////////////////////////////////////////////////////////////////////////////
 | 
|  
 | 
|  static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) {
 | 
| @@ -842,54 +675,3 @@ GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality pain
 | 
|      }
 | 
|      return textureFilterMode;
 | 
|  }
 | 
| -
 | 
| -////////////////////////////////////////////////////////////////////////////////////////////////
 | 
| -
 | 
| -GrTexture* GrTextureMaker::refCachedTexture(GrContext* ctx, const GrTextureParams& params) {
 | 
| -    SkGrStretch stretch;
 | 
| -    get_stretch(*ctx->caps(), 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());
 | 
| -    }
 | 
| -}
 | 
| 
 |