Cleanup of r2830.



git-svn-id: http://skia.googlecode.com/svn/trunk@2841 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index e306b67..29db9aa 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -602,8 +602,8 @@
 }
 
 bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) {
-
-    int rtHeight = fTarget->getRenderTarget()->height();
+    const GrDrawState& drawState = fTarget->getDrawState();
+    int rtHeight = drawState.getRenderTarget()->height();
 
     GrIRect clip;
     if (fTarget->getClip().hasConservativeBounds()) {
@@ -617,7 +617,7 @@
     // have changed since last previous path draw then we can reuse the
     // previous geoemtry.
     if (stageMask == fPreviousStages &&
-        fPreviousViewMatrix == fTarget->getViewMatrix() &&
+        fPreviousViewMatrix == drawState.getViewMatrix() &&
         fPreviousTranslate == fTranslate &&
         rtHeight == fPreviousRTHeight &&
         fClipRect == clip) {
@@ -631,7 +631,7 @@
         }
     }
 
-    GrMatrix viewM = fTarget->getViewMatrix();
+    GrMatrix viewM = drawState.getViewMatrix();
 
     PREALLOC_PTARRAY(128) lines;
     PREALLOC_PTARRAY(128) quads;
@@ -672,7 +672,7 @@
     }
 
     fPreviousStages = stageMask;
-    fPreviousViewMatrix = fTarget->getViewMatrix();
+    fPreviousViewMatrix = drawState.getViewMatrix();
     fPreviousRTHeight = rtHeight;
     fClipRect = clip;
     fPreviousTranslate = fTranslate;
@@ -685,14 +685,16 @@
         return;
     }
 
+    GrDrawState* drawState = fTarget->drawState();
+
     GrDrawTarget::AutoStateRestore asr;
