Make GrTextContext be owned by the GrDrawContext

This CL makes the GrTextContext be owned (and hidden) by the GrDrawContext. This funnels all the drawText* calls through the GrDrawContext and hides the (dispreferred) GrPipelineBuilder drawText variant.

Some consequences of this are:

GrDrawContext now has to get the text drawing settings (i.e., SkDeviceProperties & useDFT). This means that we need a separate GrDrawContext for each combination of pixel geometry and DFT-use.

All the GrTextContext-derived classes now get a back pointer to the originating GrDrawContext so their method calls no longer take one.

Committed: https://skia.googlesource.com/skia/+/5b16e740fe6ab6d679083d06f07651602265081b

Review URL: https://codereview.chromium.org/1175553002
diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
index 75aaf04..d1076bb 100644
--- a/src/gpu/GrAtlasTextContext.cpp
+++ b/src/gpu/GrAtlasTextContext.cpp
@@ -13,6 +13,7 @@
 #include "GrBlurUtils.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawContext.h"
+#include "GrDrawTarget.h"
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrResourceProvider.h"
@@ -97,9 +98,10 @@
 // Distance field text in textblobs
 
 GrAtlasTextContext::GrAtlasTextContext(GrContext* context,
+                                       GrDrawContext* drawContext,
                                        const SkDeviceProperties& properties,
-                                       bool enableDistanceFields)
-    : INHERITED(context, properties)
+                                       bool useDFT)
+    : INHERITED(context, drawContext, properties)
     , fDistanceAdjustTable(SkNEW_ARGS(DistanceAdjustTable, (properties.gamma()))) {
     // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
     // vertexStride
@@ -111,7 +113,7 @@
 #if SK_FORCE_DISTANCE_FIELD_TEXT
     fEnableDFRendering = true;
 #else
-    fEnableDFRendering = enableDistanceFields;
+    fEnableDFRendering = useDFT;
 #endif
 }
 
@@ -198,9 +200,10 @@
 }
 
 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
+                                               GrDrawContext* drawContext,
                                                const SkDeviceProperties& props,
-                                               bool enableDistanceFields) {
-    return SkNEW_ARGS(GrAtlasTextContext, (context, props, enableDistanceFields));
+                                               bool useDFT) {
+    return SkNEW_ARGS(GrAtlasTextContext, (context, drawContext, props, useDFT));
 }
 
 bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
@@ -356,11 +359,6 @@
         return;
     }
 
-    GrDrawContext* drawContext = fContext->drawContext();
-    if (!drawContext) {
-        return;
-    }
-
     SkAutoTUnref<BitmapTextBlob> cacheBlob;
     SkMaskFilter::BlurRec blurRec;
     BitmapTextBlob::Key key;
@@ -435,7 +433,7 @@
     }
 
     cacheBlob->fPaintColor = skPaint.getColor();
-    this->flush(drawContext, blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
+    this->flush(blob, cacheBlob, rt, skPaint, grPaint, drawFilter,
                 clip, viewMatrix, clipBounds, x, y, transX, transY);
 }
 
@@ -777,36 +775,32 @@
     return blob;
 }
 
-void GrAtlasTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
+void GrAtlasTextContext::onDrawText(GrRenderTarget* rt,
                                     const GrClip& clip, 
                                     const GrPaint& paint, const SkPaint& skPaint,
                                     const SkMatrix& viewMatrix,
                                     const char text[], size_t byteLength,
                                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) {
-    if (drawContext) {
-        SkAutoTUnref<BitmapTextBlob> blob(
-            this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
-                                     text, byteLength, x, y, regionClipBounds));
-        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
-    }
+    SkAutoTUnref<BitmapTextBlob> blob(
+        this->createDrawTextBlob(rt, clip, paint, skPaint, viewMatrix,
+                                 text, byteLength, x, y, regionClipBounds));
+    this->flush(blob, rt, skPaint, paint, clip, regionClipBounds);
 }
 
-void GrAtlasTextContext::onDrawPosText(GrDrawContext* drawContext, GrRenderTarget* rt,
+void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt,
                                        const GrClip& clip,
                                        const GrPaint& paint, const SkPaint& skPaint,
                                        const SkMatrix& viewMatrix,
                                        const char text[], size_t byteLength,
                                        const SkScalar pos[], int scalarsPerPosition,
                                        const SkPoint& offset, const SkIRect& regionClipBounds) {
-    if (drawContext) {
-        SkAutoTUnref<BitmapTextBlob> blob(
-            this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
-                                        text, byteLength,
-                                        pos, scalarsPerPosition,
-                                        offset, regionClipBounds));
+    SkAutoTUnref<BitmapTextBlob> blob(
+        this->createDrawPosTextBlob(rt, clip, paint, skPaint, viewMatrix,
+                                    text, byteLength,
+                                    pos, scalarsPerPosition,
+                                    offset, regionClipBounds));
 
-        this->flush(drawContext, blob, rt, skPaint, paint, clip, regionClipBounds);
-    }
+    this->flush(blob, rt, skPaint, paint, clip, regionClipBounds);
 }
 
 void GrAtlasTextContext::internalDrawBMPText(BitmapTextBlob* blob, int runIndex,
@@ -2045,8 +2039,7 @@
     float fGamma;
 };
 
