Add an opaqueness hint to GrDrawState.
authorbsalomon <bsalomon@google.com>
Fri, 8 Aug 2014 15:08:50 +0000 (08:08 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 8 Aug 2014 15:08:51 +0000 (08:08 -0700)
Check it when deciding whether to combine draw states.

R=egdaniel@google.com, robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/446953002

src/gpu/GrBitmapTextContext.cpp
src/gpu/GrContext.cpp
src/gpu/GrDistanceFieldTextContext.cpp
src/gpu/GrDrawState.cpp
src/gpu/GrDrawState.h
src/gpu/GrDrawTarget.cpp
src/gpu/GrDrawTarget.h
src/gpu/GrInOrderDrawBuffer.cpp

index b2cea2b..0c4d324 100755 (executable)
@@ -592,6 +592,9 @@ HAS_ATLAS:
                               SkFixedToFloat(texture->normalizeFixedY(ty + height)),
                               vertSize);
     if (useColorVerts) {
+        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
+            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+        }
         // color comes after position.
         GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
         for (int i = 0; i < 4; ++i) {
index 4740403..96380bd 100755 (executable)
@@ -1753,7 +1753,7 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
         fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
 #if GR_DEBUG_PARTIAL_COVERAGE_CHECK
         if ((paint->hasMask() || 0xff != paint->fCoverage) &&
-            !fGpu->canApplyCoverage()) {
+            !fDrawState->couldApplyCoverage(fGpu->caps())) {
             GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
         }
 #endif
index 4321ff1..b7b4f99 100755 (executable)
@@ -421,6 +421,9 @@ HAS_ATLAS:
                               SkFixedToFloat(texture->normalizeFixedY(ty + th)),
                               vertSize);
     if (useColorVerts) {
+        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
+            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+        }
         // color comes after position.
         GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
         for (int i = 0; i < 4; ++i) {
index a0dc426..d54d085 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "GrDrawState.h"
 #include "GrPaint.h"
+#include "GrDrawTargetCaps.h"
 
 //////////////////////////////////////////////////////////////////////////////s
 
@@ -34,7 +35,7 @@ bool GrDrawState::State::HaveCompatibleState(const State& a, const State& b,
 }
 //////////////////////////////////////////////////////////////////////////////s
 GrDrawState::CombinedState GrDrawState::CombineIfPossible(
-    const GrDrawState& a, const GrDrawState& b) {
+    const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
 
     bool usingVertexColors = a.hasColorVertexAttribute();
     if (!usingVertexColors && a.fColor != b.fColor) {
@@ -65,10 +66,35 @@ GrDrawState::CombinedState GrDrawState::CombineIfPossible(
     if (!State::HaveCompatibleState(a.fState, b.fState, explicitLocalCoords)) {
         return kIncompatible_CombinedState;
     }
+
+    if (usingVertexColors) {
+        // If one is opaque and the other is not then the combined state is not opaque. Moreover,
+        // if the opaqueness affects the ability to get color/coverage blending correct then we
+        // don't combine the draw states.
+        bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
+        bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
+        if (aIsOpaque != bIsOpaque) {
+            const GrDrawState* opaque;
+            const GrDrawState* nonOpaque;
+            if (aIsOpaque) {
+                opaque = &a;
+                nonOpaque = &b;
+            } else {
+                opaque = &b;
+                nonOpaque = &a;
+            }
+            if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
+                SkASSERT(!nonOpaque->hasSolidCoverage());
+                if (!nonOpaque->couldApplyCoverage(caps)) {
+                    return kIncompatible_CombinedState;
+                }
+            }
+            return aIsOpaque ? kB_CombinedState : kA_CombinedState;
+        }
+    }
     return kAOrB_CombinedState;
 }
 
-
 //////////////////////////////////////////////////////////////////////////////s
 
 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
@@ -102,6 +128,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
     fBlendOptFlags = that.fBlendOptFlags;
 
     fState = that.fState;
+    fHints = that.fHints;
 
     memcpy(fFixedFunctionVertexAttribIndices,
             that.fFixedFunctionVertexAttribIndices,
@@ -129,6 +156,8 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
     fCoverage = 0xffffffff;
     fDrawFace = kBoth_DrawFace;
 
+    fHints = 0;
+
     this->invalidateBlendOptFlags();
 }
 
@@ -172,6 +201,7 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
     fDrawFace = kBoth_DrawFace;
     fStencilSettings.setDisabled();
     this->resetStateFlags();
+    fHints = 0;
 
     // Enable the clip bit
     this->enableState(GrDrawState::kClip_StateBit);
@@ -326,13 +356,33 @@ bool GrDrawState::willEffectReadDstColor() const {
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
+    if (caps.dualSourceBlendingSupport()) {
+        return true;
+    }
+    // we can correctly apply coverage if a) we have dual source blending
+    // or b) one of our blend optimizations applies
+    // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
+    GrBlendCoeff srcCoeff;
+    GrBlendCoeff dstCoeff;
+    GrDrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
+    return GrDrawState::kNone_BlendOpt != flag ||
+           (this->willEffectReadDstColor() &&
+            kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
+}
+
 bool GrDrawState::srcAlphaWillBeOne() const {
     uint32_t validComponentFlags;
     GrColor color;
     // Check if per-vertex or constant color may have partial alpha
     if (this->hasColorVertexAttribute()) {
-        validComponentFlags = 0;
-        color = 0; // not strictly necessary but we get false alarms from tools about uninit.
+        if (fHints & kVertexColorsAreOpaque_Hint) {
+            validComponentFlags = kA_GrColorComponentFlag;
+            color = 0xFF << GrColor_SHIFT_A;            
+        } else {
+            validComponentFlags = 0;
+            color = 0; // not strictly necessary but we get false alarms from tools about uninit.
+        }
     } else {
         validComponentFlags = kRGBA_GrColorComponentFlags;
         color = this->getColor();
@@ -455,13 +505,10 @@ GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
 
-    bool covIsZero = !this->isCoverageDrawing() &&
-                     !this->hasCoverageVertexAttribute() &&
-                     0 == this->getCoverageColor();
     // When coeffs are (0,1) there is no reason to draw at all, unless
     // stenciling is enabled. Having color writes disabled is effectively
-    // (0,1). The same applies when coverage is known to be 0.
-    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
+    // (0,1).
+    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
         if (this->getStencil().doesWrite()) {
             return kEmitCoverage_BlendOptFlag;
         } else {
@@ -469,11 +516,7 @@ GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
         }
     }
 
-    // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
-    bool hasCoverage = forceCoverage ||
-                       0xffffffff != this->getCoverageColor() ||
-                       this->hasCoverageVertexAttribute() ||
-                       this->numCoverageStages() > 0;
+    bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
 
     // if we don't have coverage we can check whether the dst
     // has to read at all. If not, we'll disable blending.
index 6603cc9..fa4d5b0 100644 (file)
@@ -8,21 +8,18 @@
 #ifndef GrDrawState_DEFINED
 #define GrDrawState_DEFINED
 
-#include "GrBackendEffectFactory.h"
 #include "GrBlend.h"
 #include "GrColor.h"
 #include "GrEffectStage.h"
-#include "GrPaint.h"
-#include "GrRenderTarget.h"
 #include "GrStencil.h"
-#include "GrTemplates.h"
-#include "GrTexture.h"
-#include "GrTypesPriv.h"
 #include "effects/GrSimpleTextureEffect.h"
 
 #include "SkMatrix.h"
-#include "SkTypes.h"
-#include "SkXfermode.h"
+
+class GrDrawTargetCaps;
+class GrPaint;
+class GrRenderTarget;
+class GrTexture;
 
 class GrDrawState : public SkRefCnt {
 public:
@@ -161,6 +158,18 @@ public:
      */
     bool hasSolidCoverage() const;
 
+    /**
+     * Depending on features available in the underlying 3D API and the color blend mode requested
+     * it may or may not be possible to correctly blend with fractional pixel coverage generated by
+     * the fragment shader.
+     *
+     * This function considers the current draw state and the draw target's capabilities to
+     * determine whether coverage can be handled correctly. This function assumes that the caller
+     * intends to specify fractional pixel coverage (via setCoverage(), through a coverage vertex
+     * attribute, or a coverage effect) but may not have specified it yet.
+     */
+    bool couldApplyCoverage(const GrDrawTargetCaps& caps) const;
+
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
@@ -185,9 +194,7 @@ public:
      *
      *  @param alpha The alpha value to set as the color.
      */
-    void setAlpha(uint8_t a) {
-        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
-    }
+    void setAlpha(uint8_t a) { this->setColor((a << 24) | (a << 16) | (a << 8) | a); }
 
     /// @}
 
@@ -205,13 +212,9 @@ public:
         this->invalidateBlendOptFlags();
     }
 
-    uint8_t getCoverage() const {
-        return GrColorUnpackR(fCoverage);
-    }
+    uint8_t getCoverage() const { return GrColorUnpackR(fCoverage); }
 
-    GrColor getCoverageColor() const {
-        return fCoverage;
-    }
+    GrColor getCoverageColor() const { return fCoverage; }
 
     /// @}
 
@@ -561,9 +564,7 @@ public:
      *
      * @param target  The render target to set.
      */
-    void setRenderTarget(GrRenderTarget* target) {
-        fRenderTarget.reset(SkSafeRef(target));
-    }
+    void setRenderTarget(GrRenderTarget* target) { fRenderTarget.reset(SkSafeRef(target)); }
 
     /**
      * Retrieves the currently set render-target.
@@ -722,29 +723,13 @@ public:
         }
     }
 
-    bool isDitherState() const {
-        return 0 != (fFlagBits & kDither_StateBit);
-    }
-
-    bool isHWAntialiasState() const {
-        return 0 != (fFlagBits & kHWAntialias_StateBit);
-    }
+    bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
 
-    bool isClipState() const {
-        return 0 != (fFlagBits & kClip_StateBit);
-    }
-
-    bool isColorWriteDisabled() const {
-        return 0 != (fFlagBits & kNoColorWrites_StateBit);
-    }
-
-    bool isCoverageDrawing() const {
-        return 0 != (fFlagBits & kCoverageDrawing_StateBit);
-    }
-
-    bool isStateFlagEnabled(uint32_t stateBit) const {
-        return 0 != (stateBit & fFlagBits);
-    }
+    bool isDitherState() const { return 0 != (fFlagBits & kDither_StateBit); }
+    bool isHWAntialiasState() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
+    bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
+    bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
+    bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
 
     /// @}
 
@@ -779,6 +764,17 @@ public:
     /// @}
 
     ///////////////////////////////////////////////////////////////////////////
+    /// @name Hints
+    /// Hints that when provided can enable optimizations.
+    ////
+
+    enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
+
+    void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
 
     /** Return type for CombineIfPossible. */
     enum CombinedState {
@@ -796,7 +792,8 @@ public:
         a single GrDrawState. This is used to avoid storing redundant GrDrawStates and to determine
         if draws can be batched. The return value indicates whether combining is possible and, if
         so, which of the two inputs should be used. */
-    static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b);
+    static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b,
+                                           const GrDrawTargetCaps& caps);
 
     GrDrawState& operator= (const GrDrawState& that);
 
@@ -804,8 +801,8 @@ private:
     void onReset(const SkMatrix* initialViewMatrix);
 
     BlendOptFlags calcBlendOpts(bool forceCoverage = false,
-                               GrBlendCoeff* srcCoeff = NULL,
-                               GrBlendCoeff* dstCoeff = NULL) const;
+                                GrBlendCoeff* srcCoeff = NULL,
+                                GrBlendCoeff* dstCoeff = NULL) const;
 
     // These fields are roughly sorted by decreasing likelihood of being different in op==
     SkAutoTUnref<GrRenderTarget>        fRenderTarget;
@@ -820,10 +817,12 @@ private:
     DrawFace                            fDrawFace;
 
     State                               fState;
+
+    uint32_t                            fHints;
     
-    mutable GrBlendCoeff                        fOptSrcBlend;
-    mutable GrBlendCoeff                        fOptDstBlend;
-    mutable BlendOptFlags                       fBlendOptFlags;
+    mutable GrBlendCoeff                fOptSrcBlend;
+    mutable GrBlendCoeff                fOptDstBlend;
+    mutable BlendOptFlags               fBlendOptFlags;
 
     // This is simply a different representation of info in fVertexAttribs and thus does
     // not need to be compared in op==.
index f8bb910..2d27859 100644 (file)
@@ -13,6 +13,7 @@
 #include "GrDrawTargetCaps.h"
 #include "GrPath.h"
 #include "GrRenderTarget.h"
+#include "GrTemplates.h"
 #include "GrTexture.h"
 #include "GrVertexBuffer.h"
 
@@ -613,21 +614,6 @@ void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrDrawTarget::canApplyCoverage() const {
-    // we can correctly apply coverage if a) we have dual source blending
-    // or b) one of our blend optimizations applies
-    // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
-    GrBlendCoeff srcCoeff;
-    GrBlendCoeff dstCoeff;
-    GrDrawState::BlendOptFlags flag = this->getDrawState().getBlendOpts(true, &srcCoeff, &dstCoeff);
-    return this->caps()->dualSourceBlendingSupport() ||
-           GrDrawState::kNone_BlendOpt != flag ||
-           (this->getDrawState().willEffectReadDstColor() &&
-            kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
                                         int instanceCount,
                                         int verticesPerInstance,
index befa81a..b5487dc 100644 (file)
@@ -84,32 +84,13 @@ public:
      */
     GrDrawState* drawState() { return fDrawState; }
 
-    /**
-     * Color alpha and coverage are two inputs to the drawing pipeline. For some
-     * blend modes it is safe to fold the coverage into constant or per-vertex
-     * color alpha value. For other blend modes they must be handled separately.
-     * Depending on features available in the underlying 3D API this may or may
-     * not be possible.
-     *
-     * This function considers the current draw state and the draw target's
-     * capabilities to determine whether coverage can be handled correctly. The
-     * following assumptions are made:
-     *    1. The caller intends to somehow specify coverage. This can be
-     *       specified either by enabling a coverage stage on the GrDrawState or
-     *       via the vertex layout.
-     *    2. Other than enabling coverage stages or enabling coverage in the
-     *       layout, the current configuration of the target's GrDrawState is as
-     *       it will be at draw time.
-     */
-    bool canApplyCoverage() const;
-
     /** When we're using coverage AA but the blend is incompatible (given gpu
      * limitations) we should disable AA. */
-    bool shouldDisableCoverageAAForBlend() {
+    bool shouldDisableCoverageAAForBlend() const {
         // Enable below if we should draw with AA even when it produces
         // incorrect blending.
         // return false;
-        return !this->canApplyCoverage();
+        return !this->getDrawState().couldApplyCoverage(*this->caps());
     }
 
     /**
index 954437c..6d0bbd1 100644 (file)
@@ -78,63 +78,44 @@ void get_vertex_bounds(const void* vertices,
 
 namespace {
 
-extern const GrVertexAttrib kRectPosColorUVAttribs[] = {
-    {kVec2f_GrVertexAttribType,  0,               kPosition_GrVertexAttribBinding},
-    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
-    {kVec2f_GrVertexAttribType,  sizeof(SkPoint)+sizeof(GrColor),
-                                                  kLocalCoord_GrVertexAttribBinding},
+extern const GrVertexAttrib kRectAttribs[] = {
+    {kVec2f_GrVertexAttribType,  0,                               kPosition_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                 kColor_GrVertexAttribBinding},
+    {kVec2f_GrVertexAttribType,  sizeof(SkPoint)+sizeof(GrColor), kLocalCoord_GrVertexAttribBinding},
 };
+}
 
-extern const GrVertexAttrib kRectPosUVAttribs[] = {
-    {kVec2f_GrVertexAttribType,  0,              kPosition_GrVertexAttribBinding},
-    {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding},
-};
+/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
+    have explicit local coords and sometimes not. We *could* always provide explicit local coords
+    and just duplicate the positions when the caller hasn't provided a local coord rect, but we
+    haven't seen a use case which frequently switches between local rect and no local rect draws.
+
+    The color param is used to determine whether the opaque hint can be set on the draw state.
+    The caller must populate the vertex colors itself.
 
-static void set_vertex_attributes(GrDrawState* drawState,
-                                  bool hasColor, bool hasUVs,
-                                  int* colorOffset, int* localOffset) {
-    *colorOffset = -1;
-    *localOffset = -1;
-
-    // Using per-vertex colors allows batching across colors. (A lot of rects in a row differing
-    // only in color is a common occurrence in tables). However, having per-vertex colors disables
-    // blending optimizations because we don't know if the color will be solid or not. These
-    // optimizations help determine whether coverage and color can be blended correctly when
-    // dual-source blending isn't available. This comes into play when there is coverage. If colors
-    // were a stage it could take a hint that every vertex's color will be opaque.
-    if (hasColor && hasUVs) {
-        *colorOffset = sizeof(SkPoint);
-        *localOffset = sizeof(SkPoint) + sizeof(GrColor);
-        drawState->setVertexAttribs<kRectPosColorUVAttribs>(3);
-    } else if (hasColor) {
-        *colorOffset = sizeof(SkPoint);
-        drawState->setVertexAttribs<kRectPosColorUVAttribs>(2);
-    } else if (hasUVs) {
-        *localOffset = sizeof(SkPoint);
-        drawState->setVertexAttribs<kRectPosUVAttribs>(2);
+    The vertex attrib order is always pos, color, [local coords].
+ */
+static void set_vertex_attributes(GrDrawState* drawState, bool hasLocalCoords, GrColor color) {
+    if (hasLocalCoords) {
+        drawState->setVertexAttribs<kRectAttribs>(3);
     } else {
-        drawState->setVertexAttribs<kRectPosUVAttribs>(1);
+        drawState->setVertexAttribs<kRectAttribs>(2);
+    }
+    if (0xFF == GrColorUnpackA(color)) {
+        drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
     }
 }
 
-};
-
 enum {
     kTraceCmdBit = 0x80,
     kCmdMask = 0x7f,
 };
 
-static uint8_t add_trace_bit(uint8_t cmd) {
-    return cmd | kTraceCmdBit;
-}
+static inline uint8_t add_trace_bit(uint8_t cmd) { return cmd | kTraceCmdBit; }
 
-static uint8_t strip_trace_bit(uint8_t cmd) {
-    return cmd & kCmdMask;
-}
+static inline uint8_t strip_trace_bit(uint8_t cmd) { return cmd & kCmdMask; }
 
-static bool cmd_has_trace_marker(uint8_t cmd) {
-    return SkToBool(cmd & kTraceCmdBit);
-}
+static inline bool cmd_has_trace_marker(uint8_t cmd) { return SkToBool(cmd & kTraceCmdBit); }
 
 void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
                                      const SkRect* localRect,
@@ -143,11 +124,7 @@ void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
 
     GrColor color = drawState->getColor();
 
-    int colorOffset, localOffset;
-    set_vertex_attributes(drawState,
-                   this->caps()->dualSourceBlendingSupport() || drawState->hasSolidCoverage(),
-                   NULL != localRect,
-                   &colorOffset, &localOffset);
+    set_vertex_attributes(drawState, NULL != localRect,  color);
 
     AutoReleaseGeometry geo(this, 4, 0);
     if (!geo.succeeded()) {
@@ -176,22 +153,22 @@ void GrInOrderDrawBuffer::onDrawRect(const SkRect& rect,
     // unnecessary clipping in our onDraw().
     get_vertex_bounds(geo.vertices(), vsize, 4, &devBounds);
 
-    if (localOffset >= 0) {
-        SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + localOffset);
+    if (NULL != localRect) {
+        static const int kLocalOffset = sizeof(SkPoint) + sizeof(GrColor);
+        SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) + kLocalOffset);
         coords->setRectFan(localRect->fLeft, localRect->fTop,
                            localRect->fRight, localRect->fBottom,
-                            vsize);
+                           vsize);
         if (NULL != localMatrix) {
             localMatrix->mapPointsWithStride(coords, vsize, 4);
         }
     }
 
-    if (colorOffset >= 0) {
-        GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + colorOffset);
-        for (int i = 0; i < 4; ++i) {
-            *vertColor = color;
-            vertColor = (GrColor*) ((intptr_t) vertColor + vsize);
-        }
+    static const int kColorOffset = sizeof(SkPoint);
+    GrColor* vertColor = GrTCast<GrColor*>(GrTCast<intptr_t>(geo.vertices()) + kColorOffset);
+    for (int i = 0; i < 4; ++i) {
+        *vertColor = color;
+        vertColor = (GrColor*) ((intptr_t) vertColor + vsize);
     }
 
     this->setIndexSourceToBuffer(this->getContext()->getQuadIndexBuffer());
@@ -909,7 +886,7 @@ void GrInOrderDrawBuffer::recordStateIfNecessary() {
     }
     const GrDrawState& curr = this->getDrawState();
     GrDrawState& prev = fStates.back();
-    switch (GrDrawState::CombineIfPossible(prev, curr)) {
+    switch (GrDrawState::CombineIfPossible(prev, curr, *this->caps())) {
         case GrDrawState::kIncompatible_CombinedState:
             fStates.push_back() = this->getDrawState();
             this->addToCmdBuffer(kSetState_Cmd);