fission bitmapprocstate

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1753903002

CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Review URL: https://codereview.chromium.org/1753903002
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 804c688..895922c 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -20,12 +20,138 @@
 #include "effects/GrSimpleTextureEffect.h"
 #endif
 
-size_t SkBitmapProcShader::ContextSize() {
+static bool only_scale_and_translate(const SkMatrix& matrix) {
+    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
+    return (matrix.getType() & ~mask) == 0;
+}
+
+class BitmapProcInfoContext : public SkShader::Context {
+public:
+    // The context takes ownership of the info. It will call its destructor
+    // but will NOT free the memory.
+    BitmapProcInfoContext(const SkShader& shader, const SkShader::ContextRec& rec,
+                            SkBitmapProcInfo* info)
+        : INHERITED(shader, rec)
+        , fInfo(info)
+    {
+        fFlags = 0;
+        if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) {
+            fFlags |= SkShader::kOpaqueAlpha_Flag;
+        }
+
+        if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) {
+            fFlags |= SkShader::kConstInY32_Flag;
+        }
+    }
+
+    ~BitmapProcInfoContext() override {
+        // The bitmap proc state has been created outside of the context on memory that will be freed
+        // elsewhere. Only call the destructor but leave the freeing of the memory to the caller.
+        fInfo->~SkBitmapProcInfo();
+    }
+    
+    uint32_t getFlags() const override { return fFlags; }
+
+private:
+    SkBitmapProcInfo*   fInfo;
+    uint32_t            fFlags;
+
+    typedef SkShader::Context INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BitmapProcShaderContext : public BitmapProcInfoContext {
+public:
+    // The context takes ownership of the state. It will call its destructor
+    // but will NOT free the memory.
+    BitmapProcShaderContext(const SkShader& shader, const SkShader::ContextRec& rec,
+                            SkBitmapProcState* state)
+        : INHERITED(shader, rec, state)
+        , fState(state)
+    {}
+
+    void shadeSpan(int x, int y, SkPMColor dstC[], int count) override {
+        const SkBitmapProcState& state = *fState;
+        if (state.getShaderProc32()) {
+            state.getShaderProc32()(&state, x, y, dstC, count);
+            return;
+        }
+
+        const int BUF_MAX = 128;
+        uint32_t buffer[BUF_MAX];
+        SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
+        SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
+        const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
+
+        SkASSERT(state.fPixmap.addr());
+
+        for (;;) {
+            int n = SkTMin(count, max);
+            SkASSERT(n > 0 && n < BUF_MAX*2);
+            mproc(state, buffer, n, x, y);
+            sproc(state, buffer, n, dstC);
+
+            if ((count -= n) == 0) {
+                break;
+            }
+            SkASSERT(count > 0);
+            x += n;
+            dstC += n;
+        }
+    }
+
+    ShadeProc asAShadeProc(void** ctx) override {
+        if (fState->getShaderProc32()) {
+            *ctx = fState;
+            return (ShadeProc)fState->getShaderProc32();
+        }
+        return nullptr;
+    }
+
+private:
+    SkBitmapProcState*  fState;
+
+    typedef BitmapProcInfoContext INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+size_t SkBitmapProcShader::ContextSize(const ContextRec& rec) {
     // 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::MakeContext(const SkShader& shader,
+                                                   TileMode tmx, TileMode tmy,
+                                                   const SkBitmapProvider& provider,
+                                                   const ContextRec& rec, void* storage) {
+    SkMatrix totalInverse;
+    // Do this first, so we know the matrix can be inverted.
+    if (!shader.computeTotalInverse(rec, &totalInverse)) {
+        return nullptr;
+    }
+
+    void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
+    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tmx, tmy);
+
+    SkASSERT(state);
+    if (!state->setup(totalInverse, *rec.fPaint)) {
+        state->~SkBitmapProcState();
+        return nullptr;
+    }
+
+    return new (storage) BitmapProcShaderContext(shader, rec, state);
+}
+
+SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
+    return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY,
+                       SkBitmapProvider(fRawBitmap), rec, storage);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
 SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
                                        const SkMatrix* localMatrix)
         : INHERITED(localMatrix) {
@@ -72,123 +198,7 @@
     return fRawBitmap.isOpaque();
 }
 