-void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* drawContext,
-                                         GrRenderTarget* rt, const SkTextBlob::RunIterator& it, 
+void GrAtlasTextContext::flushRunAsPaths(GrRenderTarget* rt, const SkTextBlob::RunIterator& it, 
                                          const GrClip& clip, const SkPaint& skPaint,
                                          SkDrawFilter* drawFilter, const SkMatrix& viewMatrix,
                                          const SkIRect& clipBounds, SkScalar x, SkScalar y) {
@@ -2065,18 +2058,18 @@
 
     switch (it.positioning()) {
         case SkTextBlob::kDefault_Positioning:
-            this->drawTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
+            this->drawTextAsPath(rt, clip, runPaint, viewMatrix,
                                  (const char *)it.glyphs(),
                                  textLen, x + offset.x(), y + offset.y(), clipBounds);
             break;
         case SkTextBlob::kHorizontal_Positioning:
-            this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
+            this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix,
                                     (const char*)it.glyphs(),
                                     textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()),
                                     clipBounds);
             break;
         case SkTextBlob::kFull_Positioning:
-            this->drawPosTextAsPath(drawContext, rt, clip, runPaint, viewMatrix,
+            this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix,
                                     (const char*)it.glyphs(),
                                     textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
             break;
@@ -2128,8 +2121,7 @@
     return batch;
 }
 
-inline void GrAtlasTextContext::flushRun(GrDrawContext* drawContext,
-                                         GrPipelineBuilder* pipelineBuilder,
+inline void GrAtlasTextContext::flushRun(GrPipelineBuilder* pipelineBuilder,
                                          BitmapTextBlob* cacheBlob, int run, GrColor color,
                                          SkScalar transX, SkScalar transY,
                                          const SkPaint& skPaint) {
@@ -2143,12 +2135,11 @@
         SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, glyphCount, run,
                                                               subRun, color, transX, transY,
                                                               skPaint));
-        drawContext->drawText(pipelineBuilder, batch);
+        fDrawContext->drawBatch(pipelineBuilder, batch);
     }
 }
 
-inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob,
-                                               GrDrawContext* drawContext, GrRenderTarget* rt,
+inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget* rt,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                SkScalar transX, SkScalar transY,
                                                const SkIRect& clipBounds) {
@@ -2169,13 +2160,12 @@
         SkMatrix translate = cacheBlob->fViewMatrix;
         translate.postTranslate(bigGlyph.fVx, bigGlyph.fVy);
 
-        GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, bigGlyph.fPath,
+        GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, bigGlyph.fPath,
                                             skPaint, translate, &pathMatrix, clipBounds, false);
     }
 }
 
