Implement support for KHR_blend_equation_advanced

Uses KHR(or NV)_blend_equation_advanced to implement custom Xfer modes
in hardware.

BUG=skia:

Review URL: https://codereview.chromium.org/1037123003
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 540072f..8b83dc0 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -39,6 +39,49 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 
+static const GrGLenum gXfermodeEquation2Blend[] = {
+    // Basic OpenGL blend equations.
+    GR_GL_FUNC_ADD,
+    GR_GL_FUNC_SUBTRACT,
+    GR_GL_FUNC_REVERSE_SUBTRACT,
+
+    // GL_KHR_blend_equation_advanced.
+    GR_GL_SCREEN,
+    GR_GL_OVERLAY,
+    GR_GL_DARKEN,
+    GR_GL_LIGHTEN,
+    GR_GL_COLORDODGE,
+    GR_GL_COLORBURN,
+    GR_GL_HARDLIGHT,
+    GR_GL_SOFTLIGHT,
+    GR_GL_DIFFERENCE,
+    GR_GL_EXCLUSION,
+    GR_GL_MULTIPLY,
+    GR_GL_HSL_HUE,
+    GR_GL_HSL_SATURATION,
+    GR_GL_HSL_COLOR,
+    GR_GL_HSL_LUMINOSITY
+};
+GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
+GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
+GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
+GR_STATIC_ASSERT(3 == kScreen_GrBlendEquation);
+GR_STATIC_ASSERT(4 == kOverlay_GrBlendEquation);
+GR_STATIC_ASSERT(5 == kDarken_GrBlendEquation);
+GR_STATIC_ASSERT(6 == kLighten_GrBlendEquation);
+GR_STATIC_ASSERT(7 == kColorDodge_GrBlendEquation);
+GR_STATIC_ASSERT(8 == kColorBurn_GrBlendEquation);
+GR_STATIC_ASSERT(9 == kHardLight_GrBlendEquation);
+GR_STATIC_ASSERT(10 == kSoftLight_GrBlendEquation);
+GR_STATIC_ASSERT(11 == kDifference_GrBlendEquation);
+GR_STATIC_ASSERT(12 == kExclusion_GrBlendEquation);
+GR_STATIC_ASSERT(13 == kMultiply_GrBlendEquation);
+GR_STATIC_ASSERT(14 == kHSLHue_GrBlendEquation);
+GR_STATIC_ASSERT(15 == kHSLSaturation_GrBlendEquation);
+GR_STATIC_ASSERT(16 == kHSLColor_GrBlendEquation);
+GR_STATIC_ASSERT(17 == kHSLLuminosity_GrBlendEquation);
+GR_STATIC_ASSERT(18 == kTotalGrBlendEquationCount);
+
 static const GrGLenum gXfermodeCoeff2Blend[] = {
     GR_GL_ZERO,
     GR_GL_ONE,
@@ -2077,39 +2120,55 @@
 
 void GrGLGpu::flushBlend(const GrXferProcessor::BlendInfo& blendInfo) {
     // Any optimization to disable blending should have already been applied and
-    // tweaked the coeffs to (1, 0).
+    // tweaked the equation to "add" or "subtract", and the coeffs to (1, 0).
     
+    GrBlendEquation equation = blendInfo.fEquation;
     GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
     GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
-    bool blendOff = kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
+    bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
+                    kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
     if (blendOff) {
         if (kNo_TriState != fHWBlendState.fEnabled) {
             GL_CALL(Disable(GR_GL_BLEND));
             fHWBlendState.fEnabled = kNo_TriState;
         }
-    } else {
-        if (kYes_TriState != fHWBlendState.fEnabled) {
-            GL_CALL(Enable(GR_GL_BLEND));
-            fHWBlendState.fEnabled = kYes_TriState;
-        }
-        if (fHWBlendState.fSrcCoeff != srcCoeff ||
-            fHWBlendState.fDstCoeff != dstCoeff) {
-            GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
-                              gXfermodeCoeff2Blend[dstCoeff]));
-            fHWBlendState.fSrcCoeff = srcCoeff;
-            fHWBlendState.fDstCoeff = dstCoeff;
-        }
-        GrColor blendConst = blendInfo.fBlendConstant;
-        if ((BlendCoeffReferencesConstant(srcCoeff) ||
-             BlendCoeffReferencesConstant(dstCoeff)) &&
-            (!fHWBlendState.fConstColorValid ||
-             fHWBlendState.fConstColor != blendConst)) {
-            GrGLfloat c[4];
-            GrColorToRGBAFloat(blendConst, c);
-            GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
-            fHWBlendState.fConstColor = blendConst;
-            fHWBlendState.fConstColorValid = true;
-        }
+        return;
+    }
+
+    if (kYes_TriState != fHWBlendState.fEnabled) {
+        GL_CALL(Enable(GR_GL_BLEND));
+        fHWBlendState.fEnabled = kYes_TriState;
+    }
+
+    if (fHWBlendState.fEquation != equation) {
+        GL_CALL(BlendEquation(gXfermodeEquation2Blend[equation]));
+        fHWBlendState.fEquation = equation;
+    }
+
+    if (GrBlendEquationIsAdvanced(equation)) {
+        SkASSERT(this->caps()->advancedBlendEquationSupport());
+        // Advanced equations have no other blend state.
+        return;
+    }
+
+    if (fHWBlendState.fSrcCoeff != srcCoeff ||
+        fHWBlendState.fDstCoeff != dstCoeff) {
+        GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
+                          gXfermodeCoeff2Blend[dstCoeff]));
+        fHWBlendState.fSrcCoeff = srcCoeff;
+        fHWBlendState.fDstCoeff = dstCoeff;
+    }
+
+    GrColor blendConst = blendInfo.fBlendConstant;
+    if ((BlendCoeffReferencesConstant(srcCoeff) ||
+         BlendCoeffReferencesConstant(dstCoeff)) &&
+        (!fHWBlendState.fConstColorValid ||
+         fHWBlendState.fConstColor != blendConst)) {
+        GrGLfloat c[4];
+        GrColorToRGBAFloat(blendConst, c);
+        GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
+        fHWBlendState.fConstColor = blendConst;
+        fHWBlendState.fConstColorValid = true;
     }
 }
 
@@ -2736,6 +2795,11 @@
             SkASSERT(this->caps()->textureBarrierSupport());
             GL_CALL(TextureBarrier());
             return;
+        case kBlend_GrXferBarrierType:
+            SkASSERT(GrDrawTargetCaps::kAdvanced_BlendEquationSupport ==
+                     this->caps()->blendEquationSupport());
+            GL_CALL(BlendBarrier());
+            return;
     }
 }