-SkShader::Context* SkBitmapProcShader::MakeContext(const SkShader& shader,
-                                                   TileMode tmx, TileMode tmy,
-                                                   const SkBitmapProvider& provider,
-                                                   const ContextRec& rec, void* storage) {
-    SkMatrix totalInverse;
-    // Do this first, so we know the matrix can be inverted.
-    if (!shader.computeTotalInverse(rec, &totalInverse)) {
-        return nullptr;
-    }
-
-    void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext);
-    SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tmx, tmy);
-
-    SkASSERT(state);
-    if (!state->chooseProcs(totalInverse, *rec.fPaint)) {
-        state->~SkBitmapProcState();
-        return nullptr;
-    }
-
-    return new (storage) BitmapProcShaderContext(shader, rec, state);
-}
-
-SkShader::Context* SkBitmapProcShader::onCreateContext(const ContextRec& rec, void* storage) const {
-    return MakeContext(*this, (TileMode)fTileModeX, (TileMode)fTileModeY,
-                       SkBitmapProvider(fRawBitmap), rec, storage);
-}
-
-static bool only_scale_and_translate(const SkMatrix& matrix) {
-    unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
-    return (matrix.getType() & ~mask) == 0;
-}
-
-SkBitmapProcShader::BitmapProcShaderContext::BitmapProcShaderContext(const SkShader& shader,
-                                                                     const ContextRec& rec,
-                                                                     SkBitmapProcState* state)
-    : INHERITED(shader, rec)
-    , fState(state)
-{
-    fFlags = 0;
-    if (fState->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) {
-        fFlags |= kOpaqueAlpha_Flag;
-    }
-
-    if (1 == fState->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) {
-        fFlags |= kConstInY32_Flag;
-    }
-}
-
-SkBitmapProcShader::BitmapProcShaderContext::~BitmapProcShaderContext() {
-    // The bitmap proc state has been created outside of the context on memory that will be freed
-    // elsewhere. Only call the destructor but leave the freeing of the memory to the caller.
-    fState->~SkBitmapProcState();
-}
-
-#define BUF_MAX     128
-
-#define TEST_BUFFER_OVERRITEx
-
-#ifdef TEST_BUFFER_OVERRITE
-    #define TEST_BUFFER_EXTRA   32
-    #define TEST_PATTERN    0x88888888
-#else
-    #define TEST_BUFFER_EXTRA   0
-#endif
-
-void SkBitmapProcShader::BitmapProcShaderContext::shadeSpan(int x, int y, SkPMColor dstC[],
-                                                            int count) {
-    const SkBitmapProcState& state = *fState;
-    if (state.getShaderProc32()) {
-        state.getShaderProc32()(&state, x, y, dstC, count);
-        return;
-    }
-
-    uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
-    SkBitmapProcState::MatrixProc   mproc = state.getMatrixProc();
-    SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32();
-    int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
-
-    SkASSERT(state.fPixmap.addr());
-
-    for (;;) {
-        int n = count;
-        if (n > max) {
-            n = max;
-        }
-        SkASSERT(n > 0 && n < BUF_MAX*2);
-#ifdef TEST_BUFFER_OVERRITE
-        for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
-            buffer[BUF_MAX + i] = TEST_PATTERN;
-        }
-#endif
-        mproc(state, buffer, n, x, y);
-#ifdef TEST_BUFFER_OVERRITE
-        for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
-            SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
-        }
-#endif
-        sproc(state, buffer, n, dstC);
-
-        if ((count -= n) == 0) {
-            break;
-        }
-        SkASSERT(count > 0);
-        x += n;
-        dstC += n;
-    }
-}
-
-SkShader::Context::ShadeProc SkBitmapProcShader::BitmapProcShaderContext::asAShadeProc(void** ctx) {
-    if (fState->getShaderProc32()) {
-        *ctx = fState;
-        return (ShadeProc)fState->getShaderProc32();
-    }
-    return nullptr;
-}
-
-///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #include "SkUnPreMultiply.h"
 #include "SkColorShader.h"