-void GrAtlasTextContext::flush(GrDrawContext* drawContext,
-                               const SkTextBlob* blob,
+void GrAtlasTextContext::flush(const SkTextBlob* blob,
                                BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
                                const SkPaint& skPaint,
@@ -2196,21 +2186,20 @@
     SkTextBlob::RunIterator it(blob);
     for (int run = 0; !it.done(); it.next(), run++) {
         if (cacheBlob->fRuns[run].fDrawAsPaths) {
-            this->flushRunAsPaths(drawContext, rt, it, clip, skPaint,
+            this->flushRunAsPaths(rt, it, clip, skPaint,
                                   drawFilter, viewMatrix, clipBounds, x, y);
             continue;
         }
         cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
-        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color,
+        this->flushRun(&pipelineBuilder, cacheBlob, run, color,
                        transX, transY, skPaint);
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, transX, transY, clipBounds);
+    this->flushBigGlyphs(cacheBlob, rt, clip, skPaint, transX, transY, clipBounds);
 }
 
-void GrAtlasTextContext::flush(GrDrawContext* drawContext,
-                               BitmapTextBlob* cacheBlob,
+void GrAtlasTextContext::flush(BitmapTextBlob* cacheBlob,
                                GrRenderTarget* rt,
                                const SkPaint& skPaint,
                                const GrPaint& grPaint,
@@ -2221,11 +2210,11 @@
 
     GrColor color = grPaint.getColor();
     for (int run = 0; run < cacheBlob->fRunCount; run++) {
-        this->flushRun(drawContext, &pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
+        this->flushRun(&pipelineBuilder, cacheBlob, run, color, 0, 0, skPaint);
     }
 
     // Now flush big glyphs
-    this->flushBigGlyphs(cacheBlob, drawContext, rt, clip, skPaint, 0, 0, clipBounds);
+    this->flushBigGlyphs(cacheBlob, rt, clip, skPaint, 0, 0, clipBounds);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2235,15 +2224,19 @@
 BATCH_TEST_DEFINE(TextBlobBatch) {
     static uint32_t gContextID = SK_InvalidGenID;
     static GrAtlasTextContext* gTextContext = NULL;
-    static SkDeviceProperties gDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
+    static SkDeviceProperties gDevProperties;
 
     if (context->uniqueID() != gContextID) {
         gContextID = context->uniqueID();
         SkDELETE(gTextContext);
+
+        static const bool kUseDFT = false;
         // We don't yet test the fall back to paths in the GrTextContext base class.  This is mostly
         // because we don't really want to have a gpu device here.
         // We enable distance fields by twiddling a knob on the paint
-        gTextContext = GrAtlasTextContext::Create(context, gDeviceProperties, false);
+        GrDrawContext* drawContext = context->drawContext(&gDevProperties, kUseDFT);
+
+        gTextContext = GrAtlasTextContext::Create(context, drawContext, gDevProperties, kUseDFT);
     }
 
     // create dummy render target
diff --git a/src/gpu/GrAtlasTextContext.h b/src/gpu/GrAtlasTextContext.h
index 9a4ef6a..47bb7ae 100644
--- a/src/gpu/GrAtlasTextContext.h
+++ b/src/gpu/GrAtlasTextContext.h
@@ -25,6 +25,7 @@
 
 class BitmapTextBatch;
 class GrDrawContext;
+class GrDrawTarget;
 class GrPipelineBuilder;
 class GrTextBlobCache;
 
@@ -34,20 +35,20 @@
  */
 class GrAtlasTextContext : public GrTextContext {
 public:
-    static GrAtlasTextContext* Create(GrContext*, const SkDeviceProperties&,
-                                      bool enableDistanceFields);
+    static GrAtlasTextContext* Create(GrContext*, GrDrawContext*,
+                                      const SkDeviceProperties&, bool enableDistanceFields);
 
 private:
-    GrAtlasTextContext(GrContext*, const SkDeviceProperties&, bool enableDistanceFields);
+    GrAtlasTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&, bool useDFT);
     ~GrAtlasTextContext() override {}
 
     bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                  const SkPaint&, const SkMatrix& viewMatrix) override;
 
-    void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix, const char text[], size_t byteLength,
                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
-    void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&,
+    void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&,
                        const SkPaint&, const SkMatrix& viewMatrix,
                        const char text[], size_t byteLength,
                        const SkScalar pos[], int scalarsPerPosition,
@@ -271,7 +272,7 @@
                                   size_t vertexStride, bool useVertexColor,
                                   GrGlyph*);
 
-    inline void flushRunAsPaths(GrDrawContext*, GrRenderTarget*,
+    inline void flushRunAsPaths(GrRenderTarget*,
                                 const SkTextBlob::RunIterator&, const GrClip& clip,
                                 const SkPaint&, SkDrawFilter*,
                                 const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
@@ -280,18 +281,18 @@
                                         int glyphCount, int run, int subRun,
                                         GrColor, SkScalar transX, SkScalar transY,
                                         const SkPaint&);
-    inline void flushRun(GrDrawContext*, GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
+    inline void flushRun(GrPipelineBuilder*, BitmapTextBlob*, int run, GrColor,
                          SkScalar transX, SkScalar transY, const SkPaint&);
-    inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrDrawContext*, GrRenderTarget*,
+    inline void flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRenderTarget*,
                                const GrClip& clip, const SkPaint& skPaint,
                                SkScalar transX, SkScalar transY, const SkIRect& clipBounds);
 
     // We have to flush SkTextBlobs differently from drawText / drawPosText
-    void flush(GrDrawContext*, const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
+    void flush(const SkTextBlob*, BitmapTextBlob*, GrRenderTarget*,
                const SkPaint&, const GrPaint&, SkDrawFilter*, const GrClip&,
                const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, SkScalar y,
                SkScalar transX, SkScalar transY);
-    void flush(GrDrawContext*, BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
+    void flush(BitmapTextBlob*, GrRenderTarget*, const SkPaint&,
                const GrPaint&, const GrClip&, const SkIRect& clipBounds);
 
     // A helper for drawing BitmapText in a run of distance fields
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 64f4cb3..d5f9f9c 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -9,7 +9,6 @@
 #include "GrContext.h"
 
 #include "GrAARectRenderer.h"
-#include "GrAtlasTextContext.h"
 #include "GrBatch.h"
 #include "GrBatchFontCache.h"
 #include "GrBatchTarget.h"
@@ -32,7 +31,6 @@
 #include "GrResourceCache.h"
 #include "GrResourceProvider.h"
 #include "GrSoftwarePathRenderer.h"
-#include "GrStencilAndCoverTextContext.h"
 #include "GrStrokeInfo.h"
 #include "GrSurfacePriv.h"
 #include "GrTextBlobCache.h"
@@ -62,24 +60,37 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::DrawingMgr::init(GrContext* context) {
+    fContext = context;
+
 #ifdef IMMEDIATE_MODE
     fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context));
 #else
     fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context));
 #endif    
+}
 
-    fDrawContext = SkNEW_ARGS(GrDrawContext, (context, fDrawTarget));
+void GrContext::DrawingMgr::cleanup() {
+    SkSafeSetNull(fDrawTarget);
+    for (int i = 0; i < kNumPixelGeometries; ++i) {
+        SkSafeSetNull(fDrawContext[i][0]);
+        SkSafeSetNull(fDrawContext[i][1]);
+    }
 }
 
 GrContext::DrawingMgr::~DrawingMgr() {
-    SkSafeUnref(fDrawTarget);
-    SkSafeUnref(fDrawContext);
+    this->cleanup();
 }
 
 void GrContext::DrawingMgr::abandon() {
     SkSafeSetNull(fDrawTarget);
-    SkSafeSetNull(fDrawContext->fDrawTarget);
-    SkSafeSetNull(fDrawContext);
+    for (int i = 0; i < kNumPixelGeometries; ++i) {
+        for (int j = 0; j < kNumDFTOptions; ++j) {
+            if (fDrawContext[i][j]) {
+                SkSafeSetNull(fDrawContext[i][j]->fDrawTarget);
+                SkSafeSetNull(fDrawContext[i][j]);
+            }
+        }
+    }
 }
 
 void GrContext::DrawingMgr::purgeResources() {
@@ -100,11 +111,29 @@
     }
 }
 
-GrDrawContext* GrContext::DrawingMgr::drawContext() { 
+GrDrawContext* GrContext::DrawingMgr::drawContext(const SkDeviceProperties* devProps, bool useDFT) { 
     if (this->abandoned()) {
         return NULL;
     }
-    return fDrawContext; 
+
+    const SkDeviceProperties defProps;
+    if (!devProps) {
+        devProps = &defProps;
+    }
+
+    SkASSERT(devProps->pixelGeometry() < kNumPixelGeometries);
+    if (!fDrawContext[devProps->pixelGeometry()][useDFT]) {
+        fDrawContext[devProps->pixelGeometry()][useDFT] =
+                SkNEW_ARGS(GrDrawContext, (fContext, fDrawTarget, *devProps, useDFT));
+    }
+
+    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->pixelGeometry() ==
+             devProps->pixelGeometry());
+    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->gamma() == 
+             devProps->gamma());
+    SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fUseDFT == useDFT);
+
+    return fDrawContext[devProps->pixelGeometry()][useDFT]; 
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -185,6 +214,8 @@
 
     this->flush();
 
+    fDrawingMgr.cleanup();
+
     for (int i = 0; i < fCleanUpData.count(); ++i) {
         (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
     }
@@ -246,21 +277,6 @@
     }
 }
 
-GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
-                                            const SkDeviceProperties&
-                                            leakyProperties,
-                                            bool enableDistanceFieldFonts) {
-    if (fGpu->caps()->shaderCaps()->pathRenderingSupport() &&
-        renderTarget->isStencilBufferMultisampled()) {
-        GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
-        if (sb) {
-            return GrStencilAndCoverTextContext::Create(this, leakyProperties);
-        }
-    } 
-
-    return GrAtlasTextContext::Create(this, leakyProperties, enableDistanceFieldFonts);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::OverBudgetCB(void* data) {
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 23c349b..7f97275 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -7,12 +7,16 @@
  */
 
 #include "GrAARectRenderer.h"
+#include "GrAtlasTextContext.h"
 #include "GrBatch.h"
 #include "GrBatchTest.h"
 #include "GrDefaultGeoProcFactory.h"
 #include "GrDrawContext.h"
 #include "GrOvalRenderer.h"
 #include "GrPathRenderer.h"
+#include "GrRenderTarget.h"
+#include "GrRenderTargetPriv.h"
+#include "GrStencilAndCoverTextContext.h"
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fContext)
 #define RETURN_IF_ABANDONED        if (!fDrawTarget) { return; }
@@ -28,13 +32,21 @@
     GrContext* fContext;
 };
 
-GrDrawContext::GrDrawContext(GrContext* context, GrDrawTarget* drawTarget)
+GrDrawContext::GrDrawContext(GrContext* context,
+                             GrDrawTarget* drawTarget,
+                             const SkDeviceProperties& devProps,
+                             bool useDFT)
     : fContext(context)
