use SkBitmapProvider for shader-context

BUG=skia:

Review URL: https://codereview.chromium.org/1343123005
diff --git a/src/core/SkBitmapController.h b/src/core/SkBitmapController.h
index 435d9e7..e6c4443 100644
--- a/src/core/SkBitmapController.h
+++ b/src/core/SkBitmapController.h
@@ -16,8 +16,12 @@
 
 class SkBitmapProvider {
 public:
-    SkBitmapProvider(const SkBitmap& bm) : fBitmap(bm) {}
-    SkBitmapProvider(const SkImage* img) : fImage(SkRef(img)) {}
+    explicit SkBitmapProvider(const SkBitmap& bm) : fBitmap(bm) {}
+    explicit SkBitmapProvider(const SkImage* img) : fImage(SkSafeRef(img)) {}
+    SkBitmapProvider(const SkBitmapProvider& other)
+        : fBitmap(other.fBitmap)
+        , fImage(SkSafeRef(other.fImage.get()))
+    {}
 
     int width() const;
     int height() const;
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 97abbf9..36bfb1e 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -19,6 +19,12 @@
 #include "effects/GrSimpleTextureEffect.h"
 #endif
 
+size_t SkBitmapProcShader::ContextSize() {
+    // The SkBitmapProcState is stored outside of the context object, with the context holding
+    // a pointer to it.
+    return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
+}
+
 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
                                        const SkMatrix* localMatrix)
         : INHERITED(localMatrix) {
@@ -70,36 +76,36 @@
     return fRawBitmap.isOpaque();
 }
 
-SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
+SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader,
+                                                   TileMode tmx, TileMode tmy,
+                                                   const SkBitmap& bitmap,
+                                                   const ContextRec& rec, void* storage) {
     SkMatrix totalInverse;
     // Do this first, so we know the matrix can be inverted.
-    if (!this->computeTotalInverse(rec, &totalInverse)) {
+    if (!shader.computeTotalInverse(rec, &totalInverse)) {
         return nullptr;
     }
 
     void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
-    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState;
+    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(SkBitmapProvider(bitmap),
+                                                                    tmx, tmy);
 
     SkASSERT(state);
-    state->fTileModeX = fTileModeX;
-    state->fTileModeY = fTileModeY;
-    state->fOrigBitmap = fRawBitmap;
     if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
         state->~SkBitmapProcState();
         return nullptr;
     }
 
-    return new (storage) BitmapProcShaderContext(*this, rec, state);
+    return new (storage) BitmapProcShaderContext(shader, rec, state);
 }
 
-size_t SkBitmapProcShader::contextSize() const {
-    // The SkBitmapProcState is stored outside of the context object, with the context holding
-    // a pointer to it.
-    return sizeof(BitmapProcShaderContext) + sizeof(SkBitmapProcState);
+SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
+    return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY, fRawBitmap, rec, storage);
 }
 
-SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(
-        const SkBitmapProcShader& shader, const ContextRec& rec, SkBitmapProcState* state)
+SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(const SkShader& shader,
+                                                                     const ContextRec& rec,
+                                                                     SkBitmapProcState* state)
     : INHERITED(shader, rec)
     , fState(state)
 {
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 63985c0..9e90f9f 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -22,7 +22,7 @@
 
     bool isOpaque() const override;
 
-    size_t contextSize() const override;
+    size_t contextSize() const override { return ContextSize(); }
 
     SK_TO_STRING_OVERRIDE()
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBitmapProcShader)
@@ -33,11 +33,12 @@
                                                    GrProcessorDataManager*) const override;
 #endif
 
+protected:
     class BitmapProcShaderContext : public SkShader::Context {
     public:
         // The context takes ownership of the state. It will call its destructor
         // but will NOT free the memory.
-        BitmapProcShaderContext(const SkBitmapProcShader&, const ContextRec&, SkBitmapProcState*);
+        BitmapProcShaderContext(const SkShader&, const ContextRec&, SkBitmapProcState*);
         ~BitmapProcShaderContext() override;
 
         void shadeSpan(int x, int y, SkPMColor dstC[], int count) override;
@@ -52,8 +53,7 @@
 
         typedef SkShader::Context INHERITED;
     };
-
-protected:
+    
     void flatten(SkWriteBuffer&) const override;
     Context* onCreateContext(const ContextRec&, void* storage) const override;
     bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override;
@@ -62,6 +62,12 @@
     uint8_t     fTileModeX, fTileModeY;
 
 private:
+    friend class SkImageShader;
+
+    static size_t ContextSize();
+    static Context* MakeContext(const SkShader&, TileMode tmx, TileMode tmy, const SkBitmap&,
+                                const ContextRec&, void* storage);
+
     typedef SkShader INHERITED;
 };
 
