Check XpFactory equality in DrawState

BUG=skia:

Review URL: https://codereview.chromium.org/767873006
diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h
index ee3764d..10ecf54 100644
--- a/include/gpu/GrXferProcessor.h
+++ b/include/gpu/GrXferProcessor.h
@@ -54,7 +54,50 @@
      */
     virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0;
 
+    bool isEqual(const GrXPFactory& that) const {
+        if (this->classID() != that.classID()) {
+            return false;
+        }
+        return this->onIsEqual(that);
+    }
+
+    /**
+      * Helper for down-casting to a GrXPFactory subclass
+      */
+    template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
+
+    uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; }
+
+protected:
+    GrXPFactory() : fClassID(kIllegalXPFClassID) {}
+
+    template <typename XPF_SUBCLASS> void initClassID() {
+         static uint32_t kClassID = GenClassID();
+         fClassID = kClassID;
+    }
+
+    uint32_t fClassID;
+
 private:
+    virtual bool onIsEqual(const GrXPFactory&) const = 0;
+
+    static uint32_t GenClassID() {
+        // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The
+        // atomic inc returns the old value not the incremented value. So we add
+        // 1 to the returned value.
+        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1;
+        if (!id) {
+            SkFAIL("This should never wrap as it should only be called once for each GrXPFactory "
+                   "subclass.");
+        }
+        return id;
+    }
+
+    enum {
+        kIllegalXPFClassID = 0,
+    };
+    static int32_t gCurrXPFClassID;
+
     typedef GrProgramElement INHERITED;
 };
 
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index d1b30cc..9ff3bea 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -68,8 +68,12 @@
     bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE;
 
 private:
-    GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
-        : fSrc(src), fDst(dst) {}
+    GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst); 
+
+    bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
+        const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>();
+        return (fSrc == xpf.fSrc && fDst == xpf.fDst);
+    }
 
     GrBlendCoeff fSrc;
     GrBlendCoeff fDst;
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index db70bfa..8c2d75f 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -51,6 +51,10 @@
         return false;
     }
 
+    if (!this->getXPFactory()->isEqual(*that.getXPFactory())) {
+        return false;
+    }
+
     for (int i = 0; i < this->numColorStages(); i++) {
         if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
                                              explicitLocalCoords)) {
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 810c751..96dd9ea 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -11,6 +11,7 @@
 #include "GrGeometryData.h"
 #include "GrInvariantOutput.h"
 #include "GrMemoryPool.h"
+#include "GrXferProcessor.h"
 #include "SkTLS.h"
 
 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
@@ -179,3 +180,10 @@
 void GrGeometryData::operator delete(void* target) {
     GrProcessor_Globals::GetTLS()->release(target);
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Initial static variable from GrXPFactory
+int32_t GrXPFactory::gCurrXPFClassID =
+        GrXPFactory::kIllegalXPFClassID;
+
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 04a7b1f..55e0c93 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -65,6 +65,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
+    : fSrc(src), fDst(dst) {
+    this->initClassID<GrPorterDuffXPFactory>();
+}
+
 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
     switch (mode) {
         case SkXfermode::kClear_Mode: {