-    , fDrawTarget(SkRef(drawTarget)) {
+    , fDrawTarget(SkRef(drawTarget))
+    , fTextContext(NULL)
+    , fDevProps(SkNEW_ARGS(SkDeviceProperties, (devProps)))
+    , fUseDFT(useDFT) {
 }
 
 GrDrawContext::~GrDrawContext() {
     SkSafeUnref(fDrawTarget);
+    SkDELETE(fTextContext);
+    SkDELETE(fDevProps);
 }
 
 void GrDrawContext::copySurface(GrRenderTarget* dst, GrSurface* src,
@@ -46,8 +58,58 @@
     fDrawTarget->copySurface(dst, src, srcRect, dstPoint);
 }
 
-void GrDrawContext::drawText(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
-    fDrawTarget->drawBatch(pipelineBuilder, batch);
+GrTextContext* GrDrawContext::createTextContext(GrRenderTarget* renderTarget,
+                                                const SkDeviceProperties& leakyProperties,
+                                                bool enableDistanceFieldFonts) {
+    if (fContext->caps()->shaderCaps()->pathRenderingSupport() &&
+        renderTarget->isStencilBufferMultisampled()) {
+        GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
+        if (sb) {
+            return GrStencilAndCoverTextContext::Create(fContext, this, 
+                                                        leakyProperties,
+                                                        enableDistanceFieldFonts);
+        }
+    } 
+
+    return GrAtlasTextContext::Create(fContext, this, leakyProperties, enableDistanceFieldFonts);
+}
+
+void GrDrawContext::drawText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint,
+                             const SkPaint& skPaint,
+                             const SkMatrix& viewMatrix,
+                             const char text[], size_t byteLength,
+                             SkScalar x, SkScalar y, const SkIRect& clipBounds) {
+    if (!fTextContext) {
+        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
+    }
+
+    fTextContext->drawText(rt, clip, grPaint, skPaint, viewMatrix,
+                           text, byteLength, x, y, clipBounds);
+
+}
+void GrDrawContext::drawPosText(GrRenderTarget* rt, const GrClip& clip, const GrPaint& grPaint,
+                                const SkPaint& skPaint,
+                                const SkMatrix& viewMatrix,
+                                const char text[], size_t byteLength,
+                                const SkScalar pos[], int scalarsPerPosition,
+                                const SkPoint& offset, const SkIRect& clipBounds) {
+    if (!fTextContext) {
+        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
+    }
+
+    fTextContext->drawPosText(rt, clip, grPaint, skPaint, viewMatrix, text, byteLength,
+                               pos, scalarsPerPosition, offset, clipBounds);
+
+}
+void GrDrawContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const SkPaint& skPaint,
+                                 const SkMatrix& viewMatrix, const SkTextBlob* blob,
+                                 SkScalar x, SkScalar y,
+                                 SkDrawFilter* filter, const SkIRect& clipBounds) {
+    if (!fTextContext) {
+        fTextContext = this->createTextContext(rt, *fDevProps, fUseDFT);
+    }
+
+    fTextContext->drawTextBlob(rt, clip, skPaint, viewMatrix, blob, x, y, filter, clipBounds);
 }
 
 void GrDrawContext::drawPaths(GrPipelineBuilder* pipelineBuilder,
@@ -1147,6 +1209,10 @@
     return true;
 }
 
+void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrBatch* batch) {
+    fDrawTarget->drawBatch(pipelineBuilder, batch);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #ifdef GR_TEST_UTILS
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index 763863f..d1b6a84 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -22,18 +22,21 @@
 #include "SkTextFormatParams.h"
 
 GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrContext* context,
+                                                           GrDrawContext* drawContext,
                                                            const SkDeviceProperties& properties)
-    : GrTextContext(context, properties)
+    : GrTextContext(context, drawContext, properties)
     , fStroke(SkStrokeRec::kFill_InitStyle)
     , fQueuedGlyphCount(0)
     , fFallbackGlyphsIdx(kGlyphBufferSize) {
 }
 
 GrStencilAndCoverTextContext*
-GrStencilAndCoverTextContext::Create(GrContext* context, const SkDeviceProperties& props) {
+GrStencilAndCoverTextContext::Create(GrContext* context, GrDrawContext* drawContext,
+                                     const SkDeviceProperties& props, bool fallbackUsesDFT) {
     GrStencilAndCoverTextContext* textContext = SkNEW_ARGS(GrStencilAndCoverTextContext,
-                                                           (context, props));
-    textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, props, false);
+                                                           (context, drawContext, props));
+    textContext->fFallbackTextContext = GrAtlasTextContext::Create(context, drawContext,
+                                                                   props, fallbackUsesDFT);
 
     return textContext;
 }
@@ -71,7 +74,7 @@
     return rec.getFormat() != SkMask::kARGB32_Format;
 }
 
-void GrStencilAndCoverTextContext::onDrawText(GrDrawContext* drawContext, GrRenderTarget* rt,
+void GrStencilAndCoverTextContext::onDrawText(GrRenderTarget* rt,
                                               const GrClip& clip,
                                               const GrPaint& paint,
                                               const SkPaint& skPaint,
@@ -154,19 +157,17 @@
         const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
         fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
         if (glyph.fWidth) {
-            this->appendGlyph(drawContext, glyph, 
-                              SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
+            this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedToScalar(fy)));
         }
 
         fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
         fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
     }
 
-    this->finish(drawContext);
+    this->finish();
 }
 
