make set3DMask virtual, so we can safely notify the shadercontext

also boost preallocated storage to account for this combo of bitmapshader + emboss + colorfilter

BUG=skia:
R=djsollen@google.com

Author: reed@google.com

Review URL: https://codereview.chromium.org/563563002
diff --git a/gm/emboss.cpp b/gm/emboss.cpp
new file mode 100644
index 0000000..c2ee497
--- /dev/null
+++ b/gm/emboss.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkColorFilter.h"
+
+#include "SkColorFilter.h"
+static SkBitmap make_bm() {
+    SkBitmap bm;
+    bm.allocN32Pixels(100, 100);
+
+    SkCanvas canvas(bm);
+    canvas.clear(0);
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    canvas.drawCircle(50, 50, 50, paint);
+    return bm;
+}
+
+class EmbossGM : public skiagm::GM {
+public:
+    EmbossGM() {
+    }
+
+protected:
+    virtual SkString onShortName() SK_OVERRIDE {
+        return SkString("emboss");
+    }
+
+    virtual SkISize onISize() SK_OVERRIDE {
+        return SkISize::Make(600, 120);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+        SkPaint paint;
+        SkBitmap bm = make_bm();
+        canvas->drawBitmap(bm, 10, 10, &paint);
+
+        const SkScalar dir[] = { 1, 1, 1 };
+        paint.setMaskFilter(SkBlurMaskFilter::CreateEmboss(3, dir, 0.3f, 0.1f))->unref();
+        canvas->translate(bm.width() + SkIntToScalar(10), 0);
+        canvas->drawBitmap(bm, 10, 10, &paint);
+
+        // this combination of emboss+colorfilter used to crash -- so we exercise it to
+        // confirm that we have a fix.
+        paint.setColorFilter(SkColorFilter::CreateModeFilter(0xFFFF0000, SkXfermode::kSrcATop_Mode))->unref();
+        canvas->translate(bm.width() + SkIntToScalar(10), 0);
+        canvas->drawBitmap(bm, 10, 10, &paint);
+    }
+
+private:
+    typedef skiagm::GM INHERITED;
+};
+
+DEF_GM( return SkNEW(EmbossGM); )
diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi
index c8f9c2f..f3d7b80 100644
--- a/gyp/gmslides.gypi
+++ b/gyp/gmslides.gypi
@@ -71,6 +71,7 @@
         '../gm/drrect.cpp',
         '../gm/etc1bitmap.cpp',
         '../gm/extractbitmap.cpp',
+        '../gm/emboss.cpp',
         '../gm/emptypath.cpp',
         '../gm/fatpathfill.cpp',
         '../gm/factory.cpp',
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index 8530023..6effe79 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -185,6 +185,9 @@
             return SkShader::CanCallShadeSpan16(this->getFlags());
         }
 
+        // Notification from blitter::blitMask in case we need to see the non-alpha channels
+        virtual void set3DMask(const SkMask*) {}
+
     protected:
         // Reference to shader, so we don't have to dupe information.
         const SkShader& fShader;
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index d445f56..d293c50 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -73,7 +73,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, 768> SkTBlitterAllocator;
+typedef SkSmallAllocator<3, 1024> SkTBlitterAllocator;
 
 // If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
 // the SkShader.
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index b9e9917..f4669d5 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -620,7 +620,7 @@
             }
         }
 
-        void setMask(const SkMask* mask) { fMask = mask; }
+        virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { fMask = mask; }
 
         virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
             if (fProxyContext) {
@@ -740,9 +740,9 @@
 
 class Sk3DBlitter : public SkBlitter {
 public:
-    Sk3DBlitter(SkBlitter* proxy, Sk3DShader::Sk3DShaderContext* shaderContext)
+    Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext)
         : fProxy(proxy)
-        , f3DShaderContext(shaderContext)
+        , fShaderContext(shaderContext)
     {}
 
     virtual void blitH(int x, int y, int width) {
@@ -764,13 +764,13 @@
 
     virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
         if (mask.fFormat == SkMask::k3D_Format) {
-            f3DShaderContext->setMask(&mask);
+            fShaderContext->set3DMask(&mask);
 
             ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
             fProxy->blitMask(mask, clip);
             ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
 
-            f3DShaderContext->setMask(NULL);
+            fShaderContext->set3DMask(NULL);
         } else {
             fProxy->blitMask(mask, clip);
         }
@@ -778,8 +778,8 @@
 
 private:
     // Both pointers are unowned. They will be deleted by SkSmallAllocator.
-    SkBlitter*                     fProxy;
-    Sk3DShader::Sk3DShaderContext* f3DShaderContext;
+    SkBlitter*          fProxy;
+    SkShader::Context*  fShaderContext;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -987,9 +987,9 @@
     if (shader3D) {
         SkBlitter* innerBlitter = blitter;
         // innerBlitter was allocated by allocator, which will delete it.
-        // We know shaderContext is of type Sk3DShaderContext because it belongs to shader3D.
-        blitter = allocator->createT<Sk3DBlitter>(innerBlitter,
-                static_cast<Sk3DShader::Sk3DShaderContext*>(shaderContext));
+        // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
+        // wrapper the blitter to notify it when we see an emboss mask.
+        blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext);
     }
     return blitter;
 }
diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h
index 2ff6cda..b98fc83 100644
--- a/src/core/SkFilterShader.h
+++ b/src/core/SkFilterShader.h
@@ -30,6 +30,11 @@
         virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
         virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
 
+        virtual void set3DMask(const SkMask* mask) SK_OVERRIDE {
+            // forward to our proxy
+            fShaderContext->set3DMask(mask);
+        }
+
     private:
         SkShader::Context* fShaderContext;