-    if (!fTarget->getViewMatrix().hasPerspective()) {
+    if (!drawState->getViewMatrix().hasPerspective()) {
         asr.set(fTarget);
         GrMatrix ivm;
-        if (fTarget->getViewInverse(&ivm)) {
-            fTarget->preConcatSamplerMatrices(stageMask, ivm);
+        if (drawState->getViewInverse(&ivm)) {
+            drawState->preConcatSamplerMatrices(stageMask, ivm);
         }
-        fTarget->setViewMatrix(GrMatrix::I());
+        drawState->setViewMatrix(GrMatrix::I());
     }
 
     // TODO: See whether rendering lines as degenerate quads improves perf
@@ -702,7 +704,7 @@
     int nBufLines = fLinesIndexBuffer->maxQuads();
     while (lines < fLineSegmentCnt) {
         int n = GrMin(fLineSegmentCnt-lines, nBufLines);
-        fTarget->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
+        drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType);
         fTarget->drawIndexed(kTriangles_PrimitiveType,
                              kVertsPerLineSeg*lines,    // startV
                              0,                         // startI
@@ -715,7 +717,7 @@
     int quads = 0;
     while (quads < fQuadCnt) {
         int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer);
-        fTarget->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
+        drawState->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType);
         fTarget->drawIndexed(kTriangles_PrimitiveType,
                              4*fLineSegmentCnt + kVertsPerQuad*quads, // startV
                              0,                                       // startI
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index de80f65..f455984 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -218,20 +218,22 @@
 // they aren't used unless the vertex layout references them.
 // It also doesn't set the render target.
 void reset_target_state(GrDrawTarget* target){
-        target->setViewMatrix(GrMatrix::I());
-        target->setColorFilter(0, SkXfermode::kDst_Mode);
-        target->disableState(GrDrawTarget::kDither_StateBit |
-                             GrDrawTarget::kHWAntialias_StateBit |
-                             GrDrawTarget::kClip_StateBit |
-                             GrDrawTarget::kNoColorWrites_StateBit |
-                             GrDrawTarget::kEdgeAAConcave_StateBit);
-        target->setEdgeAAData(NULL, 0);
-        target->disableStencil();
-        target->setAlpha(0xFF);
+        GrDrawState* drawState = target->drawState();
+
+        drawState->setViewMatrix(GrMatrix::I());
+        drawState->setColorFilter(0, SkXfermode::kDst_Mode);
+        drawState->disableState(GrDrawState::kDither_StateBit |
+                                GrDrawState::kHWAntialias_StateBit |
+                                GrDrawState::kClip_StateBit |
+                                GrDrawState::kNoColorWrites_StateBit |
+                                GrDrawState::kEdgeAAConcave_StateBit);
+        drawState->setEdgeAAData(NULL, 0);
+        drawState->disableStencil();
+        drawState->setAlpha(0xFF);
         target->setBlendFunc(kOne_BlendCoeff,
                            kZero_BlendCoeff);
-        target->setFirstCoverageStage(GrDrawState::kNumStages);
-        target->setDrawFace(GrDrawState::kBoth_DrawFace);
+        drawState->setFirstCoverageStage(GrDrawState::kNumStages);
+        drawState->setDrawFace(GrDrawState::kBoth_DrawFace);
 }
 }
 
@@ -353,9 +355,9 @@
         if (NULL != texture) {
             GrDrawTarget::AutoStateRestore asr(fGpu);
             reset_target_state(fGpu);
-
-            fGpu->setRenderTarget(texture->asRenderTarget());
-            fGpu->setTexture(0, clampEntry.texture());
+            GrDrawState* drawState = fGpu->drawState();
+            drawState->setRenderTarget(texture->asRenderTarget());
+            drawState->setTexture(0, clampEntry.texture());
 
             GrSamplerState::Filter filter;
             // if filtering is not desired then we want to ensure all
@@ -368,7 +370,7 @@
             }
             GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
                                           filter);
-            fGpu->setSamplerState(0, stretchSampler);
+            drawState->setSampler(0, stretchSampler);
 
             static const GrVertexLayout layout =
                                 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
@@ -601,7 +603,7 @@
 
 void GrContext::setClip(const GrClip& clip) {
     fGpu->setClip(clip);
-    fGpu->enableState(GrDrawTarget::kClip_StateBit);
+    fGpu->drawState()->enableState(GrDrawState::kClip_StateBit);
 }
 
 void GrContext::setClip(const GrIRect& rect) {
@@ -624,22 +626,24 @@
     r.setLTRB(0, 0,
               GrIntToScalar(getRenderTarget()->width()),
               GrIntToScalar(getRenderTarget()->height()));
-    GrAutoMatrix am;
     GrMatrix inverse;
     SkTLazy<GrPaint> tmpPaint;
     const GrPaint* p = &paint;
+    GrDrawState* drawState = fGpu->drawState();
+    GrAutoMatrix am;
+
     // We attempt to map r by the inverse matrix and draw that. mapRect will
     // map the four corners and bound them with a new rect. This will not
     // produce a correct result for some perspective matrices.
     if (!this->getMatrix().hasPerspective()) {
-        if (!fGpu->getViewInverse(&inverse)) {
+        if (!drawState->getViewInverse(&inverse)) {
             GrPrintf("Could not invert matrix");
             return;
         }
         inverse.mapRect(&r);
     } else {
         if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
-            if (!fGpu->getViewInverse(&inverse)) {
+            if (!drawState->getViewInverse(&inverse)) {
                 GrPrintf("Could not invert matrix");
                 return;
             }
@@ -697,7 +701,7 @@
         (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->getCaps().fFSAASupport)) {
         return false;
     }
-    if (target->getRenderTarget()->isMultisampled()) {
+    if (target->getDrawState().getRenderTarget()->isMultisampled()) {
         return false;
     }
     if (disable_coverage_aa_for_blend(target)) {
@@ -801,19 +805,20 @@
     GrPaint tempPaint;
     tempPaint.reset();
     this->setPaint(tempPaint, target);
-    target->setRenderTarget(offRT0);
+    GrDrawState* drawState = target->drawState();
+    drawState->setRenderTarget(offRT0);
 #if PREFER_MSAA_OFFSCREEN_AA
-    target->enableState(GrDrawTarget::kHWAntialias_StateBit);
+    target->enableState(GrDrawState::kHWAntialias_StateBit);
 #endif
 
     GrMatrix transM;
     int left = boundRect.fLeft + tileX * record->fTileSizeX;
     int top =  boundRect.fTop  + tileY * record->fTileSizeY;
     transM.setTranslate(-left * GR_Scalar1, -top * GR_Scalar1);
-    target->postConcatViewMatrix(transM);
+    drawState->viewMatrix()->postConcat(transM);
     GrMatrix scaleM;
     scaleM.setScale(record->fScale * GR_Scalar1, record->fScale * GR_Scalar1);
-    target->postConcatViewMatrix(scaleM);
+    drawState->viewMatrix()->postConcat(scaleM);
 
     int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left :
                                                record->fTileSizeX;
@@ -872,19 +877,21 @@
         kOffscreenStage = GrPaint::kTotalStages,
     };
 
+    GrDrawState* drawState = target->drawState();
+
     if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
         GrAssert(NULL != record->fOffscreen1.texture());
         scale = 2;
         GrRenderTarget* dst = record->fOffscreen1.texture()->asRenderTarget();
-        
+
         // Do 2x2 downsample from first to second
-        target->setTexture(kOffscreenStage, src);
-        target->setRenderTarget(dst);
-        target->setViewMatrix(GrMatrix::I());
+        drawState->setTexture(kOffscreenStage, src);
+        drawState->setRenderTarget(dst);
+        drawState->setViewMatrix(GrMatrix::I());
         sampleM.setScale(scale * GR_Scalar1 / src->width(),
                          scale * GR_Scalar1 / src->height());
         sampler.setMatrix(sampleM);
-        target->setSamplerState(kOffscreenStage, sampler);
+        drawState->setSampler(kOffscreenStage, sampler);
         GrRect rect = SkRect::MakeWH(SkIntToScalar(scale * tileRect.width()),
                                      SkIntToScalar(scale * tileRect.height()));
         target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
@@ -911,24 +918,22 @@
 
     if (stageMask) {
         GrMatrix invVM;
-        if (target->getViewInverse(&invVM)) {
-            target->preConcatSamplerMatrices(stageMask, invVM);
+        if (drawState->getViewInverse(&invVM)) {
+            drawState->preConcatSamplerMatrices(stageMask, invVM);
         }
     }
     // This is important when tiling, otherwise second tile's 
     // pass 1 view matrix will be incorrect.
-    GrDrawTarget::AutoViewMatrixRestore avmr(target);
+    GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I());
 
-    target->setViewMatrix(GrMatrix::I());
-
-    target->setTexture(kOffscreenStage, src);
+    drawState->setTexture(kOffscreenStage, src);
     sampleM.setScale(scale * GR_Scalar1 / src->width(),
                      scale * GR_Scalar1 / src->height());
     sampler.setMatrix(sampleM);
     sampleM.setTranslate(SkIntToScalar(-tileRect.fLeft),
                          SkIntToScalar(-tileRect.fTop));
     sampler.preConcatMatrix(sampleM);
-    target->setSamplerState(kOffscreenStage, sampler);
+    drawState->setSampler(kOffscreenStage, sampler);
 
     GrRect dstRect;
     int stages = (1 << kOffscreenStage) | stageMask;
@@ -1040,7 +1045,7 @@
                                      bool useCoverage) {
     GrVertexLayout layout = 0;
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        if (NULL != target->getTexture(s)) {
+        if (NULL != target->getDrawState().getTexture(s)) {
             layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
         }
     }
@@ -1087,7 +1092,7 @@
     if (useVertexCoverage) {
         innerColor = 0xffffffff;
     } else {
-        innerColor = target->getColor();
+        innerColor = target->getDrawState().getColor();
     }
 
     verts += 4 * vsize;
@@ -1158,7 +1163,7 @@
     if (useVertexCoverage) {
         innerColor = 0xffffffff;
     } else {
-        innerColor = target->getColor();
+        innerColor = target->getDrawState().getColor();
     }
     verts += 4 * vsize;
     for (int i = 0; i < 8; ++i) {
@@ -1214,8 +1219,8 @@
             return false;
         }
     }
-
-    if (target->getRenderTarget()->isMultisampled()) {
+    const GrDrawState& drawState = target->getDrawState();
+    if (drawState.getRenderTarget()->isMultisampled()) {
         return false;
     }
 
@@ -1223,7 +1228,7 @@
         return false;
     }
 
-    if (!target->getViewMatrix().preservesAxisAlignment()) {
+    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
         return false;
     }
 
@@ -1232,7 +1237,7 @@
         return false;
     }
 
-    *combinedMatrix = target->getViewMatrix();
+    *combinedMatrix = drawState.getViewMatrix();
     if (NULL != matrix) {
         combinedMatrix->preConcat(*matrix);
         GrAssert(combinedMatrix->preservesAxisAlignment());
@@ -1267,14 +1272,7 @@
                                            &useVertexCoverage);
 
     if (doAA) {
-        GrDrawTarget::AutoViewMatrixRestore avm(target);
-        if (stageMask) {
-            GrMatrix inv;
-            if (combinedMatrix.invert(&inv)) {
-                target->preConcatSamplerMatrices(stageMask, inv);
-            }
-        }
-        target->setViewMatrix(GrMatrix::I());
+        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
         if (width >= 0) {
             GrVec strokeSize;;
             if (width > 0) {
@@ -1324,16 +1322,17 @@
             vertex[4].set(rect.fLeft, rect.fTop);
         }
 
-        GrDrawTarget::AutoViewMatrixRestore avmr;
+        GrDrawState::AutoViewMatrixRestore avmr;
         if (NULL != matrix) {
-            avmr.set(target);
-            target->preConcatViewMatrix(*matrix);
-            target->preConcatSamplerMatrices(stageMask, *matrix);
+            GrDrawState* drawState = target->drawState();
+            avmr.set(drawState);
+            drawState->preConcatViewMatrix(*matrix);
+            drawState->preConcatSamplerMatrices(stageMask, *matrix);
         }
 
         target->drawNonIndexed(primType, 0, vertCount);
     } else {
-        #if GR_STATIC_RECT_VB
+#if GR_STATIC_RECT_VB
             GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
             const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
             if (NULL == sqVB) {
@@ -1341,7 +1340,8 @@
                 return;
             }
             target->setVertexSourceToBuffer(layout, sqVB);
-            GrDrawTarget::AutoViewMatrixRestore avmr(target);
+            GrDrawState* drawState = target->drawState();
+            GrDrawState::AutoViewMatrixRestore avmr(drawState);
             GrMatrix m;
             m.setAll(rect.width(),    0,             rect.fLeft,
                         0,            rect.height(), rect.fTop,
@@ -1350,14 +1350,13 @@
             if (NULL != matrix) {
                 m.postConcat(*matrix);
             }
-
-            target->preConcatViewMatrix(m);
-            target->preConcatSamplerMatrices(stageMask, m);
+            drawState->preConcatViewMatrix(m);
+            drawState->preConcatSamplerMatrices(stageMask, m);
  
             target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
-        #else
+#else
             target->drawSimpleRect(rect, matrix, stageMask);
-        #endif
+#endif
     }
 }
 
@@ -1378,9 +1377,9 @@
 
 #if GR_STATIC_RECT_VB
     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
-    
+    GrDrawState* drawState = target->drawState();
     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
-    GrDrawTarget::AutoViewMatrixRestore avmr(target);
+    GrDrawState::AutoViewMatrixRestore avmr(drawState);
 
     GrMatrix m;
 
@@ -1390,13 +1389,13 @@
     if (NULL != dstMatrix) {
         m.postConcat(*dstMatrix);
     }
-    target->preConcatViewMatrix(m);
+    drawState->preConcatViewMatrix(m);
 
     // srcRect refers to first stage
     int otherStageMask = paint.getActiveStageMask() & 
                          (~(1 << GrPaint::kFirstTextureStage));
     if (otherStageMask) {
-        target->preConcatSamplerMatrices(otherStageMask, m);
+        drawState->preConcatSamplerMatrices(otherStageMask, m);
     }
 
     m.setAll(srcRect.width(), 0,                srcRect.fLeft,
@@ -1405,7 +1404,7 @@
     if (NULL != srcMatrix) {
         m.postConcat(*srcMatrix);
     }
-    target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m);
+    drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
 
     const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
     if (NULL == sqVB) {
@@ -1553,10 +1552,9 @@
 
     if (doOSAA) {
         bool needsStencil = pr->requiresStencilPass(target, path, fill);
-
+        const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
         // compute bounds as intersection of rt size, clip, and path
-        GrIRect bound = SkIRect::MakeWH(target->getRenderTarget()->width(), 
-                                        target->getRenderTarget()->height());
+        GrIRect bound = SkIRect::MakeWH(rt->width(), rt->height());
         GrIRect clipIBounds;
         if (target->getClip().hasConservativeBounds()) {
             target->getClip().getConservativeBounds().roundOut(&clipIBounds);
@@ -1564,13 +1562,13 @@
                 return;
             }
         }
-
         GrRect pathBounds = path.getBounds();
         if (!pathBounds.isEmpty()) {
             if (NULL != translate) {
                 pathBounds.offset(*translate);
             }
-            target->getViewMatrix().mapRect(&pathBounds, pathBounds);
+            target->getDrawState().getViewMatrix().mapRect(&pathBounds,
+                                                           pathBounds);
             GrIRect pathIBounds;
             pathBounds.roundOut(&pathIBounds);
             if (!bound.intersect(pathIBounds)) {
@@ -1706,7 +1704,7 @@
     ASSERT_OWNED_RESOURCE(target);
 
     if (NULL == target) { 
-        target = fGpu->getRenderTarget();
+        target = fGpu->drawState()->getRenderTarget();
         if (NULL == target) {
             return false;
         }
@@ -1782,8 +1780,8 @@
 
         GrDrawTarget::AutoStateRestore asr(fGpu);
         reset_target_state(fGpu);
-
-        fGpu->setRenderTarget(target);
+        GrDrawState* drawState = fGpu->drawState();
+        drawState->setRenderTarget(target);
 
         GrMatrix matrix;
         if (flipY) {
@@ -1799,8 +1797,8 @@
                       GrSamplerState::kNearest_Filter,
                       matrix);
         sampler.setRAndBSwap(swapRAndB);
-        fGpu->setSamplerState(0, sampler);
-        fGpu->setTexture(0, src);
+        drawState->setSampler(0, sampler);
+        drawState->setTexture(0, src);
         GrRect rect;
         rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
         fGpu->drawSimpleRect(rect, NULL, 0x1);
@@ -1820,14 +1818,15 @@
 
     GrDrawTarget::AutoStateRestore asr(fGpu);
     reset_target_state(fGpu);
-    fGpu->setRenderTarget(dst);
+    GrDrawState* drawState = fGpu->drawState();
+    drawState->setRenderTarget(dst);
     GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
                            GrSamplerState::kNearest_Filter);
     GrMatrix sampleM;
     sampleM.setIDiv(src->width(), src->height());
     sampler.setMatrix(sampleM);
-    fGpu->setTexture(0, src);
-    fGpu->setSamplerState(0, sampler);
+    drawState->setTexture(0, src);
+    drawState->setSampler(0, sampler);
     SkRect rect = SkRect::MakeXYWH(0, 0, src->width(), src->height());
     fGpu->drawSimpleRect(rect, NULL, 1 << 0);
 }
@@ -1843,7 +1842,7 @@
     ASSERT_OWNED_RESOURCE(target);
 
     if (NULL == target) { 
-        target = fGpu->getRenderTarget();
+        target = fGpu->drawState()->getRenderTarget();
         if (NULL == target) {
             return;
         }
@@ -1890,12 +1889,13 @@
 
     GrDrawTarget::AutoStateRestore  asr(fGpu);
     reset_target_state(fGpu);
+    GrDrawState* drawState = fGpu->drawState();
 
     GrMatrix matrix;
     matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
-    fGpu->setViewMatrix(matrix);
-    fGpu->setRenderTarget(target);
-    fGpu->setTexture(0, texture);
+    drawState->setViewMatrix(matrix);
+    drawState->setRenderTarget(target);
+    drawState->setTexture(0, texture);
 
     matrix.setIDiv(texture->width(), texture->height());
     GrSamplerState sampler;
@@ -1903,7 +1903,7 @@
                   GrSamplerState::kNearest_Filter,
                   matrix);
     sampler.setRAndBSwap(swapRAndB);
-    fGpu->setSamplerState(0, sampler);
+    drawState->setSampler(0, sampler);
 
     GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
     static const int VCOUNT = 4;
@@ -1919,37 +1919,38 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
+    GrDrawState* drawState = target->drawState();
 
     for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
         int s = i + GrPaint::kFirstTextureStage;
-        target->setTexture(s, paint.getTexture(i));
+        drawState->setTexture(s, paint.getTexture(i));
         ASSERT_OWNED_RESOURCE(paint.getTexture(i));
-        target->setSamplerState(s, paint.getTextureSampler(i));
+        drawState->setSampler(s, paint.getTextureSampler(i));
     }
 
-    target->setFirstCoverageStage(GrPaint::kFirstMaskStage);
+    drawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
 
     for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
         int s = i + GrPaint::kFirstMaskStage;
-        target->setTexture(s, paint.getMask(i));
+        drawState->setTexture(s, paint.getMask(i));
         ASSERT_OWNED_RESOURCE(paint.getMask(i));
-        target->setSamplerState(s, paint.getMaskSampler(i));
+        drawState->setSampler(s, paint.getMaskSampler(i));
     }
 
-    target->setColor(paint.fColor);
+    drawState->setColor(paint.fColor);
 
     if (paint.fDither) {
-        target->enableState(GrDrawTarget::kDither_StateBit);
+        drawState->enableState(GrDrawState::kDither_StateBit);
     } else {
-        target->disableState(GrDrawTarget::kDither_StateBit);
+        drawState->disableState(GrDrawState::kDither_StateBit);
     }
     if (paint.fAntiAlias) {
-        target->enableState(GrDrawTarget::kHWAntialias_StateBit);
+        drawState->enableState(GrDrawState::kHWAntialias_StateBit);
     } else {
-        target->disableState(GrDrawTarget::kHWAntialias_StateBit);
+        drawState->disableState(GrDrawState::kHWAntialias_StateBit);
     }
     target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
-    target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
+    drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
 
     if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
         GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
@@ -2000,27 +2001,27 @@
 void GrContext::setRenderTarget(GrRenderTarget* target) {
     ASSERT_OWNED_RESOURCE(target);
     this->flush(false);
-    fGpu->setRenderTarget(target);
+    fGpu->drawState()->setRenderTarget(target);
 }
 
 GrRenderTarget* GrContext::getRenderTarget() {
-    return fGpu->getRenderTarget();
+    return fGpu->drawState()->getRenderTarget();
 }
 
 const GrRenderTarget* GrContext::getRenderTarget() const {
-    return fGpu->getRenderTarget();
+    return fGpu->getDrawState().getRenderTarget();
 }
 
 const GrMatrix& GrContext::getMatrix() const {
-    return fGpu->getViewMatrix();
+    return fGpu->getDrawState().getViewMatrix();
 }
 
 void GrContext::setMatrix(const GrMatrix& m) {
-    fGpu->setViewMatrix(m);
+    fGpu->drawState()->setViewMatrix(m);
 }
 
 void GrContext::concatMatrix(const GrMatrix& m) const {
-    fGpu->preConcatViewMatrix(m);
+    fGpu->drawState()->preConcatViewMatrix(m);
 }
 
 static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
@@ -2149,10 +2150,11 @@
     sampler.setConvolutionParams(kernelWidth, kernel, imageIncrement);
     sampleM.setIDiv(texture->width(), texture->height());
     sampler.setMatrix(sampleM);
-    fGpu->setSamplerState(0, sampler);
-    fGpu->setViewMatrix(GrMatrix::I());
-    fGpu->setTexture(0, texture);
-    fGpu->setColor(0xFFFFFFFF);
+    GrDrawState* drawState = fGpu->drawState();
+    drawState->setSampler(0, sampler);
+    drawState->setViewMatrix(GrMatrix::I());
+    drawState->setTexture(0, texture);
+    drawState->setAlpha(0xFF);
     fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
     fGpu->drawSimpleRect(rect, NULL, 1 << 0);
 }
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index 197ee06..ebd0cc1 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -190,7 +190,8 @@
         return hint == kConvex_ConvexHint ||
                hint == kNonOverlappingConvexPieces_ConvexHint ||
                (hint == kSameWindingConvexPieces_ConvexHint &&
-                !target.drawWillReadDst() && !target.isDitherState());
+                !target.drawWillReadDst() &&
+                !target.getDrawState().isDitherState());
 
     }
     return false;
@@ -384,9 +385,10 @@
 void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
                                        bool stencilOnly) {
 
-    GrMatrix viewM = fTarget->getViewMatrix();
+    GrMatrix viewM = fTarget->getDrawState().getViewMatrix();
     GrScalar tol = GR_Scalar1;
     tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
+    GrDrawState* drawState = fTarget->drawState();
 
     // FIXME: It's really dumb that we recreate the verts for a new vertex
     // layout. We only do that because the GrDrawTarget API doesn't allow
@@ -405,9 +407,9 @@
 
     GrAssert(NULL != fTarget);
     GrDrawTarget::AutoStateRestore asr(fTarget);
-    bool colorWritesWereDisabled = fTarget->isColorWriteDisabled();
+    bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
     // face culling doesn't make sense here
-    GrAssert(GrDrawState::kBoth_DrawFace == fTarget->getDrawFace());
+    GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
 
     int                         passCount = 0;
     const GrStencilSettings*    passes[3];
@@ -503,36 +505,36 @@
 
     {
     for (int p = 0; p < passCount; ++p) {
-        fTarget->setDrawFace(drawFace[p]);
+        drawState->setDrawFace(drawFace[p]);
         if (NULL != passes[p]) {
-            fTarget->setStencil(*passes[p]);
+            *drawState->stencil() = *passes[p];
         }
 
         if (lastPassIsBounds && (p == passCount-1)) {
             if (!colorWritesWereDisabled) {
-                fTarget->disableState(GrDrawTarget::kNoColorWrites_StateBit);
+                drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
             }
             GrRect bounds;
             if (reverse) {
-                GrAssert(NULL != fTarget->getRenderTarget());
+                GrAssert(NULL != drawState->getRenderTarget());
                 // draw over the whole world.
                 bounds.setLTRB(0, 0,
-                               GrIntToScalar(fTarget->getRenderTarget()->width()),
-                               GrIntToScalar(fTarget->getRenderTarget()->height()));
+                               GrIntToScalar(drawState->getRenderTarget()->width()),
+                               GrIntToScalar(drawState->getRenderTarget()->height()));
                 GrMatrix vmi;
                 // mapRect through persp matrix may not be correct
-                if (!fTarget->getViewMatrix().hasPerspective() &&
-                    fTarget->getViewInverse(&vmi)) {
+                if (!drawState->getViewMatrix().hasPerspective() &&
+                    drawState->getViewInverse(&vmi)) {
                     vmi.mapRect(&bounds);
                 } else {
                     if (stageMask) {
-                        if (!fTarget->getViewInverse(&vmi)) {
+                        if (!drawState->getViewInverse(&vmi)) {
                             GrPrintf("Could not invert matrix.");
                             return;
                         }
-                        fTarget->preConcatSamplerMatrices(stageMask, vmi);
+                        drawState->preConcatSamplerMatrices(stageMask, vmi);
                     }
-                    fTarget->setViewMatrix(GrMatrix::I());
+                    drawState->setViewMatrix(GrMatrix::I());
                 }
             } else {
                 bounds = fPath->getBounds();
@@ -542,7 +544,7 @@
             fTarget->drawSimpleRect(bounds, NULL, stageMask);
         } else {
             if (passCount > 1) {
-                fTarget->enableState(GrDrawTarget::kNoColorWrites_StateBit);
+                drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
             }
             if (fUseIndexedDraw) {
                 fTarget->drawIndexed(fPrimitiveType, 0, 0, 
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 90de1a3..7526b9f 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -10,6 +10,7 @@
 
 #include "GrColor.h"
 #include "GrMatrix.h"
+#include "GrNoncopyable.h"
 #include "GrSamplerState.h"
 #include "GrStencil.h"
 
@@ -45,13 +46,433 @@
     typedef uint32_t StageMask;
     GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
 
-    enum DrawFace {
-        kBoth_DrawFace,
-        kCCW_DrawFace,
-        kCW_DrawFace,
+    GrDrawState() {
+        // make sure any pad is zero for memcmp
+        // all GrDrawState members should default to something
+        // valid by the memset
+        memset(this, 0, sizeof(GrDrawState));
+            
+        // memset exceptions
+        fColorFilterMode = SkXfermode::kDstIn_Mode;
+        fFirstCoverageStage = kNumStages;
+
+        // pedantic assertion that our ptrs will
+        // be NULL (0 ptr is mem addr 0)
+        GrAssert((intptr_t)(void*)NULL == 0LL);
+
+        GrAssert(fStencilSettings.isDisabled());
+        fFirstCoverageStage = kNumStages;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Color
+    ////
+
+    /**
+     *  Sets color for next draw to a premultiplied-alpha color.
+     *
+     *  @param color    the color to set.
+     */
+    void setColor(GrColor color) { fColor = color; }
+
+    GrColor getColor() const { return fColor; }
+
+    /**
+     *  Sets the color to be used for the next draw to be
+     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
+     *
+     *  @param alpha The alpha value to set as the color.
+     */
+    void setAlpha(uint8_t a) {
+        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
+    }
+
+    /**
+     * Add a color filter that can be represented by a color and a mode. Applied
+     * after color-computing texture stages.
+     */
+    void setColorFilter(GrColor c, SkXfermode::Mode mode) {
+        fColorFilterColor = c;
+        fColorFilterMode = mode;
+    }
+
+    GrColor getColorFilterColor() const { return fColorFilterColor; }
+    SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Textures
+    ////
+
+    /**
+     * Sets the texture used at the next drawing call
+     *
+     * @param stage The texture stage for which the texture will be set
+     *
+     * @param texture The texture to set. Can be NULL though there is no
+     * advantage to settings a NULL texture if doing non-textured drawing
+     */
+    void setTexture(int stage, GrTexture* texture) {
+        GrAssert((unsigned)stage < kNumStages);
+        fTextures[stage] = texture;
+    }
+
+    /**
+     * Retrieves the currently set texture.
+     *
+     * @return    The currently set texture. The return value will be NULL if no
+     *            texture has been set, NULL was most recently passed to
+     *            setTexture, or the last setTexture was destroyed.
+     */
+    const GrTexture* getTexture(int stage) const {
+        GrAssert((unsigned)stage < kNumStages);
+        return fTextures[stage];
+    }
+    GrTexture* getTexture(int stage) {
+        GrAssert((unsigned)stage < kNumStages);
+        return fTextures[stage];
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Samplers
+    ////
+
+    /**
+     * Returns the current sampler for a stage.
+     */
+    const GrSamplerState& getSampler(int stage) const {
+        GrAssert((unsigned)stage < kNumStages);
+        return fSamplerStates[stage];
+    }
+
+    /**
+     * Sets the sampler. This will be removed soon in favor of direct access.
+     */
+    void setSampler(int stage, const GrSamplerState& sampler) {
+        GrAssert((unsigned)stage < kNumStages);
+        fSamplerStates[stage] = sampler;
+    }
+
+    /**
+     * Writable pointer to a stage's sampler.
+     */
+    GrSamplerState* sampler(int stage) {
+        GrAssert((unsigned)stage < kNumStages);
+        return fSamplerStates + stage;
+    }
+
+    /**
+     * Preconcats the matrix of all samplers in the mask with the same matrix.
+     */
+    void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
+        GrAssert(!(stageMask & kIllegalStageMaskBits));
+        for (int i = 0; i < kNumStages; ++i) {
+            if ((1 << i) & stageMask) {
+                fSamplerStates[i].preConcatMatrix(matrix);
+            }
+        }
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Coverage / Color Stages
+    ////
+
+    /**
+     * A common pattern is to compute a color with the initial stages and then
+     * modulate that color by a coverage value in later stage(s) (AA, mask-
+     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be 
+     * computed based on the pre-coverage-modulated color. The division of 
+     * stages between color-computing and coverage-computing is specified by 
+     * this method. Initially this is kNumStages (all stages
+     * are color-computing).
+     */
+    void setFirstCoverageStage(int firstCoverageStage) {
+        GrAssert((unsigned)firstCoverageStage <= kNumStages);
+        fFirstCoverageStage = firstCoverageStage; 
+    }
+
+    /**
+     * Gets the index of the first coverage-computing stage.
+     */
+    int getFirstCoverageStage() const {
+        return fFirstCoverageStage; 
+    }
+
+    ///@}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Blending
+    ////
+
+    /**
+     * Sets the blending function coeffecients.
+     *
+     * The blend function will be:
+     *    D' = sat(S*srcCoef + D*dstCoef)
+     *
+     *   where D is the existing destination color, S is the incoming source
+     *   color, and D' is the new destination color that will be written. sat()
+     *   is the saturation function.
+     *
+     * @param srcCoef coeffecient applied to the src color.
+     * @param dstCoef coeffecient applied to the dst color.
+     */
+    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
+        fSrcBlend = srcCoeff;
+        fDstBlend = dstCoeff;
+    #if GR_DEBUG
+        switch (dstCoeff) {
+        case kDC_BlendCoeff:
+        case kIDC_BlendCoeff:
+        case kDA_BlendCoeff:
+        case kIDA_BlendCoeff:
+            GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
+                     "coverage stages.\n");
+            break;
+        default:
+            break;
+        }
+        switch (srcCoeff) {
+        case kSC_BlendCoeff:
+        case kISC_BlendCoeff:
+        case kSA_BlendCoeff:
+        case kISA_BlendCoeff:
+            GrPrintf("Unexpected src blend coeff. Won't work correctly with"
+                     "coverage stages.\n");
+            break;
+        default:
+            break;
+        }
+    #endif
+    }
+
+    GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+    GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
+
+    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
+                          GrBlendCoeff* dstBlendCoeff) const {
+        *srcBlendCoeff = fSrcBlend;
+        *dstBlendCoeff = fDstBlend;
+    }
+
+    /**
+     * Sets the blending function constant referenced by the following blending
+     * coeffecients:
+     *      kConstC_BlendCoeff
+     *      kIConstC_BlendCoeff
+     *      kConstA_BlendCoeff
+     *      kIConstA_BlendCoeff
+     *
+     * @param constant the constant to set
+     */
+    void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
+
+    /**
+     * Retrieves the last value set by setBlendConstant()
+     * @return the blending constant value
+     */
+    GrColor getBlendConstant() const { return fBlendConstant; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name View Matrix
+    ////
+
+    /**
+     * Sets the matrix applied to veretx positions.
+     *
+     * In the post-view-matrix space the rectangle [0,w]x[0,h]
+     * fully covers the render target. (w and h are the width and height of the
+     * the rendertarget.)
+     */
+    void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
+
+    /**
+     * Gets a writable pointer to the view matrix.
+     */
+    GrMatrix* viewMatrix() { return &fViewMatrix; }
+
+    /**
+     *  Multiplies the current view matrix by a matrix
+     *
+     *  After this call V' = V*m where V is the old view matrix,
+     *  m is the parameter to this function, and V' is the new view matrix.
+     *  (We consider positions to be column vectors so position vector p is
+     *  transformed by matrix X as p' = X*p.)
+     *
+     *  @param m the matrix used to modify the view matrix.
+     */
+    void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
+
+    /**
+     *  Multiplies the current view matrix by a matrix
+     *
+     *  After this call V' = m*V where V is the old view matrix,
+     *  m is the parameter to this function, and V' is the new view matrix.
+     *  (We consider positions to be column vectors so position vector p is
+     *  transformed by matrix X as p' = X*p.)
+     *
+     *  @param m the matrix used to modify the view matrix.
+     */
+    void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
+
+    /**
+     * Retrieves the current view matrix
+     * @return the current view matrix.
+     */
+    const GrMatrix& getViewMatrix() const { return fViewMatrix; }
+
+    /**
+     *  Retrieves the inverse of the current view matrix.
+     *
+     *  If the current view matrix is invertible, return true, and if matrix
+     *  is non-null, copy the inverse into it. If the current view matrix is
+     *  non-invertible, return false and ignore the matrix parameter.
+     *
+     * @param matrix if not null, will receive a copy of the current inverse.
+     */
+    bool getViewInverse(GrMatrix* matrix) const {
+        // TODO: determine whether we really need to leave matrix unmodified
+        // at call sites when inversion fails.
+        GrMatrix inverse;
+        if (fViewMatrix.invert(&inverse)) {
+            if (matrix) {
+                *matrix = inverse;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    class AutoViewMatrixRestore : public ::GrNoncopyable {
+    public:
+        AutoViewMatrixRestore() : fDrawState(NULL) {}
+        AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
+            fDrawState = NULL;
+            this->set(ds, newMatrix);
+        }
+        AutoViewMatrixRestore(GrDrawState* ds) {
+            fDrawState = NULL;
+            this->set(ds);
+        }
+        ~AutoViewMatrixRestore() {
+            this->set(NULL, GrMatrix::I());
+        }
+        void set(GrDrawState* ds, const GrMatrix& newMatrix) {
+            if (NULL != fDrawState) {
+                fDrawState->setViewMatrix(fSavedMatrix);
+            }
+            if (NULL != ds) {
+                fSavedMatrix = ds->getViewMatrix();
+                ds->setViewMatrix(newMatrix);
+            }
+            fDrawState = ds;
+        }
+        void set(GrDrawState* ds) {
+            if (NULL != fDrawState) {
+                fDrawState->setViewMatrix(fSavedMatrix);
+            }
+            if (NULL != ds) {
+                fSavedMatrix = ds->getViewMatrix();
+            }
+            fDrawState = ds;
+        }
+    private:
+        GrDrawState* fDrawState;
+        GrMatrix fSavedMatrix;
     };
 
-     /**
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Render Target
+    ////
+
+    /**
+     * Sets the rendertarget used at the next drawing call
+     *
+     * @param target  The render target to set.
+     */
+    void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
+
+    /**
+     * Retrieves the currently set rendertarget.
+     *
+     * @return    The currently set render target.
+     */
+    const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
+    GrRenderTarget* getRenderTarget() { return fRenderTarget; }
+
+    class AutoRenderTargetRestore : public ::GrNoncopyable {
+    public:
+        AutoRenderTargetRestore() : fDrawState(NULL) {}
+        AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
+            fDrawState = NULL;
+            this->set(ds, newTarget);
+        }
+        ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
+        void set(GrDrawState* ds, GrRenderTarget* newTarget) {
+            if (NULL != fDrawState) {
+                fDrawState->setRenderTarget(fSavedTarget);
+            }
+            if (NULL != ds) {
+                fSavedTarget = ds->getRenderTarget();
+                ds->setRenderTarget(newTarget);
+            }
+            fDrawState = ds;
+        }
+    private:
+        GrDrawState* fDrawState;
+        GrRenderTarget* fSavedTarget;
+    };
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Stencil
+    ////
+
+    /**
+     * Sets the stencil settings to use for the next draw.
+     * Changing the clip has the side-effect of possibly zeroing
+     * out the client settable stencil bits. So multipass algorithms
+     * using stencil should not change the clip between passes.
+     * @param settings  the stencil settings to use.
+     */
+    void setStencil(const GrStencilSettings& settings) {
+        fStencilSettings = settings;
+    }
+
+    /**
+     * Shortcut to disable stencil testing and ops.
+     */
+    void disableStencil() {
+        fStencilSettings.setDisabled();
+    }
+
+    const GrStencilSettings& getStencil() const { return fStencilSettings; }
+
+    GrStencilSettings* stencil() { return &fStencilSettings; }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    // @name Edge AA
+    // There are two ways to perform antialiasing using edge equations. One
+    // is to specify an (linear or quadratic) edge eq per-vertex. This requires
+    // splitting vertices shared by primitives.
+    //
+    // The other is via setEdgeAAData which sets a set of edges and each
+    // is tested against all the edges.
+    ////
+
+    /**
      * When specifying edges as vertex data this enum specifies what type of
      * edges are in use. The edges are always 4 GrScalars in memory, even when
      * the edge type requires fewer than 4.
@@ -66,6 +487,19 @@
     };
 
     /**
+     * Determines the interpretation per-vertex edge data when the 
+     * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
+     * are not specified the value of this setting has no effect.
+     */
+    void setVertexEdgeType(VertexEdgeType type) {
+        fVertexEdgeType = type;
+    }
+
+    VertexEdgeType getVertexEdgeType() const {
+        return fVertexEdgeType;
+    }
+
+    /**
      * The absolute maximum number of edges that may be specified for
      * a single draw call when performing edge antialiasing.  This is used for
      * the size of several static buffers, so implementations of getMaxEdges()
@@ -91,53 +525,146 @@
         float fX, fY, fZ;
     };
 
-    GrDrawState() {
-        // make sure any pad is zero for memcmp
-        // all GrDrawState members should default to something
-        // valid by the memset
-        memset(this, 0, sizeof(GrDrawState));
-            
-        // memset exceptions
-        fColorFilterXfermode = SkXfermode::kDstIn_Mode;
-        fFirstCoverageStage = kNumStages;
-
-        // pedantic assertion that our ptrs will
-        // be NULL (0 ptr is mem addr 0)
-        GrAssert((intptr_t)(void*)NULL == 0LL);
-
-        // default stencil setting should be disabled
-        GrAssert(fStencilSettings.isDisabled());
-        fFirstCoverageStage = kNumStages;
+    /**
+     * Sets the edge data required for edge antialiasing.
+     *
+     * @param edges       3 * numEdges float values, representing the edge
+     *                    equations in Ax + By + C form
+     */
+    void setEdgeAAData(const Edge* edges, int numEdges) {
+        GrAssert(numEdges <= GrDrawState::kMaxEdges);
+        memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
+        fEdgeAANumEdges = numEdges;
     }
 
-    uint8_t                 fFlagBits;
-    GrBlendCoeff            fSrcBlend : 8;
-    GrBlendCoeff            fDstBlend : 8;
-    DrawFace                fDrawFace : 8;
-    uint8_t                 fFirstCoverageStage;
-    SkXfermode::Mode        fColorFilterXfermode : 8;
-    GrColor                 fBlendConstant;
-    GrTexture*              fTextures[kNumStages];
-    GrRenderTarget*         fRenderTarget;
-    GrColor                 fColor;
-    GrColor                 fColorFilterColor;
+    int getNumAAEdges() const { return fEdgeAANumEdges; }
 
-    GrStencilSettings       fStencilSettings;
-    GrMatrix                fViewMatrix;
+    const Edge* getAAEdges() const { return fEdgeAAEdges; }
 
-    // @{ Data for GrTesselatedPathRenderer
-    // TODO: currently ignored in copying & comparison for performance.
-    // Must be considered if GrTesselatedPathRenderer is being used.
+    /// @}
 
-    int                     fEdgeAANumEdges;
-    VertexEdgeType          fVertexEdgeType;
-    Edge                    fEdgeAAEdges[kMaxEdges];
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name State Flags
+    ////
 
-    // @}
+    /**
+     *  Flags that affect rendering. Controlled using enable/disableState(). All
+     *  default to disabled.
+     */
+    enum StateBits {
+        /**
+         * Perform dithering. TODO: Re-evaluate whether we need this bit
+         */
+        kDither_StateBit        = 0x01,
+        /**
+         * Perform HW anti-aliasing. This means either HW FSAA, if supported
+         * by the render target, or smooth-line rendering if a line primitive
+         * is drawn and line smoothing is supported by the 3D API.
+         */
+        kHWAntialias_StateBit   = 0x02,
+        /**
+         * Draws will respect the clip, otherwise the clip is ignored.
+         */
+        kClip_StateBit          = 0x04,
+        /**
+         * Disables writing to the color buffer. Useful when performing stencil
+         * operations.
+         */
+        kNoColorWrites_StateBit = 0x08,
+        /**
+         * Modifies the behavior of edge AA specified by setEdgeAA. If set, 
+         * will test edge pairs for convexity when rasterizing. Set this if the 
+         * source polygon is non-convex.
+         */
+        kEdgeAAConcave_StateBit = 0x10,
 
-    // This field must be last; it will not be copied or compared
-    // if the corresponding fTexture[] is NULL.
-    GrSamplerState          fSamplerStates[kNumStages];
+        // Users of the class may add additional bits to the vector
+        kDummyStateBit,
+        kLastPublicStateBit = kDummyStateBit-1,
+    };
+
+    void resetStateFlags() {
+        fFlagBits = 0;
+    }
+
+    /**
+     * Enable render state settings.
+     *
+     * @param flags   bitfield of StateBits specifing the states to enable
+     */
+    void enableState(uint32_t stateBits) {
+        fFlagBits |= stateBits;
+    }
+
+    /**
+     * Disable render state settings.
+     *
+     * @param flags   bitfield of StateBits specifing the states to disable
+     */
+    void disableState(uint32_t stateBits) {
+        fFlagBits &= ~(stateBits);
+    }
+
+    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 isConcaveEdgeAAState() const {
+        return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
+    }
+
+    bool isStateFlagEnabled(uint32_t stateBit) const {
+        return 0 != (stateBit & fFlagBits);
+    }
+
+    void copyStateFlags(const GrDrawState& ds) {
+        fFlagBits = ds.fFlagBits;
+    }
+
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
+    /// @name Face Culling
+    ////
+
+    enum DrawFace {
+        kBoth_DrawFace,
+        kCCW_DrawFace,
+        kCW_DrawFace,
+    };
+
+    /**
+     * Controls whether clockwise, counterclockwise, or both faces are drawn.
+     * @param face  the face(s) to draw.
+     */
+    void setDrawFace(DrawFace face) {
+        fDrawFace = face;
+    }
+
+    /**
+     * Gets whether the target is drawing clockwise, counterclockwise,
+     * or both faces.
+     * @return the current draw face(s).
+     */
+    DrawFace getDrawFace() const {
+        return fDrawFace;
+    }
+    
+    /// @}
+
+    ///////////////////////////////////////////////////////////////////////////
 
     // Most stages are usually not used, so conditionals here
     // reduce the expected number of bytes touched by 50%.
@@ -172,6 +699,33 @@
     }
 
 private:
+    static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
+    uint8_t                 fFlagBits;
+    GrBlendCoeff            fSrcBlend : 8;
+    GrBlendCoeff            fDstBlend : 8;
+    DrawFace                fDrawFace : 8;
+    uint8_t                 fFirstCoverageStage;
+    SkXfermode::Mode        fColorFilterMode : 8;
+    GrColor                 fBlendConstant;
+    GrTexture*              fTextures[kNumStages];
+    GrRenderTarget*         fRenderTarget;
+    GrColor                 fColor;
+    GrColor                 fColorFilterColor;
+    GrStencilSettings       fStencilSettings;
+    GrMatrix                fViewMatrix;
+    // @{ Data for GrTesselatedPathRenderer
+    // TODO: currently ignored in copying & comparison for performance.
+    // Must be considered if GrTesselatedPathRenderer is being used.
+
+    VertexEdgeType          fVertexEdgeType;
+    int                     fEdgeAANumEdges;
+    Edge                    fEdgeAAEdges[kMaxEdges];
+
+    // @}
+    // This field must be last; it will not be copied or compared
+    // if the corresponding fTexture[] is NULL.
+    GrSamplerState          fSamplerStates[kNumStages];
+
     size_t leadingBytes() const {
         // Can't use offsetof() with non-POD types, so stuck with pointer math.
         // TODO: ignores GrTesselatedPathRenderer data structures. We don't
@@ -184,4 +738,3 @@
 };
 
 #endif
-
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 7a84262..aa5cf20 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -10,9 +10,10 @@
 
 #include "GrDrawTarget.h"
 #include "GrGpuVertex.h"
+#include "GrIndexBuffer.h"
+#include "GrRenderTarget.h"
 #include "GrTexture.h"
 #include "GrVertexBuffer.h"
-#include "GrIndexBuffer.h"
 
 namespace {
 
@@ -455,119 +456,6 @@
     return fClip;
 }
 
-void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
-    GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
-    fCurrDrawState.fTextures[stage] = tex;
-}
-
-const GrTexture* GrDrawTarget::getTexture(int stage) const {
-    GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
-    return fCurrDrawState.fTextures[stage];
-}
-
-GrTexture* GrDrawTarget::getTexture(int stage) {
-    GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
-    return fCurrDrawState.fTextures[stage];
-}
-
-void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
-    fCurrDrawState.fRenderTarget = target;
-}
-
-const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
-    return fCurrDrawState.fRenderTarget;
-}
-
-GrRenderTarget* GrDrawTarget::getRenderTarget() {
-    return fCurrDrawState.fRenderTarget;
-}
-
-void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
-    fCurrDrawState.fViewMatrix = m;
-}
-
-void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
-    fCurrDrawState.fViewMatrix.preConcat(matrix);
-}
-
-void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
-    fCurrDrawState.fViewMatrix.postConcat(matrix);
-}
-
-const GrMatrix& GrDrawTarget::getViewMatrix() const {
-    return fCurrDrawState.fViewMatrix;
-}
-
-bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
-    // Mike:  Can we cache this somewhere?
-    // Brian: Sure, do we use it often?
-
-    GrMatrix inverse;
-    if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
-        if (matrix) {
-            *matrix = inverse;
-        }
-        return true;
-    }
-    return false;
-}
-
-void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
-    GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
-    fCurrDrawState.fSamplerStates[stage] = state;
-}
-
-void GrDrawTarget::enableState(uint32_t bits) {
-    fCurrDrawState.fFlagBits |= bits;
-}
-
-void GrDrawTarget::disableState(uint32_t bits) {
-    fCurrDrawState.fFlagBits &= ~(bits);
-}
-
-void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff,
-                                GrBlendCoeff dstCoeff) {
-    fCurrDrawState.fSrcBlend = srcCoeff;
-    fCurrDrawState.fDstBlend = dstCoeff;
-#if GR_DEBUG
-    switch (dstCoeff) {
-    case kDC_BlendCoeff:
-    case kIDC_BlendCoeff:
-    case kDA_BlendCoeff:
-    case kIDA_BlendCoeff:
-        GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
-                 "coverage stages.\n");
-        break;
-    default:
-        break;
-    }
-    switch (srcCoeff) {
-    case kSC_BlendCoeff:
-    case kISC_BlendCoeff:
-    case kSA_BlendCoeff:
-    case kISA_BlendCoeff:
-        GrPrintf("Unexpected src blend coeff. Won't work correctly with"
-                 "coverage stages.\n");
-        break;
-    default:
-        break;
-    }
-#endif
-}
-
-void GrDrawTarget::setColor(GrColor c) {
-    fCurrDrawState.fColor = c;
-}
-
-void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
-    fCurrDrawState.fColorFilterColor = c;
-    fCurrDrawState.fColorFilterXfermode = mode;
-}
-
-void GrDrawTarget::setAlpha(uint8_t a) {
-    this->setColor((a << 24) | (a << 16) | (a << 8) | a);
-}
-
 void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
     state->fState = fCurrDrawState;
 }