-void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* drawContext,
-                                                 GrRenderTarget* rt,
+void GrStencilAndCoverTextContext::onDrawPosText(GrRenderTarget* rt,
                                                  const GrClip& clip,
                                                  const GrPaint& paint,
                                                  const SkPaint& skPaint,
@@ -210,12 +211,12 @@
             SkPoint loc;
             alignProc(tmsLoc, glyph, &loc);
 
-            this->appendGlyph(drawContext, glyph, loc);
+            this->appendGlyph(glyph, loc);
         }
         pos += scalarsPerPosition;
     }
 
-    this->finish(drawContext);
+    this->finish();
 }
 
 static GrPathRange* get_gr_glyphs(GrContext* ctx,
@@ -410,11 +411,10 @@
     return true;
 }
 
-inline void GrStencilAndCoverTextContext::appendGlyph(GrDrawContext* drawContext,
-                                                      const SkGlyph& glyph, const SkPoint& pos) {
+inline void GrStencilAndCoverTextContext::appendGlyph(const SkGlyph& glyph, const SkPoint& pos) {
     if (fQueuedGlyphCount >= fFallbackGlyphsIdx) {
         SkASSERT(fQueuedGlyphCount == fFallbackGlyphsIdx);
-        this->flush(drawContext);
+        this->flush();
     }
 
     // Stick the glyphs we can't draw at the end of the buffer, growing backwards.
@@ -432,17 +432,17 @@
     return &pointArray[0].fX;
 }
 
-void GrStencilAndCoverTextContext::flush(GrDrawContext* drawContext) {
+void GrStencilAndCoverTextContext::flush() {
     if (fQueuedGlyphCount > 0) {
         SkAutoTUnref<GrPathProcessor> pp(GrPathProcessor::Create(fPaint.getColor(),
                                                                  fViewMatrix,
                                                                  fLocalMatrix));
 
-        drawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
-                               fGlyphIndices, GrPathRange::kU16_PathIndexType,
-                               get_xy_scalar_array(fGlyphPositions),
-                               GrPathRendering::kTranslate_PathTransformType,
-                               fQueuedGlyphCount, GrPathRendering::kWinding_FillType);
+        fDrawContext->drawPaths(&fPipelineBuilder, pp, fGlyphs,
+                                fGlyphIndices, GrPathRange::kU16_PathIndexType,
+                                get_xy_scalar_array(fGlyphPositions),
+                                GrPathRendering::kTranslate_PathTransformType,
+                                fQueuedGlyphCount, GrPathRendering::kWinding_FillType);
 
         fQueuedGlyphCount = 0;
     }
@@ -474,8 +474,8 @@
     }
 }
 
-void GrStencilAndCoverTextContext::finish(GrDrawContext* drawContext) {
-    this->flush(drawContext);
+void GrStencilAndCoverTextContext::finish() {
+    this->flush();
 
     fGlyphs->unref();
     fGlyphs = NULL;
diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h
index d36b60f..920f2d7 100644
--- a/src/gpu/GrStencilAndCoverTextContext.h
+++ b/src/gpu/GrStencilAndCoverTextContext.h
@@ -23,7 +23,8 @@
  */
 class GrStencilAndCoverTextContext : public GrTextContext {
 public:
-    static GrStencilAndCoverTextContext* Create(GrContext*, const SkDeviceProperties&);
+    static GrStencilAndCoverTextContext* Create(GrContext*, GrDrawContext*,
+                                                const SkDeviceProperties&, bool fallbackUsesDFT);
 
     virtual ~GrStencilAndCoverTextContext();
 
@@ -67,16 +68,16 @@
     SkMatrix                                            fLocalMatrix;
     bool                                                fUsingDeviceSpaceGlyphs;
 
-    GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
+    GrStencilAndCoverTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&);
 
     bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                  const SkPaint&, const SkMatrix& viewMatrix) override;
 
-    void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix,
                     const char text[], size_t byteLength,
                     SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
-    void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
+    void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
                        const SkMatrix& viewMatrix,
                        const char text[], size_t byteLength,
                        const SkScalar pos[], int scalarsPerPosition,
@@ -86,9 +87,9 @@
               size_t textByteLength, RenderMode, const SkMatrix& viewMatrix,
               const SkIRect& regionClipBounds);
     bool mapToFallbackContext(SkMatrix* inverse);
-    void appendGlyph(GrDrawContext*, const SkGlyph&, const SkPoint&);
-    void flush(GrDrawContext*);
-    void finish(GrDrawContext*);
+    void appendGlyph(const SkGlyph&, const SkPoint&);
+    void flush();
+    void finish();
 
 };
 
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 91c8e85..5559b2d 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -20,10 +20,12 @@
 #include "SkTextMapStateProc.h"
 #include "SkTextToPathIter.h"
 
-GrTextContext::GrTextContext(GrContext* context, const SkDeviceProperties& properties)
+GrTextContext::GrTextContext(GrContext* context, GrDrawContext* drawContext,
+                             const SkDeviceProperties& properties)
     : fFallbackTextContext(NULL)
     , fContext(context)