@@ -70,7 +76,7 @@
 // an Sk3DBlitter in SkDraw.cpp
 // Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
 // yet found a situation where the size below isn't big enough.
-typedef SkSmallAllocator<3, 1152> SkTBlitterAllocator;
+typedef SkSmallAllocator<3, 1160> SkTBlitterAllocator;
 
 // If alloc is non-nullptr, it will be used to allocate the returned SkShader, and MUST outlive
 // the SkShader.
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp
index 31109aa..5ec6721 100644
--- a/src/core/SkBitmapProcState.cpp
+++ b/src/core/SkBitmapProcState.cpp
@@ -37,7 +37,23 @@
 #include "SkBitmapProcState_filter.h"
 #include "SkBitmapProcState_procs.h"
 
-SkBitmapProcState::SkBitmapProcState() : fBMState(nullptr) {}
+SkBitmapProcState::SkBitmapProcState(const SkBitmapProvider& provider,
+                                     SkShader::TileMode tmx, SkShader::TileMode tmy)
+    : fProvider(provider)
+    , fBMState(nullptr)
+{
+    fTileModeX = tmx;
+    fTileModeY = tmy;
+}
+
+SkBitmapProcState::SkBitmapProcState(const SkBitmap& bm,
+                                     SkShader::TileMode tmx, SkShader::TileMode tmy)
+    : fProvider(SkBitmapProvider(bm))
+    , fBMState(nullptr)
+{
+    fTileModeX = tmx;
+    fTileModeY = tmy;
+}
 
 SkBitmapProcState::~SkBitmapProcState() {
     SkInPlaceDeleteCheck(fBMState, fBMStateStorage.get());
@@ -119,7 +135,7 @@
     fFilterLevel = paint.getFilterQuality();
 
     SkDefaultBitmapController controller;
-    fBMState = controller.requestBitmap(fOrigBitmap, inv, paint.getFilterQuality(),
+    fBMState = controller.requestBitmap(fProvider, inv, paint.getFilterQuality(),
                                         fBMStateStorage.get(), fBMStateStorage.size());
     // Note : we allow the controller to return an empty (zero-dimension) result. Should we?
     if (nullptr == fBMState || fBMState->pixmap().info().isEmpty()) {
diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h
index 814c79a..b66299c 100644
--- a/src/core/SkBitmapProcState.h
+++ b/src/core/SkBitmapProcState.h
@@ -25,7 +25,8 @@
 class SkPaint;
 
 struct SkBitmapProcState {
-    SkBitmapProcState();
+    SkBitmapProcState(const SkBitmapProvider&, SkShader::TileMode tmx, SkShader::TileMode tmy);
+    SkBitmapProcState(const SkBitmap&, SkShader::TileMode tmx, SkShader::TileMode tmy);
     ~SkBitmapProcState();
 
     typedef void (*ShaderProc32)(const SkBitmapProcState&, int x, int y,
@@ -128,7 +129,7 @@
     SampleProc32        fSampleProc32;      // chooseProcs
     SampleProc16        fSampleProc16;      // chooseProcs
 
-    SkBitmap            fOrigBitmap;        // CONSTRUCTOR
+    const SkBitmapProvider fProvider;
 
     enum {
         kBMStateSize = 136  // found by inspection. if too small, we will call new/delete
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index 4ab233a..2907dba 100644
--- a/src/core/SkLightingShader.cpp
+++ b/src/core/SkLightingShader.cpp
@@ -664,24 +664,18 @@
     }
 
     void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext);
-    SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState;
+    SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcState(fDiffuseMap,
+                                              SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
     SkASSERT(diffuseState);
-
-    diffuseState->fTileModeX = SkShader::kClamp_TileMode;
-    diffuseState->fTileModeY = SkShader::kClamp_TileMode;
-    diffuseState->fOrigBitmap = fDiffuseMap;
     if (!diffuseState->chooseProcs(diffTotalInv, *rec.fPaint)) {
         diffuseState->~SkBitmapProcState();
         return nullptr;
     }
 
     void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + sizeof(SkBitmapProcState);
-    SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState;
+    SkBitmapProcState* normalState = new (normalStateStorage) SkBitmapProcState(fNormalMap,
+                                            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
     SkASSERT(normalState);
-
-    normalState->fTileModeX = SkShader::kClamp_TileMode;
-    normalState->fTileModeY = SkShader::kClamp_TileMode;
-    normalState->fOrigBitmap = fNormalMap;
     if (!normalState->chooseProcs(normTotalInv, *rec.fPaint)) {
         diffuseState->~SkBitmapProcState();
         normalState->~SkBitmapProcState();