@@ -800,12 +688,13 @@
         }
     }
 #endif
-    if (NULL == this->getRenderTarget()) {
+    const GrDrawState& drawState = this->getDrawState();
+    if (NULL == drawState.getRenderTarget()) {
         return false;
     }
-    if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) {
-        if (kOne_BlendCoeff != fCurrDrawState.fSrcBlend ||
-            kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
+    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
+        if (kOne_BlendCoeff != drawState.getSrcBlendCoeff() ||
+            kZero_BlendCoeff != drawState.getDstBlendCoeff()) {
             return false;
         }
     }
@@ -817,8 +706,9 @@
         // a custom bilerp in the shader. Until Skia itself supports unpremul
         // configs there is no pressure to implement this.
         if (this->isStageEnabled(s) &&
-            GrPixelConfigIsUnpremultiplied(fCurrDrawState.fTextures[s]->config()) &&
-            GrSamplerState::kNearest_Filter != fCurrDrawState.fSamplerStates[s].getFilter()) {
+            GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
+            GrSamplerState::kNearest_Filter !=
+            drawState.getSampler(s).getFilter()) {
             return false;
         }
     }
@@ -861,31 +751,33 @@
      * for Cd we find that only 1, ISA, and ISC produce the correct depth
      * coeffecient in terms of S' and D.
      */