-    , fDeviceProperties(properties) {
+    , fDeviceProperties(properties)
+    , fDrawContext(drawContext) {
 }
 
 GrTextContext::~GrTextContext() {
@@ -47,19 +49,14 @@
                              const SkPaint& skPaint, const SkMatrix& viewMatrix,
                              const char text[], size_t byteLength,
                              SkScalar x, SkScalar y, const SkIRect& clipBounds) {
-    if (fContext->abandoned()) {
-        return;
-    }
-
-    GrDrawContext* drawContext = fContext->drawContext();
-    if (!drawContext) {
+    if (fContext->abandoned() || !fDrawContext) {
         return;
     }
 
     GrTextContext* textContext = this;
     do {
         if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
-            textContext->onDrawText(drawContext, rt, clip, paint, skPaint, viewMatrix,
+            textContext->onDrawText(rt, clip, paint, skPaint, viewMatrix,
                                     text, byteLength, x, y, clipBounds);
             return;
         }
@@ -67,7 +64,7 @@
     } while (textContext);
 
     // fall back to drawing as a path
-    this->drawTextAsPath(drawContext, rt, clip, skPaint, viewMatrix,
+    this->drawTextAsPath(rt, clip, skPaint, viewMatrix,
                          text, byteLength, x, y, clipBounds);
 }
 
@@ -76,19 +73,14 @@
                                 const char text[], size_t byteLength,
                                 const SkScalar pos[], int scalarsPerPosition,
                                 const SkPoint& offset, const SkIRect& clipBounds) {
-    if (fContext->abandoned()) {
-        return;
-    }
-
-    GrDrawContext* drawContext = fContext->drawContext();
-    if (!drawContext) {
+    if (fContext->abandoned() || !fDrawContext) {
         return;
     }
 
     GrTextContext* textContext = this;
     do {
         if (textContext->canDraw(rt, clip, paint, skPaint, viewMatrix)) {
-            textContext->onDrawPosText(drawContext, rt, clip, paint, skPaint, viewMatrix,
+            textContext->onDrawPosText(rt, clip, paint, skPaint, viewMatrix,
                                        text, byteLength, pos,
                                        scalarsPerPosition, offset, clipBounds);
             return;
@@ -97,7 +89,7 @@
     } while (textContext);
 
     // fall back to drawing as a path
-    this->drawPosTextAsPath(drawContext, rt, clip, skPaint, viewMatrix, text, byteLength, pos,
+    this->drawPosTextAsPath(rt, clip, skPaint, viewMatrix, text, byteLength, pos,
                             scalarsPerPosition, offset, clipBounds);
 }
 
@@ -183,7 +175,7 @@
     }
 }
 
-void GrTextContext::drawTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
+void GrTextContext::drawTextAsPath(GrRenderTarget* rt,
                                    const GrClip& clip,
                                    const SkPaint& skPaint, const SkMatrix& viewMatrix,
                                    const char text[], size_t byteLength, SkScalar x, SkScalar y,
@@ -201,14 +193,14 @@
         matrix.postTranslate(xpos - prevXPos, 0);
         if (iterPath) {
             const SkPaint& pnt = iter.getPaint();
-            GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *iterPath,
+            GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, *iterPath,
                                                 pnt, viewMatrix, &matrix, clipBounds, false);
         }
         prevXPos = xpos;
     }
 }
 
-void GrTextContext::drawPosTextAsPath(GrDrawContext* drawContext, GrRenderTarget* rt,
+void GrTextContext::drawPosTextAsPath(GrRenderTarget* rt,
                                       const GrClip& clip,
                                       const SkPaint& origPaint, const SkMatrix& viewMatrix,
                                       const char text[], size_t byteLength,
@@ -249,7 +241,7 @@
 
                 matrix[SkMatrix::kMTransX] = loc.fX;
                 matrix[SkMatrix::kMTransY] = loc.fY;
-                GrBlurUtils::drawPathWithMaskFilter(fContext, drawContext, rt, clip, *path, paint,
+                GrBlurUtils::drawPathWithMaskFilter(fContext, fDrawContext, rt, clip, *path, paint,
                                                     viewMatrix, &matrix, clipBounds, false);
             }
         }
diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h
index f4c0982..775203e 100644
--- a/src/gpu/GrTextContext.h
+++ b/src/gpu/GrTextContext.h
@@ -48,6 +48,7 @@
     GrContext*                     fContext;
     SkDeviceProperties             fDeviceProperties;
 
+    GrDrawContext*                 fDrawContext;  // owning drawContext
     SkAutoTUnref<GrRenderTarget>   fRenderTarget;
     GrClip                         fClip;
     SkIRect                        fClipRect;
@@ -55,27 +56,27 @@
     GrPaint                        fPaint;
     SkPaint                        fSkPaint;
 
-    GrTextContext(GrContext*, const SkDeviceProperties&);
+    GrTextContext(GrContext*, GrDrawContext*, const SkDeviceProperties&);
 
     virtual bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
                          const SkPaint&, const SkMatrix& viewMatrix) = 0;
 
-    virtual void onDrawText(GrDrawContext*, GrRenderTarget*, const GrClip&,
+    virtual void onDrawText(GrRenderTarget*, const GrClip&,
                             const GrPaint&, const SkPaint&,
                             const SkMatrix& viewMatrix, const char text[], size_t byteLength,
                             SkScalar x, SkScalar y, const SkIRect& clipBounds) = 0;
-    virtual void onDrawPosText(GrDrawContext*, GrRenderTarget*, const GrClip&,
+    virtual void onDrawPosText(GrRenderTarget*, const GrClip&,
                                const GrPaint&, const SkPaint&,
                                const SkMatrix& viewMatrix,
                                const char text[], size_t byteLength,
                                const SkScalar pos[], int scalarsPerPosition,
                                const SkPoint& offset, const SkIRect& clipBounds) = 0;
 
-    void drawTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
+    void drawTextAsPath(GrRenderTarget*, const GrClip& clip,
                         const SkPaint& origPaint, const SkMatrix& viewMatrix,
                         const char text[], size_t byteLength, SkScalar x, SkScalar y,
                         const SkIRect& clipBounds);
-    void drawPosTextAsPath(GrDrawContext*, GrRenderTarget*, const GrClip& clip,
+    void drawPosTextAsPath(GrRenderTarget*, const GrClip& clip,
                            const SkPaint& origPaint, const SkMatrix& viewMatrix,
                            const char text[], size_t byteLength,
                            const SkScalar pos[], int scalarsPerPosition,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 18b2643..07c8dc1 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -10,6 +10,7 @@
 #include "GrBlurUtils.h"
 #include "GrContext.h"
 #include "GrDrawContext.h"
+#include "GrFontScaler.h"
 #include "GrGpu.h"
 #include "GrGpuResourcePriv.h"
 #include "GrLayerHoister.h"
@@ -137,7 +138,7 @@
     if (props) {
         return SkDeviceProperties(props->pixelGeometry());
     } else {
-        return SkDeviceProperties(SkDeviceProperties::kLegacyLCD_InitType);
+        return SkDeviceProperties();
     }
 }
 
@@ -167,8 +168,7 @@
     fLegacyBitmap.setPixelRef(pr)->unref();
 
     bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
-    fTextContext = fContext->createTextContext(fRenderTarget, this->getLeakyProperties(), useDFT);
-    fDrawContext.reset(SkRef(fContext->drawContext()));
+    fDrawContext.reset(SkRef(fContext->drawContext(&this->getLeakyProperties(), useDFT)));
 }
 
 GrRenderTarget* SkGpuDevice::CreateRenderTarget(GrContext* context, SkSurface::Budgeted budgeted,
@@ -227,8 +227,6 @@
         delete fDrawProcs;
     }
 
-    SkDELETE(fTextContext);
-
     fRenderTarget->unref();
     fContext->unref();
 }
@@ -355,7 +353,9 @@
     SkPixelRef* pr = SkNEW_ARGS(SkGrPixelRef, (fRenderTarget->surfacePriv().info(), fRenderTarget));
     fLegacyBitmap.setPixelRef(pr)->unref();
 
-    fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext()));
+    bool useDFT = fSurfaceProps.isUseDistanceFieldFonts();
+    fDrawContext.reset(SkRef(fRenderTarget->getContext()->drawContext(&this->getLeakyProperties(),
+                                                                      useDFT)));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1638,7 +1638,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fTextContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
+    fDrawContext->drawText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
                            (const char *)text, byteLength, x, y, draw.fClip->getBounds());
 }
 