-    return kOne_BlendCoeff == fCurrDrawState.fDstBlend||
-           kISA_BlendCoeff == fCurrDrawState.fDstBlend ||
-           kISC_BlendCoeff == fCurrDrawState.fDstBlend;
+    GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
+    return kOne_BlendCoeff == dstCoeff ||
+           kISA_BlendCoeff == dstCoeff ||
+           kISC_BlendCoeff == dstCoeff;
 }
 
 
 bool GrDrawTarget::srcAlphaWillBeOne() const {
     const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
+    const GrDrawState& drawState = this->getDrawState();
 
     // Check if per-vertex or constant color may have partial alpha
     if ((layout & kColor_VertexLayoutBit) ||
-        0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
+        0xff != GrColorUnpackA(drawState.getColor())) {
         return false;
     }
     // Check if color filter could introduce an alpha
     // (TODO: Consider being more aggressive with regards to detecting 0xff
     // final alpha from color filter).
-    if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
+    if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
         return false;
     }
     // Check if a color stage could create a partial alpha
-    for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
+    for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
         if (StageWillBeUsed(s, layout, fCurrDrawState)) {
-            GrAssert(NULL != fCurrDrawState.fTextures[s]);
-            GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
+            GrAssert(NULL != drawState.getTexture(s));
+            GrPixelConfig config = drawState.getTexture(s)->config();
             if (!GrPixelConfigIsOpaque(config)) {
                 return false;
             }
@@ -900,17 +792,18 @@
                            GrBlendCoeff* dstCoeff) const {
 
     const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
+    const GrDrawState& drawState = this->getDrawState();
 
     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
     if (NULL == srcCoeff) {
         srcCoeff = &bogusSrcCoeff;
     }
-    *srcCoeff = fCurrDrawState.fSrcBlend;
+    *srcCoeff = drawState.getSrcBlendCoeff();
 
     if (NULL == dstCoeff) {
         dstCoeff = &bogusDstCoeff;
     }
-    *dstCoeff = fCurrDrawState.fDstBlend;
+    *dstCoeff = drawState.getDstBlendCoeff();
 
     // We don't ever expect source coeffecients to reference the source
     GrAssert(kSA_BlendCoeff != *srcCoeff &&
@@ -923,7 +816,7 @@
              kDC_BlendCoeff != *dstCoeff &&
              kIDC_BlendCoeff != *dstCoeff);
 
-    if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) {
+    if (drawState.isColorWriteDisabled()) {
         *srcCoeff = kZero_BlendCoeff;
         *dstCoeff = kOne_BlendCoeff;
     }
@@ -939,7 +832,7 @@
     // stenciling is enabled. Having color writes disabled is effectively
     // (0,1).
     if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) {
-        if (fCurrDrawState.fStencilSettings.doesWrite()) {
+        if (drawState.getStencil().doesWrite()) {
             if (fCaps.fShaderSupport) {
                 return kDisableBlend_BlendOptFlag |
                        kEmitTransBlack_BlendOptFlag;
@@ -953,10 +846,10 @@
 
     // check for coverage due to edge aa or coverage texture stage
     bool hasCoverage = forceCoverage ||
-                       fCurrDrawState.fEdgeAANumEdges > 0 ||
+                       drawState.getNumAAEdges() > 0 ||
                        (layout & kCoverage_VertexLayoutBit) ||
                        (layout & kEdge_VertexLayoutBit);
-    for (int s = fCurrDrawState.fFirstCoverageStage;
+    for (int s = drawState.getFirstCoverageStage();
          !hasCoverage && s < GrDrawState::kNumStages;
          ++s) {
         if (StageWillBeUsed(s, layout, fCurrDrawState)) {
@@ -1023,7 +916,7 @@
     // but not in a premul-alpha way. So we only use them when our alpha
     // is 0xff and tweaking the color for partial coverage is OK
     if (!fCaps.fHWAALineSupport ||
-        !(kHWAntialias_StateBit & fCurrDrawState.fFlagBits)) {
+        !this->getDrawState().isHWAntialiasState()) {
         return false;
     }
     BlendOptFlags opts = this->getBlendOpts();
@@ -1043,15 +936,6 @@
                     this->getBlendOpts());
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-void GrDrawTarget::setEdgeAAData(const GrDrawState::Edge* edges, int numEdges) {
-    GrAssert(numEdges <= GrDrawState::kMaxEdges);
-    memcpy(fCurrDrawState.fEdgeAAEdges, edges,
-           numEdges * sizeof(GrDrawState::Edge));
-    fCurrDrawState.fEdgeAANumEdges = numEdges;
-}
-
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -1174,32 +1058,34 @@
                                             GrDrawTarget* target,
                                             GrDrawState::StageMask stageMask) {
     GrAssert(NULL != target);
+    GrDrawState* drawState = target->drawState();
 
     fDrawTarget = target;
-    fViewMatrix = target->getViewMatrix();
+    fViewMatrix = drawState->getViewMatrix();
     fStageMask = stageMask;
     if (fStageMask) {
         GrMatrix invVM;
         if (fViewMatrix.invert(&invVM)) {
             for (int s = 0; s < GrDrawState::kNumStages; ++s) {
                 if (fStageMask & (1 << s)) {
-                    fSamplerMatrices[s] = target->getSamplerMatrix(s);
+                    fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
                 }
             }
-            target->preConcatSamplerMatrices(fStageMask, invVM);
+            drawState->preConcatSamplerMatrices(fStageMask, invVM);
         } else {
             // sad trombone sound
             fStageMask = 0;
         }
     }
-    target->setViewMatrix(GrMatrix::I());
+    drawState->setViewMatrix(GrMatrix::I());
 }
 
 GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
-    fDrawTarget->setViewMatrix(fViewMatrix);
+    GrDrawState* drawState = fDrawTarget->drawState();
+    drawState->setViewMatrix(fViewMatrix);
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         if (fStageMask & (1 << s)) {
-            fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]);
+            drawState->sampler(s)->setMatrix(fSamplerMatrices[s]);
         }
     }
 }
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 4bd9eee..262f72c 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -16,7 +16,6 @@
 #include "GrDrawState.h"
 #include "GrMatrix.h"
 #include "GrRefCnt.h"
-#include "GrRenderTarget.h"
 #include "GrSamplerState.h"
 #include "GrStencil.h"
 #include "GrTexture.h"
@@ -57,62 +56,9 @@
         int fMaxTextureSize;
     };
 
+    // for convenience
     typedef GrDrawState::StageMask StageMask;
 
-    /**
-     *  Flags that affect rendering. Controlled using enable/disableState(). All
-     *  default to disabled.
-     */
-    enum StateBits {
-        /**
-         * Perform dithering. TODO: Re-evaluate whether we need this bit
-         */
-        kDither_StateBit        = 0x01,
-        /**
-         * Perform HW anti-aliasing. This means either HW FSAA, if supported
-         * by the render target, or smooth-line rendering if a line primitive
-         * is drawn and line smoothing is supported by the 3D API.
-         */
-        kHWAntialias_StateBit   = 0x02,
-        /**
-         * Draws will respect the clip, otherwise the clip is ignored.
-         */
-        kClip_StateBit          = 0x04,
-        /**
-         * Disables writing to the color buffer. Useful when performing stencil
-         * operations.
-         */
-        kNoColorWrites_StateBit = 0x08,
-        /**
-         * Modifies the behavior of edge AA specified by setEdgeAA. If set, 
-         * will test edge pairs for convexity when rasterizing. Set this if the 
-         * source polygon is non-convex.
-         */
-        kEdgeAAConcave_StateBit =  0x10,
-        // subclass may use additional bits internally
-        kDummyStateBit,
-        kLastPublicStateBit = kDummyStateBit-1
-    };
-
-    /**
-     * Sets the stencil settings to use for the next draw.
-     * Changing the clip has the side-effect of possibly zeroing
-     * out the client settable stencil bits. So multipass algorithms
-     * using stencil should not change the clip between passes.
-     * @param settings  the stencil settings to use.
-     */
-    void setStencil(const GrStencilSettings& settings) {
-        fCurrDrawState.fStencilSettings = settings;
-    }
-
-    /**
-     * Shortcut to disable stencil testing and ops.
-     */
-    void disableStencil() {
-        fCurrDrawState.fStencilSettings.setDisabled();
-    }
-
-public:
     ///////////////////////////////////////////////////////////////////////////
 
     GrDrawTarget();
@@ -140,286 +86,25 @@
      */
     const GrClip& getClip() const;
 
-    /**
-     * Sets the texture used at the next drawing call
-     *
-     * @param stage The texture stage for which the texture will be set
-     *
-     * @param texture The texture to set. Can be NULL though there is no advantage
-     * to settings a NULL texture if doing non-textured drawing
-     */
-    void setTexture(int stage, GrTexture* texture);
+    const GrDrawState& getDrawState() const { return fCurrDrawState; }
+    GrDrawState* drawState() { return &fCurrDrawState; }
 
-    /**
-     * Retrieves the currently set texture.
-     *
-     * @return    The currently set texture. The return value will be NULL if no
-     *            texture has been set, NULL was most recently passed to
-     *            setTexture, or the last setTexture was destroyed.
-     */
-    const GrTexture* getTexture(int stage) const;
-    GrTexture* getTexture(int stage);
-
-    /**
-     * Sets the rendertarget used at the next drawing call
-     *
-     * @param target  The render target to set.
-     */
-    void setRenderTarget(GrRenderTarget* target);
-
-    /**
-     * Retrieves the currently set rendertarget.
-     *
-     * @return    The currently set render target.
-     */
-    const GrRenderTarget* getRenderTarget() const;
-    GrRenderTarget* getRenderTarget();
-
-    /**
-     * Sets the sampler state for a stage used in subsequent draws.
-     *
-     * The sampler state determines how texture coordinates are
-     * intepretted and used to sample the texture.
-     *
-     * @param stage           the stage of the sampler to set
-     * @param samplerState    Specifies the sampler state.
-     */
-    void setSamplerState(int stage, const GrSamplerState& samplerState);
-
-    /**
-     * Concats the matrix of a stage's sampler.
-     *
-     * @param stage   the stage of the sampler to set
-     * @param matrix  the matrix to concat
-     */
-    void preConcatSamplerMatrix(int stage, const GrMatrix& matrix)  {
-        GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
-        fCurrDrawState.fSamplerStates[stage].preConcatMatrix(matrix);
+    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
+        this->drawState()->setBlendFunc(srcCoeff, dstCoeff);
     }
 
     /**
-     * Shortcut for preConcatSamplerMatrix on all stages in mask with same
-     * matrix
-     */
-    void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
-        for (int i = 0; i < GrDrawState::kNumStages; ++i) {
-            if ((1 << i) & stageMask) {
-                this->preConcatSamplerMatrix(i, matrix);
-            }
-        }
-    }
-
-    /**
-     * Shortcut for preConcatSamplerMatrix on all enabled stages in mask with
-     * same matrix
+     * Shortcut for drawState()->preConcatSamplerMatrices() on all enabled
+     * stages
      *
-     * @param stage   the stage of the sampler to set
      * @param matrix  the matrix to concat
      */
     void preConcatEnabledSamplerMatrices(const GrMatrix& matrix) {
         StageMask stageMask = this->enabledStages();
-        this->preConcatSamplerMatrices(stageMask, matrix);
+        this->drawState()->preConcatSamplerMatrices(stageMask, matrix);
     }
 
     /**
-     * Gets the matrix of a stage's sampler
-     *
-     * @param stage     the stage to of sampler to get
-     * @return the sampler state's matrix
-     */
-    const GrMatrix& getSamplerMatrix(int stage) const {
-        return fCurrDrawState.fSamplerStates[stage].getMatrix();
-    }
-
-    /**
-     * Sets the matrix of a stage's sampler
-     *
-     * @param stage     the stage of sampler set
-     * @param matrix    the matrix to set
-     */
-    void setSamplerMatrix(int stage, const GrMatrix& matrix) {
-        fCurrDrawState.fSamplerStates[stage].setMatrix(matrix);
-    }
-
-    /**
-     * Sets the matrix applied to veretx positions.
-     *
-     * In the post-view-matrix space the rectangle [0,w]x[0,h]
-     * fully covers the render target. (w and h are the width and height of the
-     * the rendertarget.)
-     *
-     * @param m the matrix used to transform the vertex positions.
-     */
-    void setViewMatrix(const GrMatrix& m);
-
-    /**
-     *  Multiplies the current view matrix by a matrix
-     *
-     *  After this call V' = V*m where V is the old view matrix,
-     *  m is the parameter to this function, and V' is the new view matrix.
-     *  (We consider positions to be column vectors so position vector p is
-     *  transformed by matrix X as p' = X*p.)
-     *
-     *  @param m the matrix used to modify the view matrix.
-     */
-    void preConcatViewMatrix(const GrMatrix& m);
-
-    /**
-     *  Multiplies the current view matrix by a matrix
-     *
-     *  After this call V' = m*V where V is the old view matrix,
-     *  m is the parameter to this function, and V' is the new view matrix.
-     *  (We consider positions to be column vectors so position vector p is
-     *  transformed by matrix X as p' = X*p.)
-     *
-     *  @param m the matrix used to modify the view matrix.
-     */
-    void postConcatViewMatrix(const GrMatrix& m);
-
-    /**
-     * Retrieves the current view matrix
-     * @return the current view matrix.
-     */
-    const GrMatrix& getViewMatrix() const;
-
-    /**
-     *  Retrieves the inverse of the current view matrix.
-     *
-     *  If the current view matrix is invertible, return true, and if matrix
-     *  is non-null, copy the inverse into it. If the current view matrix is
-     *  non-invertible, return false and ignore the matrix parameter.
-     *
-     * @param matrix if not null, will receive a copy of the current inverse.
-     */
-    bool getViewInverse(GrMatrix* matrix) const;
-
-    /**
-     *  Sets color for next draw to a premultiplied-alpha color.
-     *
-     *  @param the color to set.
-     */
-    void setColor(GrColor);
-
-    /**
-     * Gets the currently set color.
-     * @return the current color.
-     */
-    GrColor getColor() const { return fCurrDrawState.fColor; }
-
-    /**
-     * Add a color filter that can be represented by a color and a mode.
-     */
-    void setColorFilter(GrColor, SkXfermode::Mode);
-
-    /**
-     *  Sets the color to be used for the next draw to be
-     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
-     *
-     *  @param alpha The alpha value to set as the color.
-     */
-    void setAlpha(uint8_t alpha);
-
-    /**
-     * Controls whether clockwise, counterclockwise, or both faces are drawn.
-     * @param face  the face(s) to draw.
-     */
-    void setDrawFace(GrDrawState::DrawFace face) {
-        fCurrDrawState.fDrawFace = face;
-    }
-
-    /**
-     * A common pattern is to compute a color with the initial stages and then
-     * modulate that color by a coverage value in later stage(s) (AA, mask-
-     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be 
-     * computed based on the pre-coverage-modulated color. The division of 
-     * stages between color-computing and coverage-computing is specified by 
-     * this method. Initially this is GrDrawState::kNumStages (all stages
-     * are color-computing).
-     */
-    void setFirstCoverageStage(int firstCoverageStage) { 
-        fCurrDrawState.fFirstCoverageStage = firstCoverageStage; 
-    }
-
-    /**
-     * Gets the index of the first coverage-computing stage.
-     */
-    int getFirstCoverageStage() const { 
-        return fCurrDrawState.fFirstCoverageStage; 
-    }
-
-    /**
-     * Gets whether the target is drawing clockwise, counterclockwise,
-     * or both faces.
-     * @return the current draw face(s).
-     */
-    GrDrawState::DrawFace getDrawFace() const {
-        return fCurrDrawState.fDrawFace;
-    }
-
-    /**
-     * Enable render state settings.
-     *
-     * @param flags   bitfield of StateBits specifing the states to enable
-     */
-    void enableState(uint32_t stateBits);
-
-    /**
-     * Disable render state settings.
-     *
-     * @param flags   bitfield of StateBits specifing the states to disable
-     */
-    void disableState(uint32_t stateBits);
-
-    bool isDitherState() const {
-        return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit);
-    }
-
-    bool isHWAntialiasState() const {
-        return 0 != (fCurrDrawState.fFlagBits & kHWAntialias_StateBit);
-    }
-
-    bool isClipState() const {
-        return 0 != (fCurrDrawState.fFlagBits & kClip_StateBit);
-    }
-
-    bool isColorWriteDisabled() const {
-        return 0 != (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit);
-    }
-
-    /**
-     * Sets the blending function coeffecients.
-     *
-     * The blend function will be:
-     *    D' = sat(S*srcCoef + D*dstCoef)
-     *
-     *   where D is the existing destination color, S is the incoming source
-     *   color, and D' is the new destination color that will be written. sat()
-     *   is the saturation function.
-     *
-     * @param srcCoef coeffecient applied to the src color.
-     * @param dstCoef coeffecient applied to the dst color.
-     */
-    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff);
-
-    /**
-     * Sets the blending function constant referenced by the following blending
-     * coeffecients:
-     *      kConstC_BlendCoeff
-     *      kIConstC_BlendCoeff
-     *      kConstA_BlendCoeff
-     *      kIConstA_BlendCoeff
-     *
-     * @param constant the constant to set
-     */
-    void setBlendConstant(GrColor constant) { fCurrDrawState.fBlendConstant = constant; }
-
-    /**
-     * Retrieves the last value set by setBlendConstant()
-     * @return the blending constant value
-     */
-    GrColor getBlendConstant() const { return fCurrDrawState.fBlendConstant; }
-
-    /**
      * Determines if blending will require a read of a dst given the current
      * state set on the draw target
      *
@@ -448,15 +133,6 @@
      */
     bool canTweakAlphaForCoverage() const;
 