@@ -1655,7 +1655,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fTextContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
+    fDrawContext->drawPosText(fRenderTarget, fClip, grPaint, paint, *draw.fMatrix,
                               (const char *)text, byteLength, pos, scalarsPerPos, offset,
                               draw.fClip->getBounds());
 }
@@ -1667,7 +1667,7 @@
 
     SkDEBUGCODE(this->validate();)
 
-    fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix,
+    fDrawContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix,
                                blob, x, y, drawFilter, draw.fClip->getBounds());
 }
 
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index c06cdc2..cf85cd9 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -23,7 +23,6 @@
 
 class GrAccelData;
 struct GrCachedLayer;
-class GrTextContext;
 
 /**
  *  Subclass of SkBaseDevice, which directs all drawing to the GrGpu owned by the
@@ -151,7 +150,6 @@
     SkAutoTUnref<const SkClipStack> fClipStack;
     SkIPoint                        fClipOrigin;
     GrClip                          fClip;
-    GrTextContext*                  fTextContext;
     SkAutoTUnref<GrDrawContext>     fDrawContext;
     SkSurfaceProps                  fSurfaceProps;
     GrRenderTarget*                 fRenderTarget;
@@ -219,7 +217,6 @@
                                               int sampleCount);
 
     friend class GrAtlasTextContext;
-    friend class GrTextContext;
     typedef SkBaseDevice INHERITED;
 };