-     /**
-      * Determines the interpretation per-vertex edge data when the
-      * kEdge_VertexLayoutBit is set (see below). When per-vertex edges are not
-      * specified the value of this setting has no effect.
-      */
-    void setVertexEdgeType(GrDrawState::VertexEdgeType type) {
-        fCurrDrawState.fVertexEdgeType = type;
-    }
-
     /**
      * Given the current draw state, vertex layout, and hw support, will HW AA
      * lines be used (if line primitive type is drawn)? (Note that lines are
@@ -465,14 +141,6 @@
     bool willUseHWAALines() const;
 
     /**
-     * Sets the edge data required for edge antialiasing.
-     *
-     * @param edges       3 * 6 float values, representing the edge
-     *                    equations in Ax + By + C form
-     */
-    void setEdgeAAData(const GrDrawState::Edge* edges, int numEdges);
-
-    /**
      * Used to save and restore the GrGpu's drawing state
      */
     struct SavedDrawState {
@@ -888,39 +556,6 @@
 
     ////////////////////////////////////////////////////////////////////////////
 
-    class AutoViewMatrixRestore : ::GrNoncopyable {
-    public:
-        AutoViewMatrixRestore() {
-            fDrawTarget = NULL;
-        }
-
-        AutoViewMatrixRestore(GrDrawTarget* target)
-            : fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) {
-            GrAssert(NULL != target);
-        }
-
-        void set(GrDrawTarget* target) {
-            GrAssert(NULL != target);
-            if (NULL != fDrawTarget) {
-                fDrawTarget->setViewMatrix(fMatrix);
-            }
-            fDrawTarget = target;
-            fMatrix = target->getViewMatrix();
-        }
-
-        ~AutoViewMatrixRestore() {
-            if (NULL != fDrawTarget) {
-                fDrawTarget->setViewMatrix(fMatrix);
-            }
-        }
-
-    private:
-        GrDrawTarget*       fDrawTarget;
-        GrMatrix            fMatrix;
-    };
-
-    ////////////////////////////////////////////////////////////////////////////
-
     /** 
      * Sets the view matrix to I and preconcats all stage matrices enabled in
      * mask by the view inverse. Destructor undoes these changes.
@@ -1279,7 +914,8 @@
     // given a vertex layout and a draw state, will a stage be used?
     static bool StageWillBeUsed(int stage, GrVertexLayout layout, 
                                 const GrDrawState& state) {
-        return NULL != state.fTextures[stage] && VertexUsesStage(stage, layout);
+        return NULL != state.getTexture(stage) &&
+               VertexUsesStage(stage, layout);
     }
 
     bool isStageEnabled(int stage) const {
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 1583630..eb96c57 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -185,10 +185,8 @@
         // We used to clear down in the GL subclass using a special purpose
         // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported
         // FBO status.
-        GrRenderTarget* oldRT = fCurrDrawState.fRenderTarget;
-        fCurrDrawState.fRenderTarget = rt;
+        GrDrawState::AutoRenderTargetRestore artr(this->drawState(), rt);
         this->clearStencil();
-        fCurrDrawState.fRenderTarget = oldRT;
         return true;
     } else {
         return false;
@@ -230,7 +228,7 @@
 }
 
 void GrGpu::clear(const GrIRect* rect, GrColor color) {
-    if (NULL == this->getRenderTarget()) {
+    if (NULL == this->getDrawState().getRenderTarget()) {
         return;
     }
     this->handleDirtyContext();
@@ -530,16 +528,18 @@
     const GrIRect* r = NULL;
     GrIRect clipRect;
 
-    // GrDrawTarget should have filtered this for us
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
+    GrDrawState* drawState = this->drawState();
+    const GrRenderTarget* rt = drawState->getRenderTarget();
 
-    if (fCurrDrawState.fFlagBits & kClip_StateBit) {
-        GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
+    // GrDrawTarget should have filtered this for us
+    GrAssert(NULL != rt);
+
+    if (drawState->isClipState()) {
 
         GrRect bounds;
         GrRect rtRect;
         rtRect.setLTRB(0, 0,
-                       GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
+                       GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
         if (fClip.hasConservativeBounds()) {
             bounds = fClip.getConservativeBounds();
             if (!bounds.intersect(rtRect)) {
@@ -560,15 +560,15 @@
                          !bounds.isEmpty();
 
         // TODO: dynamically attach a SB when needed.
-        GrStencilBuffer* stencilBuffer = rt.getStencilBuffer();
+        GrStencilBuffer* stencilBuffer = rt->getStencilBuffer();
         if (fClipInStencil && NULL == stencilBuffer) {
             return false;
         }
 
         if (fClipInStencil &&
-            stencilBuffer->mustRenderClip(fClip, rt.width(), rt.height())) {
+            stencilBuffer->mustRenderClip(fClip, rt->width(), rt->height())) {
 
-            stencilBuffer->setLastClip(fClip, rt.width(), rt.height());
+            stencilBuffer->setLastClip(fClip, rt->width(), rt->height());
 
             // we set the current clip to the bounds so that our recursive
             // draws are scissored to them. We use the copy of the complex clip
@@ -580,12 +580,12 @@
             AutoStateRestore asr(this);
             AutoGeometryPush agp(this);
 
-            this->setViewMatrix(GrMatrix::I());
+            drawState->setViewMatrix(GrMatrix::I());
             this->flushScissor(NULL);
 #if !VISUALIZE_COMPLEX_CLIP
-            this->enableState(kNoColorWrites_StateBit);
+            drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
 #else
-            this->disableState(kNoColorWrites_StateBit);
+            drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
 #endif
             int count = clip.getElementCount();
             int clipBit = stencilBuffer->bits();
@@ -606,7 +606,7 @@
                 GrPathFill fill;
                 bool fillInverted;
                 // enabled at bottom of loop
-                this->disableState(kModifyStencilClip_StateBit);
+                drawState->disableState(kModifyStencilClip_StateBit);
 
                 bool canRenderDirectToStencil; // can the clip element be drawn
                                                // directly to the stencil buffer
@@ -664,11 +664,11 @@
                     };
                     SET_RANDOM_COLOR
                     if (kRect_ClipType == clip.getElementType(c)) {
-                        this->setStencil(gDrawToStencil);
+                        *drawState->stencil() = gDrawToStencil;
                         this->drawSimpleRect(clip.getRect(c), NULL, 0);
                     } else {
                         if (canRenderDirectToStencil) {
-                            this->setStencil(gDrawToStencil);
+                            *drawState->stencil() = gDrawToStencil;
                             pr->drawPath(0);
                         } else {
                             pr->drawPathToStencil();
@@ -678,9 +678,9 @@
 
                 // now we modify the clip bit by rendering either the clip
                 // element directly or a bounding rect of the entire clip.
-                this->enableState(kModifyStencilClip_StateBit);
+                drawState->enableState(kModifyStencilClip_StateBit);
                 for (int p = 0; p < passes; ++p) {
-                    this->setStencil(stencilSettings[p]);
+                    *drawState->stencil() = stencilSettings[p];
                     if (canDrawDirectToClip) {
                         if (kRect_ClipType == clip.getElementType(c)) {
                             SET_RANDOM_COLOR
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 11bf153..11f5083 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -327,8 +327,8 @@
     }
 
 protected:
-    enum PrivateStateBits {
-        kFirstBit = (kLastPublicStateBit << 1),
+    enum PrivateDrawStateStateBits {
+        kFirstBit = (GrDrawState::kLastPublicStateBit << 1),
 
         kModifyStencilClip_StateBit = kFirstBit, // allows draws to modify
                                                  // stencil bits used for
diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp
index 9f7e4ec..2a8634f 100644
--- a/src/gpu/GrGpuGL.cpp
+++ b/src/gpu/GrGpuGL.cpp
@@ -480,7 +480,7 @@
 
     GL_CALL(Disable(GR_GL_CULL_FACE));
     GL_CALL(FrontFace(GR_GL_CCW));
-    fHWDrawState.fDrawFace = GrDrawState::kBoth_DrawFace;
+    fHWDrawState.setDrawFace(GrDrawState::kBoth_DrawFace);
 
     GL_CALL(Disable(GR_GL_DITHER));
     if (kDesktop_GrGLBinding == this->glBinding()) {
@@ -492,7 +492,7 @@
     }
 
     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
-    fHWDrawState.fFlagBits = 0;
+    fHWDrawState.resetStateFlags();
 
     // we only ever use lines in hairline mode
     GL_CALL(LineWidth(1));
@@ -501,24 +501,22 @@
     fActiveTextureUnitIdx = -1;
 
     // illegal values
-    //fHWDrawState.fSrcBlend = (GrBlendCoeff)(uint8_t)-1;
-    fHWDrawState.fSrcBlend = (GrBlendCoeff)0xFF;
-    fHWDrawState.fDstBlend = (GrBlendCoeff)(uint8_t)-1;
+    fHWDrawState.setBlendFunc((GrBlendCoeff)0xFF, (GrBlendCoeff)0xFF);
 
-    fHWDrawState.fBlendConstant = 0x00000000;
+    fHWDrawState.setBlendConstant(0x00000000);
     GL_CALL(BlendColor(0,0,0,0));
 
-    fHWDrawState.fColor = GrColor_ILLEGAL;
+    fHWDrawState.setColor(GrColor_ILLEGAL);
 
-    fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
+    fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix());
 
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        fHWDrawState.fTextures[s] = NULL;
-        fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax,
-                                                        -GR_ScalarMax,
-                                                        true);
-        fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix());
-        fHWDrawState.fSamplerStates[s].setConvolutionParams(0, NULL, NULL);
+        fHWDrawState.setTexture(s, NULL);
+        fHWDrawState.sampler(s)->setRadial2Params(-GR_ScalarMax,
+                                                  -GR_ScalarMax,
+                                                  true);
+        fHWDrawState.sampler(s)->setMatrix(GrMatrix::InvalidMatrix());
+        fHWDrawState.sampler(s)->setConvolutionParams(0, NULL, NULL);
     }
 
     fHWBounds.fScissorRect.invalidate();
@@ -526,7 +524,7 @@
     GL_CALL(Disable(GR_GL_SCISSOR_TEST));
     fHWBounds.fViewportRect.invalidate();
 
-    fHWDrawState.fStencilSettings.invalidate();
+    fHWDrawState.stencil()->invalidate();
     fHWStencilClip = false;
     fClipInStencil = false;
 
@@ -536,7 +534,7 @@
     fHWGeometryState.fArrayPtrsDirty = true;
 
     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
-    fHWDrawState.fRenderTarget = NULL;
+    fHWDrawState.setRenderTarget(NULL);
 
     // we assume these values
     if (this->glCaps().fUnpackRowLengthSupport) {
@@ -1191,7 +1189,7 @@
         GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb;
         GrGLuint rb = glsb->renderbufferID();
 
-        fHWDrawState.fRenderTarget = NULL;
+        fHWDrawState.setRenderTarget(NULL);
         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
         GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
                                       GR_GL_STENCIL_ATTACHMENT,
@@ -1276,9 +1274,12 @@
 }
 
 void GrGpuGL::flushScissor(const GrIRect* rect) {
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
-    const GrGLIRect& vp =
-            ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport();
+    const GrDrawState& drawState = this->getDrawState();
+    const GrGLRenderTarget* rt =
+        static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
+
+    GrAssert(NULL != rt);
+    const GrGLIRect& vp = rt->getViewport();
 
     GrGLIRect scissor;
     if (NULL != rect) {
@@ -1307,15 +1308,16 @@
 }
 
 void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
+    const GrDrawState& drawState = this->getDrawState();
+    const GrRenderTarget* rt = drawState.getRenderTarget();
     // parent class should never let us get here with no RT
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
+    GrAssert(NULL != rt);
 
     GrIRect clippedRect;
     if (NULL != rect) {
         // flushScissor expects rect to be clipped to the target.
         clippedRect = *rect;
-        GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(),
-                                         fCurrDrawState.fRenderTarget->height());
+        GrIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
         if (clippedRect.intersect(rtRect)) {
             rect = &clippedRect;
         } else {
@@ -1329,7 +1331,7 @@
     static const GrGLfloat scale255 = 1.f / 255.f;
     a = GrColorUnpackA(color) * scale255;
     GrGLfloat scaleRGB = scale255;
-    if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) {
+    if (GrPixelConfigIsUnpremultiplied(rt->config())) {
         scaleRGB *= a;
     }
     r = GrColorUnpackR(color) * scaleRGB;
@@ -1337,13 +1339,13 @@
     b = GrColorUnpackB(color) * scaleRGB;
 
     GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE));
-    fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit;
+    fHWDrawState.disableState(GrDrawState::kNoColorWrites_StateBit);
     GL_CALL(ClearColor(r, g, b, a));
     GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
 }
 
 void GrGpuGL::clearStencil() {
-    if (NULL == fCurrDrawState.fRenderTarget) {
+    if (NULL == this->getDrawState().getRenderTarget()) {
         return;
     }
     
@@ -1356,17 +1358,18 @@
     GL_CALL(StencilMask(0xffffffff));
     GL_CALL(ClearStencil(0));
     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
-    fHWDrawState.fStencilSettings.invalidate();
+    fHWDrawState.stencil()->invalidate();
 }
 
 void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
+    const GrDrawState& drawState = this->getDrawState();
+    const GrRenderTarget* rt = drawState.getRenderTarget();
+    GrAssert(NULL != rt);
 
     // this should only be called internally when we know we have a
     // stencil buffer.
-    GrAssert(NULL != fCurrDrawState.fRenderTarget->getStencilBuffer());
-    GrGLint stencilBitCount = 
-        fCurrDrawState.fRenderTarget->getStencilBuffer()->bits();
+    GrAssert(NULL != rt->getStencilBuffer());
+    GrGLint stencilBitCount =  rt->getStencilBuffer()->bits();
 #if 0
     GrAssert(stencilBitCount > 0);
     GrGLint clipStencilMask  = (1 << (stencilBitCount - 1));
@@ -1389,7 +1392,7 @@
     GL_CALL(StencilMask(clipStencilMask));
     GL_CALL(ClearStencil(value));
     GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
-    fHWDrawState.fStencilSettings.invalidate();
+    fHWDrawState.stencil()->invalidate();
 }
 
 void GrGpuGL::onForceRenderTargetFlush() {
@@ -1445,13 +1448,12 @@
 
     // resolve the render target if necessary
     GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
-    GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore;
+    GrDrawState::AutoRenderTargetRestore artr;
     switch (tgt->getResolveType()) {
         case GrGLRenderTarget::kCantResolve_ResolveType:
             return false;
         case GrGLRenderTarget::kAutoResolves_ResolveType:
-            autoTargetRestore.save(&fCurrDrawState.fRenderTarget);
-            fCurrDrawState.fRenderTarget = target;
+            artr.set(this->drawState(), target);
             this->flushRenderTarget(&GrIRect::EmptyIRect());
             break;
         case GrGLRenderTarget::kCanResolve_ResolveType:
@@ -1549,10 +1551,11 @@
 
 void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
 
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
+    GrGLRenderTarget* rt =
+        static_cast<GrGLRenderTarget*>(this->drawState()->getRenderTarget());
+    GrAssert(NULL != rt);
 
-    GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
-    if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
+    if (fHWDrawState.getRenderTarget() != rt) {
         GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
     #if GR_COLLECT_STATS
         ++fStats.fRenderTargetChngCnt;
@@ -1565,7 +1568,7 @@
         }
     #endif
         fDirtyFlags.fRenderTargetChanged = true;
-        fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget;
+        fHWDrawState.setRenderTarget(rt);
         const GrGLIRect& vp = rt->getViewport();
         if (fHWBounds.fViewportRect != vp) {
             vp.pushToGLViewport(this->glInterface());
@@ -1682,7 +1685,7 @@
     #endif
         // make sure we go through flushRenderTarget() since we've modified
         // the bound DRAW FBO ID.
-        fHWDrawState.fRenderTarget = NULL;
+        fHWDrawState.setRenderTarget(NULL);
         const GrGLIRect& vp = rt->getViewport();
         const GrIRect dirtyRect = rt->getResolveRect();
         GrGLIRect r;
@@ -1754,21 +1757,25 @@
 GR_STATIC_ASSERT(7 == kInvert_StencilOp);
 
 void GrGpuGL::flushStencil() {
-    const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings;
+    const GrDrawState& drawState = this->getDrawState();
+
+    const GrStencilSettings* settings = &drawState.getStencil();
 
     // use stencil for clipping if clipping is enabled and the clip
     // has been written into the stencil.
-    bool stencilClip = fClipInStencil &&
-                       (kClip_StateBit & fCurrDrawState.fFlagBits);
+    bool stencilClip = fClipInStencil && drawState.isClipState();
+    bool drawClipToStencil =
+        drawState.isStateFlagEnabled(kModifyStencilClip_StateBit);
     bool stencilChange = fHWStencilClip != stencilClip  ||
-                         fHWDrawState.fStencilSettings != *settings ||
-                         ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) !=
-                          (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
+                         fHWDrawState.getStencil() != *settings ||
+                         (fHWDrawState.isStateFlagEnabled(kModifyStencilClip_StateBit) !=
+                          drawClipToStencil);
 
     if (stencilChange) {
 
-        // we can't simultaneously perform stencil-clipping and modify the stencil clip
-        GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit));
+        // we can't simultaneously perform stencil-clipping and 
+        // modify the stencil clip
+        GrAssert(!stencilClip || !drawClipToStencil);
 
         if (settings->isDisabled()) {
             if (stencilClip) {
@@ -1793,15 +1800,14 @@
             }
     #endif
             int stencilBits = 0;
-            GrStencilBuffer* stencilBuffer = 
-                            fCurrDrawState.fRenderTarget->getStencilBuffer();
+            GrStencilBuffer* stencilBuffer =
+                drawState.getRenderTarget()->getStencilBuffer();
             if (NULL != stencilBuffer) {
                 stencilBits = stencilBuffer->bits();
             }
             // TODO: dynamically attach a stencil buffer
             GrAssert(stencilBits ||
-                     (GrStencilSettings::gDisabled ==
-                      fCurrDrawState.fStencilSettings));
+                     (GrStencilSettings::gDisabled == *settings));
 
             GrGLuint clipStencilMask = 0;
             GrGLuint userStencilMask = ~0;
@@ -1815,8 +1821,7 @@
             unsigned int frontWriteMask = settings->fFrontWriteMask;
             GrGLenum frontFunc;
 
-            if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
-
+            if (drawClipToStencil) {
                 GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
                 frontFunc = grToGLStencilFunc[settings->fFrontFunc];
             } else {
@@ -1847,7 +1852,7 @@
                 unsigned int backWriteMask = settings->fBackWriteMask;
 
 
-                if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) {
+                if (drawClipToStencil) {
                     GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
                     backFunc = grToGLStencilFunc[settings->fBackFunc];
                 } else {
@@ -1885,12 +1890,13 @@
                                 grToGLStencilOp[settings->fFrontPassOp]));
             }
         }
-        fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings;
+        *fHWDrawState.stencil() = *settings;
         fHWStencilClip = stencilClip;
     }
 }
 
 void GrGpuGL::flushAAState(GrPrimitiveType type) {
+    const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
     if (kDesktop_GrGLBinding == this->glBinding()) {
         // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
         // smooth lines.
@@ -1906,13 +1912,13 @@
                 GL_CALL(Disable(GR_GL_LINE_SMOOTH));
                 fHWAAState.fSmoothLineEnabled = false;
             }
-            if (fCurrDrawState.fRenderTarget->isMultisampled() && 
+            if (rt->isMultisampled() && 
                 fHWAAState.fMSAAEnabled) {
                 GL_CALL(Disable(GR_GL_MULTISAMPLE));
                 fHWAAState.fMSAAEnabled = false;
             }
-        } else if (fCurrDrawState.fRenderTarget->isMultisampled() &&
-                   SkToBool(kHWAntialias_StateBit & fCurrDrawState.fFlagBits) !=
+        } else if (rt->isMultisampled() &&
+                   this->getDrawState().isHWAntialiasState() !=
                    fHWAAState.fMSAAEnabled) {
             if (fHWAAState.fMSAAEnabled) {
                 GL_CALL(Disable(GR_GL_MULTISAMPLE));
@@ -1933,12 +1939,11 @@
             GL_CALL(Enable(GR_GL_BLEND));
             fHWBlendDisabled = false;
         }
-        if (kSA_BlendCoeff != fHWDrawState.fSrcBlend ||
-            kISA_BlendCoeff != fHWDrawState.fDstBlend) {
+        if (kSA_BlendCoeff != fHWDrawState.getSrcBlendCoeff() ||
+            kISA_BlendCoeff != fHWDrawState.getDstBlendCoeff()) {
             GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
                               gXfermodeCoeff2Blend[kISA_BlendCoeff]));
-            fHWDrawState.fSrcBlend = kSA_BlendCoeff;
-            fHWDrawState.fDstBlend = kISA_BlendCoeff;
+            fHWDrawState.setBlendFunc(kSA_BlendCoeff, kISA_BlendCoeff);
         }
     } else {
         // any optimization to disable blending should
@@ -1955,25 +1960,25 @@
             fHWBlendDisabled = blendOff;
         }
         if (!blendOff) {
-            if (fHWDrawState.fSrcBlend != srcCoeff ||
-                fHWDrawState.fDstBlend != dstCoeff) {
+            if (fHWDrawState.getSrcBlendCoeff() != srcCoeff ||
+                fHWDrawState.getDstBlendCoeff() != dstCoeff) {
                 GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
                                   gXfermodeCoeff2Blend[dstCoeff]));
-                fHWDrawState.fSrcBlend = srcCoeff;
-                fHWDrawState.fDstBlend = dstCoeff;
+                fHWDrawState.setBlendFunc(srcCoeff, dstCoeff);
             }
+            GrColor blendConst = fCurrDrawState.getBlendConstant();
             if ((BlendCoeffReferencesConstant(srcCoeff) ||
                  BlendCoeffReferencesConstant(dstCoeff)) &&
-                fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
+                fHWDrawState.getBlendConstant() != blendConst) {
 
                 float c[] = {
-                    GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
-                    GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
-                    GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
-                    GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
+                    GrColorUnpackR(blendConst) / 255.f,
+                    GrColorUnpackG(blendConst) / 255.f,
+                    GrColorUnpackB(blendConst) / 255.f,
+                    GrColorUnpackA(blendConst) / 255.f
                 };
                 GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
-                fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
+                fHWDrawState.setBlendConstant(blendConst);
             }
         }
     }
@@ -2031,14 +2036,16 @@
 
 bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
 
+    GrDrawState* drawState = this->drawState();
     // GrGpu::setupClipAndFlushState should have already checked this
     // and bailed if not true.
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
+    GrAssert(NULL != drawState->getRenderTarget());
 
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         // bind texture and set sampler state
         if (this->isStageEnabled(s)) {
-            GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s];
+            GrGLTexture* nextTexture = 
+                static_cast<GrGLTexture*>(drawState->getTexture(s));
 
             // true for now, but maybe not with GrEffect.
             GrAssert(NULL != nextTexture);
@@ -2052,20 +2059,20 @@
                 resolveRenderTarget(texRT);
             }
 
-            if (fHWDrawState.fTextures[s] != nextTexture) {
+            if (fHWDrawState.getTexture(s) != nextTexture) {
                 setTextureUnit(s);
                 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
             #if GR_COLLECT_STATS
                 ++fStats.fTextureChngCnt;
             #endif
                 //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
-                fHWDrawState.fTextures[s] = nextTexture;
+                fHWDrawState.setTexture(s, nextTexture);
                 // The texture matrix has to compensate for texture width/height
                 // and NPOT-embedded-in-POT
                 fDirtyFlags.fTextureChangedMask |= (1 << s);
             }
 
-            const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+            const GrSamplerState& sampler = drawState->getSampler(s);
             ResetTimestamp timestamp;
             const GrGLTexture::TexParams& oldTexParams =
                                     nextTexture->getCachedTexParams(&timestamp);
@@ -2117,7 +2124,7 @@
 
     GrIRect* rect = NULL;
     GrIRect clipBounds;
-    if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
+    if (drawState->isClipState() &&
         fClip.hasConservativeBounds()) {
         fClip.getConservativeBounds().roundOut(&clipBounds);
         rect = &clipBounds;
@@ -2125,19 +2132,18 @@
     this->flushRenderTarget(rect);
     this->flushAAState(type);
     
-    if ((fCurrDrawState.fFlagBits & kDither_StateBit) !=
-        (fHWDrawState.fFlagBits & kDither_StateBit)) {
-        if (fCurrDrawState.fFlagBits & kDither_StateBit) {
+    if (drawState->isDitherState() != fHWDrawState.isDitherState()) {
+        if (drawState->isDitherState()) {
             GL_CALL(Enable(GR_GL_DITHER));
         } else {
             GL_CALL(Disable(GR_GL_DITHER));
         }
     }
 
-    if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) !=
-        (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) {
+    if (drawState->isColorWriteDisabled() !=
+        fHWDrawState.isColorWriteDisabled()) {
         GrGLenum mask;
-        if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) {
+        if (drawState->isColorWriteDisabled()) {
             mask = GR_GL_FALSE;
         } else {
             mask = GR_GL_TRUE;
@@ -2145,8 +2151,8 @@
         GL_CALL(ColorMask(mask, mask, mask, mask));
     }
 
-    if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
-        switch (fCurrDrawState.fDrawFace) {
+    if (fHWDrawState.getDrawFace() != drawState->getDrawFace()) {
+        switch (fCurrDrawState.getDrawFace()) {
             case GrDrawState::kCCW_DrawFace:
                 GL_CALL(Enable(GR_GL_CULL_FACE));
                 GL_CALL(CullFace(GR_GL_BACK));
@@ -2161,24 +2167,26 @@
             default:
                 GrCrash("Unknown draw face.");
         }
-        fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace;
+        fHWDrawState.setDrawFace(drawState->getDrawFace());
     }
 
 #if GR_DEBUG
     // check for circular rendering
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         GrAssert(!this->isStageEnabled(s) ||
-                 NULL == fCurrDrawState.fRenderTarget ||
-                 NULL == fCurrDrawState.fTextures[s] ||
-                 fCurrDrawState.fTextures[s]->asRenderTarget() !=
-                    fCurrDrawState.fRenderTarget);
+                 NULL == drawState->getRenderTarget() ||
+                 NULL == drawState->getTexture(s) ||
+                 drawState->getTexture(s)->asRenderTarget() !=
+                    drawState->getRenderTarget());
     }
 #endif
 
-    flushStencil();
+    this->flushStencil();
 
-    // flushStencil may look at the private state bits, so keep it before this.
-    fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
+    // This copy must happen after flushStencil() is called. flushStencil()
+    // relies on detecting when the kModifyStencilClip_StateBit state has
+    // changed since the last draw.
+    fHWDrawState.copyStateFlags(*drawState);
     return true;
 }
 
@@ -2210,22 +2218,24 @@
 
 void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
     GrAssert(NULL != renderTarget);
-    if (fCurrDrawState.fRenderTarget == renderTarget) {
-        fCurrDrawState.fRenderTarget = NULL;
+    GrDrawState* drawState = this->drawState();
+    if (drawState->getRenderTarget() == renderTarget) {
+        drawState->setRenderTarget(NULL);
     }
-    if (fHWDrawState.fRenderTarget == renderTarget) {
-        fHWDrawState.fRenderTarget = NULL;
+    if (fHWDrawState.getRenderTarget() == renderTarget) {
+        fHWDrawState.setRenderTarget(NULL);
     }
 }
 
 void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        if (fCurrDrawState.fTextures[s] == texture) {
-            fCurrDrawState.fTextures[s] = NULL;
+        GrDrawState* drawState = this->drawState();
+        if (drawState->getTexture(s) == texture) {
+            fCurrDrawState.setTexture(s, NULL);
         }
-        if (fHWDrawState.fTextures[s] == texture) {
+        if (fHWDrawState.getTexture(s) == texture) {
             // deleting bound texture does implied bind to 0
-            fHWDrawState.fTextures[s] = NULL;
+            fHWDrawState.setTexture(s, NULL);
        }
     }
 }
diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp
index 9018a4e..5534d05 100644
--- a/src/gpu/GrGpuGLShaders.cpp
+++ b/src/gpu/GrGpuGLShaders.cpp
@@ -338,12 +338,33 @@
     delete fProgramCache;
 }
 
+const GrMatrix& GrGpuGLShaders::getHWViewMatrix() {
+    GrAssert(fProgramData);
+
+    if (GrGLProgram::kSetAsAttribute == 
+        fProgramData->fUniLocations.fViewMatrixUni) {
+        return fHWDrawState.getViewMatrix();
+    } else {
+        return fProgramData->fViewMatrix;
+    }
+}
+
+void GrGpuGLShaders::recordHWViewMatrix(const GrMatrix& matrix) {
+    GrAssert(fProgramData);
+    if (GrGLProgram::kSetAsAttribute == 
+        fProgramData->fUniLocations.fViewMatrixUni) {
+        fHWDrawState.setViewMatrix(matrix);
+    } else {
+        fProgramData->fViewMatrix = matrix;
+    }
+}
+
 const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
     GrAssert(fProgramData);
 
     if (GrGLProgram::kSetAsAttribute == 
         fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
-        return fHWDrawState.fSamplerStates[stage].getMatrix();
+        return fHWDrawState.getSampler(stage).getMatrix();
     } else {
         return fProgramData->fTextureMatrices[stage];
     }
@@ -353,7 +374,7 @@
     GrAssert(fProgramData);
     if (GrGLProgram::kSetAsAttribute == 
         fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
-        fHWDrawState.fSamplerStates[stage].setMatrix(matrix);
+        fHWDrawState.sampler(stage)->setMatrix(matrix);
     } else {
         fProgramData->fTextureMatrices[stage] = matrix;
     }
@@ -388,47 +409,53 @@
 }
 
 void GrGpuGLShaders::flushViewMatrix() {
-    GrAssert(NULL != fCurrDrawState.fRenderTarget);
-    GrMatrix m;
-    m.setAll(
-        GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
-        0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
-        0, 0, GrMatrix::I()[8]);
-    m.setConcat(m, fCurrDrawState.fViewMatrix);
+    const GrMatrix& vm = this->getDrawState().getViewMatrix();
+    if (GrGpuGLShaders::getHWViewMatrix() != vm) {
 
-    // ES doesn't allow you to pass true to the transpose param,
-    // so do our own transpose
-    GrGLfloat mt[]  = {
-        GrScalarToFloat(m[GrMatrix::kMScaleX]),
-        GrScalarToFloat(m[GrMatrix::kMSkewY]),
-        GrScalarToFloat(m[GrMatrix::kMPersp0]),
-        GrScalarToFloat(m[GrMatrix::kMSkewX]),
-        GrScalarToFloat(m[GrMatrix::kMScaleY]),
-        GrScalarToFloat(m[GrMatrix::kMPersp1]),
-        GrScalarToFloat(m[GrMatrix::kMTransX]),
-        GrScalarToFloat(m[GrMatrix::kMTransY]),
-        GrScalarToFloat(m[GrMatrix::kMPersp2])
-    };
+        const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
+        GrAssert(NULL != rt);
+        GrMatrix m;
+        m.setAll(
+            GrIntToScalar(2) / rt->width(), 0, -GR_Scalar1,
+            0,-GrIntToScalar(2) / rt->height(), GR_Scalar1,
+            0, 0, GrMatrix::I()[8]);
+        m.setConcat(m, vm);
 
-    if (GrGLProgram::kSetAsAttribute ==  
-        fProgramData->fUniLocations.fViewMatrixUni) {
-        int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
-        GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0));
-        GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3));
-        GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6));
-    } else {
-        GrAssert(GrGLProgram::kUnusedUniform != 
-                 fProgramData->fUniLocations.fViewMatrixUni);
-        GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
-                                 1, false, mt));
+        // ES doesn't allow you to pass true to the transpose param,
+        // so do our own transpose
+        GrGLfloat mt[]  = {
+            GrScalarToFloat(m[GrMatrix::kMScaleX]),
+            GrScalarToFloat(m[GrMatrix::kMSkewY]),
+            GrScalarToFloat(m[GrMatrix::kMPersp0]),
+            GrScalarToFloat(m[GrMatrix::kMSkewX]),
+            GrScalarToFloat(m[GrMatrix::kMScaleY]),
+            GrScalarToFloat(m[GrMatrix::kMPersp1]),
+            GrScalarToFloat(m[GrMatrix::kMTransX]),
+            GrScalarToFloat(m[GrMatrix::kMTransY]),
+            GrScalarToFloat(m[GrMatrix::kMPersp2])
+        };
+
+        if (GrGLProgram::kSetAsAttribute ==  
+            fProgramData->fUniLocations.fViewMatrixUni) {
+            int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
+            GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0));
+            GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3));
+            GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6));
+        } else {
+            GrAssert(GrGLProgram::kUnusedUniform != 
+                     fProgramData->fUniLocations.fViewMatrixUni);
+            GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
+                                     1, false, mt));
+        }
+        this->recordHWViewMatrix(vm);
     }
 }
 
 void GrGpuGLShaders::flushTextureDomain(int s) {
     const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
+    const GrDrawState& drawState = this->getDrawState();
     if (GrGLProgram::kUnusedUniform != uni) {
-        const GrRect &texDom =
-            fCurrDrawState.fSamplerStates[s].getTextureDomain();
+        const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
 
         if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
             fProgramData->fTextureDomain[s] != texDom) {
@@ -442,7 +469,8 @@
                 GrScalarToFloat(texDom.bottom())
             };
 
-            GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+            const GrGLTexture* texture =
+                static_cast<const GrGLTexture*>(drawState.getTexture(s));
             GrGLTexture::Orientation orientation = texture->orientation();
 
             // vertical flip if necessary
@@ -461,19 +489,17 @@
 
 void GrGpuGLShaders::flushTextureMatrix(int s) {
     const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
-    GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+    const GrDrawState& drawState = this->getDrawState();
+    const GrGLTexture* texture =
+        static_cast<const GrGLTexture*>(drawState.getTexture(s));
     if (NULL != texture) {
         if (GrGLProgram::kUnusedUniform != uni &&
             (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
-            getHWSamplerMatrix(s) != getSamplerMatrix(s))) {
+            this->getHWSamplerMatrix(s) != drawState.getSampler(s).getMatrix())) {
 
-            GrAssert(NULL != fCurrDrawState.fTextures[s]);
-
-            GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
-
-            GrMatrix m = getSamplerMatrix(s);
-            GrSamplerState::SampleMode mode = 
-                fCurrDrawState.fSamplerStates[s].getSampleMode();
+            GrMatrix m = drawState.getSampler(s).getMatrix();
+            GrSamplerState::SampleMode mode =
+                drawState.getSampler(s).getSampleMode();
             AdjustTextureMatrix(texture, mode, &m);
 
             // ES doesn't allow you to pass true to the transpose param,
@@ -499,7 +525,7 @@
             } else {
                 GL_CALL(UniformMatrix3fv(uni, 1, false, mt));
             }
-            recordHWSamplerMatrix(s, getSamplerMatrix(s));
+            this->recordHWSamplerMatrix(s, drawState.getSampler(s).getMatrix());
         }
     }
 }
@@ -507,7 +533,7 @@
 void GrGpuGLShaders::flushRadial2(int s) {
 
     const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
-    const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+    const GrSamplerState& sampler = this->getDrawState().getSampler(s);
     if (GrGLProgram::kUnusedUniform != uni &&
         (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
          fProgramData->fRadial2Radius0[s]  != sampler.getRadial2Radius0()  ||
@@ -539,7 +565,7 @@
 }
 
 void GrGpuGLShaders::flushConvolution(int s) {
-    const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+    const GrSamplerState& sampler = this->getDrawState().getSampler(s);
     int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni;
     if (GrGLProgram::kUnusedUniform != kernelUni) {
         GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(),
@@ -554,7 +580,8 @@
 void GrGpuGLShaders::flushTexelSize(int s) {
     const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
     if (GrGLProgram::kUnusedUniform != uni) {
-        GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+        const GrGLTexture* texture =
+            static_cast<const GrGLTexture*>(this->getDrawState().getTexture(s));
         if (texture->width() != fProgramData->fTextureWidth[s] ||
             texture->height() != fProgramData->fTextureHeight[s]) {
 
@@ -570,13 +597,13 @@
 void GrGpuGLShaders::flushEdgeAAData() {
     const int& uni = fProgramData->fUniLocations.fEdgesUni;
     if (GrGLProgram::kUnusedUniform != uni) {
-        int count = fCurrDrawState.fEdgeAANumEdges;
+        int count = this->getDrawState().getNumAAEdges();
         GrDrawState::Edge edges[GrDrawState::kMaxEdges];
         // Flip the edges in Y
         float height = 
-            static_cast<float>(fCurrDrawState.fRenderTarget->height());
+            static_cast<float>(this->getDrawState().getRenderTarget()->height());
         for (int i = 0; i < count; ++i) {
-            edges[i] = fCurrDrawState.fEdgeAAEdges[i];
+            edges[i] = this->getDrawState().getAAEdges()[i];
             float b = edges[i].fY;
             edges[i].fY = -b;
             edges[i].fZ += b * height;
@@ -596,19 +623,21 @@
 
 void GrGpuGLShaders::flushColor(GrColor color) {
     const ProgramDesc& desc = fCurrentProgram.getDesc();
+    const GrDrawState& drawState = this->getDrawState();
+
     if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) {
         // color will be specified per-vertex as an attribute
         // invalidate the const vertex attrib color
-        fHWDrawState.fColor = GrColor_ILLEGAL;
+        fHWDrawState.setColor(GrColor_ILLEGAL);
     } else {
         switch (desc.fColorInput) {
             case ProgramDesc::kAttribute_ColorInput:
-                if (fHWDrawState.fColor != color) {
+                if (fHWDrawState.getColor() != color) {
                     // OpenGL ES only supports the float varities of glVertexAttrib
                     float c[] = GR_COLOR_TO_VEC4(color);
                     GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), 
                                             c));
-                    fHWDrawState.fColor = color;
+                    fHWDrawState.setColor(color);
                 }
                 break;
             case ProgramDesc::kUniform_ColorInput:
@@ -632,10 +661,10 @@
     if (fProgramData->fUniLocations.fColorFilterUni
                 != GrGLProgram::kUnusedUniform
             && fProgramData->fColorFilterColor
-                != fCurrDrawState.fColorFilterColor) {
-        float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor);
+                != drawState.getColorFilterColor()) {
+        float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor());
         GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
-        fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor;
+        fProgramData->fColorFilterColor = drawState.getColorFilterColor();
     }
 }
 
@@ -645,10 +674,12 @@
         return false;
     }
 
+    const GrDrawState& drawState = this->getDrawState();
+
     if (fDirtyFlags.fRenderTargetChanged) {
         // our coords are in pixel space and the GL matrices map to NDC
         // so if the viewport changed, our matrix is now wrong.
-        fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
+        fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix());
         // we assume all shader matrices may be wrong after viewport changes
         fProgramCache->invalidateViewMatrices();
     }
@@ -680,22 +711,11 @@
     } else if (blendOpts & kEmitCoverage_BlendOptFlag) {
         color = 0xffffffff;
     } else {
-        color = fCurrDrawState.fColor;
+        color = drawState.getColor();
     }
     this->flushColor(color);
 
-    GrMatrix* currViewMatrix;
-    if (GrGLProgram::kSetAsAttribute == 
-        fProgramData->fUniLocations.fViewMatrixUni) {
-        currViewMatrix = &fHWDrawState.fViewMatrix;
-    } else {
-        currViewMatrix = &fProgramData->fViewMatrix;
-    }
-
-    if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
-        flushViewMatrix();
-        *currViewMatrix = fCurrDrawState.fViewMatrix;
-    }
+    this->flushViewMatrix();
 
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
         this->flushTextureMatrix(s);
@@ -857,6 +877,7 @@
                                   BlendOptFlags blendOpts,
                                   GrBlendCoeff dstCoeff) {
     ProgramDesc& desc = fCurrentProgram.fProgramDesc;
+    const GrDrawState& drawState = this->getDrawState();
 
     // This should already have been caught
     GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts));
@@ -885,7 +906,7 @@
 
     desc.fColorFilterXfermode = skipColor ?
                                 SkXfermode::kDst_Mode :
-                                fCurrDrawState.fColorFilterXfermode;
+                                drawState.getColorFilterMode();
 
     // no reason to do edge aa or look at per-vertex coverage if coverage is
     // ignored
@@ -897,7 +918,7 @@
     bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
     bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) ||
                              (!requiresAttributeColors &&
-                              0xffffffff == fCurrDrawState.fColor);
+                              0xffffffff == drawState.getColor());
     if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
         desc.fColorInput = ProgramDesc::kTransBlack_ColorInput;
     } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
@@ -908,16 +929,15 @@
         desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
     }
 
-    desc.fEdgeAANumEdges = skipCoverage ? 0 : fCurrDrawState.fEdgeAANumEdges;
+    desc.fEdgeAANumEdges = skipCoverage ? 0 : drawState.getNumAAEdges();
     desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 &&
-                          SkToBool(fCurrDrawState.fFlagBits &
-                                   kEdgeAAConcave_StateBit);
+                          drawState.isConcaveEdgeAAState();
 
     int lastEnabledStage = -1;
 
     if (!skipCoverage && (desc.fVertexLayout &
                           GrDrawTarget::kEdge_VertexLayoutBit)) {
-        desc.fVertexEdgeType = fCurrDrawState.fVertexEdgeType;
+        desc.fVertexEdgeType = drawState.getVertexEdgeType();
     } else {
         // use canonical value when not set to avoid cache misses
         desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
@@ -929,19 +949,20 @@
         stage.fOptFlags = 0;
         stage.setEnabled(this->isStageEnabled(s));
 
-        bool skip = s < fCurrDrawState.fFirstCoverageStage ? skipColor :
+        bool skip = s < drawState.getFirstCoverageStage() ? skipColor :
                                                              skipCoverage;
 
         if (!skip && stage.isEnabled()) {
             lastEnabledStage = s;
-            GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
+            const GrGLTexture* texture =
+                static_cast<const GrGLTexture*>(drawState.getTexture(s));
             GrAssert(NULL != texture);
-            const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s];
+            const GrSamplerState& sampler = drawState.getSampler(s);
             // we matrix to invert when orientation is TopDown, so make sure
             // we aren't in that case before flagging as identity.
             if (TextureMatrixIsIdentity(texture, sampler)) {
                 stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
-            } else if (!getSamplerMatrix(s).hasPerspective()) {
+            } else if (!sampler.getMatrix().hasPerspective()) {
                 stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
             }
             switch (sampler.getSampleMode()) {
@@ -1024,7 +1045,7 @@
         }
     }
 
-    if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) {
+    if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
         desc.fOutputPM = ProgramDesc::kNo_OutputPM;
     } else {
         desc.fOutputPM = ProgramDesc::kYes_OutputPM;
@@ -1046,9 +1067,9 @@
     // immaterial.
     int firstCoverageStage = GrDrawState::kNumStages;
     desc.fFirstCoverageStage = GrDrawState::kNumStages;
-    bool hasCoverage = fCurrDrawState.fFirstCoverageStage <= lastEnabledStage;
+    bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
     if (hasCoverage) {
-        firstCoverageStage = fCurrDrawState.fFirstCoverageStage;
+        firstCoverageStage = drawState.getFirstCoverageStage();
     }
 
     // other coverage inputs
diff --git a/src/gpu/GrGpuGLShaders.h b/src/gpu/GrGpuGLShaders.h
index baa5d9d..3671296 100644
--- a/src/gpu/GrGpuGLShaders.h
+++ b/src/gpu/GrGpuGLShaders.h
@@ -46,6 +46,8 @@
     class ProgramCache;
 
     // Helpers to make code more readable
+    const GrMatrix& getHWViewMatrix();
+    void recordHWViewMatrix(const GrMatrix& matrix);
     const GrMatrix& getHWSamplerMatrix(int stage);
     void recordHWSamplerMatrix(int stage, const GrMatrix& matrix);
 
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 340cff1..cbe153c 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -9,6 +9,7 @@
 
 
 #include "GrInOrderDrawBuffer.h"
+#include "GrRenderTarget.h"
 #include "GrTexture.h"
 #include "GrBufferAllocPool.h"
 #include "GrIndexBuffer.h"
@@ -78,6 +79,8 @@
     GrAssert(!(fDraws.empty() && fCurrQuad));
     GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
 
+    GrDrawState* drawState = this->drawState();
+
     // if we have a quad IB then either append to the previous run of
     // rects or start a new run
     if (fMaxQuads) {
@@ -89,9 +92,8 @@
             GrPrintf("Failed to get space for vertices!\n");
             return;
         }
-        AutoViewMatrixRestore avmr(this);
-        GrMatrix combinedMatrix = this->getViewMatrix();
-        this->setViewMatrix(GrMatrix::I());
+        GrMatrix combinedMatrix = drawState->getViewMatrix();
+        GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I());
         if (NULL != matrix) {
             combinedMatrix.preConcat(*matrix);
         }
@@ -102,14 +104,14 @@
         // simply because the clip has changed if the clip doesn't affect
         // the rect.
         bool disabledClip = false;
-        if (this->isClipState() && fClip.isRect()) {
+        if (drawState->isClipState() && fClip.isRect()) {
 
             GrRect clipRect = fClip.getRect(0);
             // If the clip rect touches the edge of the viewport, extended it
             // out (close) to infinity to avoid bogus intersections.
             // We might consider a more exact clip to viewport if this
             // conservative test fails.
-            const GrRenderTarget* target = this->getRenderTarget();
+            const GrRenderTarget* target = drawState->getRenderTarget();
             if (0 >= clipRect.fLeft) {
                 clipRect.fLeft = GR_ScalarMin;
             }
@@ -132,7 +134,7 @@
                 }
             }
             if (insideClip) {
-                this->disableState(kClip_StateBit);
+                drawState->disableState(GrDrawState::kClip_StateBit);
                 disabledClip = true;
             }
         }
@@ -176,7 +178,7 @@
             fLastRectVertexLayout = layout;
         }
         if (disabledClip) {
-            this->enableState(kClip_StateBit);
+            drawState->enableState(GrDrawState::kClip_StateBit);
         }
     } else {
         INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
@@ -310,8 +312,8 @@
         // the current render target. If we get that smart we have to make sure
         // those draws aren't read before this clear (render-to-texture).
         r.setLTRB(0, 0, 
-                  this->getRenderTarget()->width(), 
-                  this->getRenderTarget()->height());
+                  this->getDrawState().getRenderTarget()->width(), 
+                  this->getDrawState().getRenderTarget()->height());
         rect = &r;
     }
     Clear& clr = fClears.push_back();
@@ -328,9 +330,9 @@
     for (uint32_t i = 0; i < numStates; ++i) {
         const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]);
         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-            GrSafeUnref(dstate.fTextures[s]);
+            GrSafeUnref(dstate.getTexture(s));
         }
-        GrSafeUnref(dstate.fRenderTarget);
+        GrSafeUnref(dstate.getRenderTarget());
     }
     int numDraws = fDraws.count();
     for (int d = 0; d < numDraws; ++d) {
@@ -593,15 +595,16 @@
 }
 
 void GrInOrderDrawBuffer::pushState() {
+    const GrDrawState& drawState = this->getDrawState();
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        GrSafeRef(fCurrDrawState.fTextures[s]);
+        GrSafeRef(drawState.getTexture(s));
     }
-    GrSafeRef(fCurrDrawState.fRenderTarget);
+    GrSafeRef(drawState.getRenderTarget());
     this->saveCurrentDrawState(&fStates.push_back());
  }
 
 bool GrInOrderDrawBuffer::needsNewClip() const {
-   if (fCurrDrawState.fFlagBits & kClip_StateBit) {
+   if (this->getDrawState().isClipState()) {
        if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
            return true;
        }
diff --git a/src/gpu/GrTesselatedPathRenderer.cpp b/src/gpu/GrTesselatedPathRenderer.cpp
index b6612d1..f7fd8e4 100644
--- a/src/gpu/GrTesselatedPathRenderer.cpp
+++ b/src/gpu/GrTesselatedPathRenderer.cpp
@@ -12,6 +12,7 @@
 #include "GrDrawState.h"
 #include "GrPathUtils.h"
 #include "GrPoint.h"
+#include "GrRenderTarget.h"
 #include "GrTDArray.h"
 
 #include "SkTemplates.h"
@@ -348,10 +349,11 @@
 
 void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) {
     GrDrawTarget::AutoStateRestore asr(fTarget);
+    GrDrawState* drawState = fTarget->drawState();
     // face culling doesn't make sense here
-    GrAssert(GrDrawState::kBoth_DrawFace == fTarget->getDrawFace());
+    GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
 
-    GrMatrix viewM = fTarget->getViewMatrix();
+    GrMatrix viewM = drawState->getViewMatrix();
 
     GrScalar tol = GR_Scalar1;
     tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds());
@@ -433,12 +435,12 @@
 
     if (inverted) {
         GrRect bounds;
-        GrAssert(NULL != fTarget->getRenderTarget());
+        GrAssert(NULL != drawState->getRenderTarget());
         bounds.setLTRB(0, 0,
-                       GrIntToScalar(fTarget->getRenderTarget()->width()),
-                       GrIntToScalar(fTarget->getRenderTarget()->height()));
+                       GrIntToScalar(drawState->getRenderTarget()->width()),
+                       GrIntToScalar(drawState->getRenderTarget()->height()));
         GrMatrix vmi;
-        if (fTarget->getViewInverse(&vmi)) {
+        if (drawState->getViewInverse(&vmi)) {
             vmi.mapRect(&bounds);
         }
         *vert++ = GrPoint::Make(bounds.fLeft, bounds.fTop);
@@ -460,8 +462,8 @@
     if (subpathCnt == 1 && !inverted && fPath->isConvex()) {
         if (fAntiAlias) {
             GrEdgeArray edges;
-            GrMatrix inverse, matrix = fTarget->getViewMatrix();
-            fTarget->getViewInverse(&inverse);
+            GrMatrix inverse, matrix = drawState->getViewMatrix();
+            drawState->getViewInverse(&inverse);
 
             count = computeEdgesAndIntersect(matrix, inverse, base, count, &edges, 0.0f);
             size_t maxEdges = fTarget->getMaxEdges();
@@ -471,7 +473,7 @@
             if (count <= maxEdges) {
                 // All edges fit; upload all edges and draw all verts as a fan
                 fTarget->setVertexSourceToArray(layout, base, count);
-                fTarget->setEdgeAAData(&edges[0], count);
+                drawState->setEdgeAAData(&edges[0], count);
                 fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
             } else {
                 // Upload "maxEdges" edges and verts at a time, and draw as
@@ -481,11 +483,11 @@
                     base[i] = base[0];
                     int size = GR_CT_MIN(count - i, maxEdges);
                     fTarget->setVertexSourceToArray(layout, &base[i], size);
-                    fTarget->setEdgeAAData(&edges[i], size);
+                    drawState->setEdgeAAData(&edges[i], size);
                     fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size);
                 }
             }
-            fTarget->setEdgeAAData(NULL, 0);
+            drawState->setEdgeAAData(NULL, 0);
         } else {
             fTarget->setVertexSourceToArray(layout, base, count);
             fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
@@ -498,8 +500,8 @@
         GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fFill));
         btess.addVertices(base, subpathVertCount, subpathCnt);
 
-        GrMatrix inverse, matrix = fTarget->getViewMatrix();
-        if (!fTarget->getViewInverse(&inverse)) {
+        GrMatrix inverse, matrix = drawState->getViewMatrix();
+        if (!drawState->getViewInverse(&inverse)) {
             return;
         }
 
@@ -534,7 +536,7 @@
         }
 
         // Draw the resulting polys and upload their edge data.
-        fTarget->enableState(GrDrawTarget::kEdgeAAConcave_StateBit);
+        drawState->enableState(GrDrawState::kEdgeAAConcave_StateBit);
         const GrPointArray& vertices = ptess.vertices();
         const GrIndexArray& indices = ptess.indices();
         const GrDrawState::Edge* edges = ptess.edges();
@@ -567,12 +569,12 @@
                 tri_edges[t++] = edge4;
                 tri_edges[t++] = edge5;
             }
-            fTarget->setEdgeAAData(&tri_edges[0], t);
+            drawState->setEdgeAAData(&tri_edges[0], t);
             fTarget->setVertexSourceToArray(layout, &tri_verts[0], 3);
             fTarget->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
         }
-        fTarget->setEdgeAAData(NULL, 0);
-        fTarget->disableState(GrDrawTarget::kEdgeAAConcave_StateBit);
+        drawState->setEdgeAAData(NULL, 0);
+        drawState->disableState(GrDrawState::kEdgeAAConcave_StateBit);
         return;
     }
 
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 4b78d4a..3b3841b 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -25,7 +25,7 @@
 void GrTextContext::flushGlyphs() {
     if (fCurrVertex > 0) {
         GrDrawTarget::AutoStateRestore asr(fDrawTarget);
-
+        GrDrawState* drawState = fDrawTarget->drawState();
         // setup our sampler state for our text texture/atlas
         GrSamplerState::Filter filter;
         if (fExtMatrix.isIdentity()) {
@@ -35,12 +35,12 @@
         }
         GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode,
                                filter);
-        fDrawTarget->setSamplerState(kGlyphMaskStage, sampler);
+        drawState->setSampler(kGlyphMaskStage, sampler);
 
         GrAssert(GrIsALIGN4(fCurrVertex));
         int nIndices = fCurrVertex + (fCurrVertex >> 1);
         GrAssert(fCurrTexture);
-        fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture);
+        drawState->setTexture(kGlyphMaskStage, fCurrTexture);
 
         if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
             if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
@@ -49,15 +49,15 @@
                 GrPrintf("LCD Text will not draw correctly.\n");
             }
             // setup blend so that we get mask * paintColor + (1-mask)*dstColor
-            fDrawTarget->setBlendConstant(fPaint.fColor);
+            drawState->setBlendConstant(fPaint.fColor);
             fDrawTarget->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff);
             // don't modulate by the paint's color in the frag since we're
             // already doing it via the blend const.
-            fDrawTarget->setColor(0xffffffff);
+            drawState->setColor(0xffffffff);
         } else {
             // set back to normal in case we took LCD path previously.
             fDrawTarget->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff);
-            fDrawTarget->setColor(fPaint.fColor);
+            drawState->setColor(fPaint.fColor);
         }
 
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());